diff options
Diffstat (limited to 'drivers/net/wireless')
299 files changed, 59069 insertions, 3186 deletions
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 24b983edb357..eca87f7c5b6c 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -1855,7 +1855,7 @@ void ath10k_ce_dump_registers(struct ath10k *ar, struct ath10k_ce_crash_data ce_data; u32 addr, id; - lockdep_assert_held(&ar->data_lock); + lockdep_assert_held(&ar->dump_mutex); ath10k_err(ar, "Copy Engine register dump:\n"); diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 835b8de92d55..aff585658fc0 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -3119,6 +3119,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, goto err_free_wq; mutex_init(&ar->conf_mutex); + mutex_init(&ar->dump_mutex); spin_lock_init(&ar->data_lock); INIT_LIST_HEAD(&ar->peers); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index e08a17b01e03..e35aae5146f1 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -1063,6 +1063,9 @@ struct ath10k { /* prevents concurrent FW reconfiguration */ struct mutex conf_mutex; + /* protects coredump data */ + struct mutex dump_mutex; + /* protects shared structure data */ spinlock_t data_lock; diff --git a/drivers/net/wireless/ath/ath10k/coredump.c b/drivers/net/wireless/ath/ath10k/coredump.c index 33838d9c1cb6..45a355fb62b9 100644 --- a/drivers/net/wireless/ath/ath10k/coredump.c +++ b/drivers/net/wireless/ath/ath10k/coredump.c @@ -1102,7 +1102,7 @@ struct ath10k_fw_crash_data *ath10k_coredump_new(struct ath10k *ar) { struct ath10k_fw_crash_data *crash_data = ar->coredump.fw_crash_data; - lockdep_assert_held(&ar->data_lock); + lockdep_assert_held(&ar->dump_mutex); if (ath10k_coredump_mask == 0) /* coredump disabled */ @@ -1146,7 +1146,7 @@ static struct ath10k_dump_file_data *ath10k_coredump_build(struct ath10k *ar) if (!buf) return NULL; - spin_lock_bh(&ar->data_lock); + mutex_lock(&ar->dump_mutex); dump_data = (struct ath10k_dump_file_data *)(buf); strlcpy(dump_data->df_magic, "ATH10K-FW-DUMP", @@ -1213,7 +1213,7 @@ static struct ath10k_dump_file_data *ath10k_coredump_build(struct ath10k *ar) sofar += sizeof(*dump_tlv) + crash_data->ramdump_buf_len; } - spin_unlock_bh(&ar->data_lock); + mutex_unlock(&ar->dump_mutex); return dump_data; } diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index a20ea270d519..1acc622d2183 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2728,7 +2728,7 @@ static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb) num_msdus++; num_bytes += ret; } - ieee80211_return_txq(hw, txq); + ieee80211_return_txq(hw, txq, false); ieee80211_txq_schedule_end(hw, txq->ac); record->num_msdus = cpu_to_le16(num_msdus); diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index b73c23d4ce86..9c703d287333 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4089,7 +4089,7 @@ static int ath10k_mac_schedule_txq(struct ieee80211_hw *hw, u32 ac) if (ret < 0) break; } - ieee80211_return_txq(hw, txq); + ieee80211_return_txq(hw, txq, false); ath10k_htt_tx_txq_update(hw, txq); if (ret == -EBUSY) break; @@ -4374,7 +4374,7 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw, if (ret < 0) break; } - ieee80211_return_txq(hw, txq); + ieee80211_return_txq(hw, txq, false); ath10k_htt_tx_txq_update(hw, txq); out: ieee80211_txq_schedule_end(hw, ac); @@ -5774,7 +5774,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_MCAST_RATE && - !WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def))) { + !ath10k_mac_vif_chan(arvif->vif, &def)) { band = def.chan->band; rateidx = vif->bss_conf.mcast_rate[band] - 1; @@ -5812,7 +5812,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_BASIC_RATES) { - if (WARN_ON(ath10k_mac_vif_chan(vif, &def))) { + if (ath10k_mac_vif_chan(vif, &def)) { mutex_unlock(&ar->conf_mutex); return; } diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 271f92c24d44..2c27f407a851 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1441,7 +1441,7 @@ static void ath10k_pci_dump_registers(struct ath10k *ar, __le32 reg_dump_values[REG_DUMP_COUNT_QCA988X] = {}; int i, ret; - lockdep_assert_held(&ar->data_lock); + lockdep_assert_held(&ar->dump_mutex); ret = ath10k_pci_diag_read_hi(ar, ®_dump_values[0], hi_failure_state, @@ -1656,7 +1656,7 @@ static void ath10k_pci_dump_memory(struct ath10k *ar, int ret, i; u8 *buf; - lockdep_assert_held(&ar->data_lock); + lockdep_assert_held(&ar->dump_mutex); if (!crash_data) return; @@ -1734,14 +1734,19 @@ static void ath10k_pci_dump_memory(struct ath10k *ar, } } -static void ath10k_pci_fw_crashed_dump(struct ath10k *ar) +static void ath10k_pci_fw_dump_work(struct work_struct *work) { + struct ath10k_pci *ar_pci = container_of(work, struct ath10k_pci, + dump_work); struct ath10k_fw_crash_data *crash_data; + struct ath10k *ar = ar_pci->ar; char guid[UUID_STRING_LEN + 1]; - spin_lock_bh(&ar->data_lock); + mutex_lock(&ar->dump_mutex); + spin_lock_bh(&ar->data_lock); ar->stats.fw_crash_counter++; + spin_unlock_bh(&ar->data_lock); crash_data = ath10k_coredump_new(ar); @@ -1756,11 +1761,18 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar) ath10k_ce_dump_registers(ar, crash_data); ath10k_pci_dump_memory(ar, crash_data); - spin_unlock_bh(&ar->data_lock); + mutex_unlock(&ar->dump_mutex); queue_work(ar->workqueue, &ar->restart_work); } +static void ath10k_pci_fw_crashed_dump(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + queue_work(ar->workqueue, &ar_pci->dump_work); +} + void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, int force) { @@ -3442,6 +3454,8 @@ int ath10k_pci_setup_resource(struct ath10k *ar) spin_lock_init(&ar_pci->ps_lock); mutex_init(&ar_pci->ce_diag_mutex); + INIT_WORK(&ar_pci->dump_work, ath10k_pci_fw_dump_work); + timer_setup(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, 0); if (QCA_REV_6174(ar) || QCA_REV_9377(ar)) diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 3773c79f322f..4455ed6c5275 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -121,6 +121,8 @@ struct ath10k_pci { /* For protecting ce_diag */ struct mutex ce_diag_mutex; + struct work_struct dump_work; + struct ath10k_ce ce; struct timer_list rx_post_retry; diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index 6433ff10d80e..a29cfb9c72c2 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -416,8 +416,8 @@ int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct nlattr *tb[ATH10K_TM_ATTR_MAX + 1]; int ret; - ret = nla_parse(tb, ATH10K_TM_ATTR_MAX, data, len, ath10k_tm_policy, - NULL); + ret = nla_parse_deprecated(tb, ATH10K_TM_ATTR_MAX, data, len, + ath10k_tm_policy, NULL); if (ret) return ret; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index a2351ef45ae0..65a4c142640d 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -837,7 +837,6 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, txq->link = &ds->ds_link; ath5k_hw_start_tx_dma(ah, txq->qnum); - mmiowb(); spin_unlock_bh(&txq->lock); return 0; @@ -2174,7 +2173,6 @@ ath5k_beacon_config(struct ath5k_hw *ah) } ath5k_hw_set_imr(ah, ah->imask); - mmiowb(); spin_unlock_bh(&ah->block); } @@ -2779,7 +2777,6 @@ int ath5k_start(struct ieee80211_hw *hw) ret = 0; done: - mmiowb(); mutex_unlock(&ah->lock); set_bit(ATH_STAT_STARTED, ah->status); @@ -2839,7 +2836,6 @@ void ath5k_stop(struct ieee80211_hw *hw) "putting device to sleep\n"); } - mmiowb(); mutex_unlock(&ah->lock); ath5k_stop_tasklets(ah); diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 16e052d02c94..5e866a193ed0 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -263,7 +263,6 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); common->curaid = 0; ath5k_hw_set_bssid(ah); - mmiowb(); } if (changes & BSS_CHANGED_BEACON_INT) @@ -528,7 +527,6 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ret = -EINVAL; } - mmiowb(); mutex_unlock(&ah->lock); return ret; } diff --git a/drivers/net/wireless/ath/ath6kl/testmode.c b/drivers/net/wireless/ath/ath6kl/testmode.c index d8dcacda9add..f3906dbe5495 100644 --- a/drivers/net/wireless/ath/ath6kl/testmode.c +++ b/drivers/net/wireless/ath/ath6kl/testmode.c @@ -74,8 +74,8 @@ int ath6kl_tm_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, int err, buf_len; void *buf; - err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len, ath6kl_tm_policy, - NULL); + err = nla_parse_deprecated(tb, ATH6KL_TM_ATTR_MAX, data, len, + ath6kl_tm_policy, NULL); if (err) return err; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 98141b699c88..a04d8616fe09 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -642,7 +642,7 @@ static int ath9k_of_init(struct ath_softc *sc) } mac = of_get_mac_address(np); - if (mac) + if (!IS_ERR(mac)) ether_addr_copy(common->macaddr, mac); return 0; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 773d428ff1b0..b17e1ca40995 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1938,12 +1938,15 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) goto out; while ((queue = ieee80211_next_txq(hw, txq->mac80211_qnum))) { + bool force; + tid = (struct ath_atx_tid *)queue->drv_priv; ret = ath_tx_sched_aggr(sc, txq, tid); ath_dbg(common, QUEUE, "ath_tx_sched_aggr returned %d\n", ret); - ieee80211_return_txq(hw, queue); + force = !skb_queue_empty(&tid->retry_q); + ieee80211_return_txq(hw, queue, force); } out: diff --git a/drivers/net/wireless/ath/wcn36xx/testmode.c b/drivers/net/wireless/ath/wcn36xx/testmode.c index 51a038022c8b..7ae14b4d2d0e 100644 --- a/drivers/net/wireless/ath/wcn36xx/testmode.c +++ b/drivers/net/wireless/ath/wcn36xx/testmode.c @@ -132,8 +132,8 @@ int wcn36xx_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, unsigned short attr; wcn36xx_dbg_dump(WCN36XX_DBG_TESTMODE_DUMP, "Data:", data, len); - ret = nla_parse(tb, WCN36XX_TM_ATTR_MAX, data, len, - wcn36xx_tm_policy, NULL); + ret = nla_parse_deprecated(tb, WCN36XX_TM_ATTR_MAX, data, len, + wcn36xx_tm_policy, NULL); if (ret) return ret; diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index a1e226652b4a..804955d24b30 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -465,7 +465,7 @@ static int wil_cfg80211_validate_add_iface(struct wil6210_priv *wil, .num_different_channels = 1, }; - for (i = 0; i < wil->max_vifs; i++) { + for (i = 0; i < GET_MAX_VIFS(wil); i++) { if (wil->vifs[i]) { wdev = vif_to_wdev(wil->vifs[i]); params.iftype_num[wdev->iftype]++; @@ -486,7 +486,7 @@ static int wil_cfg80211_validate_change_iface(struct wil6210_priv *wil, }; bool check_combos = false; - for (i = 0; i < wil->max_vifs; i++) { + for (i = 0; i < GET_MAX_VIFS(wil); i++) { struct wil6210_vif *vif_pos = wil->vifs[i]; if (vif_pos && vif != vif_pos) { @@ -1274,7 +1274,12 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, params->wait); out: + /* when the sent packet was not acked by receiver(ACK=0), rc will + * be -EAGAIN. In this case this function needs to return success, + * the ACK=0 will be reflected in tx_status. + */ tx_status = (rc == 0); + rc = (rc == -EAGAIN) ? 0 : rc; cfg80211_mgmt_tx_status(wdev, cookie ? *cookie : 0, buf, len, tx_status, GFP_KERNEL); @@ -1806,7 +1811,7 @@ void wil_cfg80211_ap_recovery(struct wil6210_priv *wil) int rc, i; struct wiphy *wiphy = wil_to_wiphy(wil); - for (i = 0; i < wil->max_vifs; i++) { + for (i = 0; i < GET_MAX_VIFS(wil); i++) { struct wil6210_vif *vif = wil->vifs[i]; struct net_device *ndev; struct cfg80211_beacon_data bcon = {}; @@ -2620,8 +2625,8 @@ static int wil_rf_sector_get_cfg(struct wiphy *wiphy, if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities)) return -EOPNOTSUPP; - rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len, - wil_rf_sector_policy, NULL); + rc = nla_parse_deprecated(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, + data_len, wil_rf_sector_policy, NULL); if (rc) { wil_err(wil, "Invalid rf sector ATTR\n"); return rc; @@ -2679,13 +2684,13 @@ static int wil_rf_sector_get_cfg(struct wiphy *wiphy, QCA_ATTR_PAD)) goto nla_put_failure; - nl_cfgs = nla_nest_start(msg, QCA_ATTR_DMG_RF_SECTOR_CFG); + nl_cfgs = nla_nest_start_noflag(msg, QCA_ATTR_DMG_RF_SECTOR_CFG); if (!nl_cfgs) goto nla_put_failure; for (i = 0; i < WMI_MAX_RF_MODULES_NUM; i++) { if (!(rf_modules_vec & BIT(i))) continue; - nl_cfg = nla_nest_start(msg, i); + nl_cfg = nla_nest_start_noflag(msg, i); if (!nl_cfg) goto nla_put_failure; si = &reply.evt.sectors_info[i]; @@ -2740,8 +2745,8 @@ static int wil_rf_sector_set_cfg(struct wiphy *wiphy, if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities)) return -EOPNOTSUPP; - rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len, - wil_rf_sector_policy, NULL); + rc = nla_parse_deprecated(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, + data_len, wil_rf_sector_policy, NULL); if (rc) { wil_err(wil, "Invalid rf sector ATTR\n"); return rc; @@ -2773,9 +2778,11 @@ static int wil_rf_sector_set_cfg(struct wiphy *wiphy, cmd.sector_type = sector_type; nla_for_each_nested(nl_cfg, tb[QCA_ATTR_DMG_RF_SECTOR_CFG], tmp) { - rc = nla_parse_nested(tb2, QCA_ATTR_DMG_RF_SECTOR_CFG_MAX, - nl_cfg, wil_rf_sector_cfg_policy, - NULL); + rc = nla_parse_nested_deprecated(tb2, + QCA_ATTR_DMG_RF_SECTOR_CFG_MAX, + nl_cfg, + wil_rf_sector_cfg_policy, + NULL); if (rc) { wil_err(wil, "invalid sector cfg\n"); return -EINVAL; @@ -2847,8 +2854,8 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities)) return -EOPNOTSUPP; - rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len, - wil_rf_sector_policy, NULL); + rc = nla_parse_deprecated(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, + data_len, wil_rf_sector_policy, NULL); if (rc) { wil_err(wil, "Invalid rf sector ATTR\n"); return rc; @@ -2955,8 +2962,8 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities)) return -EOPNOTSUPP; - rc = nla_parse(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, data_len, - wil_rf_sector_policy, NULL); + rc = nla_parse_deprecated(tb, QCA_ATTR_DMG_RF_SECTOR_MAX, data, + data_len, wil_rf_sector_policy, NULL); if (rc) { wil_err(wil, "Invalid rf sector ATTR\n"); return rc; diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 7ad4e5328439..df2adff6c33a 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -207,6 +207,8 @@ static void wil_print_sring(struct seq_file *s, struct wil6210_priv *wil, seq_puts(s, "???\n"); } seq_printf(s, " desc_rdy_pol = %d\n", sring->desc_rdy_pol); + seq_printf(s, " invalid_buff_id_cnt = %d\n", + sring->invalid_buff_id_cnt); if (sring->va && (sring->size <= (1 << WIL_RING_SIZE_ORDER_MAX))) { uint i; @@ -258,6 +260,11 @@ static void wil_print_mbox_ring(struct seq_file *s, const char *prefix, wil_halp_vote(wil); + if (wil_mem_access_lock(wil)) { + wil_halp_unvote(wil); + return; + } + wil_memcpy_fromio_32(&r, off, sizeof(r)); wil_mbox_ring_le2cpus(&r); /* @@ -323,6 +330,7 @@ static void wil_print_mbox_ring(struct seq_file *s, const char *prefix, } out: seq_puts(s, "}\n"); + wil_mem_access_unlock(wil); wil_halp_unvote(wil); } @@ -601,6 +609,12 @@ static int memread_show(struct seq_file *s, void *data) if (ret < 0) return ret; + ret = wil_mem_access_lock(wil); + if (ret) { + wil_pm_runtime_put(wil); + return ret; + } + a = wmi_buffer(wil, cpu_to_le32(mem_addr)); if (a) @@ -608,6 +622,7 @@ static int memread_show(struct seq_file *s, void *data) else seq_printf(s, "[0x%08x] = INVALID\n", mem_addr); + wil_mem_access_unlock(wil); wil_pm_runtime_put(wil); return 0; @@ -626,10 +641,6 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, size_t unaligned_bytes, aligned_count, ret; int rc; - if (test_bit(wil_status_suspending, wil_blob->wil->status) || - test_bit(wil_status_suspended, wil_blob->wil->status)) - return 0; - if (pos < 0) return -EINVAL; @@ -656,11 +667,19 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, return rc; } + rc = wil_mem_access_lock(wil); + if (rc) { + kfree(buf); + wil_pm_runtime_put(wil); + return rc; + } + wil_memcpy_fromio_32(buf, (const void __iomem *) wil_blob->blob.data + aligned_pos, aligned_count); ret = copy_to_user(user_buf, buf + unaligned_bytes, count); + wil_mem_access_unlock(wil); wil_pm_runtime_put(wil); kfree(buf); @@ -1364,7 +1383,7 @@ static int link_show(struct seq_file *s, void *data) if (p->status != wil_sta_connected) continue; - vif = (mid < wil->max_vifs) ? wil->vifs[mid] : NULL; + vif = (mid < GET_MAX_VIFS(wil)) ? wil->vifs[mid] : NULL; if (vif) { rc = wil_cid_fill_sinfo(vif, i, sinfo); if (rc) @@ -1562,7 +1581,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) break; } mid = (p->status != wil_sta_unused) ? p->mid : U8_MAX; - if (mid < wil->max_vifs) { + if (mid < GET_MAX_VIFS(wil)) { struct wil6210_vif *vif = wil->vifs[mid]; if (vif->wdev.iftype == NL80211_IFTYPE_STATION && @@ -1628,7 +1647,7 @@ static int mids_show(struct seq_file *s, void *data) int i; mutex_lock(&wil->vif_mutex); - for (i = 0; i < wil->max_vifs; i++) { + for (i = 0; i < GET_MAX_VIFS(wil); i++) { vif = wil->vifs[i]; if (vif) { @@ -1849,7 +1868,7 @@ static int wil_link_stats_debugfs_show(struct seq_file *s, void *data) /* iterate over all MIDs and show per-cid statistics. Then show the * global statistics */ - for (i = 0; i < wil->max_vifs; i++) { + for (i = 0; i < GET_MAX_VIFS(wil); i++) { vif = wil->vifs[i]; seq_printf(s, "MID %d ", i); @@ -1905,7 +1924,7 @@ static ssize_t wil_link_stats_write(struct file *file, const char __user *buf, if (rc) return rc; - for (i = 0; i < wil->max_vifs; i++) { + for (i = 0; i < GET_MAX_VIFS(wil); i++) { vif = wil->vifs[i]; if (!vif) continue; @@ -2375,6 +2394,7 @@ static const struct dbg_off dbg_wil_regs[] = { {"RGF_MAC_MTRL_COUNTER_0", 0444, HOSTADDR(RGF_MAC_MTRL_COUNTER_0), doff_io32}, {"RGF_USER_USAGE_1", 0444, HOSTADDR(RGF_USER_USAGE_1), doff_io32}, + {"RGF_USER_USAGE_2", 0444, HOSTADDR(RGF_USER_USAGE_2), doff_io32}, {}, }; diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c index 388b3d4717ca..3ec0f2fab9b7 100644 --- a/drivers/net/wireless/ath/wil6210/fw_inc.c +++ b/drivers/net/wireless/ath/wil6210/fw_inc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -647,6 +647,8 @@ int wil_request_firmware(struct wil6210_priv *wil, const char *name, out: release_firmware(fw); + if (rc) + wil_err_fw(wil, "Loading <%s> failed, rc %d\n", name, rc); return rc; } @@ -741,6 +743,8 @@ int wil_request_board(struct wil6210_priv *wil, const char *name) out: release_firmware(brd); + if (rc) + wil_err_fw(wil, "Loading <%s> failed, rc %d\n", name, rc); return rc; } diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 277abfdf3322..9b9c9ec01536 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -184,6 +184,28 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, } } +/* Device memory access is prohibited while reset or suspend. + * wil_mem_access_lock protects accessing device memory in these cases + */ +int wil_mem_access_lock(struct wil6210_priv *wil) +{ + if (!down_read_trylock(&wil->mem_lock)) + return -EBUSY; + + if (test_bit(wil_status_suspending, wil->status) || + test_bit(wil_status_suspended, wil->status)) { + up_read(&wil->mem_lock); + return -EBUSY; + } + + return 0; +} + +void wil_mem_access_unlock(struct wil6210_priv *wil) +{ + up_read(&wil->mem_lock); +} + static void wil_ring_fini_tx(struct wil6210_priv *wil, int id) { struct wil_ring *ring = &wil->ring_tx[id]; @@ -663,7 +685,7 @@ void wil_bcast_fini_all(struct wil6210_priv *wil) int i; struct wil6210_vif *vif; - for (i = 0; i < wil->max_vifs; i++) { + for (i = 0; i < GET_MAX_VIFS(wil); i++) { vif = wil->vifs[i]; if (vif) wil_bcast_fini(vif); @@ -703,6 +725,7 @@ int wil_priv_init(struct wil6210_priv *wil) spin_lock_init(&wil->wmi_ev_lock); spin_lock_init(&wil->net_queue_lock); init_waitqueue_head(&wil->wq); + init_rwsem(&wil->mem_lock); wil->wmi_wq = create_singlethread_workqueue(WIL_NAME "_wmi"); if (!wil->wmi_wq) @@ -1390,13 +1413,22 @@ static int wil_get_otp_info(struct wil6210_priv *wil) u8 mac[8]; int mac_addr; - if (wil->hw_version >= HW_VER_TALYN_MB) - mac_addr = RGF_OTP_MAC_TALYN_MB; - else - mac_addr = RGF_OTP_MAC; + /* OEM MAC has precedence */ + mac_addr = RGF_OTP_OEM_MAC; + wil_memcpy_fromio_32(mac, wil->csr + HOSTADDR(mac_addr), sizeof(mac)); + + if (is_valid_ether_addr(mac)) { + wil_info(wil, "using OEM MAC %pM\n", mac); + } else { + if (wil->hw_version >= HW_VER_TALYN_MB) + mac_addr = RGF_OTP_MAC_TALYN_MB; + else + mac_addr = RGF_OTP_MAC; + + wil_memcpy_fromio_32(mac, wil->csr + HOSTADDR(mac_addr), + sizeof(mac)); + } - wil_memcpy_fromio_32(mac, wil->csr + HOSTADDR(mac_addr), - sizeof(mac)); if (!is_valid_ether_addr(mac)) { wil_err(wil, "Invalid MAC %pM\n", mac); return -EINVAL; @@ -1460,7 +1492,7 @@ void wil_abort_scan_all_vifs(struct wil6210_priv *wil, bool sync) lockdep_assert_held(&wil->vif_mutex); - for (i = 0; i < wil->max_vifs; i++) { + for (i = 0; i < GET_MAX_VIFS(wil); i++) { struct wil6210_vif *vif = wil->vifs[i]; if (vif) @@ -1500,11 +1532,6 @@ static void wil_pre_fw_config(struct wil6210_priv *wil) if (wil->hw_version < HW_VER_TALYN_MB) { wil_s(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, ICR), 0); wil_w(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, IMV), ~0); - } else { - wil_s(wil, - RGF_CAF_ICR_TALYN_MB + offsetof(struct RGF_ICR, ICR), 0); - wil_w(wil, RGF_CAF_ICR_TALYN_MB + - offsetof(struct RGF_ICR, IMV), ~0); } /* clear PAL_UNIT_ICR (potential D0->D3 leftover) * In Talyn-MB host cannot access this register due to @@ -1528,7 +1555,7 @@ static int wil_restore_vifs(struct wil6210_priv *wil) struct wireless_dev *wdev; int i, rc; - for (i = 0; i < wil->max_vifs; i++) { + for (i = 0; i < GET_MAX_VIFS(wil); i++) { vif = wil->vifs[i]; if (!vif) continue; @@ -1580,7 +1607,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) if (wil->hw_version == HW_VER_UNKNOWN) return -ENODEV; - if (test_bit(WIL_PLATFORM_CAPA_T_PWR_ON_0, wil->platform_capa)) { + if (test_bit(WIL_PLATFORM_CAPA_T_PWR_ON_0, wil->platform_capa) && + wil->hw_version < HW_VER_TALYN_MB) { wil_dbg_misc(wil, "Notify FW to set T_POWER_ON=0\n"); wil_s(wil, RGF_USER_USAGE_8, BIT_USER_SUPPORT_T_POWER_ON_0); } @@ -1599,20 +1627,11 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) } set_bit(wil_status_resetting, wil->status); - if (test_bit(wil_status_collecting_dumps, wil->status)) { - /* Device collects crash dump, cancel the reset. - * following crash dump collection, reset would take place. - */ - wil_dbg_misc(wil, "reject reset while collecting crash dump\n"); - rc = -EBUSY; - goto out; - } - mutex_lock(&wil->vif_mutex); wil_abort_scan_all_vifs(wil, false); mutex_unlock(&wil->vif_mutex); - for (i = 0; i < wil->max_vifs; i++) { + for (i = 0; i < GET_MAX_VIFS(wil); i++) { vif = wil->vifs[i]; if (vif) { cancel_work_sync(&vif->disconnect_worker); @@ -1782,7 +1801,9 @@ int __wil_up(struct wil6210_priv *wil) WARN_ON(!mutex_is_locked(&wil->mutex)); + down_write(&wil->mem_lock); rc = wil_reset(wil, true); + up_write(&wil->mem_lock); if (rc) return rc; @@ -1854,6 +1875,7 @@ int wil_up(struct wil6210_priv *wil) int __wil_down(struct wil6210_priv *wil) { + int rc; WARN_ON(!mutex_is_locked(&wil->mutex)); set_bit(wil_status_resetting, wil->status); @@ -1873,7 +1895,11 @@ int __wil_down(struct wil6210_priv *wil) wil_abort_scan_all_vifs(wil, false); mutex_unlock(&wil->vif_mutex); - return wil_reset(wil, false); + down_write(&wil->mem_lock); + rc = wil_reset(wil, false); + up_write(&wil->mem_lock); + + return rc; } int wil_down(struct wil6210_priv *wil) diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index b4e0eb1585b9..59f041d708fe 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -27,7 +27,7 @@ bool wil_has_other_active_ifaces(struct wil6210_priv *wil, struct wil6210_vif *vif; struct net_device *ndev_i; - for (i = 0; i < wil->max_vifs; i++) { + for (i = 0; i < GET_MAX_VIFS(wil); i++) { vif = wil->vifs[i]; if (vif) { ndev_i = vif_to_ndev(vif); @@ -155,7 +155,7 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget) struct wil6210_vif *vif; if (!ring->va || !txdata->enabled || - txdata->mid >= wil->max_vifs) + txdata->mid >= GET_MAX_VIFS(wil)) continue; vif = wil->vifs[txdata->mid]; @@ -294,7 +294,7 @@ static u8 wil_vif_find_free_mid(struct wil6210_priv *wil) { u8 i; - for (i = 0; i < wil->max_vifs; i++) { + for (i = 0; i < GET_MAX_VIFS(wil); i++) { if (!wil->vifs[i]) return i; } @@ -500,7 +500,7 @@ void wil_vif_remove(struct wil6210_priv *wil, u8 mid) bool any_active = wil_has_active_ifaces(wil, true, false); ASSERT_RTNL(); - if (mid >= wil->max_vifs) { + if (mid >= GET_MAX_VIFS(wil)) { wil_err(wil, "invalid MID: %d\n", mid); return; } diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index c8c6613371d1..3b82d6cfc218 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -176,7 +176,7 @@ static void wil_remove_all_additional_vifs(struct wil6210_priv *wil) struct wil6210_vif *vif; int i; - for (i = 1; i < wil->max_vifs; i++) { + for (i = 1; i < GET_MAX_VIFS(wil); i++) { vif = wil->vifs[i]; if (vif) { wil_vif_prepare_stop(vif); diff --git a/drivers/net/wireless/ath/wil6210/pm.c b/drivers/net/wireless/ath/wil6210/pm.c index 75fe9323547c..56143e7670ed 100644 --- a/drivers/net/wireless/ath/wil6210/pm.c +++ b/drivers/net/wireless/ath/wil6210/pm.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2014,2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -26,7 +26,7 @@ static void wil_pm_wake_connected_net_queues(struct wil6210_priv *wil) int i; mutex_lock(&wil->vif_mutex); - for (i = 0; i < wil->max_vifs; i++) { + for (i = 0; i < GET_MAX_VIFS(wil); i++) { struct wil6210_vif *vif = wil->vifs[i]; if (vif && test_bit(wil_vif_fwconnected, vif->status)) @@ -40,7 +40,7 @@ static void wil_pm_stop_all_net_queues(struct wil6210_priv *wil) int i; mutex_lock(&wil->vif_mutex); - for (i = 0; i < wil->max_vifs; i++) { + for (i = 0; i < GET_MAX_VIFS(wil); i++) { struct wil6210_vif *vif = wil->vifs[i]; if (vif) @@ -123,7 +123,7 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime) /* interface is running */ mutex_lock(&wil->vif_mutex); - for (i = 0; i < wil->max_vifs; i++) { + for (i = 0; i < GET_MAX_VIFS(wil); i++) { struct wil6210_vif *vif = wil->vifs[i]; if (!vif) @@ -195,14 +195,18 @@ static int wil_suspend_keep_radio_on(struct wil6210_priv *wil) wil_dbg_pm(wil, "suspend keep radio on\n"); /* Prevent handling of new tx and wmi commands */ - set_bit(wil_status_suspending, wil->status); - if (test_bit(wil_status_collecting_dumps, wil->status)) { - /* Device collects crash dump, cancel the suspend */ - wil_dbg_pm(wil, "reject suspend while collecting crash dump\n"); - clear_bit(wil_status_suspending, wil->status); + rc = down_write_trylock(&wil->mem_lock); + if (!rc) { + wil_err(wil, + "device is busy. down_write_trylock failed, returned (0x%x)\n", + rc); wil->suspend_stats.rejected_by_host++; return -EBUSY; } + + set_bit(wil_status_suspending, wil->status); + up_write(&wil->mem_lock); + wil_pm_stop_all_net_queues(wil); if (!wil_is_tx_idle(wil)) { @@ -310,15 +314,18 @@ static int wil_suspend_radio_off(struct wil6210_priv *wil) wil_dbg_pm(wil, "suspend radio off\n"); - set_bit(wil_status_suspending, wil->status); - if (test_bit(wil_status_collecting_dumps, wil->status)) { - /* Device collects crash dump, cancel the suspend */ - wil_dbg_pm(wil, "reject suspend while collecting crash dump\n"); - clear_bit(wil_status_suspending, wil->status); + rc = down_write_trylock(&wil->mem_lock); + if (!rc) { + wil_err(wil, + "device is busy. down_write_trylock failed, returned (0x%x)\n", + rc); wil->suspend_stats.rejected_by_host++; return -EBUSY; } + set_bit(wil_status_suspending, wil->status); + up_write(&wil->mem_lock); + /* if netif up, hardware is alive, shut it down */ mutex_lock(&wil->vif_mutex); active_ifaces = wil_has_active_ifaces(wil, true, false); diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c index c38773878ae3..f6fce6ff73d9 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.c +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c @@ -29,6 +29,7 @@ #define WIL_EDMA_MAX_DATA_OFFSET (2) /* RX buffer size must be aligned to 4 bytes */ #define WIL_EDMA_RX_BUF_LEN_DEFAULT (2048) +#define MAX_INVALID_BUFF_ID_RETRY (3) static void wil_tx_desc_unmap_edma(struct device *dev, union wil_tx_desc *desc, @@ -312,7 +313,8 @@ static int wil_init_rx_buff_arr(struct wil6210_priv *wil, struct list_head *free = &wil->rx_buff_mgmt.free; int i; - wil->rx_buff_mgmt.buff_arr = kcalloc(size, sizeof(struct wil_rx_buff), + wil->rx_buff_mgmt.buff_arr = kcalloc(size + 1, + sizeof(struct wil_rx_buff), GFP_KERNEL); if (!wil->rx_buff_mgmt.buff_arr) return -ENOMEM; @@ -321,14 +323,16 @@ static int wil_init_rx_buff_arr(struct wil6210_priv *wil, INIT_LIST_HEAD(active); INIT_LIST_HEAD(free); - /* Linkify the list */ + /* Linkify the list. + * buffer id 0 should not be used (marks invalid id). + */ buff_arr = wil->rx_buff_mgmt.buff_arr; - for (i = 0; i < size; i++) { + for (i = 1; i <= size; i++) { list_add(&buff_arr[i].list, free); buff_arr[i].id = i; } - wil->rx_buff_mgmt.size = size; + wil->rx_buff_mgmt.size = size + 1; return 0; } @@ -428,6 +432,9 @@ static void wil_ring_free_edma(struct wil6210_priv *wil, struct wil_ring *ring) &ring->pa, ring->ctx); wil_move_all_rx_buff_to_free_list(wil, ring); + dma_free_coherent(dev, sizeof(*ring->edma_rx_swtail.va), + ring->edma_rx_swtail.va, + ring->edma_rx_swtail.pa); goto out; } @@ -804,18 +811,9 @@ static int wil_rx_error_check_edma(struct wil6210_priv *wil, struct sk_buff *skb, struct wil_net_stats *stats) { - int error; int l2_rx_status; - int l3_rx_status; - int l4_rx_status; void *msg = wil_skb_rxstatus(skb); - error = wil_rx_status_get_error(msg); - if (!error) { - skb->ip_summed = CHECKSUM_UNNECESSARY; - return 0; - } - l2_rx_status = wil_rx_status_get_l2_rx_status(msg); if (l2_rx_status != 0) { wil_dbg_txrx(wil, "L2 RX error, l2_rx_status=0x%x\n", @@ -844,17 +842,7 @@ static int wil_rx_error_check_edma(struct wil6210_priv *wil, return -EFAULT; } - l3_rx_status = wil_rx_status_get_l3_rx_status(msg); - l4_rx_status = wil_rx_status_get_l4_rx_status(msg); - if (!l3_rx_status && !l4_rx_status) - skb->ip_summed = CHECKSUM_UNNECESSARY; - /* If HW reports bad checksum, let IP stack re-check it - * For example, HW don't understand Microsoft IP stack that - * mis-calculates TCP checksum - if it should be 0x0, - * it writes 0xffff in violation of RFC 1624 - */ - else - stats->rx_csum_err++; + skb->ip_summed = wil_rx_status_get_checksum(msg, stats); return 0; } @@ -892,26 +880,50 @@ again: /* Extract the buffer ID from the status message */ buff_id = le16_to_cpu(wil_rx_status_get_buff_id(msg)); - if (unlikely(!wil_val_in_range(buff_id, 0, wil->rx_buff_mgmt.size))) { + + while (!buff_id) { + struct wil_rx_status_extended *s; + int invalid_buff_id_retry = 0; + + wil_dbg_txrx(wil, + "buff_id is not updated yet by HW, (swhead 0x%x)\n", + sring->swhead); + if (++invalid_buff_id_retry > MAX_INVALID_BUFF_ID_RETRY) + break; + + /* Read the status message again */ + s = (struct wil_rx_status_extended *) + (sring->va + (sring->elem_size * sring->swhead)); + *(struct wil_rx_status_extended *)msg = *s; + buff_id = le16_to_cpu(wil_rx_status_get_buff_id(msg)); + } + + if (unlikely(!wil_val_in_range(buff_id, 1, wil->rx_buff_mgmt.size))) { wil_err(wil, "Corrupt buff_id=%d, sring->swhead=%d\n", buff_id, sring->swhead); + wil_rx_status_reset_buff_id(sring); wil_sring_advance_swhead(sring); + sring->invalid_buff_id_cnt++; goto again; } - wil_sring_advance_swhead(sring); - /* Extract the SKB from the rx_buff management array */ skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb; wil->rx_buff_mgmt.buff_arr[buff_id].skb = NULL; if (!skb) { wil_err(wil, "No Rx skb at buff_id %d\n", buff_id); + wil_rx_status_reset_buff_id(sring); /* Move the buffer from the active list to the free list */ - list_move(&wil->rx_buff_mgmt.buff_arr[buff_id].list, - &wil->rx_buff_mgmt.free); + list_move_tail(&wil->rx_buff_mgmt.buff_arr[buff_id].list, + &wil->rx_buff_mgmt.free); + wil_sring_advance_swhead(sring); + sring->invalid_buff_id_cnt++; goto again; } + wil_rx_status_reset_buff_id(sring); + wil_sring_advance_swhead(sring); + memcpy(&pa, skb->cb, sizeof(pa)); dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE); dmalen = le16_to_cpu(wil_rx_status_get_length(msg)); @@ -926,8 +938,8 @@ again: sizeof(struct wil_rx_status_extended), false); /* Move the buffer from the active list to the free list */ - list_move(&wil->rx_buff_mgmt.buff_arr[buff_id].list, - &wil->rx_buff_mgmt.free); + list_move_tail(&wil->rx_buff_mgmt.buff_arr[buff_id].list, + &wil->rx_buff_mgmt.free); eop = wil_rx_status_get_eop(msg); diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.h b/drivers/net/wireless/ath/wil6210/txrx_edma.h index 343516a03a1e..bb4ff28b73e5 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.h +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016,2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2016,2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -427,6 +427,12 @@ static inline int wil_rx_status_get_eop(void *msg) /* EoP = End of Packet */ 30, 30); } +static inline void wil_rx_status_reset_buff_id(struct wil_status_ring *s) +{ + ((struct wil_rx_status_compressed *) + (s->va + (s->elem_size * s->swhead)))->buff_id = 0; +} + static inline __le16 wil_rx_status_get_buff_id(void *msg) { return ((struct wil_rx_status_compressed *)msg)->buff_id; @@ -511,6 +517,45 @@ static inline int wil_rx_status_get_l4_rx_status(void *msg) 5, 6); } +/* L4 L3 Expected result + * 0 0 Ok. No L3 and no L4 known protocols found. + * Treated as L2 packet. (no offloads on this packet) + * 0 1 Ok. It means that L3 was found, and checksum check passed. + * No known L4 protocol was found. + * 0 2 It means that L3 protocol was found, and checksum check failed. + * No L4 known protocol was found. + * 1 any Ok. It means that L4 was found, and checksum check passed. + * 3 0 Not a possible scenario. + * 3 1 Recalculate. It means that L3 protocol was found, and checksum + * passed. But L4 checksum failed. Need to see if really failed, + * or due to fragmentation. + * 3 2 Both L3 and L4 checksum check failed. + */ +static inline int wil_rx_status_get_checksum(void *msg, + struct wil_net_stats *stats) +{ + int l3_rx_status = wil_rx_status_get_l3_rx_status(msg); + int l4_rx_status = wil_rx_status_get_l4_rx_status(msg); + + if (l4_rx_status == 1) + return CHECKSUM_UNNECESSARY; + + if (l4_rx_status == 0 && l3_rx_status == 1) + return CHECKSUM_UNNECESSARY; + + if (l3_rx_status == 0 && l4_rx_status == 0) + /* L2 packet */ + return CHECKSUM_NONE; + + /* If HW reports bad checksum, let IP stack re-check it + * For example, HW doesn't understand Microsoft IP stack that + * mis-calculates TCP checksum - if it should be 0x0, + * it writes 0xffff in violation of RFC 1624 + */ + stats->rx_csum_err++; + return CHECKSUM_NONE; +} + static inline int wil_rx_status_get_security(void *msg) { return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d0, diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index e1b1039b13ab..8724d9975606 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -185,6 +185,7 @@ struct RGF_ICR { /* registers - FW addresses */ #define RGF_USER_USAGE_1 (0x880004) +#define RGF_USER_USAGE_2 (0x880008) #define RGF_USER_USAGE_6 (0x880018) #define BIT_USER_OOB_MODE BIT(31) #define BIT_USER_OOB_R2_MODE BIT(30) @@ -367,6 +368,7 @@ struct RGF_ICR { #define REVISION_ID_SPARROW_D0 (0x3) #define RGF_OTP_MAC_TALYN_MB (0x8a0304) +#define RGF_OTP_OEM_MAC (0x8a0334) #define RGF_OTP_MAC (0x8a0620) /* Talyn-MB */ @@ -566,10 +568,11 @@ struct wil_status_ring { bool is_rx; u8 desc_rdy_pol; /* Expected descriptor ready bit polarity */ struct wil_ring_rx_data rx_data; + u32 invalid_buff_id_cnt; /* relevant only for RX */ }; #define WIL_STA_TID_NUM (16) -#define WIL_MCS_MAX (12) /* Maximum MCS supported */ +#define WIL_MCS_MAX (15) /* Maximum MCS supported */ struct wil_net_stats { unsigned long rx_packets; @@ -660,7 +663,6 @@ enum { /* for wil6210_priv.status */ wil_status_suspending, /* suspend in progress */ wil_status_suspended, /* suspend completed, device is suspended */ wil_status_resuming, /* resume in progress */ - wil_status_collecting_dumps, /* crashdump collection in progress */ wil_status_last /* keep last */ }; @@ -992,6 +994,8 @@ struct wil6210_priv { struct wil_txrx_ops txrx_ops; struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */ + /* for synchronizing device memory access while reset or suspend */ + struct rw_semaphore mem_lock; /* statistics */ atomic_t isr_count_rx, isr_count_tx; /* debugfs */ @@ -1060,6 +1064,7 @@ struct wil6210_priv { #define vif_to_wil(v) (v->wil) #define vif_to_ndev(v) (v->ndev) #define vif_to_wdev(v) (&v->wdev) +#define GET_MAX_VIFS(wil) min_t(int, (wil)->max_vifs, WIL_MAX_VIFS) static inline struct wil6210_vif *wdev_to_vif(struct wil6210_priv *wil, struct wireless_dev *wdev) @@ -1176,6 +1181,8 @@ void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, size_t count); void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, size_t count); +int wil_mem_access_lock(struct wil6210_priv *wil); +void wil_mem_access_unlock(struct wil6210_priv *wil); struct wil6210_vif * wil_vif_alloc(struct wil6210_priv *wil, const char *name, diff --git a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c index dc33a0b4c3fa..772cb00c2002 100644 --- a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c +++ b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015,2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -57,7 +57,7 @@ static int wil_fw_get_crash_dump_bounds(struct wil6210_priv *wil, int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size) { - int i; + int i, rc; const struct fw_map *map; void *data; u32 host_min, dump_size, offset, len; @@ -73,14 +73,9 @@ int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size) return -EINVAL; } - set_bit(wil_status_collecting_dumps, wil->status); - if (test_bit(wil_status_suspending, wil->status) || - test_bit(wil_status_suspended, wil->status) || - test_bit(wil_status_resetting, wil->status)) { - wil_err(wil, "cannot collect fw dump during suspend/reset\n"); - clear_bit(wil_status_collecting_dumps, wil->status); - return -EINVAL; - } + rc = wil_mem_access_lock(wil); + if (rc) + return rc; /* copy to crash dump area */ for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { @@ -100,8 +95,7 @@ int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size) wil_memcpy_fromio_32((void * __force)(dest + offset), (const void __iomem * __force)data, len); } - - clear_bit(wil_status_collecting_dumps, wil->status); + wil_mem_access_unlock(wil); return 0; } diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index bda4a9712f91..d89cd41e78ac 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -41,6 +41,7 @@ MODULE_PARM_DESC(led_id, #define WIL_WAIT_FOR_SUSPEND_RESUME_COMP 200 #define WIL_WMI_CALL_GENERAL_TO_MS 100 +#define WIL_WMI_PCP_STOP_TO_MS 5000 /** * WMI event receiving - theory of operations @@ -2195,7 +2196,8 @@ int wmi_pcp_stop(struct wil6210_vif *vif) return rc; return wmi_call(wil, WMI_PCP_STOP_CMDID, vif->mid, NULL, 0, - WMI_PCP_STOPPED_EVENTID, NULL, 0, 20); + WMI_PCP_STOPPED_EVENTID, NULL, 0, + WIL_WMI_PCP_STOP_TO_MS); } int wmi_set_ssid(struct wil6210_vif *vif, u8 ssid_len, const void *ssid) @@ -2957,6 +2959,10 @@ static const char *suspend_status2name(u8 status) switch (status) { case WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE: return "LINK_NOT_IDLE"; + case WMI_TRAFFIC_SUSPEND_REJECTED_DISCONNECT: + return "DISCONNECT"; + case WMI_TRAFFIC_SUSPEND_REJECTED_OTHER: + return "OTHER"; default: return "Untracked status"; } @@ -3046,6 +3052,9 @@ static void resume_triggers2string(u32 triggers, char *string, int str_size) if (triggers & WMI_RESUME_TRIGGER_WMI_EVT) strlcat(string, " WMI_EVT", str_size); + + if (triggers & WMI_RESUME_TRIGGER_DISCONNECT) + strlcat(string, " DISCONNECT", str_size); } int wmi_resume(struct wil6210_priv *wil) @@ -3196,7 +3205,7 @@ static void wmi_event_handle(struct wil6210_priv *wil, if (mid == MID_BROADCAST) mid = 0; - if (mid >= ARRAY_SIZE(wil->vifs) || mid >= wil->max_vifs) { + if (mid >= GET_MAX_VIFS(wil)) { wil_dbg_wmi(wil, "invalid mid %d, event skipped\n", mid); return; @@ -3502,8 +3511,9 @@ int wmi_mgmt_tx(struct wil6210_vif *vif, const u8 *buf, size_t len) rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, vif->mid, cmd, total, WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000); if (!rc && evt.evt.status != WMI_FW_STATUS_SUCCESS) { - wil_err(wil, "mgmt_tx failed with status %d\n", evt.evt.status); - rc = -EINVAL; + wil_dbg_wmi(wil, "mgmt_tx failed with status %d\n", + evt.evt.status); + rc = -EAGAIN; } kfree(cmd); @@ -3555,9 +3565,9 @@ int wmi_mgmt_tx_ext(struct wil6210_vif *vif, const u8 *buf, size_t len, rc = wmi_call(wil, WMI_SW_TX_REQ_EXT_CMDID, vif->mid, cmd, total, WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000); if (!rc && evt.evt.status != WMI_FW_STATUS_SUCCESS) { - wil_err(wil, "mgmt_tx_ext failed with status %d\n", - evt.evt.status); - rc = -EINVAL; + wil_dbg_wmi(wil, "mgmt_tx_ext failed with status %d\n", + evt.evt.status); + rc = -EAGAIN; } kfree(cmd); diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index b668758da994..da46fc8d39cf 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * Copyright (c) 2006-2012 Wilocity * @@ -104,6 +104,7 @@ enum wmi_fw_capability { WMI_FW_CAPABILITY_RAW_MODE = 24, WMI_FW_CAPABILITY_TX_REQ_EXT = 25, WMI_FW_CAPABILITY_CHANNEL_4 = 26, + WMI_FW_CAPABILITY_IPA = 27, WMI_FW_CAPABILITY_MAX, }; @@ -294,6 +295,7 @@ enum wmi_command_id { WMI_SET_AP_SLOT_SIZE_CMDID = 0xA0F, WMI_SET_VRING_PRIORITY_WEIGHT_CMDID = 0xA10, WMI_SET_VRING_PRIORITY_CMDID = 0xA11, + WMI_RBUFCAP_CFG_CMDID = 0xA12, WMI_SET_MAC_ADDRESS_CMDID = 0xF003, WMI_ABORT_SCAN_CMDID = 0xF007, WMI_SET_PROMISCUOUS_MODE_CMDID = 0xF041, @@ -979,10 +981,22 @@ enum wmi_rx_msg_type { WMI_RX_MSG_TYPE_EXTENDED = 0x01, }; +enum wmi_ring_add_irq_mode { + /* Backwards compatibility + * for DESC ring - interrupt disabled + * for STATUS ring - interrupt enabled + */ + WMI_RING_ADD_IRQ_MODE_BWC = 0x00, + WMI_RING_ADD_IRQ_MODE_DISABLE = 0x01, + WMI_RING_ADD_IRQ_MODE_ENABLE = 0x02, +}; + struct wmi_tx_status_ring_add_cmd { struct wmi_edma_ring_cfg ring_cfg; u8 irq_index; - u8 reserved[3]; + /* wmi_ring_add_irq_mode */ + u8 irq_mode; + u8 reserved[2]; } __packed; struct wmi_rx_status_ring_add_cmd { @@ -1016,7 +1030,10 @@ struct wmi_tx_desc_ring_add_cmd { u8 mac_ctrl; u8 to_resolution; u8 agg_max_wsize; - u8 reserved[3]; + u8 irq_index; + /* wmi_ring_add_irq_mode */ + u8 irq_mode; + u8 reserved; struct wmi_vring_cfg_schd schd_params; } __packed; @@ -1982,6 +1999,7 @@ enum wmi_event_id { WMI_BEAMFORMING_MGMT_DONE_EVENTID = 0x1836, WMI_BF_TXSS_MGMT_DONE_EVENTID = 0x1837, WMI_BF_RXSS_MGMT_DONE_EVENTID = 0x1839, + WMI_BF_TRIG_EVENTID = 0x183A, WMI_RS_MGMT_DONE_EVENTID = 0x1852, WMI_RF_MGMT_STATUS_EVENTID = 0x1853, WMI_BF_SM_MGMT_DONE_EVENTID = 0x1838, @@ -2082,6 +2100,7 @@ enum wmi_event_id { WMI_SET_AP_SLOT_SIZE_EVENTID = 0x1A0F, WMI_SET_VRING_PRIORITY_WEIGHT_EVENTID = 0x1A10, WMI_SET_VRING_PRIORITY_EVENTID = 0x1A11, + WMI_RBUFCAP_CFG_EVENTID = 0x1A12, WMI_SET_CHANNEL_EVENTID = 0x9000, WMI_ASSOC_REQ_EVENTID = 0x9001, WMI_EAPOL_RX_EVENTID = 0x9002, @@ -2267,7 +2286,9 @@ struct wmi_notify_req_done_event { __le32 status; __le64 tsf; s8 rssi; - u8 reserved0[3]; + /* enum wmi_edmg_tx_mode */ + u8 tx_mode; + u8 reserved0[2]; __le32 tx_tpt; __le32 tx_goodput; __le32 rx_goodput; @@ -2316,6 +2337,7 @@ enum wmi_disconnect_reason { WMI_DIS_REASON_PROFILE_MISMATCH = 0x0C, WMI_DIS_REASON_CONNECTION_EVICTED = 0x0D, WMI_DIS_REASON_IBSS_MERGE = 0x0E, + WMI_DIS_REASON_HIGH_TEMPERATURE = 0x0F, }; /* WMI_DISCONNECT_EVENTID */ @@ -3168,6 +3190,30 @@ struct wmi_brp_set_ant_limit_event { u8 reserved[3]; } __packed; +enum wmi_bf_type { + WMI_BF_TYPE_SLS = 0x00, + WMI_BF_TYPE_BRP_RX = 0x01, +}; + +/* WMI_BF_TRIG_CMDID */ +struct wmi_bf_trig_cmd { + /* enum wmi_bf_type - type of requested beamforming */ + u8 bf_type; + /* used only for WMI_BF_TYPE_BRP_RX */ + u8 cid; + /* used only for WMI_BF_TYPE_SLS */ + u8 dst_mac[WMI_MAC_LEN]; + u8 reserved[4]; +} __packed; + +/* WMI_BF_TRIG_EVENTID */ +struct wmi_bf_trig_event { + /* enum wmi_fw_status */ + u8 status; + u8 cid; + u8 reserved[2]; +} __packed; + /* broadcast connection ID */ #define WMI_LINK_MAINTAIN_CFG_CID_BROADCAST (0xFFFFFFFF) @@ -3263,6 +3309,8 @@ struct wmi_link_maintain_cfg_read_done_event { enum wmi_traffic_suspend_status { WMI_TRAFFIC_SUSPEND_APPROVED = 0x0, WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE = 0x1, + WMI_TRAFFIC_SUSPEND_REJECTED_DISCONNECT = 0x2, + WMI_TRAFFIC_SUSPEND_REJECTED_OTHER = 0x3, }; /* WMI_TRAFFIC_SUSPEND_EVENTID */ @@ -3282,6 +3330,7 @@ enum wmi_resume_trigger { WMI_RESUME_TRIGGER_UCAST_RX = 0x2, WMI_RESUME_TRIGGER_BCAST_RX = 0x4, WMI_RESUME_TRIGGER_WMI_EVT = 0x8, + WMI_RESUME_TRIGGER_DISCONNECT = 0x10, }; /* WMI_TRAFFIC_RESUME_EVENTID */ @@ -4057,4 +4106,38 @@ struct wmi_set_vring_priority_event { u8 reserved[3]; } __packed; +/* WMI_RADAR_PCI_CTRL_BLOCK struct */ +struct wmi_radar_pci_ctrl_block { + /* last fw tail address index */ + __le32 fw_tail_index; + /* last SW head address index known to FW */ + __le32 sw_head_index; + __le32 last_wr_pulse_tsf_low; + __le32 last_wr_pulse_count; + __le32 last_wr_in_bytes; + __le32 last_wr_pulse_id; + __le32 last_wr_burst_id; + /* When pre overflow detected, advance sw head in unit of pulses */ + __le32 sw_head_inc; + __le32 reserved[8]; +} __packed; + +/* WMI_RBUFCAP_CFG_CMD */ +struct wmi_rbufcap_cfg_cmd { + u8 enable; + u8 reserved; + /* RBUFCAP indicates rx space unavailable when number of rx + * descriptors drops below this threshold. Set 0 to use system + * default + */ + __le16 rx_desc_threshold; +} __packed; + +/* WMI_RBUFCAP_CFG_EVENTID */ +struct wmi_rbufcap_cfg_event { + /* enum wmi_fw_status */ + u8 status; + u8 reserved[3]; +} __packed; + #endif /* __WILOCITY_WMI_H__ */ diff --git a/drivers/net/wireless/atmel/at76c50x-usb.c b/drivers/net/wireless/atmel/at76c50x-usb.c index e99e766a3028..1cabae424839 100644 --- a/drivers/net/wireless/atmel/at76c50x-usb.c +++ b/drivers/net/wireless/atmel/at76c50x-usb.c @@ -2585,8 +2585,8 @@ static int __init at76_mod_init(void) if (result < 0) printk(KERN_ERR DRIVER_NAME ": usb_register failed (status %d)\n", result); - - led_trigger_register_simple("at76_usb-tx", &ledtrig_tx); + else + led_trigger_register_simple("at76_usb-tx", &ledtrig_tx); return result; } diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c index 74be3c809225..4c7980f84591 100644 --- a/drivers/net/wireless/broadcom/b43/main.c +++ b/drivers/net/wireless/broadcom/b43/main.c @@ -485,7 +485,6 @@ static void b43_ram_write(struct b43_wldev *dev, u16 offset, u32 val) val = swab32(val); b43_write32(dev, B43_MMIO_RAM_CONTROL, offset); - mmiowb(); b43_write32(dev, B43_MMIO_RAM_DATA, val); } @@ -656,9 +655,7 @@ static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf) /* The hardware guarantees us an atomic write, if we * write the low register first. */ b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, low); - mmiowb(); b43_write32(dev, B43_MMIO_REV3PLUS_TSF_HIGH, high); - mmiowb(); } void b43_tsf_write(struct b43_wldev *dev, u64 tsf) @@ -1822,11 +1819,9 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) if (b43_bus_host_is_sdio(dev->dev)) { /* wl->mutex is enough. */ b43_do_beacon_update_trigger_work(dev); - mmiowb(); } else { spin_lock_irq(&wl->hardirq_lock); b43_do_beacon_update_trigger_work(dev); - mmiowb(); spin_unlock_irq(&wl->hardirq_lock); } } @@ -2078,7 +2073,6 @@ static irqreturn_t b43_interrupt_thread_handler(int irq, void *dev_id) mutex_lock(&dev->wl->mutex); b43_do_interrupt_thread(dev); - mmiowb(); mutex_unlock(&dev->wl->mutex); return IRQ_HANDLED; @@ -2143,7 +2137,6 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id) spin_lock(&dev->wl->hardirq_lock); ret = b43_do_interrupt(dev); - mmiowb(); spin_unlock(&dev->wl->hardirq_lock); return ret; diff --git a/drivers/net/wireless/broadcom/b43/phy_lp.c b/drivers/net/wireless/broadcom/b43/phy_lp.c index 46408a560814..6b7f0238723f 100644 --- a/drivers/net/wireless/broadcom/b43/phy_lp.c +++ b/drivers/net/wireless/broadcom/b43/phy_lp.c @@ -1826,16 +1826,10 @@ static void lpphy_stop_tx_tone(struct b43_wldev *dev) } -static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains, - int mode, bool useindex, u8 index) -{ - //TODO -} - static void lpphy_papd_cal_txpwr(struct b43_wldev *dev) { struct b43_phy_lp *lpphy = dev->phy.lp; - struct lpphy_tx_gains gains, oldgains; + struct lpphy_tx_gains oldgains; int old_txpctl, old_afe_ovr, old_rf, old_bbmult; lpphy_read_tx_pctl_mode_from_hardware(dev); @@ -1848,11 +1842,6 @@ static void lpphy_papd_cal_txpwr(struct b43_wldev *dev) lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF); - if (dev->dev->chip_id == 0x4325 && dev->dev->chip_rev == 0) - lpphy_papd_cal(dev, gains, 0, 1, 30); - else - lpphy_papd_cal(dev, gains, 0, 1, 65); - if (old_afe_ovr) lpphy_set_tx_gains(dev, oldgains); lpphy_set_bb_mult(dev, old_bbmult); diff --git a/drivers/net/wireless/broadcom/b43/sysfs.c b/drivers/net/wireless/broadcom/b43/sysfs.c index 3190493bd07f..93d03b673670 100644 --- a/drivers/net/wireless/broadcom/b43/sysfs.c +++ b/drivers/net/wireless/broadcom/b43/sysfs.c @@ -129,7 +129,6 @@ static ssize_t b43_attr_interfmode_store(struct device *dev, } else err = -ENOSYS; - mmiowb(); mutex_unlock(&wldev->wl->mutex); return err ? err : count; diff --git a/drivers/net/wireless/broadcom/b43legacy/ilt.c b/drivers/net/wireless/broadcom/b43legacy/ilt.c index ee5682e54204..6d15fb4d30c6 100644 --- a/drivers/net/wireless/broadcom/b43legacy/ilt.c +++ b/drivers/net/wireless/broadcom/b43legacy/ilt.c @@ -315,14 +315,12 @@ const u16 b43legacy_ilt_sigmasqr2[B43legacy_ILT_SIGMASQR_SIZE] = { void b43legacy_ilt_write(struct b43legacy_wldev *dev, u16 offset, u16 val) { b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_CTRL, offset); - mmiowb(); b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_DATA1, val); } void b43legacy_ilt_write32(struct b43legacy_wldev *dev, u16 offset, u32 val) { b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_CTRL, offset); - mmiowb(); b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_DATA2, (val & 0xFFFF0000) >> 16); b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_DATA1, diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c index 55f411925960..c777efc6dc13 100644 --- a/drivers/net/wireless/broadcom/b43legacy/main.c +++ b/drivers/net/wireless/broadcom/b43legacy/main.c @@ -264,7 +264,6 @@ static void b43legacy_ram_write(struct b43legacy_wldev *dev, u16 offset, val = swab32(val); b43legacy_write32(dev, B43legacy_MMIO_RAM_CONTROL, offset); - mmiowb(); b43legacy_write32(dev, B43legacy_MMIO_RAM_DATA, val); } @@ -341,14 +340,11 @@ void b43legacy_shm_write32(struct b43legacy_wldev *dev, if (offset & 0x0003) { /* Unaligned access */ b43legacy_shm_control_word(dev, routing, offset >> 2); - mmiowb(); b43legacy_write16(dev, B43legacy_MMIO_SHM_DATA_UNALIGNED, (value >> 16) & 0xffff); - mmiowb(); b43legacy_shm_control_word(dev, routing, (offset >> 2) + 1); - mmiowb(); b43legacy_write16(dev, B43legacy_MMIO_SHM_DATA, value & 0xffff); return; @@ -356,7 +352,6 @@ void b43legacy_shm_write32(struct b43legacy_wldev *dev, offset >>= 2; } b43legacy_shm_control_word(dev, routing, offset); - mmiowb(); b43legacy_write32(dev, B43legacy_MMIO_SHM_DATA, value); } @@ -368,7 +363,6 @@ void b43legacy_shm_write16(struct b43legacy_wldev *dev, u16 routing, u16 offset, if (offset & 0x0003) { /* Unaligned access */ b43legacy_shm_control_word(dev, routing, offset >> 2); - mmiowb(); b43legacy_write16(dev, B43legacy_MMIO_SHM_DATA_UNALIGNED, value); @@ -377,7 +371,6 @@ void b43legacy_shm_write16(struct b43legacy_wldev *dev, u16 routing, u16 offset, offset >>= 2; } b43legacy_shm_control_word(dev, routing, offset); - mmiowb(); b43legacy_write16(dev, B43legacy_MMIO_SHM_DATA, value); } @@ -471,7 +464,6 @@ static void b43legacy_time_lock(struct b43legacy_wldev *dev) status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); status |= B43legacy_MACCTL_TBTTHOLD; b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); - mmiowb(); } static void b43legacy_time_unlock(struct b43legacy_wldev *dev) @@ -494,10 +486,8 @@ static void b43legacy_tsf_write_locked(struct b43legacy_wldev *dev, u64 tsf) u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32; b43legacy_write32(dev, B43legacy_MMIO_REV3PLUS_TSF_LOW, 0); - mmiowb(); b43legacy_write32(dev, B43legacy_MMIO_REV3PLUS_TSF_HIGH, hi); - mmiowb(); b43legacy_write32(dev, B43legacy_MMIO_REV3PLUS_TSF_LOW, lo); } else { @@ -507,13 +497,9 @@ static void b43legacy_tsf_write_locked(struct b43legacy_wldev *dev, u64 tsf) u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48; b43legacy_write16(dev, B43legacy_MMIO_TSF_0, 0); - mmiowb(); b43legacy_write16(dev, B43legacy_MMIO_TSF_3, v3); - mmiowb(); b43legacy_write16(dev, B43legacy_MMIO_TSF_2, v2); - mmiowb(); b43legacy_write16(dev, B43legacy_MMIO_TSF_1, v1); - mmiowb(); b43legacy_write16(dev, B43legacy_MMIO_TSF_0, v0); } } @@ -1250,7 +1236,6 @@ static void b43legacy_beacon_update_trigger_work(struct work_struct *work) /* The handler might have updated the IRQ mask. */ b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask); - mmiowb(); spin_unlock_irq(&wl->irq_lock); } mutex_unlock(&wl->mutex); @@ -1346,7 +1331,6 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev) dma_reason[2], dma_reason[3], dma_reason[4], dma_reason[5]); b43legacy_controller_restart(dev, "DMA error"); - mmiowb(); spin_unlock_irqrestore(&dev->wl->irq_lock, flags); return; } @@ -1396,7 +1380,6 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev) handle_irq_transmit_status(dev); b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask); - mmiowb(); spin_unlock_irqrestore(&dev->wl->irq_lock, flags); } @@ -1488,7 +1471,6 @@ static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id) dev->irq_reason = reason; tasklet_schedule(&dev->isr_tasklet); out: - mmiowb(); spin_unlock(&dev->wl->irq_lock); return ret; @@ -2781,7 +2763,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, spin_lock_irqsave(&wl->irq_lock, flags); b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask); - mmiowb(); spin_unlock_irqrestore(&wl->irq_lock, flags); out_unlock_mutex: mutex_unlock(&wl->mutex); @@ -2900,7 +2881,6 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw, spin_lock_irqsave(&wl->irq_lock, flags); b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask); /* XXX: why? */ - mmiowb(); spin_unlock_irqrestore(&wl->irq_lock, flags); out_unlock_mutex: mutex_unlock(&wl->mutex); diff --git a/drivers/net/wireless/broadcom/b43legacy/phy.c b/drivers/net/wireless/broadcom/b43legacy/phy.c index 995c7d0c212a..f949766d27ca 100644 --- a/drivers/net/wireless/broadcom/b43legacy/phy.c +++ b/drivers/net/wireless/broadcom/b43legacy/phy.c @@ -134,7 +134,6 @@ u16 b43legacy_phy_read(struct b43legacy_wldev *dev, u16 offset) void b43legacy_phy_write(struct b43legacy_wldev *dev, u16 offset, u16 val) { b43legacy_write16(dev, B43legacy_MMIO_PHY_CONTROL, offset); - mmiowb(); b43legacy_write16(dev, B43legacy_MMIO_PHY_DATA, val); } diff --git a/drivers/net/wireless/broadcom/b43legacy/pio.h b/drivers/net/wireless/broadcom/b43legacy/pio.h index 1cd1b9ca5e9c..08cd02282beb 100644 --- a/drivers/net/wireless/broadcom/b43legacy/pio.h +++ b/drivers/net/wireless/broadcom/b43legacy/pio.h @@ -92,7 +92,6 @@ void b43legacy_pio_write(struct b43legacy_pioqueue *queue, u16 offset, u16 value) { b43legacy_write16(queue->dev, queue->mmio_base + offset, value); - mmiowb(); } diff --git a/drivers/net/wireless/broadcom/b43legacy/radio.c b/drivers/net/wireless/broadcom/b43legacy/radio.c index eab1c9387846..c6db444ea07e 100644 --- a/drivers/net/wireless/broadcom/b43legacy/radio.c +++ b/drivers/net/wireless/broadcom/b43legacy/radio.c @@ -95,7 +95,6 @@ void b43legacy_radio_lock(struct b43legacy_wldev *dev) B43legacy_WARN_ON(status & B43legacy_MACCTL_RADIOLOCK); status |= B43legacy_MACCTL_RADIOLOCK; b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); - mmiowb(); udelay(10); } @@ -108,7 +107,6 @@ void b43legacy_radio_unlock(struct b43legacy_wldev *dev) B43legacy_WARN_ON(!(status & B43legacy_MACCTL_RADIOLOCK)); status &= ~B43legacy_MACCTL_RADIOLOCK; b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); - mmiowb(); } u16 b43legacy_radio_read16(struct b43legacy_wldev *dev, u16 offset) @@ -141,7 +139,6 @@ u16 b43legacy_radio_read16(struct b43legacy_wldev *dev, u16 offset) void b43legacy_radio_write16(struct b43legacy_wldev *dev, u16 offset, u16 val) { b43legacy_write16(dev, B43legacy_MMIO_RADIO_CONTROL, offset); - mmiowb(); b43legacy_write16(dev, B43legacy_MMIO_RADIO_DATA_LOW, val); } @@ -333,7 +330,6 @@ u8 b43legacy_radio_aci_scan(struct b43legacy_wldev *dev) void b43legacy_nrssi_hw_write(struct b43legacy_wldev *dev, u16 offset, s16 val) { b43legacy_phy_write(dev, B43legacy_PHY_NRSSILT_CTRL, offset); - mmiowb(); b43legacy_phy_write(dev, B43legacy_PHY_NRSSILT_DATA, (u16)val); } diff --git a/drivers/net/wireless/broadcom/b43legacy/sysfs.c b/drivers/net/wireless/broadcom/b43legacy/sysfs.c index 2a1da15c913b..2db83eec7a11 100644 --- a/drivers/net/wireless/broadcom/b43legacy/sysfs.c +++ b/drivers/net/wireless/broadcom/b43legacy/sysfs.c @@ -143,7 +143,6 @@ static ssize_t b43legacy_attr_interfmode_store(struct device *dev, if (err) b43legacyerr(wldev->wl, "Interference Mitigation not " "supported by device\n"); - mmiowb(); spin_unlock_irqrestore(&wldev->wl->irq_lock, flags); mutex_unlock(&wldev->wl->mutex); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c index 73d3c1a0a7c9..98b168736df0 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c @@ -490,11 +490,18 @@ fail: return -ENOMEM; } -void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) +void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr) +{ + struct brcmf_bcdc *bcdc = drvr->proto->pd; + + brcmf_fws_detach_pre_delif(bcdc->fws); +} + +void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr) { struct brcmf_bcdc *bcdc = drvr->proto->pd; drvr->proto->pd = NULL; - brcmf_fws_detach(bcdc->fws); + brcmf_fws_detach_post_delif(bcdc->fws); kfree(bcdc); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h index 3b0e9eff21b5..4bc52240ccea 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h @@ -18,14 +18,16 @@ #ifdef CONFIG_BRCMFMAC_PROTO_BCDC int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr); -void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr); +void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr); +void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr); void brcmf_proto_bcdc_txflowblock(struct device *dev, bool state); void brcmf_proto_bcdc_txcomplete(struct device *dev, struct sk_buff *txp, bool success); struct brcmf_fws_info *drvr_to_fws(struct brcmf_pub *drvr); #else static inline int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) { return 0; } -static inline void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) {} +static void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr) {}; +static inline void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr) {} #endif #endif /* BRCMFMAC_BCDC_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index ec129864cc9c..60aede5abb4d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -628,15 +628,13 @@ int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes) err = brcmf_sdiod_set_backplane_window(sdiodev, addr); if (err) - return err; + goto out; addr &= SBSDIO_SB_OFT_ADDR_MASK; addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - if (!err) - err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2, addr, - mypkt); - + err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2, addr, mypkt); +out: brcmu_pkt_buf_free_skb(mypkt); return err; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index 3d441c5c745c..2fe167eae22c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -91,6 +91,7 @@ struct brcmf_bus_ops { int (*get_fwname)(struct device *dev, const char *ext, unsigned char *fw_name); void (*debugfs_create)(struct device *dev); + int (*reset)(struct device *dev); }; @@ -245,6 +246,15 @@ void brcmf_bus_debugfs_create(struct brcmf_bus *bus) return bus->ops->debugfs_create(bus->dev); } +static inline +int brcmf_bus_reset(struct brcmf_bus *bus) +{ + if (!bus->ops->reset) + return -EOPNOTSUPP; + + return bus->ops->reset(bus->dev); +} + /* * interface functions from common layer */ @@ -262,6 +272,8 @@ void brcmf_detach(struct device *dev); void brcmf_dev_reset(struct device *dev); /* Request from bus module to initiate a coredump */ void brcmf_dev_coredump(struct device *dev); +/* Indication that firmware has halted or crashed */ +void brcmf_fw_crashed(struct device *dev); /* Configure the "global" bus state used by upper layers */ void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index e92f6351bd22..8ee8af4e7ec4 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -5464,6 +5464,8 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, conn_info->req_ie = kmemdup(cfg->extra_buf, conn_info->req_ie_len, GFP_KERNEL); + if (!conn_info->req_ie) + conn_info->req_ie_len = 0; } else { conn_info->req_ie_len = 0; conn_info->req_ie = NULL; @@ -5480,6 +5482,8 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, conn_info->resp_ie = kmemdup(cfg->extra_buf, conn_info->resp_ie_len, GFP_KERNEL); + if (!conn_info->resp_ie) + conn_info->resp_ie_len = 0; } else { conn_info->resp_ie_len = 0; conn_info->resp_ie = NULL; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 4fbe8791f674..7d6a08779693 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -841,17 +841,17 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx, bool rtnl_locked) { struct brcmf_if *ifp; + int ifidx; ifp = drvr->iflist[bsscfgidx]; - drvr->iflist[bsscfgidx] = NULL; if (!ifp) { bphy_err(drvr, "Null interface, bsscfgidx=%d\n", bsscfgidx); return; } brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", bsscfgidx, ifp->ifidx); - if (drvr->if2bss[ifp->ifidx] == bsscfgidx) - drvr->if2bss[ifp->ifidx] = BRCMF_BSSIDX_INVALID; + ifidx = ifp->ifidx; + if (ifp->ndev) { if (bsscfgidx == 0) { if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) { @@ -879,6 +879,10 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx, brcmf_p2p_ifp_removed(ifp, rtnl_locked); kfree(ifp); } + + drvr->iflist[bsscfgidx] = NULL; + if (drvr->if2bss[ifidx] == bsscfgidx) + drvr->if2bss[ifidx] = BRCMF_BSSIDX_INVALID; } void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked) @@ -1084,6 +1088,14 @@ static int brcmf_revinfo_read(struct seq_file *s, void *data) return 0; } +static void brcmf_core_bus_reset(struct work_struct *work) +{ + struct brcmf_pub *drvr = container_of(work, struct brcmf_pub, + bus_reset); + + brcmf_bus_reset(drvr->bus_if); +} + static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops) { int ret = -1; @@ -1155,6 +1167,8 @@ static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops) #endif #endif /* CONFIG_INET */ + INIT_WORK(&drvr->bus_reset, brcmf_core_bus_reset); + /* populate debugfs */ brcmf_debugfs_add_entry(drvr, "revinfo", brcmf_revinfo_read); brcmf_feat_debugfs_create(drvr); @@ -1273,6 +1287,18 @@ void brcmf_dev_coredump(struct device *dev) brcmf_dbg(TRACE, "failed to create coredump\n"); } +void brcmf_fw_crashed(struct device *dev) +{ + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_pub *drvr = bus_if->drvr; + + bphy_err(drvr, "Firmware has halted or crashed\n"); + + brcmf_dev_coredump(dev); + + schedule_work(&drvr->bus_reset); +} + void brcmf_detach(struct device *dev) { s32 i; @@ -1299,6 +1325,8 @@ void brcmf_detach(struct device *dev) brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN); + brcmf_proto_detach_pre_delif(drvr); + /* make sure primary interface removed last */ for (i = BRCMF_MAX_IFS-1; i > -1; i--) brcmf_remove_interface(drvr->iflist[i], false); @@ -1308,7 +1336,7 @@ void brcmf_detach(struct device *dev) brcmf_bus_stop(drvr->bus_if); - brcmf_proto_detach(drvr); + brcmf_proto_detach_post_delif(drvr); bus_if->drvr = NULL; wiphy_free(drvr->wiphy); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index d8085ce579f4..9f09aa31eeda 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -143,6 +143,8 @@ struct brcmf_pub { struct notifier_block inet6addr_notifier; struct brcmf_mp_device *settings; + struct work_struct bus_reset; + u8 clmver[BRCMF_DCMD_SMLEN]; }; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c index 7535cb0d4ac0..9f1417e00073 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c @@ -31,6 +31,10 @@ struct brcmf_dmi_data { /* NOTE: Please keep all entries sorted alphabetically */ +static const struct brcmf_dmi_data acepc_t8_data = { + BRCM_CC_4345_CHIP_ID, 6, "acepc-t8" +}; + static const struct brcmf_dmi_data gpd_win_pocket_data = { BRCM_CC_4356_CHIP_ID, 2, "gpd-win-pocket" }; @@ -49,6 +53,28 @@ static const struct brcmf_dmi_data pov_tab_p1006w_data = { static const struct dmi_system_id dmi_platform_data[] = { { + /* ACEPC T8 Cherry Trail Z8350 mini PC */ + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "T8"), + /* also match on somewhat unique bios-version */ + DMI_EXACT_MATCH(DMI_BIOS_VERSION, "1.000"), + }, + .driver_data = (void *)&acepc_t8_data, + }, + { + /* ACEPC T11 Cherry Trail Z8350 mini PC, same wifi as the T8 */ + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "T11"), + /* also match on somewhat unique bios-version */ + DMI_EXACT_MATCH(DMI_BIOS_VERSION, "1.000"), + }, + .driver_data = (void *)&acepc_t8_data, + }, + { /* Match for the GPDwin which unfortunately uses somewhat * generic dmi strings, which is why we test for 4 strings. * Comparing against 23 other byt/cht boards, board_vendor diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index 8209a42dea72..6a333dd80b2d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -711,7 +711,6 @@ brcmf_fw_alloc_request(u32 chip, u32 chiprev, size_t mp_path_len; u32 i, j; char end = '\0'; - size_t reqsz; for (i = 0; i < table_size; i++) { if (mapping_table[i].chipid == chip && @@ -726,8 +725,7 @@ brcmf_fw_alloc_request(u32 chip, u32 chiprev, return NULL; } - reqsz = sizeof(*fwreq) + n_fwnames * sizeof(struct brcmf_fw_item); - fwreq = kzalloc(reqsz, GFP_KERNEL); + fwreq = kzalloc(struct_size(fwreq, items, n_fwnames), GFP_KERNEL); if (!fwreq) return NULL; @@ -743,6 +741,7 @@ brcmf_fw_alloc_request(u32 chip, u32 chiprev, for (j = 0; j < n_fwnames; j++) { fwreq->items[j].path = fwnames[j].path; + fwnames[j].path[0] = '\0'; /* check if firmware path is provided by module parameter */ if (brcmf_mp_global.firmware_path[0] != '\0') { strlcpy(fwnames[j].path, mp_path, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index abeb305492e0..c22c49ae552e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -580,24 +580,6 @@ static bool brcmf_fws_ifidx_match(struct sk_buff *skb, void *arg) return ifidx == *(int *)arg; } -static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q, - int ifidx) -{ - bool (*matchfn)(struct sk_buff *, void *) = NULL; - struct sk_buff *skb; - int prec; - - if (ifidx != -1) - matchfn = brcmf_fws_ifidx_match; - for (prec = 0; prec < q->num_prec; prec++) { - skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx); - while (skb) { - brcmu_pkt_buf_free_skb(skb); - skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx); - } - } -} - static void brcmf_fws_hanger_init(struct brcmf_fws_hanger *hanger) { int i; @@ -669,6 +651,28 @@ static inline int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h, return 0; } +static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q, + int ifidx) +{ + bool (*matchfn)(struct sk_buff *, void *) = NULL; + struct sk_buff *skb; + int prec; + u32 hslot; + + if (ifidx != -1) + matchfn = brcmf_fws_ifidx_match; + for (prec = 0; prec < q->num_prec; prec++) { + skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx); + while (skb) { + hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); + brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, + true); + brcmu_pkt_buf_free_skb(skb); + skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx); + } + } +} + static int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h, u32 slot_id) { @@ -2200,6 +2204,8 @@ void brcmf_fws_del_interface(struct brcmf_if *ifp) brcmf_fws_lock(fws); ifp->fws_desc = NULL; brcmf_dbg(TRACE, "deleting %s\n", entry->name); + brcmf_fws_macdesc_cleanup(fws, &fws->desc.iface[ifp->ifidx], + ifp->ifidx); brcmf_fws_macdesc_deinit(entry); brcmf_fws_cleanup(fws, ifp->ifidx); brcmf_fws_unlock(fws); @@ -2437,17 +2443,25 @@ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr) return fws; fail: - brcmf_fws_detach(fws); + brcmf_fws_detach_pre_delif(fws); + brcmf_fws_detach_post_delif(fws); return ERR_PTR(rc); } -void brcmf_fws_detach(struct brcmf_fws_info *fws) +void brcmf_fws_detach_pre_delif(struct brcmf_fws_info *fws) { if (!fws) return; - - if (fws->fws_wq) + if (fws->fws_wq) { destroy_workqueue(fws->fws_wq); + fws->fws_wq = NULL; + } +} + +void brcmf_fws_detach_post_delif(struct brcmf_fws_info *fws) +{ + if (!fws) + return; /* cleanup */ brcmf_fws_lock(fws); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h index 4e6835766d5d..749c06dcdc17 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h @@ -19,7 +19,8 @@ #define FWSIGNAL_H_ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr); -void brcmf_fws_detach(struct brcmf_fws_info *fws); +void brcmf_fws_detach_pre_delif(struct brcmf_fws_info *fws); +void brcmf_fws_detach_post_delif(struct brcmf_fws_info *fws); void brcmf_fws_debugfs_create(struct brcmf_pub *drvr); bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws); bool brcmf_fws_fc_active(struct brcmf_fws_info *fws); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index d3780eae7f19..9d1f9ff25bfa 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -375,7 +375,7 @@ brcmf_msgbuf_get_pktid(struct device *dev, struct brcmf_msgbuf_pktids *pktids, struct brcmf_msgbuf_pktid *pktid; struct sk_buff *skb; - if (idx >= pktids->array_size) { + if (idx < 0 || idx >= pktids->array_size) { brcmf_err("Invalid packet id %d (max %d)\n", idx, pktids->array_size); return NULL; @@ -747,7 +747,7 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid) tx_msghdr = (struct msgbuf_tx_msghdr *)ret_ptr; tx_msghdr->msg.msgtype = MSGBUF_TYPE_TX_POST; - tx_msghdr->msg.request_id = cpu_to_le32(pktid); + tx_msghdr->msg.request_id = cpu_to_le32(pktid + 1); tx_msghdr->msg.ifidx = brcmf_flowring_ifidx_get(flow, flowid); tx_msghdr->flags = BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_3; tx_msghdr->flags |= (skb->priority & 0x07) << @@ -884,7 +884,7 @@ brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf) u16 flowid; tx_status = (struct msgbuf_tx_status *)buf; - idx = le32_to_cpu(tx_status->msg.request_id); + idx = le32_to_cpu(tx_status->msg.request_id) - 1; flowid = le16_to_cpu(tx_status->compl_hdr.flow_ring_id); flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART; skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 58a6bc379358..83e4938527f4 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -345,6 +345,10 @@ static const u32 brcmf_ring_itemsize[BRCMF_NROF_COMMON_MSGRINGS] = { BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE }; +static void brcmf_pcie_setup(struct device *dev, int ret, + struct brcmf_fw_request *fwreq); +static struct brcmf_fw_request * +brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo); static u32 brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset) @@ -671,6 +675,7 @@ static int brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data) { struct brcmf_pcie_shared_info *shared; + struct brcmf_core *core; u32 addr; u32 cur_htod_mb_data; u32 i; @@ -694,7 +699,11 @@ brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data) brcmf_pcie_write_tcm32(devinfo, addr, htod_mb_data); pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1); - pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1); + + /* Send mailbox interrupt twice as a hardware workaround */ + core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2); + if (core->rev <= 13) + pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1); return 0; } @@ -730,7 +739,7 @@ static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo) } if (dtoh_mb_data & BRCMF_D2H_DEV_FWHALT) { brcmf_dbg(PCIE, "D2H_MB_DATA: FW HALT\n"); - brcmf_dev_coredump(&devinfo->pdev->dev); + brcmf_fw_crashed(&devinfo->pdev->dev); } } @@ -755,15 +764,22 @@ static void brcmf_pcie_bus_console_init(struct brcmf_pciedev_info *devinfo) console->base_addr, console->buf_addr, console->bufsize); } - -static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo) +/** + * brcmf_pcie_bus_console_read - reads firmware messages + * + * @error: specifies if error has occurred (prints messages unconditionally) + */ +static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo, + bool error) { + struct pci_dev *pdev = devinfo->pdev; + struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev); struct brcmf_pcie_console *console; u32 addr; u8 ch; u32 newidx; - if (!BRCMF_FWCON_ON()) + if (!error && !BRCMF_FWCON_ON()) return; console = &devinfo->shared.console; @@ -787,7 +803,10 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo) } if (ch == '\n') { console->log_str[console->log_idx] = 0; - pr_debug("CONSOLE: %s", console->log_str); + if (error) + brcmf_err(bus, "CONSOLE: %s", console->log_str); + else + pr_debug("CONSOLE: %s", console->log_str); console->log_idx = 0; } } @@ -848,7 +867,7 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg) &devinfo->pdev->dev); } } - brcmf_pcie_bus_console_read(devinfo); + brcmf_pcie_bus_console_read(devinfo, false); if (devinfo->state == BRCMFMAC_PCIE_STATE_UP) brcmf_pcie_intr_enable(devinfo); devinfo->in_irq = false; @@ -1409,6 +1428,38 @@ int brcmf_pcie_get_fwname(struct device *dev, const char *ext, u8 *fw_name) return 0; } +static int brcmf_pcie_reset(struct device *dev) +{ + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie; + struct brcmf_pciedev_info *devinfo = buspub->devinfo; + struct brcmf_fw_request *fwreq; + int err; + + brcmf_pcie_bus_console_read(devinfo, true); + + brcmf_detach(dev); + + brcmf_pcie_release_irq(devinfo); + brcmf_pcie_release_scratchbuffers(devinfo); + brcmf_pcie_release_ringbuffers(devinfo); + brcmf_pcie_reset_device(devinfo); + + fwreq = brcmf_pcie_prepare_fw_request(devinfo); + if (!fwreq) { + dev_err(dev, "Failed to prepare FW request\n"); + return -ENOMEM; + } + + err = brcmf_fw_get_firmwares(dev, fwreq, brcmf_pcie_setup); + if (err) { + dev_err(dev, "Failed to prepare FW request\n"); + kfree(fwreq); + } + + return err; +} + static const struct brcmf_bus_ops brcmf_pcie_bus_ops = { .txdata = brcmf_pcie_tx, .stop = brcmf_pcie_down, @@ -1418,6 +1469,7 @@ static const struct brcmf_bus_ops brcmf_pcie_bus_ops = { .get_ramsize = brcmf_pcie_get_ramsize, .get_memdump = brcmf_pcie_get_memdump, .get_fwname = brcmf_pcie_get_fwname, + .reset = brcmf_pcie_reset, }; @@ -1778,7 +1830,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret, if (brcmf_attach(&devinfo->pdev->dev, devinfo->settings) == 0) return; - brcmf_pcie_bus_console_read(devinfo); + brcmf_pcie_bus_console_read(devinfo, false); fail: device_release_driver(dev); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c index 024c643052bc..c7964ccdda69 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c @@ -67,16 +67,22 @@ fail: return -ENOMEM; } -void brcmf_proto_detach(struct brcmf_pub *drvr) +void brcmf_proto_detach_post_delif(struct brcmf_pub *drvr) { brcmf_dbg(TRACE, "Enter\n"); if (drvr->proto) { if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC) - brcmf_proto_bcdc_detach(drvr); + brcmf_proto_bcdc_detach_post_delif(drvr); else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF) brcmf_proto_msgbuf_detach(drvr); kfree(drvr->proto); drvr->proto = NULL; } } + +void brcmf_proto_detach_pre_delif(struct brcmf_pub *drvr) +{ + if (drvr->proto && drvr->bus_if->proto_type == BRCMF_PROTO_BCDC) + brcmf_proto_bcdc_detach_pre_delif(drvr); +} diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h index d3c3b9a815ad..72355aea9028 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h @@ -54,7 +54,8 @@ struct brcmf_proto { int brcmf_proto_attach(struct brcmf_pub *drvr); -void brcmf_proto_detach(struct brcmf_pub *drvr); +void brcmf_proto_detach_pre_delif(struct brcmf_pub *drvr); +void brcmf_proto_detach_post_delif(struct brcmf_pub *drvr); static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, struct sk_buff *skb, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 4d104ab80fd8..22b73da42822 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -622,6 +622,7 @@ BRCMF_FW_DEF(43430A0, "brcmfmac43430a0-sdio"); /* Note the names are not postfixed with a1 for backward compatibility */ BRCMF_FW_DEF(43430A1, "brcmfmac43430-sdio"); BRCMF_FW_DEF(43455, "brcmfmac43455-sdio"); +BRCMF_FW_DEF(43456, "brcmfmac43456-sdio"); BRCMF_FW_DEF(4354, "brcmfmac4354-sdio"); BRCMF_FW_DEF(4356, "brcmfmac4356-sdio"); BRCMF_FW_DEF(4373, "brcmfmac4373-sdio"); @@ -642,7 +643,8 @@ static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { BRCMF_FW_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0x00000001, 43430A0), BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFE, 43430A1), - BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, 43455), + BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0x00000200, 43456), + BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFDC0, 43455), BRCMF_FW_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354), BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356), BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373), @@ -1090,8 +1092,8 @@ static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus) /* dongle indicates the firmware has halted/crashed */ if (hmb_data & HMB_DATA_FWHALT) { - brcmf_err("mailbox indicates firmware halted\n"); - brcmf_dev_coredump(&sdiod->func1->dev); + brcmf_dbg(SDIO, "mailbox indicates firmware halted\n"); + brcmf_fw_crashed(&sdiod->func1->dev); } /* Dongle recomposed rx frames, accept them again */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index e9cbfd077710..75fcd6752edc 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -160,7 +160,7 @@ struct brcmf_usbdev_info { struct usb_device *usbdev; struct device *dev; - struct mutex dev_init_lock; + struct completion dev_init_done; int ctl_in_pipe, ctl_out_pipe; struct urb *ctl_urb; /* URB for control endpoint */ @@ -445,22 +445,17 @@ fail: } -static void brcmf_usb_free_q(struct list_head *q, bool pending) +static void brcmf_usb_free_q(struct list_head *q) { struct brcmf_usbreq *req, *next; - int i = 0; + list_for_each_entry_safe(req, next, q, list) { if (!req->urb) { brcmf_err("bad req\n"); break; } - i++; - if (pending) { - usb_kill_urb(req->urb); - } else { - usb_free_urb(req->urb); - list_del_init(&req->list); - } + usb_free_urb(req->urb); + list_del_init(&req->list); } } @@ -682,12 +677,18 @@ static int brcmf_usb_up(struct device *dev) static void brcmf_cancel_all_urbs(struct brcmf_usbdev_info *devinfo) { + int i; + if (devinfo->ctl_urb) usb_kill_urb(devinfo->ctl_urb); if (devinfo->bulk_urb) usb_kill_urb(devinfo->bulk_urb); - brcmf_usb_free_q(&devinfo->tx_postq, true); - brcmf_usb_free_q(&devinfo->rx_postq, true); + if (devinfo->tx_reqs) + for (i = 0; i < devinfo->bus_pub.ntxq; i++) + usb_kill_urb(devinfo->tx_reqs[i].urb); + if (devinfo->rx_reqs) + for (i = 0; i < devinfo->bus_pub.nrxq; i++) + usb_kill_urb(devinfo->rx_reqs[i].urb); } static void brcmf_usb_down(struct device *dev) @@ -1023,8 +1024,8 @@ static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo) brcmf_dbg(USB, "Enter, devinfo %p\n", devinfo); /* free the URBS */ - brcmf_usb_free_q(&devinfo->rx_freeq, false); - brcmf_usb_free_q(&devinfo->tx_freeq, false); + brcmf_usb_free_q(&devinfo->rx_freeq); + brcmf_usb_free_q(&devinfo->tx_freeq); usb_free_urb(devinfo->ctl_urb); usb_free_urb(devinfo->bulk_urb); @@ -1193,11 +1194,11 @@ static void brcmf_usb_probe_phase2(struct device *dev, int ret, if (ret) goto error; - mutex_unlock(&devinfo->dev_init_lock); + complete(&devinfo->dev_init_done); return; error: brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), ret); - mutex_unlock(&devinfo->dev_init_lock); + complete(&devinfo->dev_init_done); device_release_driver(dev); } @@ -1265,7 +1266,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) if (ret) goto fail; /* we are done */ - mutex_unlock(&devinfo->dev_init_lock); + complete(&devinfo->dev_init_done); return 0; } bus->chip = bus_pub->devid; @@ -1325,11 +1326,10 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) devinfo->usbdev = usb; devinfo->dev = &usb->dev; - /* Take an init lock, to protect for disconnect while still loading. + /* Init completion, to protect for disconnect while still loading. * Necessary because of the asynchronous firmware load construction */ - mutex_init(&devinfo->dev_init_lock); - mutex_lock(&devinfo->dev_init_lock); + init_completion(&devinfo->dev_init_done); usb_set_intfdata(intf, devinfo); @@ -1407,7 +1407,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) return 0; fail: - mutex_unlock(&devinfo->dev_init_lock); + complete(&devinfo->dev_init_done); kfree(devinfo); usb_set_intfdata(intf, NULL); return ret; @@ -1422,7 +1422,7 @@ brcmf_usb_disconnect(struct usb_interface *intf) devinfo = (struct brcmf_usbdev_info *)usb_get_intfdata(intf); if (devinfo) { - mutex_lock(&devinfo->dev_init_lock); + wait_for_completion(&devinfo->dev_init_done); /* Make sure that devinfo still exists. Firmware probe routines * may have released the device and cleared the intfdata. */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c index 8eff2753abad..d493021f6031 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c @@ -35,9 +35,10 @@ static int brcmf_cfg80211_vndr_cmds_dcmd_handler(struct wiphy *wiphy, struct brcmf_if *ifp; const struct brcmf_vndr_dcmd_hdr *cmdhdr = data; struct sk_buff *reply; - int ret, payload, ret_len; + unsigned int payload, ret_len; void *dcmd_buf = NULL, *wr_pointer; u16 msglen, maxmsglen = PAGE_SIZE - 0x100; + int ret; if (len < sizeof(*cmdhdr)) { brcmf_err("vendor command too short: %d\n", len); @@ -65,7 +66,7 @@ static int brcmf_cfg80211_vndr_cmds_dcmd_handler(struct wiphy *wiphy, brcmf_err("oversize return buffer %d\n", ret_len); ret_len = BRCMF_DCMD_MAXLEN; } - payload = max(ret_len, len) + 1; + payload = max_t(unsigned int, ret_len, len) + 1; dcmd_buf = vzalloc(payload); if (NULL == dcmd_buf) return -ENOMEM; diff --git a/drivers/net/wireless/intel/iwlegacy/3945-debug.c b/drivers/net/wireless/intel/iwlegacy/3945-debug.c index a2960032be81..4b912e707f38 100644 --- a/drivers/net/wireless/intel/iwlegacy/3945-debug.c +++ b/drivers/net/wireless/intel/iwlegacy/3945-debug.c @@ -185,7 +185,7 @@ il3945_ucode_rx_stats_read(struct file *file, char __user *user_buf, pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" - "acumulative delta max\n", + "accumulative delta max\n", "Statistics_Rx - CCK:"); pos += scnprintf(buf + pos, bufsz - pos, @@ -273,7 +273,7 @@ il3945_ucode_rx_stats_read(struct file *file, char __user *user_buf, pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" - "acumulative delta max\n", + "accumulative delta max\n", "Statistics_Rx - GENERAL:"); pos += scnprintf(buf + pos, bufsz - pos, @@ -346,7 +346,7 @@ il3945_ucode_tx_stats_read(struct file *file, char __user *user_buf, pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" - "acumulative delta max\n", + "accumulative delta max\n", "Statistics_Tx:"); pos += scnprintf(buf + pos, bufsz - pos, @@ -447,7 +447,7 @@ il3945_ucode_general_stats_read(struct file *file, char __user *user_buf, pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" - "acumulative delta max\n", + "accumulative delta max\n", "Statistics_General:"); pos += scnprintf(buf + pos, bufsz - pos, diff --git a/drivers/net/wireless/intel/iwlegacy/4965.c b/drivers/net/wireless/intel/iwlegacy/4965.c index ce4144a89217..a20b6c885047 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965.c +++ b/drivers/net/wireless/intel/iwlegacy/4965.c @@ -577,7 +577,6 @@ il4965_math_div_round(s32 num, s32 denom, s32 * res) sign = -sign; denom = -denom; } - *res = 1; *res = ((num * 2 + denom) / (denom * 2)) * sign; return 1; diff --git a/drivers/net/wireless/intel/iwlegacy/common.h b/drivers/net/wireless/intel/iwlegacy/common.h index b079c64ca014..986646af8dfd 100644 --- a/drivers/net/wireless/intel/iwlegacy/common.h +++ b/drivers/net/wireless/intel/iwlegacy/common.h @@ -2030,13 +2030,6 @@ static inline void _il_release_nic_access(struct il_priv *il) { _il_clear_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - /* - * In above we are reading CSR_GP_CNTRL register, what will flush any - * previous writes, but still want write, which clear MAC_ACCESS_REQ - * bit, be performed on PCI bus before any other writes scheduled on - * different CPUs (after we drop reg_lock). - */ - mmiowb(); } static inline u32 diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index fdc56f821b5a..a9c846c59289 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -56,7 +56,7 @@ #include "iwl-config.h" /* Highest firmware API version supported */ -#define IWL_22000_UCODE_API_MAX 46 +#define IWL_22000_UCODE_API_MAX 48 /* Lowest firmware API version supported */ #define IWL_22000_UCODE_API_MIN 39 @@ -80,14 +80,15 @@ #define IWL_22000_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-" #define IWL_22000_HR_B_FW_PRE "iwlwifi-QuQnj-b0-hr-b0-" #define IWL_22000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-" -#define IWL_22000_SU_Z0_FW_PRE "iwlwifi-su-z0-" #define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0-" +#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0-" #define IWL_QNJ_B_JF_B_FW_PRE "iwlwifi-QuQnj-b0-jf-b0-" #define IWL_CC_A_FW_PRE "iwlwifi-cc-a0-" #define IWL_22000_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0-" #define IWL_22000_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0-" #define IWL_22000_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0-" #define IWL_22000_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0-" +#define IWL_22000_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0-" #define IWL_22000_HR_MODULE_FIRMWARE(api) \ IWL_22000_HR_FW_PRE __stringify(api) ".ucode" @@ -103,10 +104,8 @@ IWL_22000_HR_B_FW_PRE __stringify(api) ".ucode" #define IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(api) \ IWL_22000_HR_A0_FW_PRE __stringify(api) ".ucode" -#define IWL_22000_SU_Z0_MODULE_FIRMWARE(api) \ - IWL_22000_SU_Z0_FW_PRE __stringify(api) ".ucode" -#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \ - IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode" +#define IWL_QUZ_A_HR_B_MODULE_FIRMWARE(api) \ + IWL_QUZ_A_HR_B_FW_PRE __stringify(api) ".ucode" #define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \ IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode" #define IWL_QNJ_B_JF_B_MODULE_FIRMWARE(api) \ @@ -179,7 +178,11 @@ static const struct iwl_ht_params iwl_22000_ht_params = { .dbgc_supported = true, \ .min_umac_error_event_table = 0x400000, \ .d3_debug_data_base_addr = 0x401000, \ - .d3_debug_data_length = 60 * 1024 + .d3_debug_data_length = 60 * 1024, \ + .fw_mon_smem_write_ptr_addr = 0xa0c16c, \ + .fw_mon_smem_write_ptr_msk = 0xfffff, \ + .fw_mon_smem_cycle_cnt_ptr_addr = 0xa0c174, \ + .fw_mon_smem_cycle_cnt_ptr_msk = 0xfffff #define IWL_DEVICE_AX200_COMMON \ IWL_DEVICE_22000_COMMON, \ @@ -189,7 +192,8 @@ static const struct iwl_ht_params iwl_22000_ht_params = { IWL_DEVICE_22000_COMMON, \ .device_family = IWL_DEVICE_FAMILY_22000, \ .base_params = &iwl_22000_base_params, \ - .csr = &iwl_csr_v1 + .csr = &iwl_csr_v1, \ + .gp2_reg_addr = 0xa02c68 #define IWL_DEVICE_22560 \ IWL_DEVICE_22000_COMMON, \ @@ -200,9 +204,11 @@ static const struct iwl_ht_params iwl_22000_ht_params = { #define IWL_DEVICE_AX210 \ IWL_DEVICE_AX200_COMMON, \ .device_family = IWL_DEVICE_FAMILY_AX210, \ - .base_params = &iwl_22000_base_params, \ + .base_params = &iwl_22560_base_params, \ .csr = &iwl_csr_v1, \ - .min_txq_size = 128 + .min_txq_size = 128, \ + .gp2_reg_addr = 0xd02c68, \ + .min_256_ba_txq_size = 512 const struct iwl_cfg iwl22000_2ac_cfg_hr = { .name = "Intel(R) Dual Band Wireless AC 22000", @@ -235,8 +241,20 @@ const struct iwl_cfg iwl_ax101_cfg_qu_hr = { .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, }; -const struct iwl_cfg iwl22260_2ax_cfg = { - .name = "Intel(R) Wireless-AX 22260", +const struct iwl_cfg iwl_ax101_cfg_quz_hr = { + .name = "Intel(R) Wi-Fi 6 AX101", + .fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE, + IWL_DEVICE_22500, + /* + * This device doesn't support receiving BlockAck with a large bitmap + * so we need to restrict the size of transmitted aggregation to the + * HT size; mac80211 would otherwise pick the HE max (256) by default. + */ + .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, +}; + +const struct iwl_cfg iwl_ax200_cfg_cc = { + .name = "Intel(R) Wi-Fi 6 AX200 160MHz", .fw_name_pre = IWL_CC_A_FW_PRE, IWL_DEVICE_22500, /* @@ -249,7 +267,7 @@ const struct iwl_cfg iwl22260_2ax_cfg = { }; const struct iwl_cfg killer1650x_2ax_cfg = { - .name = "Killer(R) Wireless-AX 1650x Wireless Network Adapter (200NGW)", + .name = "Killer(R) Wi-Fi 6 AX1650x 160MHz Wireless Network Adapter (200NGW)", .fw_name_pre = IWL_CC_A_FW_PRE, IWL_DEVICE_22500, /* @@ -262,7 +280,7 @@ const struct iwl_cfg killer1650x_2ax_cfg = { }; const struct iwl_cfg killer1650w_2ax_cfg = { - .name = "Killer(R) Wireless-AX 1650w Wireless Network Adapter (200D2W)", + .name = "Killer(R) Wi-Fi 6 AX1650w 160MHz Wireless Network Adapter (200D2W)", .fw_name_pre = IWL_CC_A_FW_PRE, IWL_DEVICE_22500, /* @@ -328,7 +346,7 @@ const struct iwl_cfg killer1550s_2ac_cfg_qu_b0_jf_b0 = { }; const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = { - .name = "Killer(R) Wireless-AX 1650i Wireless Network Adapter (22560NGW)", + .name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)", .fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE, IWL_DEVICE_22500, /* @@ -340,7 +358,7 @@ const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = { }; const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = { - .name = "Killer(R) Wireless-AX 1650s Wireless Network Adapter (22560D2W)", + .name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)", .fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE, IWL_DEVICE_22500, /* @@ -399,19 +417,6 @@ const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0 = { .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, }; -const struct iwl_cfg iwl22560_2ax_cfg_su_cdb = { - .name = "Intel(R) Dual Band Wireless AX 22560", - .fw_name_pre = IWL_22000_SU_Z0_FW_PRE, - IWL_DEVICE_22560, - .cdb = true, - /* - * This device doesn't support receiving BlockAck with a large bitmap - * so we need to restrict the size of transmitted aggregation to the - * HT size; mac80211 would otherwise pick the HE max (256) by default. - */ - .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, -}; - const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0 = { .name = "Intel(R) Wireless-AC 9560 160MHz", .fw_name_pre = IWL_22000_SO_A_JF_B_FW_PRE, @@ -427,12 +432,20 @@ const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0 = { const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0 = { .name = "Intel(R) Wi-Fi 7 AX211 160MHz", .fw_name_pre = IWL_22000_SO_A_GF_A_FW_PRE, + .uhb_supported = true, IWL_DEVICE_AX210, }; const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = { .name = "Intel(R) Wi-Fi 7 AX210 160MHz", .fw_name_pre = IWL_22000_TY_A_GF_A_FW_PRE, + .uhb_supported = true, + IWL_DEVICE_AX210, +}; + +const struct iwl_cfg iwlax210_2ax_cfg_so_gf4_a0 = { + .name = "Intel(R) Wi-Fi 7 AX210 160MHz", + .fw_name_pre = IWL_22000_SO_A_GF4_A_FW_PRE, IWL_DEVICE_AX210, }; @@ -442,8 +455,8 @@ MODULE_FIRMWARE(IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_HR_B_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_22000_SU_Z0_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QNJ_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_SO_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c index 575a7022d045..3846064d51a5 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -136,6 +136,7 @@ const struct iwl_cfg iwl5350_agn_cfg = { .ht_params = &iwl5000_ht_params, .led_mode = IWL_LED_BLINK, .internal_wimax_coex = true, + .csr = &iwl_csr_v1, }; #define IWL_DEVICE_5150 \ diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index 3225b64eb845..41bdd0eaf62c 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -6,7 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -20,7 +20,7 @@ * BSD LICENSE * * Copyright(c) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -148,7 +148,11 @@ static const struct iwl_tt_params iwl9000_tt_params = { .d3_debug_data_length = 92 * 1024, \ .ht_params = &iwl9000_ht_params, \ .nvm_ver = IWL9000_NVM_VERSION, \ - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ + .fw_mon_smem_write_ptr_addr = 0xa0476c, \ + .fw_mon_smem_write_ptr_msk = 0xfffff, \ + .fw_mon_smem_cycle_cnt_ptr_addr = 0xa04774, \ + .fw_mon_smem_cycle_cnt_ptr_msk = 0xfffff const struct iwl_cfg iwl9160_2ac_cfg = { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h index 86ea0784e1a3..31231b223aae 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -214,7 +214,7 @@ struct iwl_proto_offload_cmd_v3_large { #define IWL_WOWLAN_MIN_PATTERN_LEN 16 #define IWL_WOWLAN_MAX_PATTERN_LEN 128 -struct iwl_wowlan_pattern { +struct iwl_wowlan_pattern_v1 { u8 mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8]; u8 pattern[IWL_WOWLAN_MAX_PATTERN_LEN]; u8 mask_size; @@ -227,7 +227,7 @@ struct iwl_wowlan_pattern { /** * struct iwl_wowlan_patterns_cmd - WoWLAN wakeup patterns */ -struct iwl_wowlan_patterns_cmd { +struct iwl_wowlan_patterns_cmd_v1 { /** * @n_patterns: number of patterns */ @@ -236,9 +236,129 @@ struct iwl_wowlan_patterns_cmd { /** * @patterns: the patterns, array length in @n_patterns */ - struct iwl_wowlan_pattern patterns[]; + struct iwl_wowlan_pattern_v1 patterns[]; } __packed; /* WOWLAN_PATTERN_ARRAY_API_S_VER_1 */ +#define IPV4_ADDR_SIZE 4 +#define IPV6_ADDR_SIZE 16 + +enum iwl_wowlan_pattern_type { + WOWLAN_PATTERN_TYPE_BITMASK, + WOWLAN_PATTERN_TYPE_IPV4_TCP_SYN, + WOWLAN_PATTERN_TYPE_IPV6_TCP_SYN, + WOWLAN_PATTERN_TYPE_IPV4_TCP_SYN_WILDCARD, + WOWLAN_PATTERN_TYPE_IPV6_TCP_SYN_WILDCARD, +}; /* WOWLAN_PATTERN_TYPE_API_E_VER_1 */ + +/** + * struct iwl_wowlan_ipv4_tcp_syn - WoWLAN IPv4 TCP SYN pattern data + */ +struct iwl_wowlan_ipv4_tcp_syn { + /** + * @src_addr: source IP address to match + */ + u8 src_addr[IPV4_ADDR_SIZE]; + + /** + * @dst_addr: destination IP address to match + */ + u8 dst_addr[IPV4_ADDR_SIZE]; + + /** + * @src_port: source TCP port to match + */ + __le16 src_port; + + /** + * @dst_port: destination TCP port to match + */ + __le16 dst_port; +} __packed; /* WOWLAN_IPV4_TCP_SYN_API_S_VER_1 */ + +/** + * struct iwl_wowlan_ipv6_tcp_syn - WoWLAN Ipv6 TCP SYN pattern data + */ +struct iwl_wowlan_ipv6_tcp_syn { + /** + * @src_addr: source IP address to match + */ + u8 src_addr[IPV6_ADDR_SIZE]; + + /** + * @dst_addr: destination IP address to match + */ + u8 dst_addr[IPV6_ADDR_SIZE]; + + /** + * @src_port: source TCP port to match + */ + __le16 src_port; + + /** + * @dst_port: destination TCP port to match + */ + __le16 dst_port; +} __packed; /* WOWLAN_IPV6_TCP_SYN_API_S_VER_1 */ + +/** + * union iwl_wowlan_pattern_data - Data for the different pattern types + * + * If wildcard addresses/ports are to be used, the union can be left + * undefined. + */ +union iwl_wowlan_pattern_data { + /** + * @bitmask: bitmask pattern data + */ + struct iwl_wowlan_pattern_v1 bitmask; + + /** + * @ipv4_tcp_syn: IPv4 TCP SYN pattern data + */ + struct iwl_wowlan_ipv4_tcp_syn ipv4_tcp_syn; + + /** + * @ipv6_tcp_syn: IPv6 TCP SYN pattern data + */ + struct iwl_wowlan_ipv6_tcp_syn ipv6_tcp_syn; +}; /* WOWLAN_PATTERN_API_U_VER_1 */ + +/** + * struct iwl_wowlan_pattern_v2 - Pattern entry for the WoWLAN wakeup patterns + */ +struct iwl_wowlan_pattern_v2 { + /** + * @pattern_type: defines the struct type to be used in the union + */ + u8 pattern_type; + + /** + * @reserved: reserved for alignment + */ + u8 reserved[3]; + + /** + * @u: the union containing the match data, or undefined for + * wildcard matches + */ + union iwl_wowlan_pattern_data u; +} __packed; /* WOWLAN_PATTERN_API_S_VER_2 */ + +/** + * struct iwl_wowlan_patterns_cmd - WoWLAN wakeup patterns command + */ +struct iwl_wowlan_patterns_cmd { + /** + * @n_patterns: number of patterns + */ + __le32 n_patterns; + + /** + * @patterns: the patterns, array length in @n_patterns + */ + struct iwl_wowlan_pattern_v2 patterns[]; +} __packed; /* WOWLAN_PATTERN_ARRAY_API_S_VER_2 */ + enum iwl_wowlan_wakeup_filters { IWL_WOWLAN_WAKEUP_MAGIC_PACKET = BIT(0), IWL_WOWLAN_WAKEUP_PATTERN_MATCH = BIT(1), @@ -383,7 +503,11 @@ enum iwl_wowlan_wakeup_reason { IWL_WOWLAN_WAKEUP_BY_D3_WAKEUP_HOST_TIMER = BIT(14), IWL_WOWLAN_WAKEUP_BY_RXFRAME_FILTERED_IN = BIT(15), IWL_WOWLAN_WAKEUP_BY_BEACON_FILTERED_IN = BIT(16), - + IWL_WAKEUP_BY_11W_UNPROTECTED_DEAUTH_OR_DISASSOC = BIT(17), + IWL_WAKEUP_BY_PATTERN_IPV4_TCP_SYN = BIT(18), + IWL_WAKEUP_BY_PATTERN_IPV4_TCP_SYN_WILDCARD = BIT(19), + IWL_WAKEUP_BY_PATTERN_IPV6_TCP_SYN = BIT(20), + IWL_WAKEUP_BY_PATTERN_IPV6_TCP_SYN_WILDCARD = BIT(21), }; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */ struct iwl_wowlan_gtk_status_v1 { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h index 33858787817b..f4202bc231a6 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h @@ -60,12 +60,13 @@ #include <linux/bitops.h> -/* +/** * struct iwl_fw_ini_header: Common Header for all debug group TLV's structures + * * @tlv_version: version info * @apply_point: &enum iwl_fw_ini_apply_point * @data: TLV data followed - **/ + */ struct iwl_fw_ini_header { __le32 tlv_version; __le32 apply_point; @@ -73,7 +74,7 @@ struct iwl_fw_ini_header { } __packed; /* FW_DEBUG_TLV_HEADER_S */ /** - * struct iwl_fw_ini_allocation_tlv - (IWL_FW_INI_TLV_TYPE_BUFFER_ALLOCATION) + * struct iwl_fw_ini_allocation_tlv - (IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION) * buffer allocation TLV - for debug * * @iwl_fw_ini_header: header @@ -84,7 +85,7 @@ struct iwl_fw_ini_header { * @max_fragments: the maximum allowed fragmentation in the desired memory * allocation above * @min_frag_size: the minimum allowed fragmentation size in bytes -*/ + */ struct iwl_fw_ini_allocation_tlv { struct iwl_fw_ini_header header; __le32 allocation_id; @@ -95,33 +96,52 @@ struct iwl_fw_ini_allocation_tlv { } __packed; /* FW_DEBUG_TLV_BUFFER_ALLOCATION_TLV_S_VER_1 */ /** - * struct iwl_fw_ini_hcmd (IWL_FW_INI_TLV_TYPE_HCMD) - * Generic Host command pass through TLV + * enum iwl_fw_ini_dbg_domain - debug domains + * allows to send host cmd or collect memory region if a given domain is enabled + * + * @IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON: the default domain, always on + * @IWL_FW_INI_DBG_DOMAIN_REPORT_PS: power save domain + */ +enum iwl_fw_ini_dbg_domain { + IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON = 0, + IWL_FW_INI_DBG_DOMAIN_REPORT_PS, +}; /* FW_DEBUG_TLV_DOMAIN_API_E_VER_1 */ + +/** + * struct iwl_fw_ini_hcmd * * @id: the debug configuration command type for instance: 0xf6 / 0xf5 / DHC * @group: the desired cmd group - * @padding: all zeros for dword alignment - * @data: all of the relevant command (0xf6/0xf5) to be sent -*/ + * @reserved: to align to FW struct + * @data: all of the relevant command data to be sent + */ struct iwl_fw_ini_hcmd { u8 id; u8 group; - __le16 padding; + __le16 reserved; u8 data[0]; -} __packed; /* FW_DEBUG_TLV_HCMD_DATA_S */ +} __packed; /* FW_DEBUG_TLV_HCMD_DATA_API_S_VER_1 */ /** - * struct iwl_fw_ini_hcmd_tlv + * struct iwl_fw_ini_hcmd_tlv - (IWL_UCODE_TLV_TYPE_HCMD) + * Generic Host command pass through TLV + * * @header: header + * @domain: send command only if the specific domain is enabled + * &enum iwl_fw_ini_dbg_domain + * @period_msec: period in which the hcmd will be sent to FW. Measured in msec + * (0 = one time command). * @hcmd: a variable length host-command to be sent to apply the configuration. */ struct iwl_fw_ini_hcmd_tlv { struct iwl_fw_ini_header header; + __le32 domain; + __le32 period_msec; struct iwl_fw_ini_hcmd hcmd; -} __packed; /* FW_DEBUG_TLV_HCMD_S_VER_1 */ +} __packed; /* FW_DEBUG_TLV_HCMD_API_S_VER_1 */ -/* - * struct iwl_fw_ini_debug_flow_tlv (IWL_FW_INI_TLV_TYPE_DEBUG_FLOW) +/** + * struct iwl_fw_ini_debug_flow_tlv - (IWL_UCODE_TLV_TYPE_DEBUG_FLOW) * * @header: header * @debug_flow_cfg: &enum iwl_fw_ini_debug_flow @@ -135,7 +155,19 @@ struct iwl_fw_ini_debug_flow_tlv { #define IWL_FW_INI_MAX_NAME 32 /** + * struct iwl_fw_ini_region_cfg_dhc - defines dhc response to dump. + * + * @id_and_grp: id and group of dhc response. + * @desc: dhc response descriptor. + */ +struct iwl_fw_ini_region_cfg_dhc { + __le32 id_and_grp; + __le32 desc; +} __packed; /* FW_DEBUG_TLV_REGION_DHC_API_S_VER_1 */ + +/** * struct iwl_fw_ini_region_cfg_internal - meta data of internal memory region + * * @num_of_range: the amount of ranges in the region * @range_data_size: size of the data to read per range, in bytes. */ @@ -146,6 +178,7 @@ struct iwl_fw_ini_region_cfg_internal { /** * struct iwl_fw_ini_region_cfg_fifos - meta data of fifos region + * * @fid1: fifo id 1 - bitmap of lmac tx/rx fifos to include in the region * @fid2: fifo id 2 - bitmap of umac rx fifos to include in the region. * It is unused for tx. @@ -163,34 +196,43 @@ struct iwl_fw_ini_region_cfg_fifos { /** * struct iwl_fw_ini_region_cfg + * * @region_id: ID of this dump configuration * @region_type: &enum iwl_fw_ini_region_type - * @num_regions: amount of regions in the address array. + * @domain: dump this region only if the specific domain is enabled + * &enum iwl_fw_ini_dbg_domain * @name_len: name length * @name: file name to use for this region * @internal: used in case the region uses internal memory. * @allocation_id: For DRAM type field substitutes for allocation_id * @fifos: used in case of fifos region. + * @dhc_desc: dhc response descriptor. + * @notif_id_and_grp: dump this region only if the specific notification + * occurred. * @offset: offset to use for each memory base address * @start_addr: array of addresses. */ struct iwl_fw_ini_region_cfg { __le32 region_id; __le32 region_type; + __le32 domain; __le32 name_len; u8 name[IWL_FW_INI_MAX_NAME]; union { struct iwl_fw_ini_region_cfg_internal internal; __le32 allocation_id; struct iwl_fw_ini_region_cfg_fifos fifos; - }; + struct iwl_fw_ini_region_cfg_dhc dhc_desc; + __le32 notif_id_and_grp; + }; /* FW_DEBUG_TLV_REGION_EXT_INT_PARAMS_API_U_VER_1 */ __le32 offset; __le32 start_addr[]; -} __packed; /* FW_DEBUG_TLV_REGION_CONFIG_S */ +} __packed; /* FW_DEBUG_TLV_REGION_CONFIG_API_S_VER_1 */ /** - * struct iwl_fw_ini_region_tlv - (IWL_FW_INI_TLV_TYPE_REGION_CFG) - * DUMP sections define IDs and triggers that use those IDs TLV + * struct iwl_fw_ini_region_tlv - (IWL_UCODE_TLV_TYPE_REGIONS) + * defines memory regions to dump + * * @header: header * @num_regions: how many different region section and IDs are coming next * @region_config: list of dump configurations @@ -199,13 +241,12 @@ struct iwl_fw_ini_region_tlv { struct iwl_fw_ini_header header; __le32 num_regions; struct iwl_fw_ini_region_cfg region_config[]; -} __packed; /* FW_DEBUG_TLV_REGIONS_S_VER_1 */ +} __packed; /* FW_DEBUG_TLV_REGIONS_API_S_VER_1 */ /** - * struct iwl_fw_ini_trigger - (IWL_FW_INI_TLV_TYPE_DUMP_CFG) - * Region sections define IDs and triggers that use those IDs TLV + * struct iwl_fw_ini_trigger * - * @trigger_id: enum &iwl_fw_ini_tigger_id + * @trigger_id: &enum iwl_fw_ini_trigger_id * @override_trig: determines how apply trigger in case a trigger with the * same id is already in use. Using the first 2 bytes: * Byte 0: if 0, override trigger configuration, otherwise use the @@ -214,6 +255,7 @@ struct iwl_fw_ini_region_tlv { * existing trigger. * @dump_delay: delay from trigger fire to dump, in usec * @occurrences: max amount of times to be fired + * @reserved: to align to FW struct * @ignore_consec: ignore consecutive triggers, in usec * @force_restart: force FW restart * @multi_dut: initiate debug dump data on several DUTs @@ -226,17 +268,18 @@ struct iwl_fw_ini_trigger { __le32 override_trig; __le32 dump_delay; __le32 occurrences; + __le32 reserved; __le32 ignore_consec; __le32 force_restart; __le32 multi_dut; __le32 trigger_data; __le32 num_regions; __le32 data[]; -} __packed; /* FW_TLV_DEBUG_TRIGGER_CONFIG_S */ +} __packed; /* FW_TLV_DEBUG_TRIGGER_CONFIG_API_S_VER_1 */ /** - * struct iwl_fw_ini_trigger_tlv - (IWL_FW_INI_TLV_TYPE_TRIGGERS_CFG) - * DUMP sections define IDs and triggers that use those IDs TLV + * struct iwl_fw_ini_trigger_tlv - (IWL_UCODE_TLV_TYPE_TRIGGERS) + * Triggers that hold memory regions to dump in case a trigger fires * * @header: header * @num_triggers: how many different triggers section and IDs are coming next @@ -246,16 +289,18 @@ struct iwl_fw_ini_trigger_tlv { struct iwl_fw_ini_header header; __le32 num_triggers; struct iwl_fw_ini_trigger trigger_config[]; -} __packed; /* FW_TLV_DEBUG_TRIGGERS_S_VER_1 */ +} __packed; /* FW_TLV_DEBUG_TRIGGERS_API_S_VER_1 */ /** * enum iwl_fw_ini_trigger_id + * * @IWL_FW_TRIGGER_ID_FW_ASSERT: FW assert * @IWL_FW_TRIGGER_ID_FW_HW_ERROR: HW assert * @IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG: TFD queue hang * @IWL_FW_TRIGGER_ID_FW_DEBUG_HOST_TRIGGER: FW debug notification - * @IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFOCATION: FW generic notification + * @IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFICATION: FW generic notification * @IWL_FW_TRIGGER_ID_USER_TRIGGER: User trigger + * @IWL_FW_TRIGGER_ID_PERIODIC_TRIGGER: triggers periodically * @IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY: peer inactivity * @IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED: TX latency * threshold was crossed @@ -299,47 +344,51 @@ enum iwl_fw_ini_trigger_id { /* FW triggers */ IWL_FW_TRIGGER_ID_FW_DEBUG_HOST_TRIGGER = 4, - IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFOCATION = 5, + IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFICATION = 5, /* User trigger */ IWL_FW_TRIGGER_ID_USER_TRIGGER = 6, + /* periodic uses the data field for the interval time */ + IWL_FW_TRIGGER_ID_PERIODIC_TRIGGER = 7, + /* Host triggers */ - IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY = 7, - IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED = 8, - IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED = 9, - IWL_FW_TRIGGER_ID_HOST_OS_REQ_DEAUTH_PEER = 10, - IWL_FW_TRIGGER_ID_HOST_STOP_GO_REQUEST = 11, - IWL_FW_TRIGGER_ID_HOST_START_GO_REQUEST = 12, - IWL_FW_TRIGGER_ID_HOST_JOIN_GROUP_REQUEST = 13, - IWL_FW_TRIGGER_ID_HOST_SCAN_START = 14, - IWL_FW_TRIGGER_ID_HOST_SCAN_SUBMITTED = 15, - IWL_FW_TRIGGER_ID_HOST_SCAN_PARAMS = 16, - IWL_FW_TRIGGER_ID_HOST_CHECK_FOR_HANG = 17, - IWL_FW_TRIGGER_ID_HOST_BAR_RECEIVED = 18, - IWL_FW_TRIGGER_ID_HOST_AGG_TX_RESPONSE_STATUS_FAILED = 19, - IWL_FW_TRIGGER_ID_HOST_EAPOL_TX_RESPONSE_FAILED = 20, - IWL_FW_TRIGGER_ID_HOST_FAKE_TX_RESPONSE_SUSPECTED = 21, - IWL_FW_TRIGGER_ID_HOST_AUTH_REQ_FROM_ASSOC_CLIENT = 22, - IWL_FW_TRIGGER_ID_HOST_ROAM_COMPLETE = 23, - IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAST_FAILED = 24, - IWL_FW_TRIGGER_ID_HOST_D3_START = 25, - IWL_FW_TRIGGER_ID_HOST_D3_END = 26, - IWL_FW_TRIGGER_ID_HOST_BSS_MISSED_BEACONS = 27, - IWL_FW_TRIGGER_ID_HOST_P2P_CLIENT_MISSED_BEACONS = 28, - IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_TX_FAILURES = 29, - IWL_FW_TRIGGER_ID_HOST_TX_WFD_ACTION_FRAME_FAILED = 30, - IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAILED = 31, - IWL_FW_TRIGGER_ID_HOST_SCAN_COMPLETE = 32, - IWL_FW_TRIGGER_ID_HOST_SCAN_ABORT = 33, - IWL_FW_TRIGGER_ID_HOST_NIC_ALIVE = 34, - IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE = 35, + IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY = 8, + IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED = 9, + IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED = 10, + IWL_FW_TRIGGER_ID_HOST_OS_REQ_DEAUTH_PEER = 11, + IWL_FW_TRIGGER_ID_HOST_STOP_GO_REQUEST = 12, + IWL_FW_TRIGGER_ID_HOST_START_GO_REQUEST = 13, + IWL_FW_TRIGGER_ID_HOST_JOIN_GROUP_REQUEST = 14, + IWL_FW_TRIGGER_ID_HOST_SCAN_START = 15, + IWL_FW_TRIGGER_ID_HOST_SCAN_SUBMITTED = 16, + IWL_FW_TRIGGER_ID_HOST_SCAN_PARAMS = 17, + IWL_FW_TRIGGER_ID_HOST_CHECK_FOR_HANG = 18, + IWL_FW_TRIGGER_ID_HOST_BAR_RECEIVED = 19, + IWL_FW_TRIGGER_ID_HOST_AGG_TX_RESPONSE_STATUS_FAILED = 20, + IWL_FW_TRIGGER_ID_HOST_EAPOL_TX_RESPONSE_FAILED = 21, + IWL_FW_TRIGGER_ID_HOST_FAKE_TX_RESPONSE_SUSPECTED = 22, + IWL_FW_TRIGGER_ID_HOST_AUTH_REQ_FROM_ASSOC_CLIENT = 23, + IWL_FW_TRIGGER_ID_HOST_ROAM_COMPLETE = 24, + IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAST_FAILED = 25, + IWL_FW_TRIGGER_ID_HOST_D3_START = 26, + IWL_FW_TRIGGER_ID_HOST_D3_END = 27, + IWL_FW_TRIGGER_ID_HOST_BSS_MISSED_BEACONS = 28, + IWL_FW_TRIGGER_ID_HOST_P2P_CLIENT_MISSED_BEACONS = 29, + IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_TX_FAILURES = 30, + IWL_FW_TRIGGER_ID_HOST_TX_WFD_ACTION_FRAME_FAILED = 31, + IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAILED = 32, + IWL_FW_TRIGGER_ID_HOST_SCAN_COMPLETE = 33, + IWL_FW_TRIGGER_ID_HOST_SCAN_ABORT = 34, + IWL_FW_TRIGGER_ID_HOST_NIC_ALIVE = 35, + IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE = 36, IWL_FW_TRIGGER_ID_NUM, }; /* FW_DEBUG_TLV_TRIGGER_ID_E_VER_1 */ /** * enum iwl_fw_ini_apply_point + * * @IWL_FW_INI_APPLY_INVALID: invalid * @IWL_FW_INI_APPLY_EARLY: pre loading FW * @IWL_FW_INI_APPLY_AFTER_ALIVE: first cmd from host after alive @@ -360,6 +409,7 @@ enum iwl_fw_ini_apply_point { /** * enum iwl_fw_ini_allocation_id + * * @IWL_FW_INI_ALLOCATION_INVALID: invalid * @IWL_FW_INI_ALLOCATION_ID_DBGC1: allocation meant for DBGC1 configuration * @IWL_FW_INI_ALLOCATION_ID_DBGC2: allocation meant for DBGC2 configuration @@ -380,18 +430,22 @@ enum iwl_fw_ini_allocation_id { /** * enum iwl_fw_ini_buffer_location + * * @IWL_FW_INI_LOCATION_INVALID: invalid * @IWL_FW_INI_LOCATION_SRAM_PATH: SRAM location * @IWL_FW_INI_LOCATION_DRAM_PATH: DRAM location + * @IWL_FW_INI_LOCATION_NPK_PATH: NPK location */ enum iwl_fw_ini_buffer_location { IWL_FW_INI_LOCATION_INVALID, IWL_FW_INI_LOCATION_SRAM_PATH, IWL_FW_INI_LOCATION_DRAM_PATH, + IWL_FW_INI_LOCATION_NPK_PATH, }; /* FW_DEBUG_TLV_BUFFER_LOCATION_E_VER_1 */ /** * enum iwl_fw_ini_debug_flow + * * @IWL_FW_INI_DEBUG_INVALID: invalid * @IWL_FW_INI_DEBUG_DBTR_FLOW: undefined * @IWL_FW_INI_DEBUG_TB2DTF_FLOW: undefined @@ -404,6 +458,7 @@ enum iwl_fw_ini_debug_flow { /** * enum iwl_fw_ini_region_type + * * @IWL_FW_INI_REGION_INVALID: invalid * @IWL_FW_INI_REGION_DEVICE_MEMORY: device internal memory * @IWL_FW_INI_REGION_PERIPHERY_MAC: periphery registers of MAC @@ -416,6 +471,10 @@ enum iwl_fw_ini_debug_flow { * @IWL_FW_INI_REGION_RXF: RX fifo * @IWL_FW_INI_REGION_PAGING: paging memory * @IWL_FW_INI_REGION_CSR: CSR registers + * @IWL_FW_INI_REGION_NOTIFICATION: FW notification data + * @IWL_FW_INI_REGION_DHC: dhc response to dump + * @IWL_FW_INI_REGION_LMAC_ERROR_TABLE: lmac error table + * @IWL_FW_INI_REGION_UMAC_ERROR_TABLE: umac error table * @IWL_FW_INI_REGION_NUM: number of region types */ enum iwl_fw_ini_region_type { @@ -431,6 +490,10 @@ enum iwl_fw_ini_region_type { IWL_FW_INI_REGION_RXF, IWL_FW_INI_REGION_PAGING, IWL_FW_INI_REGION_CSR, + IWL_FW_INI_REGION_NOTIFICATION, + IWL_FW_INI_REGION_DHC, + IWL_FW_INI_REGION_LMAC_ERROR_TABLE, + IWL_FW_INI_REGION_UMAC_ERROR_TABLE, IWL_FW_INI_REGION_NUM }; /* FW_DEBUG_TLV_REGION_TYPE_E_VER_1 */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h index 5dddb21c1c4d..8d78b0e671c0 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h @@ -675,6 +675,59 @@ struct iwl_tof_range_rsp_ap_entry_ntfy_v3 { } __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_3 */ /** + * struct iwl_tof_range_rsp_ap_entry_ntfy_v4 - AP parameters (response) + * @bssid: BSSID of the AP + * @measure_status: current APs measurement status, one of + * &enum iwl_tof_entry_status. + * @measure_bw: Current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz + * @rtt: The Round Trip Time that took for the last measurement for + * current AP [pSec] + * @rtt_variance: The Variance of the RTT values measured for current AP + * @rtt_spread: The Difference between the maximum and the minimum RTT + * values measured for current AP in the current session [pSec] + * @rssi: RSSI as uploaded in the Channel Estimation notification + * @rssi_spread: The Difference between the maximum and the minimum RSSI values + * measured for current AP in the current session + * @last_burst: 1 if no more FTM sessions are scheduled for this responder + * @refusal_period: refusal period in case of + * @IWL_TOF_ENTRY_RESPONDER_CANNOT_COLABORATE [sec] + * @timestamp: The GP2 Clock [usec] where Channel Estimation notification was + * uploaded by the LMAC + * @start_tsf: measurement start time in TSF of the mac specified in the range + * request + * @rx_rate_n_flags: rate and flags of the last FTM frame received from this + * responder + * @tx_rate_n_flags: rate and flags of the last ack sent to this responder + * @t2t3_initiator: as calculated from the algo in the initiator + * @t1t4_responder: as calculated from the algo in the responder + * @common_calib: Calib val that was used in for this AP measurement + * @specific_calib: val that was used in for this AP measurement + * @papd_calib_output: The result of the tof papd calibration that was injected + * into the algorithm. + */ +struct iwl_tof_range_rsp_ap_entry_ntfy_v4 { + u8 bssid[ETH_ALEN]; + u8 measure_status; + u8 measure_bw; + __le32 rtt; + __le32 rtt_variance; + __le32 rtt_spread; + s8 rssi; + u8 rssi_spread; + u8 last_burst; + u8 refusal_period; + __le32 timestamp; + __le32 start_tsf; + __le32 rx_rate_n_flags; + __le32 tx_rate_n_flags; + __le32 t2t3_initiator; + __le32 t1t4_responder; + __le16 common_calib; + __le16 specific_calib; + __le32 papd_calib_output; +} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_4 */ + +/** * struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response) * @bssid: BSSID of the AP * @measure_status: current APs measurement status, one of @@ -704,6 +757,8 @@ struct iwl_tof_range_rsp_ap_entry_ntfy_v3 { * @specific_calib: val that was used in for this AP measurement * @papd_calib_output: The result of the tof papd calibration that was injected * into the algorithm. + * @rttConfidence: a value between 0 - 31 that represents the rtt accuracy. + * @reserved: for alignment */ struct iwl_tof_range_rsp_ap_entry_ntfy { u8 bssid[ETH_ALEN]; @@ -725,7 +780,9 @@ struct iwl_tof_range_rsp_ap_entry_ntfy { __le16 common_calib; __le16 specific_calib; __le32 papd_calib_output; -} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_4 */ + u8 rttConfidence; + u8 reserved[3]; +} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_5 */ /** * enum iwl_tof_response_status - tof response status @@ -761,6 +818,22 @@ struct iwl_tof_range_rsp_ntfy_v5 { } __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_5 */ /** + * struct iwl_tof_range_rsp_ntfy_v6 - ranging response notification + * @request_id: A Token ID of the corresponding Range request + * @num_of_aps: Number of APs results + * @last_report: 1 if no more FTM sessions are scheduled, 0 otherwise. + * @reserved: reserved + * @ap: per-AP data + */ +struct iwl_tof_range_rsp_ntfy_v6 { + u8 request_id; + u8 num_of_aps; + u8 last_report; + u8 reserved; + struct iwl_tof_range_rsp_ap_entry_ntfy_v4 ap[IWL_MVM_TOF_MAX_APS]; +} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_6 */ + +/** * struct iwl_tof_range_rsp_ntfy - ranging response notification * @request_id: A Token ID of the corresponding Range request * @num_of_aps: Number of APs results @@ -774,7 +847,7 @@ struct iwl_tof_range_rsp_ntfy { u8 last_report; u8 reserved; struct iwl_tof_range_rsp_ap_entry_ntfy ap[IWL_MVM_TOF_MAX_APS]; -} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_6 */ +} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_7 */ #define IWL_MVM_TOF_MCSI_BUF_SIZE (245) /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h index 941c50477003..85c5e367cbf1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h @@ -542,6 +542,66 @@ enum iwl_he_htc_flags { #define IWL_HE_HTC_LINK_ADAP_BOTH (3 << IWL_HE_HTC_LINK_ADAP_POS) /** + * struct iwl_he_sta_context_cmd_v1 - configure FW to work with HE AP + * @sta_id: STA id + * @tid_limit: max num of TIDs in TX HE-SU multi-TID agg + * 0 - bad value, 1 - multi-tid not supported, 2..8 - tid limit + * @reserved1: reserved byte for future use + * @reserved2: reserved byte for future use + * @flags: see %iwl_11ax_sta_ctxt_flags + * @ref_bssid_addr: reference BSSID used by the AP + * @reserved0: reserved 2 bytes for aligning the ref_bssid_addr field to 8 bytes + * @htc_flags: which features are supported in HTC + * @frag_flags: frag support in A-MSDU + * @frag_level: frag support level + * @frag_max_num: max num of "open" MSDUs in the receiver (in power of 2) + * @frag_min_size: min frag size (except last frag) + * @pkt_ext: optional, exists according to PPE-present bit in the HE-PHY capa + * @bss_color: 11ax AP ID that is used in the HE SIG-A to mark inter BSS frame + * @htc_trig_based_pkt_ext: default PE in 4us units + * @frame_time_rts_th: HE duration RTS threshold, in units of 32us + * @rand_alloc_ecwmin: random CWmin = 2**ECWmin-1 + * @rand_alloc_ecwmax: random CWmax = 2**ECWmax-1 + * @reserved3: reserved byte for future use + * @trig_based_txf: MU EDCA Parameter set for the trigger based traffic queues + */ +struct iwl_he_sta_context_cmd_v1 { + u8 sta_id; + u8 tid_limit; + u8 reserved1; + u8 reserved2; + __le32 flags; + + /* The below fields are set via Multiple BSSID IE */ + u8 ref_bssid_addr[6]; + __le16 reserved0; + + /* The below fields are set via HE-capabilities IE */ + __le32 htc_flags; + + u8 frag_flags; + u8 frag_level; + u8 frag_max_num; + u8 frag_min_size; + + /* The below fields are set via PPE thresholds element */ + struct iwl_he_pkt_ext pkt_ext; + + /* The below fields are set via HE-Operation IE */ + u8 bss_color; + u8 htc_trig_based_pkt_ext; + __le16 frame_time_rts_th; + + /* Random access parameter set (i.e. RAPS) */ + u8 rand_alloc_ecwmin; + u8 rand_alloc_ecwmax; + __le16 reserved3; + + /* The below fields are set via MU EDCA parameter set element */ + struct iwl_he_backoff_conf trig_based_txf[AC_NUM]; +} __packed; /* STA_CONTEXT_DOT11AX_API_S_VER_1 */ + +/** * struct iwl_he_sta_context_cmd - configure FW to work with HE AP * @sta_id: STA id * @tid_limit: max num of TIDs in TX HE-SU multi-TID agg @@ -564,6 +624,14 @@ enum iwl_he_htc_flags { * @rand_alloc_ecwmax: random CWmax = 2**ECWmax-1 * @reserved3: reserved byte for future use * @trig_based_txf: MU EDCA Parameter set for the trigger based traffic queues + * @max_bssid_indicator: indicator of the max bssid supported on the associated + * bss + * @bssid_index: index of the associated VAP + * @ema_ap: AP supports enhanced Multi BSSID advertisement + * @profile_periodicity: number of Beacon periods that are needed to receive the + * complete VAPs info + * @bssid_count: actual number of VAPs in the MultiBSS Set + * @reserved4: alignment */ struct iwl_he_sta_context_cmd { u8 sta_id; @@ -599,7 +667,14 @@ struct iwl_he_sta_context_cmd { /* The below fields are set via MU EDCA parameter set element */ struct iwl_he_backoff_conf trig_based_txf[AC_NUM]; -} __packed; /* STA_CONTEXT_DOT11AX_API_S */ + + u8 max_bssid_indicator; + u8 bssid_index; + u8 ema_ap; + u8 profile_periodicity; + u8 bssid_count; + u8 reserved4[3]; +} __packed; /* STA_CONTEXT_DOT11AX_API_S_VER_2 */ /** * struct iwl_he_monitor_cmd - configure air sniffer for HE diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h index 93b392f0c6a4..97b49843e318 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright(C) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright(C) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -233,7 +233,8 @@ struct iwl_nvm_get_info_phy { __le32 rx_chains; } __packed; /* REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */ -#define IWL_NUM_CHANNELS (51) +#define IWL_NUM_CHANNELS_V1 51 +#define IWL_NUM_CHANNELS 110 /** * struct iwl_nvm_get_info_regulatory - regulatory information @@ -241,13 +242,39 @@ struct iwl_nvm_get_info_phy { * @channel_profile: regulatory data of this channel * @reserved: reserved */ -struct iwl_nvm_get_info_regulatory { +struct iwl_nvm_get_info_regulatory_v1 { __le32 lar_enabled; - __le16 channel_profile[IWL_NUM_CHANNELS]; + __le16 channel_profile[IWL_NUM_CHANNELS_V1]; __le16 reserved; } __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_1 */ /** + * struct iwl_nvm_get_info_regulatory - regulatory information + * @lar_enabled: is LAR enabled + * @n_channels: number of valid channels in the array + * @channel_profile: regulatory data of this channel + */ +struct iwl_nvm_get_info_regulatory { + __le32 lar_enabled; + __le32 n_channels; + __le32 channel_profile[IWL_NUM_CHANNELS]; +} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_2 */ + +/** + * struct iwl_nvm_get_info_rsp_v3 - response to get NVM data + * @general: general NVM data + * @mac_sku: data relating to MAC sku + * @phy_sku: data relating to PHY sku + * @regulatory: regulatory data + */ +struct iwl_nvm_get_info_rsp_v3 { + struct iwl_nvm_get_info_general general; + struct iwl_nvm_get_info_sku mac_sku; + struct iwl_nvm_get_info_phy phy_sku; + struct iwl_nvm_get_info_regulatory_v1 regulatory; +} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_3 */ + +/** * struct iwl_nvm_get_info_rsp - response to get NVM data * @general: general NVM data * @mac_sku: data relating to MAC sku @@ -259,7 +286,7 @@ struct iwl_nvm_get_info_rsp { struct iwl_nvm_get_info_sku mac_sku; struct iwl_nvm_get_info_phy phy_sku; struct iwl_nvm_get_info_regulatory regulatory; -} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_3 */ +} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_4 */ /** * struct iwl_nvm_access_complete_cmd - NVM_ACCESS commands are completed diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h index 6e8224ce8906..d55312ef58c9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -688,13 +688,6 @@ struct iwl_rx_mpdu_desc { #define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1) -#define IWL_CD_STTS_OPTIMIZED_POS 0 -#define IWL_CD_STTS_OPTIMIZED_MSK 0x01 -#define IWL_CD_STTS_TRANSFER_STATUS_POS 1 -#define IWL_CD_STTS_TRANSFER_STATUS_MSK 0x0E -#define IWL_CD_STTS_WIFI_STATUS_POS 4 -#define IWL_CD_STTS_WIFI_STATUS_MSK 0xF0 - #define RX_NO_DATA_CHAIN_A_POS 0 #define RX_NO_DATA_CHAIN_A_MSK (0xff << RX_NO_DATA_CHAIN_A_POS) #define RX_NO_DATA_CHAIN_B_POS 8 @@ -747,62 +740,6 @@ struct iwl_rx_no_data { __le32 rx_vec[2]; } __packed; /* RX_NO_DATA_NTFY_API_S_VER_1 */ -/** - * enum iwl_completion_desc_transfer_status - transfer status (bits 1-3) - * @IWL_CD_STTS_UNUSED: unused - * @IWL_CD_STTS_UNUSED_2: unused - * @IWL_CD_STTS_END_TRANSFER: successful transfer complete. - * In sniffer mode, when split is used, set in last CD completion. (RX) - * @IWL_CD_STTS_OVERFLOW: In sniffer mode, when using split - used for - * all CD completion. (RX) - * @IWL_CD_STTS_ABORTED: CR abort / close flow. (RX) - * @IWL_CD_STTS_ERROR: general error (RX) - */ -enum iwl_completion_desc_transfer_status { - IWL_CD_STTS_UNUSED, - IWL_CD_STTS_UNUSED_2, - IWL_CD_STTS_END_TRANSFER, - IWL_CD_STTS_OVERFLOW, - IWL_CD_STTS_ABORTED, - IWL_CD_STTS_ERROR, -}; - -/** - * enum iwl_completion_desc_wifi_status - wifi status (bits 4-7) - * @IWL_CD_STTS_VALID: the packet is valid (RX) - * @IWL_CD_STTS_FCS_ERR: frame check sequence error (RX) - * @IWL_CD_STTS_SEC_KEY_ERR: error handling the security key of rx (RX) - * @IWL_CD_STTS_DECRYPTION_ERR: error decrypting the frame (RX) - * @IWL_CD_STTS_DUP: duplicate packet (RX) - * @IWL_CD_STTS_ICV_MIC_ERR: MIC error (RX) - * @IWL_CD_STTS_INTERNAL_SNAP_ERR: problems removing the snap (RX) - * @IWL_CD_STTS_SEC_PORT_FAIL: security port fail (RX) - * @IWL_CD_STTS_BA_OLD_SN: block ack received old SN (RX) - * @IWL_CD_STTS_QOS_NULL: QoS null packet (RX) - * @IWL_CD_STTS_MAC_HDR_ERR: MAC header conversion error (RX) - * @IWL_CD_STTS_MAX_RETRANS: reached max number of retransmissions (TX) - * @IWL_CD_STTS_EX_LIFETIME: exceeded lifetime (TX) - * @IWL_CD_STTS_NOT_USED: completed but not used (RX) - * @IWL_CD_STTS_REPLAY_ERR: pn check failed, replay error (RX) - */ -enum iwl_completion_desc_wifi_status { - IWL_CD_STTS_VALID, - IWL_CD_STTS_FCS_ERR, - IWL_CD_STTS_SEC_KEY_ERR, - IWL_CD_STTS_DECRYPTION_ERR, - IWL_CD_STTS_DUP, - IWL_CD_STTS_ICV_MIC_ERR, - IWL_CD_STTS_INTERNAL_SNAP_ERR, - IWL_CD_STTS_SEC_PORT_FAIL, - IWL_CD_STTS_BA_OLD_SN, - IWL_CD_STTS_QOS_NULL, - IWL_CD_STTS_MAC_HDR_ERR, - IWL_CD_STTS_MAX_RETRANS, - IWL_CD_STTS_EX_LIFETIME, - IWL_CD_STTS_NOT_USED, - IWL_CD_STTS_REPLAY_ERR, -}; - struct iwl_frame_release { u8 baid; u8 reserved; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h index 890a939c463d..1a67a2a439ab 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h @@ -788,7 +788,53 @@ struct iwl_umac_scan_complete { __le32 reserved; } __packed; /* SCAN_COMPLETE_NTF_UMAC_API_S_VER_1 */ -#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN 5 +#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1 5 +#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN 7 + +/** + * struct iwl_scan_offload_profile_match_v1 - match information + * @bssid: matched bssid + * @reserved: reserved + * @channel: channel where the match occurred + * @energy: energy + * @matching_feature: feature matches + * @matching_channels: bitmap of channels that matched, referencing + * the channels passed in the scan offload request. + */ +struct iwl_scan_offload_profile_match_v1 { + u8 bssid[ETH_ALEN]; + __le16 reserved; + u8 channel; + u8 energy; + u8 matching_feature; + u8 matching_channels[SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1]; +} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_1 */ + +/** + * struct iwl_scan_offload_profiles_query_v1 - match results query response + * @matched_profiles: bitmap of matched profiles, referencing the + * matches passed in the scan offload request + * @last_scan_age: age of the last offloaded scan + * @n_scans_done: number of offloaded scans done + * @gp2_d0u: GP2 when D0U occurred + * @gp2_invoked: GP2 when scan offload was invoked + * @resume_while_scanning: not used + * @self_recovery: obsolete + * @reserved: reserved + * @matches: array of match information, one for each match + */ +struct iwl_scan_offload_profiles_query_v1 { + __le32 matched_profiles; + __le32 last_scan_age; + __le32 n_scans_done; + __le32 gp2_d0u; + __le32 gp2_invoked; + u8 resume_while_scanning; + u8 self_recovery; + __le16 reserved; + struct iwl_scan_offload_profile_match_v1 matches[IWL_SCAN_MAX_PROFILES]; +} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_2 */ + /** * struct iwl_scan_offload_profile_match - match information * @bssid: matched bssid @@ -797,7 +843,7 @@ struct iwl_umac_scan_complete { * @energy: energy * @matching_feature: feature matches * @matching_channels: bitmap of channels that matched, referencing - * the channels passed in tue scan offload request + * the channels passed in the scan offload request. */ struct iwl_scan_offload_profile_match { u8 bssid[ETH_ALEN]; @@ -806,7 +852,7 @@ struct iwl_scan_offload_profile_match { u8 energy; u8 matching_feature; u8 matching_channels[SCAN_OFFLOAD_MATCHING_CHANNELS_LEN]; -} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_1 */ +} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_2 */ /** * struct iwl_scan_offload_profiles_query - match results query response @@ -831,7 +877,7 @@ struct iwl_scan_offload_profiles_query { u8 self_recovery; __le16 reserved; struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES]; -} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_2 */ +} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_3 */ /** * struct iwl_umac_scan_iter_complete_notif - notifies end of scanning iteration diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/txq.h b/drivers/net/wireless/intel/iwlwifi/fw/api/txq.h index 6ac240b6eace..73196cbc7fbe 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/txq.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/txq.h @@ -8,6 +8,7 @@ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,6 +31,7 @@ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -133,6 +135,7 @@ enum iwl_tx_queue_cfg_actions { #define IWL_DEFAULT_QUEUE_SIZE 256 #define IWL_MGMT_QUEUE_SIZE 16 +#define IWL_CMD_QUEUE_SIZE 32 /** * struct iwl_tx_queue_cfg_cmd - txq hw scheduler config command * @sta_id: station id diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index f119c49cd39c..5f52e40a2903 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -545,6 +545,7 @@ static const struct iwl_prph_range iwl_prph_dump_addr_22000[] = { { .start = 0x00a04590, .end = 0x00a04590 }, { .start = 0x00a04598, .end = 0x00a04598 }, { .start = 0x00a045c0, .end = 0x00a045f4 }, + { .start = 0x00a05c18, .end = 0x00a05c1c }, { .start = 0x00a0c000, .end = 0x00a0c018 }, { .start = 0x00a0c020, .end = 0x00a0c028 }, { .start = 0x00a0c038, .end = 0x00a0c094 }, @@ -557,6 +558,12 @@ static const struct iwl_prph_range iwl_prph_dump_addr_22000[] = { { .start = 0x00a0c1b0, .end = 0x00a0c1b8 }, }; +static const struct iwl_prph_range iwl_prph_dump_addr_ax210[] = { + { .start = 0x00d03c00, .end = 0x00d03c64 }, + { .start = 0x00d05c18, .end = 0x00d05c1c }, + { .start = 0x00d0c000, .end = 0x00d0c174 }, +}; + static void iwl_read_prph_block(struct iwl_trans *trans, u32 start, u32 len_bytes, __le32 *data) { @@ -675,7 +682,8 @@ static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr, u32 range_len; if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { - /* TODO */ + range_len = ARRAY_SIZE(iwl_prph_dump_addr_ax210); + handler(fwrt, iwl_prph_dump_addr_ax210, range_len, ptr); } else if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) { range_len = ARRAY_SIZE(iwl_prph_dump_addr_22000); handler(fwrt, iwl_prph_dump_addr_22000, range_len, ptr); @@ -804,8 +812,8 @@ static void iwl_dump_paging(struct iwl_fw_runtime *fwrt, } static struct iwl_fw_error_dump_file * -_iwl_fw_error_dump(struct iwl_fw_runtime *fwrt, - struct iwl_fw_dump_ptrs *fw_error_dump) +iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt, + struct iwl_fw_dump_ptrs *fw_error_dump) { struct iwl_fw_error_dump_file *dump_file; struct iwl_fw_error_dump_data *dump_data; @@ -909,11 +917,8 @@ _iwl_fw_error_dump(struct iwl_fw_runtime *fwrt, dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO); dump_data->len = cpu_to_le32(sizeof(*dump_info)); dump_info = (void *)dump_data->data; - dump_info->device_family = - fwrt->trans->cfg->device_family == - IWL_DEVICE_FAMILY_7000 ? - cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_7) : - cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_8); + dump_info->hw_type = + cpu_to_le32(CSR_HW_REV_TYPE(fwrt->trans->hw_rev)); dump_info->hw_step = cpu_to_le32(CSR_HW_REV_STEP(fwrt->trans->hw_rev)); memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable, @@ -967,10 +972,11 @@ _iwl_fw_error_dump(struct iwl_fw_runtime *fwrt, if (fifo_len) { iwl_fw_dump_rxf(fwrt, &dump_data); iwl_fw_dump_txf(fwrt, &dump_data); - if (radio_len) - iwl_read_radio_regs(fwrt, &dump_data); } + if (radio_len) + iwl_read_radio_regs(fwrt, &dump_data); + if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_ERROR_INFO) && fwrt->dump.desc) { dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_ERROR_INFO); @@ -1049,14 +1055,14 @@ static int iwl_dump_ini_prph_iter(struct iwl_fw_runtime *fwrt, { struct iwl_fw_ini_error_dump_range *range = range_ptr; __le32 *val = range->data; - u32 addr, prph_val, offset = le32_to_cpu(reg->offset); + u32 prph_val; + u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset); int i; - range->start_addr = reg->start_addr[idx]; + range->start_addr = cpu_to_le64(addr); range->range_data_size = reg->internal.range_data_size; for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) { - addr = le32_to_cpu(range->start_addr) + i; - prph_val = iwl_read_prph(fwrt->trans, addr + offset); + prph_val = iwl_read_prph(fwrt->trans, addr + i); if (prph_val == 0x5a5a5a5a) return -EBUSY; *val++ = cpu_to_le32(prph_val); @@ -1071,16 +1077,13 @@ static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt, { struct iwl_fw_ini_error_dump_range *range = range_ptr; __le32 *val = range->data; - u32 addr, offset = le32_to_cpu(reg->offset); + u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset); int i; - range->start_addr = reg->start_addr[idx]; + range->start_addr = cpu_to_le64(addr); range->range_data_size = reg->internal.range_data_size; - for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) { - addr = le32_to_cpu(range->start_addr) + i; - *val++ = cpu_to_le32(iwl_trans_read32(fwrt->trans, - addr + offset)); - } + for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) + *val++ = cpu_to_le32(iwl_trans_read32(fwrt->trans, addr + i)); return sizeof(*range) + le32_to_cpu(range->range_data_size); } @@ -1090,12 +1093,11 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt, void *range_ptr, int idx) { struct iwl_fw_ini_error_dump_range *range = range_ptr; - u32 addr = le32_to_cpu(range->start_addr); - u32 offset = le32_to_cpu(reg->offset); + u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset); - range->start_addr = reg->start_addr[idx]; + range->start_addr = cpu_to_le64(addr); range->range_data_size = reg->internal.range_data_size; - iwl_trans_read_mem_bytes(fwrt->trans, addr + offset, range->data, + iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data, le32_to_cpu(reg->internal.range_data_size)); return sizeof(*range) + le32_to_cpu(range->range_data_size); @@ -1109,7 +1111,7 @@ iwl_dump_ini_paging_gen2_iter(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_error_dump_range *range = range_ptr; u32 page_size = fwrt->trans->init_dram.paging[idx].size; - range->start_addr = cpu_to_le32(idx); + range->start_addr = cpu_to_le64(idx); range->range_data_size = cpu_to_le32(page_size); memcpy(range->data, fwrt->trans->init_dram.paging[idx].block, page_size); @@ -1129,7 +1131,7 @@ static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt, dma_addr_t addr = fwrt->fw_paging_db[idx].fw_paging_phys; u32 page_size = fwrt->fw_paging_db[idx].fw_paging_size; - range->start_addr = cpu_to_le32(idx); + range->start_addr = cpu_to_le64(idx); range->range_data_size = cpu_to_le32(page_size); dma_sync_single_for_cpu(fwrt->trans->dev, addr, page_size, DMA_BIDIRECTIONAL); @@ -1152,7 +1154,7 @@ iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt, if (start_addr == 0x5a5a5a5a) return -EBUSY; - range->start_addr = cpu_to_le32(start_addr); + range->start_addr = cpu_to_le64(start_addr); range->range_data_size = cpu_to_le32(fwrt->trans->fw_mon[idx].size); memcpy(range->data, fwrt->trans->fw_mon[idx].block, @@ -1228,10 +1230,11 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt, { struct iwl_fw_ini_fifo_error_dump_range *range = range_ptr; struct iwl_ini_txf_iter_data *iter; + struct iwl_fw_ini_error_dump_register *reg_dump = (void *)range->data; u32 offs = le32_to_cpu(reg->offset), addr; u32 registers_size = - le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); - __le32 *val = range->data; + le32_to_cpu(reg->fifos.num_of_registers) * sizeof(*reg_dump); + __le32 *data; unsigned long flags; int i; @@ -1249,11 +1252,18 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt, iwl_write_prph_no_grab(fwrt->trans, TXF_LARC_NUM + offs, iter->fifo); - /* read txf registers */ + /* + * read txf registers. for each register, write to the dump the + * register address and its value + */ for (i = 0; i < le32_to_cpu(reg->fifos.num_of_registers); i++) { addr = le32_to_cpu(reg->start_addr[i]) + offs; - *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); + reg_dump->addr = cpu_to_le32(addr); + reg_dump->data = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, + addr)); + + reg_dump++; } if (reg->fifos.header_only) { @@ -1270,8 +1280,9 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt, /* Read FIFO */ addr = TXF_READ_MODIFY_DATA + offs; - for (i = 0; i < iter->fifo_size; i += sizeof(__le32)) - *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); + data = (void *)reg_dump; + for (i = 0; i < iter->fifo_size; i += sizeof(*data)) + *data++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); out: iwl_trans_release_nic_access(fwrt->trans, &flags); @@ -1327,10 +1338,11 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt, { struct iwl_fw_ini_fifo_error_dump_range *range = range_ptr; struct iwl_ini_rxf_data rxf_data; + struct iwl_fw_ini_error_dump_register *reg_dump = (void *)range->data; u32 offs = le32_to_cpu(reg->offset), addr; u32 registers_size = - le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); - __le32 *val = range->data; + le32_to_cpu(reg->fifos.num_of_registers) * sizeof(*reg_dump); + __le32 *data; unsigned long flags; int i; @@ -1341,17 +1353,22 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt, if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) return -EBUSY; - offs += rxf_data.offset; - range->fifo_num = cpu_to_le32(rxf_data.fifo_num); range->num_of_registers = reg->fifos.num_of_registers; range->range_data_size = cpu_to_le32(rxf_data.size + registers_size); - /* read rxf registers */ + /* + * read rxf registers. for each register, write to the dump the + * register address and its value + */ for (i = 0; i < le32_to_cpu(reg->fifos.num_of_registers); i++) { addr = le32_to_cpu(reg->start_addr[i]) + offs; - *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); + reg_dump->addr = cpu_to_le32(addr); + reg_dump->data = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, + addr)); + + reg_dump++; } if (reg->fifos.header_only) { @@ -1359,6 +1376,12 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt, goto out; } + /* + * region register have absolute value so apply rxf offset after + * reading the registers + */ + offs += rxf_data.offset; + /* Lock fence */ iwl_write_prph_no_grab(fwrt->trans, RXF_SET_FENCE_MODE + offs, 0x1); /* Set fence pointer to the same place like WR pointer */ @@ -1369,8 +1392,9 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt, /* Read FIFO */ addr = RXF_FIFO_RD_FENCE_INC + offs; - for (i = 0; i < rxf_data.size; i += sizeof(__le32)) - *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); + data = (void *)reg_dump; + for (i = 0; i < rxf_data.size; i += sizeof(*data)) + *data++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); out: iwl_trans_release_nic_access(fwrt->trans, &flags); @@ -1384,32 +1408,86 @@ static void *iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt, { struct iwl_fw_ini_error_dump *dump = data; + dump->header.version = cpu_to_le32(IWL_INI_DUMP_MEM_VER); + return dump->ranges; } static void -*iwl_dump_ini_mon_dram_fill_header(struct iwl_fw_runtime *fwrt, - struct iwl_fw_ini_region_cfg *reg, - void *data) +*iwl_dump_ini_mon_fill_header(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg, + struct iwl_fw_ini_monitor_dump *data, + u32 write_ptr_addr, u32 write_ptr_msk, + u32 cycle_cnt_addr, u32 cycle_cnt_msk) { - struct iwl_fw_ini_monitor_dram_dump *mon_dump = (void *)data; u32 write_ptr, cycle_cnt; unsigned long flags; if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) { - IWL_ERR(fwrt, "Failed to get DRAM monitor header\n"); + IWL_ERR(fwrt, "Failed to get monitor header\n"); return NULL; } - write_ptr = iwl_read_umac_prph_no_grab(fwrt->trans, - MON_BUFF_WRPTR_VER2); - cycle_cnt = iwl_read_umac_prph_no_grab(fwrt->trans, - MON_BUFF_CYCLE_CNT_VER2); + + write_ptr = iwl_read_prph_no_grab(fwrt->trans, write_ptr_addr); + cycle_cnt = iwl_read_prph_no_grab(fwrt->trans, cycle_cnt_addr); + iwl_trans_release_nic_access(fwrt->trans, &flags); - mon_dump->write_ptr = cpu_to_le32(write_ptr); - mon_dump->cycle_cnt = cpu_to_le32(cycle_cnt); + data->header.version = cpu_to_le32(IWL_INI_DUMP_MONITOR_VER); + data->write_ptr = cpu_to_le32(write_ptr & write_ptr_msk); + data->cycle_cnt = cpu_to_le32(cycle_cnt & cycle_cnt_msk); + + return data->ranges; +} + +static void +*iwl_dump_ini_mon_dram_fill_header(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg, + void *data) +{ + struct iwl_fw_ini_monitor_dump *mon_dump = (void *)data; + u32 write_ptr_addr, write_ptr_msk, cycle_cnt_addr, cycle_cnt_msk; + + switch (fwrt->trans->cfg->device_family) { + case IWL_DEVICE_FAMILY_9000: + case IWL_DEVICE_FAMILY_22000: + write_ptr_addr = MON_BUFF_WRPTR_VER2; + write_ptr_msk = -1; + cycle_cnt_addr = MON_BUFF_CYCLE_CNT_VER2; + cycle_cnt_msk = -1; + break; + default: + IWL_ERR(fwrt, "Unsupported device family %d\n", + fwrt->trans->cfg->device_family); + return NULL; + } + + return iwl_dump_ini_mon_fill_header(fwrt, reg, mon_dump, write_ptr_addr, + write_ptr_msk, cycle_cnt_addr, + cycle_cnt_msk); +} + +static void +*iwl_dump_ini_mon_smem_fill_header(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg, + void *data) +{ + struct iwl_fw_ini_monitor_dump *mon_dump = (void *)data; + const struct iwl_cfg *cfg = fwrt->trans->cfg; + + if (fwrt->trans->cfg->device_family != IWL_DEVICE_FAMILY_9000 && + fwrt->trans->cfg->device_family != IWL_DEVICE_FAMILY_22000) { + IWL_ERR(fwrt, "Unsupported device family %d\n", + fwrt->trans->cfg->device_family); + return NULL; + } + + return iwl_dump_ini_mon_fill_header(fwrt, reg, mon_dump, + cfg->fw_mon_smem_write_ptr_addr, + cfg->fw_mon_smem_write_ptr_msk, + cfg->fw_mon_smem_cycle_cnt_ptr_addr, + cfg->fw_mon_smem_cycle_cnt_ptr_msk); - return mon_dump->ranges; } static void *iwl_dump_ini_fifo_fill_header(struct iwl_fw_runtime *fwrt, @@ -1418,6 +1496,8 @@ static void *iwl_dump_ini_fifo_fill_header(struct iwl_fw_runtime *fwrt, { struct iwl_fw_ini_fifo_error_dump *dump = data; + dump->header.version = cpu_to_le32(IWL_INI_DUMP_FIFO_VER); + return dump->ranges; } @@ -1509,7 +1589,8 @@ static u32 iwl_dump_ini_paging_get_size(struct iwl_fw_runtime *fwrt, static u32 iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg) { - u32 size = sizeof(struct iwl_fw_ini_monitor_dram_dump); + u32 size = sizeof(struct iwl_fw_ini_monitor_dump) + + sizeof(struct iwl_fw_ini_error_dump_range); if (fwrt->trans->num_blocks) size += fwrt->trans->fw_mon[0].size; @@ -1517,6 +1598,15 @@ static u32 iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt, return size; } +static u32 iwl_dump_ini_mon_smem_get_size(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + return sizeof(struct iwl_fw_ini_monitor_dump) + + iwl_dump_ini_mem_ranges(fwrt, reg) * + (sizeof(struct iwl_fw_ini_error_dump_range) + + le32_to_cpu(reg->internal.range_data_size)); +} + static u32 iwl_dump_ini_txf_get_size(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg) { @@ -1524,7 +1614,7 @@ static u32 iwl_dump_ini_txf_get_size(struct iwl_fw_runtime *fwrt, void *fifo_iter = fwrt->dump.fifo_iter; u32 size = 0; u32 fifo_hdr = sizeof(struct iwl_fw_ini_fifo_error_dump_range) + - le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); + le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32) * 2; fwrt->dump.fifo_iter = &iter; while (iwl_ini_txf_iter(fwrt, reg)) { @@ -1547,7 +1637,7 @@ static u32 iwl_dump_ini_rxf_get_size(struct iwl_fw_runtime *fwrt, struct iwl_ini_rxf_data rx_data; u32 size = sizeof(struct iwl_fw_ini_fifo_error_dump) + sizeof(struct iwl_fw_ini_fifo_error_dump_range) + - le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); + le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32) * 2; if (reg->fifos.header_only) return size; @@ -1584,27 +1674,31 @@ struct iwl_dump_ini_mem_ops { * @fwrt: fw runtime struct. * @data: dump memory data. * @reg: region to copy to the dump. + * @ops: memory dump operations. */ static void iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, - enum iwl_fw_ini_region_type type, struct iwl_fw_error_dump_data **data, struct iwl_fw_ini_region_cfg *reg, struct iwl_dump_ini_mem_ops *ops) { struct iwl_fw_ini_error_dump_header *header = (void *)(*data)->data; + u32 num_of_ranges, i, type = le32_to_cpu(reg->region_type); void *range; - u32 num_of_ranges, i; if (WARN_ON(!ops || !ops->get_num_of_ranges || !ops->get_size || !ops->fill_mem_hdr || !ops->fill_range)) return; + IWL_DEBUG_FW(fwrt, "WRT: collecting region: id=%d, type=%d\n", + le32_to_cpu(reg->region_id), type); + num_of_ranges = ops->get_num_of_ranges(fwrt, reg); (*data)->type = cpu_to_le32(type | INI_DUMP_BIT); (*data)->len = cpu_to_le32(ops->get_size(fwrt, reg)); + header->region_id = reg->region_id; header->num_of_ranges = cpu_to_le32(num_of_ranges); header->name_len = cpu_to_le32(min_t(int, IWL_FW_INI_MAX_NAME, le32_to_cpu(reg->name_len))); @@ -1612,8 +1706,10 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, range = ops->fill_mem_hdr(fwrt, reg, header); if (!range) { - IWL_ERR(fwrt, "Failed to fill region header: id=%d, type=%d\n", + IWL_ERR(fwrt, + "WRT: failed to fill region header: id=%d, type=%d\n", le32_to_cpu(reg->region_id), type); + memset(*data, 0, le32_to_cpu((*data)->len)); return; } @@ -1621,8 +1717,10 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, int range_size = ops->fill_range(fwrt, reg, range, i); if (range_size < 0) { - IWL_ERR(fwrt, "Failed to dump region: id=%d, type=%d\n", + IWL_ERR(fwrt, + "WRT: failed to dump region: id=%d, type=%d\n", le32_to_cpu(reg->region_id), type); + memset(*data, 0, le32_to_cpu((*data)->len)); return; } range = range + range_size; @@ -1641,23 +1739,30 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, for (i = 0; i < le32_to_cpu(trigger->num_regions); i++) { u32 reg_id = le32_to_cpu(trigger->data[i]); struct iwl_fw_ini_region_cfg *reg; - enum iwl_fw_ini_region_type type; if (WARN_ON(reg_id >= ARRAY_SIZE(fwrt->dump.active_regs))) continue; reg = fwrt->dump.active_regs[reg_id]; - if (WARN(!reg, "Unassigned region %d\n", reg_id)) + if (!reg) { + IWL_WARN(fwrt, + "WRT: unassigned region id %d, skipping\n", + reg_id); continue; + } - type = le32_to_cpu(reg->region_type); - switch (type) { + /* currently the driver supports always on domain only */ + if (le32_to_cpu(reg->domain) != IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON) + continue; + + switch (le32_to_cpu(reg->region_type)) { case IWL_FW_INI_REGION_DEVICE_MEMORY: case IWL_FW_INI_REGION_PERIPHERY_MAC: case IWL_FW_INI_REGION_PERIPHERY_PHY: case IWL_FW_INI_REGION_PERIPHERY_AUX: - case IWL_FW_INI_REGION_INTERNAL_BUFFER: case IWL_FW_INI_REGION_CSR: + case IWL_FW_INI_REGION_LMAC_ERROR_TABLE: + case IWL_FW_INI_REGION_UMAC_ERROR_TABLE: size += hdr_len + iwl_dump_ini_mem_get_size(fwrt, reg); break; case IWL_FW_INI_REGION_TXF: @@ -1666,7 +1771,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, case IWL_FW_INI_REGION_RXF: size += hdr_len + iwl_dump_ini_rxf_get_size(fwrt, reg); break; - case IWL_FW_INI_REGION_PAGING: { + case IWL_FW_INI_REGION_PAGING: size += hdr_len; if (iwl_fw_dbg_is_paging_enabled(fwrt)) { size += iwl_dump_ini_paging_get_size(fwrt, reg); @@ -1675,13 +1780,16 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, reg); } break; - } case IWL_FW_INI_REGION_DRAM_BUFFER: if (!fwrt->trans->num_blocks) break; size += hdr_len + iwl_dump_ini_mon_dram_get_size(fwrt, reg); break; + case IWL_FW_INI_REGION_INTERNAL_BUFFER: + size += hdr_len + + iwl_dump_ini_mon_smem_get_size(fwrt, reg); + break; case IWL_FW_INI_REGION_DRAM_IMR: /* Undefined yet */ default: @@ -1699,7 +1807,6 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, for (i = 0; i < num; i++) { u32 reg_id = le32_to_cpu(trigger->data[i]); - enum iwl_fw_ini_region_type type; struct iwl_fw_ini_region_cfg *reg; struct iwl_dump_ini_mem_ops ops; @@ -1711,15 +1818,19 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, if (!reg) continue; - type = le32_to_cpu(reg->region_type); - switch (type) { + /* currently the driver supports always on domain only */ + if (le32_to_cpu(reg->domain) != IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON) + continue; + + switch (le32_to_cpu(reg->region_type)) { case IWL_FW_INI_REGION_DEVICE_MEMORY: - case IWL_FW_INI_REGION_INTERNAL_BUFFER: + case IWL_FW_INI_REGION_LMAC_ERROR_TABLE: + case IWL_FW_INI_REGION_UMAC_ERROR_TABLE: ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; ops.get_size = iwl_dump_ini_mem_get_size; ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; ops.fill_range = iwl_dump_ini_dev_mem_iter; - iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + iwl_dump_ini_mem(fwrt, data, reg, &ops); break; case IWL_FW_INI_REGION_PERIPHERY_MAC: case IWL_FW_INI_REGION_PERIPHERY_PHY: @@ -1728,16 +1839,23 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, ops.get_size = iwl_dump_ini_mem_get_size; ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; ops.fill_range = iwl_dump_ini_prph_iter; - iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + iwl_dump_ini_mem(fwrt, data, reg, &ops); break; case IWL_FW_INI_REGION_DRAM_BUFFER: ops.get_num_of_ranges = iwl_dump_ini_mon_dram_ranges; ops.get_size = iwl_dump_ini_mon_dram_get_size; ops.fill_mem_hdr = iwl_dump_ini_mon_dram_fill_header; ops.fill_range = iwl_dump_ini_mon_dram_iter; - iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + iwl_dump_ini_mem(fwrt, data, reg, &ops); break; - case IWL_FW_INI_REGION_PAGING: { + case IWL_FW_INI_REGION_INTERNAL_BUFFER: + ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; + ops.get_size = iwl_dump_ini_mon_smem_get_size; + ops.fill_mem_hdr = iwl_dump_ini_mon_smem_fill_header; + ops.fill_range = iwl_dump_ini_dev_mem_iter; + iwl_dump_ini_mem(fwrt, data, reg, &ops); + break; + case IWL_FW_INI_REGION_PAGING: ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; if (iwl_fw_dbg_is_paging_enabled(fwrt)) { ops.get_num_of_ranges = @@ -1752,9 +1870,8 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, ops.fill_range = iwl_dump_ini_paging_gen2_iter; } - iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + iwl_dump_ini_mem(fwrt, data, reg, &ops); break; - } case IWL_FW_INI_REGION_TXF: { struct iwl_ini_txf_iter_data iter = { .init = true }; void *fifo_iter = fwrt->dump.fifo_iter; @@ -1764,7 +1881,7 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, ops.get_size = iwl_dump_ini_txf_get_size; ops.fill_mem_hdr = iwl_dump_ini_fifo_fill_header; ops.fill_range = iwl_dump_ini_txf_iter; - iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + iwl_dump_ini_mem(fwrt, data, reg, &ops); fwrt->dump.fifo_iter = fifo_iter; break; } @@ -1773,14 +1890,14 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, ops.get_size = iwl_dump_ini_rxf_get_size; ops.fill_mem_hdr = iwl_dump_ini_fifo_fill_header; ops.fill_range = iwl_dump_ini_rxf_iter; - iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + iwl_dump_ini_mem(fwrt, data, reg, &ops); break; case IWL_FW_INI_REGION_CSR: ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; ops.get_size = iwl_dump_ini_mem_get_size; ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; ops.fill_range = iwl_dump_ini_csr_iter; - iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + iwl_dump_ini_mem(fwrt, data, reg, &ops); break; case IWL_FW_INI_REGION_DRAM_IMR: /* This is undefined yet */ @@ -1791,34 +1908,29 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, } static struct iwl_fw_error_dump_file * -_iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, - struct iwl_fw_dump_ptrs *fw_error_dump) +iwl_fw_error_ini_dump_file(struct iwl_fw_runtime *fwrt) { - int size, id = le32_to_cpu(fwrt->dump.desc->trig_desc.type); + int size; struct iwl_fw_error_dump_data *dump_data; struct iwl_fw_error_dump_file *dump_file; struct iwl_fw_ini_trigger *trigger; - - if (id == FW_DBG_TRIGGER_FW_ASSERT) - id = IWL_FW_TRIGGER_ID_FW_ASSERT; + enum iwl_fw_ini_trigger_id id = fwrt->dump.ini_trig_id; if (!iwl_fw_ini_trigger_on(fwrt, id)) return NULL; trigger = fwrt->dump.active_trigs[id].trig; - size = sizeof(*dump_file); - size += iwl_fw_ini_get_trigger_len(fwrt, trigger); - + size = iwl_fw_ini_get_trigger_len(fwrt, trigger); if (!size) return NULL; + size += sizeof(*dump_file); + dump_file = vzalloc(size); if (!dump_file) return NULL; - fw_error_dump->fwrt_ptr = dump_file; - dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER); dump_data = (void *)dump_file->data; dump_file->file_len = cpu_to_le32(size); @@ -1828,47 +1940,27 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, return dump_file; } -void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) +static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) { - struct iwl_fw_dump_ptrs *fw_error_dump; + struct iwl_fw_dump_ptrs fw_error_dump = {}; struct iwl_fw_error_dump_file *dump_file; struct scatterlist *sg_dump_data; u32 file_len; u32 dump_mask = fwrt->fw->dbg.dump_mask; - IWL_DEBUG_INFO(fwrt, "WRT dump start\n"); - - /* there's no point in fw dump if the bus is dead */ - if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) { - IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n"); - goto out; - } - - fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL); - if (!fw_error_dump) - goto out; - - if (fwrt->trans->ini_valid) - dump_file = _iwl_fw_error_ini_dump(fwrt, fw_error_dump); - else - dump_file = _iwl_fw_error_dump(fwrt, fw_error_dump); - - if (!dump_file) { - kfree(fw_error_dump); + dump_file = iwl_fw_error_dump_file(fwrt, &fw_error_dump); + if (!dump_file) goto out; - } if (!fwrt->trans->ini_valid && fwrt->dump.monitor_only) dump_mask &= IWL_FW_ERROR_DUMP_FW_MONITOR; - if (!fwrt->trans->ini_valid) - fw_error_dump->trans_ptr = - iwl_trans_dump_data(fwrt->trans, dump_mask); - + fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask); file_len = le32_to_cpu(dump_file->file_len); - fw_error_dump->fwrt_len = file_len; - if (fw_error_dump->trans_ptr) { - file_len += fw_error_dump->trans_ptr->len; + fw_error_dump.fwrt_len = file_len; + + if (fw_error_dump.trans_ptr) { + file_len += fw_error_dump.trans_ptr->len; dump_file->file_len = cpu_to_le32(file_len); } @@ -1876,27 +1968,49 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) if (sg_dump_data) { sg_pcopy_from_buffer(sg_dump_data, sg_nents(sg_dump_data), - fw_error_dump->fwrt_ptr, - fw_error_dump->fwrt_len, 0); - if (fw_error_dump->trans_ptr) + fw_error_dump.fwrt_ptr, + fw_error_dump.fwrt_len, 0); + if (fw_error_dump.trans_ptr) sg_pcopy_from_buffer(sg_dump_data, sg_nents(sg_dump_data), - fw_error_dump->trans_ptr->data, - fw_error_dump->trans_ptr->len, - fw_error_dump->fwrt_len); + fw_error_dump.trans_ptr->data, + fw_error_dump.trans_ptr->len, + fw_error_dump.fwrt_len); dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len, GFP_KERNEL); } - vfree(fw_error_dump->fwrt_ptr); - vfree(fw_error_dump->trans_ptr); - kfree(fw_error_dump); + vfree(fw_error_dump.fwrt_ptr); + vfree(fw_error_dump.trans_ptr); out: iwl_fw_free_dump_desc(fwrt); clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status); - IWL_DEBUG_INFO(fwrt, "WRT dump done\n"); } -IWL_EXPORT_SYMBOL(iwl_fw_error_dump); + +static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt) +{ + struct iwl_fw_error_dump_file *dump_file; + struct scatterlist *sg_dump_data; + u32 file_len; + + dump_file = iwl_fw_error_ini_dump_file(fwrt); + if (!dump_file) + goto out; + + file_len = le32_to_cpu(dump_file->file_len); + + sg_dump_data = alloc_sgtable(file_len); + if (sg_dump_data) { + sg_pcopy_from_buffer(sg_dump_data, sg_nents(sg_dump_data), + dump_file, file_len, 0); + dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len, + GFP_KERNEL); + } + vfree(dump_file); +out: + fwrt->dump.ini_trig_id = IWL_FW_TRIGGER_ID_INVALID; + clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status); +} const struct iwl_fw_dump_desc iwl_dump_desc_assert = { .trig_desc = { @@ -1910,6 +2024,17 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, bool monitor_only, unsigned int delay) { + u32 trig_type = le32_to_cpu(desc->trig_desc.type); + int ret; + + if (fwrt->trans->ini_valid) { + ret = iwl_fw_dbg_ini_collect(fwrt, trig_type); + if (!ret) + iwl_fw_free_dump_desc(fwrt); + + return ret; + } + if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) return -EBUSY; @@ -1942,23 +2067,19 @@ int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt, iwl_dump_error_desc->len = 0; ret = iwl_fw_dbg_collect_desc(fwrt, iwl_dump_error_desc, false, 0); - if (ret) { + if (ret) kfree(iwl_dump_error_desc); - } else { - set_bit(STATUS_FW_WAIT_DUMP, &fwrt->trans->status); - - /* trigger nmi to halt the fw */ - iwl_force_nmi(fwrt->trans); - } + else + iwl_trans_sync_nmi(fwrt->trans); return ret; } IWL_EXPORT_SYMBOL(iwl_fw_dbg_error_collect); -int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, - enum iwl_fw_dbg_trigger trig, - const char *str, size_t len, - struct iwl_fw_dbg_trigger_tlv *trigger) +int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, + enum iwl_fw_dbg_trigger trig, + const char *str, size_t len, + struct iwl_fw_dbg_trigger_tlv *trigger) { struct iwl_fw_dump_desc *desc; unsigned int delay = 0; @@ -1995,50 +2116,73 @@ int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, return iwl_fw_dbg_collect_desc(fwrt, desc, monitor_only, delay); } -IWL_EXPORT_SYMBOL(_iwl_fw_dbg_collect); +IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect); -int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, - u32 id, const char *str, size_t len) +int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, + enum iwl_fw_ini_trigger_id id) { - struct iwl_fw_dump_desc *desc; struct iwl_fw_ini_active_triggers *active; u32 occur, delay; - if (!fwrt->trans->ini_valid) - return _iwl_fw_dbg_collect(fwrt, id, str, len, NULL); - - if (id == FW_DBG_TRIGGER_USER) - id = IWL_FW_TRIGGER_ID_USER_TRIGGER; + if (WARN_ON(!iwl_fw_ini_trigger_on(fwrt, id))) + return -EINVAL; - active = &fwrt->dump.active_trigs[id]; + if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) + return -EBUSY; - if (WARN_ON(!active->active)) + if (!iwl_fw_ini_trigger_on(fwrt, id)) { + IWL_WARN(fwrt, "WRT: Trigger %d is not active, aborting dump\n", + id); return -EINVAL; + } + active = &fwrt->dump.active_trigs[id]; delay = le32_to_cpu(active->trig->dump_delay); occur = le32_to_cpu(active->trig->occurrences); if (!occur) return 0; + active->trig->occurrences = cpu_to_le32(--occur); + if (le32_to_cpu(active->trig->force_restart)) { - IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", id); + IWL_WARN(fwrt, "WRT: force restart: trigger %d fired.\n", id); iwl_force_nmi(fwrt->trans); return 0; } - desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC); - if (!desc) - return -ENOMEM; + if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) + return -EBUSY; - active->trig->occurrences = cpu_to_le32(--occur); + fwrt->dump.ini_trig_id = id; - desc->len = len; - desc->trig_desc.type = cpu_to_le32(id); - memcpy(desc->trig_desc.data, str, len); + IWL_WARN(fwrt, "WRT: collecting data: ini trigger %d fired.\n", id); + + schedule_delayed_work(&fwrt->dump.wk, usecs_to_jiffies(delay)); - return iwl_fw_dbg_collect_desc(fwrt, desc, true, delay); + return 0; } -IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect); +IWL_EXPORT_SYMBOL(_iwl_fw_dbg_ini_collect); + +int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, u32 legacy_trigger_id) +{ + int id; + + switch (legacy_trigger_id) { + case FW_DBG_TRIGGER_FW_ASSERT: + case FW_DBG_TRIGGER_ALIVE_TIMEOUT: + case FW_DBG_TRIGGER_DRIVER: + id = IWL_FW_TRIGGER_ID_FW_ASSERT; + break; + case FW_DBG_TRIGGER_USER: + id = IWL_FW_TRIGGER_ID_USER_TRIGGER; + break; + default: + return -EIO; + } + + return _iwl_fw_dbg_ini_collect(fwrt, id); +} +IWL_EXPORT_SYMBOL(iwl_fw_dbg_ini_collect); int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt, struct iwl_fw_dbg_trigger_tlv *trigger, @@ -2066,8 +2210,8 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt, len = strlen(buf) + 1; } - ret = _iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len, - trigger); + ret = iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len, + trigger); if (ret) return ret; @@ -2141,9 +2285,20 @@ void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt) return; } + /* there's no point in fw dump if the bus is dead */ + if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) { + IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n"); + return; + } + iwl_fw_dbg_stop_recording(fwrt, ¶ms); - iwl_fw_error_dump(fwrt); + IWL_DEBUG_FW_INFO(fwrt, "WRT: data collection start\n"); + if (fwrt->trans->ini_valid) + iwl_fw_error_ini_dump(fwrt); + else + iwl_fw_error_dump(fwrt); + IWL_DEBUG_FW_INFO(fwrt, "WRT: data collection done\n"); /* start recording again if the firmware is not crashed */ if (!test_bit(STATUS_FW_ERROR, &fwrt->trans->status) && @@ -2213,12 +2368,14 @@ iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, u32 size) if (!virtual_addr) IWL_ERR(fwrt, "Failed to allocate debug memory\n"); + IWL_DEBUG_FW(trans, + "Allocated DRAM buffer[%d], size=0x%x\n", + trans->num_blocks, size); + trans->fw_mon[trans->num_blocks].block = virtual_addr; trans->fw_mon[trans->num_blocks].physical = phys_addr; trans->fw_mon[trans->num_blocks].size = size; trans->num_blocks++; - - IWL_DEBUG_FW(trans, "Allocated debug block of size %d\n", size); } static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt, @@ -2241,11 +2398,15 @@ static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt, if (buf_location == IWL_FW_INI_LOCATION_SRAM_PATH) { if (!WARN(pnt != IWL_FW_INI_APPLY_EARLY, - "Invalid apply point %d for SMEM buffer allocation", - pnt)) + "WRT: Invalid apply point %d for SMEM buffer allocation, aborting\n", + pnt)) { + IWL_DEBUG_FW(trans, + "WRT: applying SMEM buffer destination\n"); + /* set sram monitor by enabling bit 7 */ iwl_set_bit(fwrt->trans, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM); + } return; } @@ -2264,6 +2425,9 @@ static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt, if (trans->num_blocks == 1) return; + IWL_DEBUG_FW(trans, + "WRT: applying DRAM buffer[%d] destination\n", block_idx); + cmd->num_frags = cpu_to_le32(1); cmd->fragments[0].address = cpu_to_le64(trans->fw_mon[block_idx].physical); @@ -2275,7 +2439,8 @@ static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt, } static void iwl_fw_dbg_send_hcmd(struct iwl_fw_runtime *fwrt, - struct iwl_ucode_tlv *tlv) + struct iwl_ucode_tlv *tlv, + bool ext) { struct iwl_fw_ini_hcmd_tlv *hcmd_tlv = (void *)&tlv->data[0]; struct iwl_fw_ini_hcmd *data = &hcmd_tlv->hcmd; @@ -2287,6 +2452,14 @@ static void iwl_fw_dbg_send_hcmd(struct iwl_fw_runtime *fwrt, .data = { data->data, }, }; + /* currently the driver supports always on domain only */ + if (le32_to_cpu(hcmd_tlv->domain) != IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON) + return; + + IWL_DEBUG_FW(fwrt, + "WRT: ext=%d. Sending host command id=0x%x, group=0x%x\n", + ext, data->id, data->group); + iwl_trans_send_cmd(fwrt->trans, &hcmd); } @@ -2296,24 +2469,32 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt, { void *iter = (void *)tlv->region_config; int i, size = le32_to_cpu(tlv->num_regions); + const char *err_st = + "WRT: ext=%d. Invalid region %s %d for apply point %d\n"; for (i = 0; i < size; i++) { struct iwl_fw_ini_region_cfg *reg = iter, **active; int id = le32_to_cpu(reg->region_id); u32 type = le32_to_cpu(reg->region_type); - if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_regs), - "Invalid region id %d for apply point %d\n", id, pnt)) + if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_regs), err_st, ext, + "id", id, pnt)) + break; + + if (WARN(type == 0 || type >= IWL_FW_INI_REGION_NUM, err_st, + ext, "type", type, pnt)) break; active = &fwrt->dump.active_regs[id]; if (*active) - IWL_WARN(fwrt->trans, "region TLV %d override\n", id); + IWL_WARN(fwrt->trans, + "WRT: ext=%d. Region id %d override\n", + ext, id); IWL_DEBUG_FW(fwrt, - "%s: apply point %d, activating region ID %d\n", - __func__, pnt, id); + "WRT: ext=%d. Activating region id %d\n", + ext, id); *active = reg; @@ -2321,7 +2502,15 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt, type == IWL_FW_INI_REGION_RXF) iter += le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); - else if (type != IWL_FW_INI_REGION_DRAM_BUFFER) + else if (type == IWL_FW_INI_REGION_DEVICE_MEMORY || + type == IWL_FW_INI_REGION_PERIPHERY_MAC || + type == IWL_FW_INI_REGION_PERIPHERY_PHY || + type == IWL_FW_INI_REGION_PERIPHERY_AUX || + type == IWL_FW_INI_REGION_INTERNAL_BUFFER || + type == IWL_FW_INI_REGION_PAGING || + type == IWL_FW_INI_REGION_CSR || + type == IWL_FW_INI_REGION_LMAC_ERROR_TABLE || + type == IWL_FW_INI_REGION_UMAC_ERROR_TABLE) iter += le32_to_cpu(reg->internal.num_of_ranges) * sizeof(__le32); @@ -2340,7 +2529,8 @@ static int iwl_fw_dbg_trig_realloc(struct iwl_fw_runtime *fwrt, ptr = krealloc(active->trig, size, GFP_KERNEL); if (!ptr) { - IWL_ERR(fwrt, "Failed to allocate memory for trigger %d\n", id); + IWL_ERR(fwrt, "WRT: Failed to allocate memory for trigger %d\n", + id); return -ENOMEM; } active->trig = ptr; @@ -2364,7 +2554,9 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, u32 trig_regs_size = le32_to_cpu(trig->num_regions) * sizeof(__le32); - if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs))) + if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_trigs), + "WRT: ext=%d. Invalid trigger id %d for apply point %d\n", + ext, id, apply_point)) break; active = &fwrt->dump.active_trigs[id]; @@ -2372,6 +2564,10 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, if (!active->active) { size_t trig_size = sizeof(*trig) + trig_regs_size; + IWL_DEBUG_FW(fwrt, + "WRT: ext=%d. Activating trigger %d\n", + ext, id); + if (iwl_fw_dbg_trig_realloc(fwrt, active, id, trig_size)) goto next; @@ -2390,8 +2586,16 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, int mem_to_add = trig_regs_size; if (region_override) { + IWL_DEBUG_FW(fwrt, + "WRT: ext=%d. Trigger %d regions override\n", + ext, id); + mem_to_add -= active_regs * sizeof(__le32); } else { + IWL_DEBUG_FW(fwrt, + "WRT: ext=%d. Trigger %d regions appending\n", + ext, id); + offset += active_regs; new_regs += active_regs; } @@ -2400,8 +2604,13 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, active->size + mem_to_add)) goto next; - if (conf_override) + if (conf_override) { + IWL_DEBUG_FW(fwrt, + "WRT: ext=%d. Trigger %d configuration override\n", + ext, id); + memcpy(active->trig, trig, sizeof(*trig)); + } memcpy(active->trig->data + offset, trig->data, trig_regs_size); @@ -2413,6 +2622,20 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, active->trig->occurrences = cpu_to_le32(-1); active->active = true; + + if (id == IWL_FW_TRIGGER_ID_PERIODIC_TRIGGER) { + u32 collect_interval = le32_to_cpu(trig->trigger_data); + + /* the minimum allowed interval is 50ms */ + if (collect_interval < 50) { + collect_interval = 50; + trig->trigger_data = + cpu_to_le32(collect_interval); + } + + mod_timer(&fwrt->dump.periodic_trig, + jiffies + msecs_to_jiffies(collect_interval)); + } next: iter += sizeof(*trig) + trig_regs_size; @@ -2442,11 +2665,11 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, case IWL_UCODE_TLV_TYPE_HCMD: if (pnt < IWL_FW_INI_APPLY_AFTER_ALIVE) { IWL_ERR(fwrt, - "Invalid apply point %x for host command\n", - pnt); + "WRT: ext=%d. Invalid apply point %d for host command\n", + ext, pnt); goto next; } - iwl_fw_dbg_send_hcmd(fwrt, tlv); + iwl_fw_dbg_send_hcmd(fwrt, tlv, ext); break; case IWL_UCODE_TLV_TYPE_REGIONS: iwl_fw_dbg_update_regions(fwrt, ini_tlv, ext, pnt); @@ -2457,7 +2680,9 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, case IWL_UCODE_TLV_TYPE_DEBUG_FLOW: break; default: - WARN_ONCE(1, "Invalid TLV %x for apply point\n", type); + WARN_ONCE(1, + "WRT: ext=%d. Invalid TLV 0x%x for apply point\n", + ext, type); break; } next: @@ -2471,6 +2696,8 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, void *data = &fwrt->trans->apply_points[apply_point]; int i; + IWL_DEBUG_FW(fwrt, "WRT: enabling apply point %d\n", apply_point); + if (apply_point == IWL_FW_INI_APPLY_EARLY) { for (i = 0; i < IWL_FW_INI_MAX_REGION_ID; i++) fwrt->dump.active_regs[i] = NULL; @@ -2489,24 +2716,34 @@ IWL_EXPORT_SYMBOL(iwl_fw_dbg_apply_point); void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt) { - /* if the wait event timeout elapses instead of wake up then - * the driver did not receive NMI interrupt and can not assume the FW - * is halted - */ - int ret = wait_event_timeout(fwrt->trans->fw_halt_waitq, - !test_bit(STATUS_FW_WAIT_DUMP, - &fwrt->trans->status), - msecs_to_jiffies(2000)); - if (!ret) { - /* failed to receive NMI interrupt, assuming the FW is stuck */ - set_bit(STATUS_FW_ERROR, &fwrt->trans->status); - - clear_bit(STATUS_FW_WAIT_DUMP, &fwrt->trans->status); - } - - /* Assuming the op mode mutex is held at this point */ + del_timer(&fwrt->dump.periodic_trig); iwl_fw_dbg_collect_sync(fwrt); iwl_trans_stop_device(fwrt->trans); } IWL_EXPORT_SYMBOL(iwl_fwrt_stop_device); + +void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t) +{ + struct iwl_fw_runtime *fwrt; + enum iwl_fw_ini_trigger_id id = IWL_FW_TRIGGER_ID_PERIODIC_TRIGGER; + int ret; + typeof(fwrt->dump) *dump_ptr = container_of(t, typeof(fwrt->dump), + periodic_trig); + + fwrt = container_of(dump_ptr, typeof(*fwrt), dump); + + ret = _iwl_fw_dbg_ini_collect(fwrt, id); + if (!ret || ret == -EBUSY) { + struct iwl_fw_ini_trigger *trig = + fwrt->dump.active_trigs[id].trig; + u32 occur = le32_to_cpu(trig->occurrences); + u32 collect_interval = le32_to_cpu(trig->trigger_data); + + if (!occur) + return; + + mod_timer(&fwrt->dump.periodic_trig, + jiffies + msecs_to_jiffies(collect_interval)); + } +} diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index a199056234d3..2a9e560a906b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -108,18 +108,17 @@ static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt) fwrt->dump.umac_err_id = 0; } -void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt); int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, const struct iwl_fw_dump_desc *desc, bool monitor_only, unsigned int delay); int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt, enum iwl_fw_dbg_trigger trig_type); -int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, - enum iwl_fw_dbg_trigger trig, - const char *str, size_t len, - struct iwl_fw_dbg_trigger_tlv *trigger); +int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, + enum iwl_fw_ini_trigger_id id); +int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, u32 legacy_trigger_id); int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, - u32 id, const char *str, size_t len); + enum iwl_fw_dbg_trigger trig, const char *str, + size_t len, struct iwl_fw_dbg_trigger_tlv *trigger); int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt, struct iwl_fw_dbg_trigger_tlv *trigger, const char *fmt, ...) __printf(3, 4); @@ -229,10 +228,8 @@ iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_trigger *trig; u32 usec; - - - if (!fwrt->trans->ini_valid || id >= IWL_FW_TRIGGER_ID_NUM || - !fwrt->dump.active_trigs[id].active) + if (!fwrt->trans->ini_valid || id == IWL_FW_TRIGGER_ID_INVALID || + id >= IWL_FW_TRIGGER_ID_NUM || !fwrt->dump.active_trigs[id].active) return false; trig = fwrt->dump.active_trigs[id].trig; @@ -388,11 +385,13 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt); static inline void iwl_fw_flush_dump(struct iwl_fw_runtime *fwrt) { + del_timer(&fwrt->dump.periodic_trig); flush_delayed_work(&fwrt->dump.wk); } static inline void iwl_fw_cancel_dump(struct iwl_fw_runtime *fwrt) { + del_timer(&fwrt->dump.periodic_trig); cancel_delayed_work_sync(&fwrt->dump.wk); } @@ -461,4 +460,15 @@ static inline void iwl_fw_umac_set_alive_err_table(struct iwl_trans *trans, /* This bit is used to differentiate the legacy dump from the ini dump */ #define INI_DUMP_BIT BIT(31) +static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt) +{ + if (fwrt->trans->ini_valid && fwrt->trans->hw_error) { + _iwl_fw_dbg_ini_collect(fwrt, IWL_FW_TRIGGER_ID_FW_HW_ERROR); + fwrt->trans->hw_error = false; + } else { + iwl_fw_dbg_collect_desc(fwrt, &iwl_dump_desc_assert, false, 0); + } +} + +void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t); #endif /* __iwl_fw_dbg_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index 9b5077bd46c3..0feff4c33e39 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -184,7 +184,7 @@ enum iwl_fw_error_dump_family { /** * struct iwl_fw_error_dump_info - info on the device / firmware - * @device_family: the family of the device (7 / 8) + * @hw_type: the type of the device * @hw_step: the step of the device * @fw_human_readable: human readable FW version * @dev_human_readable: name of the device @@ -196,7 +196,7 @@ enum iwl_fw_error_dump_family { * if the dump collection was not initiated by an assert, the value is 0 */ struct iwl_fw_error_dump_info { - __le32 device_family; + __le32 hw_type; __le32 hw_step; u8 fw_human_readable[FW_VER_HUMAN_READABLE_SZ]; u8 dev_human_readable[64]; @@ -211,6 +211,9 @@ struct iwl_fw_error_dump_info { * @fw_mon_wr_ptr: the position of the write pointer in the cyclic buffer * @fw_mon_base_ptr: base pointer of the data * @fw_mon_cycle_cnt: number of wraparounds + * @fw_mon_base_high_ptr: used in AX210 devices, the base adderss is 64 bit + * so fw_mon_base_ptr holds LSB 32 bits and fw_mon_base_high_ptr hold + * MSB 32 bits * @reserved: for future use * @data: captured data */ @@ -218,7 +221,8 @@ struct iwl_fw_error_dump_fw_mon { __le32 fw_mon_wr_ptr; __le32 fw_mon_base_ptr; __le32 fw_mon_cycle_cnt; - __le32 reserved[3]; + __le32 fw_mon_base_high_ptr; + __le32 reserved[2]; u8 data[]; } __packed; @@ -274,25 +278,33 @@ struct iwl_fw_error_dump_mem { u8 data[]; }; +#define IWL_INI_DUMP_MEM_VER 1 +#define IWL_INI_DUMP_MONITOR_VER 1 +#define IWL_INI_DUMP_FIFO_VER 1 + /** * struct iwl_fw_ini_error_dump_range - range of memory - * @start_addr: the start address of this range * @range_data_size: the size of this range, in bytes + * @start_addr: the start address of this range * @data: the actual memory */ struct iwl_fw_ini_error_dump_range { - __le32 start_addr; __le32 range_data_size; + __le64 start_addr; __le32 data[]; } __packed; /** * struct iwl_fw_ini_error_dump_header - ini region dump header + * @version: dump version + * @region_id: id of the region * @num_of_ranges: number of ranges in this region * @name_len: number of bytes allocated to the name string of this region * @name: name of the region */ struct iwl_fw_ini_error_dump_header { + __le32 version; + __le32 region_id; __le32 num_of_ranges; __le32 name_len; u8 name[IWL_FW_INI_MAX_NAME]; @@ -312,12 +324,23 @@ struct iwl_fw_ini_error_dump { #define IWL_RXF_UMAC_BIT BIT(31) /** + * struct iwl_fw_ini_error_dump_register - ini register dump + * @addr: address of the register + * @data: data of the register + */ +struct iwl_fw_ini_error_dump_register { + __le32 addr; + __le32 data; +} __packed; + +/** * struct iwl_fw_ini_fifo_error_dump_range - ini fifo range dump * @fifo_num: the fifo num. In case of rxf and umac rxf, set BIT(31) to * distinguish between lmac and umac * @num_of_registers: num of registers to dump, dword size each - * @range_data_size: the size of the registers and fifo data - * @data: fifo data + * @range_data_size: the size of the data + * @data: consist of + * num_of_registers * (register address + register value) + fifo data */ struct iwl_fw_ini_fifo_error_dump_range { __le32 fifo_num; @@ -351,13 +374,13 @@ struct iwl_fw_error_dump_rb { }; /** - * struct iwl_fw_ini_monitor_dram_dump - ini dram monitor dump + * struct iwl_fw_ini_monitor_dump - ini monitor dump * @header - header of the region - * @write_ptr - write pointer position in the dram + * @write_ptr - write pointer position in the buffer * @cycle_cnt - cycles count * @ranges - the memory ranges of this this region */ -struct iwl_fw_ini_monitor_dram_dump { +struct iwl_fw_ini_monitor_dump { struct iwl_fw_ini_error_dump_header header; __le32 write_ptr; __le32 cycle_cnt; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index 641c95d03b15..de9243d30135 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -93,7 +93,7 @@ struct iwl_ucode_header { } u; }; -#define IWL_UCODE_INI_TLV_GROUP BIT(24) +#define IWL_UCODE_INI_TLV_GROUP 0x1000000 /* * new TLV uCode file layout @@ -142,17 +142,22 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_FW_DBG_DEST = 38, IWL_UCODE_TLV_FW_DBG_CONF = 39, IWL_UCODE_TLV_FW_DBG_TRIGGER = 40, + IWL_UCODE_TLV_CMD_VERSIONS = 48, IWL_UCODE_TLV_FW_GSCAN_CAPA = 50, IWL_UCODE_TLV_FW_MEM_SEG = 51, IWL_UCODE_TLV_IML = 52, IWL_UCODE_TLV_UMAC_DEBUG_ADDRS = 54, IWL_UCODE_TLV_LMAC_DEBUG_ADDRS = 55, IWL_UCODE_TLV_FW_RECOVERY_INFO = 57, - IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_INI_TLV_GROUP | 0x1, - IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_INI_TLV_GROUP | 0x2, - IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_INI_TLV_GROUP | 0x3, - IWL_UCODE_TLV_TYPE_TRIGGERS = IWL_UCODE_INI_TLV_GROUP | 0x4, - IWL_UCODE_TLV_TYPE_DEBUG_FLOW = IWL_UCODE_INI_TLV_GROUP | 0x5, + IWL_UCODE_TLV_FW_FSEQ_VERSION = 60, + + IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_INI_TLV_GROUP + 0x1, + IWL_UCODE_TLV_DEBUG_BASE = IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION, + IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_INI_TLV_GROUP + 0x2, + IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_INI_TLV_GROUP + 0x3, + IWL_UCODE_TLV_TYPE_TRIGGERS = IWL_UCODE_INI_TLV_GROUP + 0x4, + IWL_UCODE_TLV_TYPE_DEBUG_FLOW = IWL_UCODE_INI_TLV_GROUP + 0x5, + IWL_UCODE_TLV_DEBUG_MAX = IWL_UCODE_TLV_TYPE_DEBUG_FLOW, /* TLVs 0x1000-0x2000 are for internal driver usage */ IWL_UCODE_TLV_FW_DBG_DUMP_LST = 0x1000, @@ -272,8 +277,15 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t; * version of the beacon notification. * @IWL_UCODE_TLV_API_BEACON_FILTER_V4: This ucode supports v4 of * BEACON_FILTER_CONFIG_API_S_VER_4. + * @IWL_UCODE_TLV_API_REGULATORY_NVM_INFO: This ucode supports v4 of + * REGULATORY_NVM_GET_INFO_RSP_API_S. * @IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ: This ucode supports v7 of * LOCATION_RANGE_REQ_CMD_API_S and v6 of LOCATION_RANGE_RESP_NTFY_API_S. + * @IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS: This ucode supports v2 of + * SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S and v3 of + * SCAN_OFFLOAD_PROFILES_QUERY_RSP_S. + * @IWL_UCODE_TLV_API_MBSSID_HE: This ucode supports v2 of + * STA_CONTEXT_DOT11AX_API_S * * @NUM_IWL_UCODE_TLV_API: number of bits used */ @@ -300,7 +312,12 @@ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_REDUCE_TX_POWER = (__force iwl_ucode_tlv_api_t)45, IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF = (__force iwl_ucode_tlv_api_t)46, IWL_UCODE_TLV_API_BEACON_FILTER_V4 = (__force iwl_ucode_tlv_api_t)47, + IWL_UCODE_TLV_API_REGULATORY_NVM_INFO = (__force iwl_ucode_tlv_api_t)48, IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ = (__force iwl_ucode_tlv_api_t)49, + IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS = (__force iwl_ucode_tlv_api_t)50, + IWL_UCODE_TLV_API_MBSSID_HE = (__force iwl_ucode_tlv_api_t)52, + IWL_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE = (__force iwl_ucode_tlv_api_t)53, + IWL_UCODE_TLV_API_FTM_RTT_ACCURACY = (__force iwl_ucode_tlv_api_t)54, NUM_IWL_UCODE_TLV_API #ifdef __CHECKER__ @@ -350,6 +367,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD: firmware supports CSA command * @IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS: firmware supports ultra high band * (6 GHz). + * @IWL_UCODE_TLV_CAPA_CS_MODIFY: firmware supports modify action CSA command * @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement * @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts * @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT @@ -420,6 +438,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD = (__force iwl_ucode_tlv_capa_t)46, IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS = (__force iwl_ucode_tlv_capa_t)48, IWL_UCODE_TLV_CAPA_FTM_CALIBRATED = (__force iwl_ucode_tlv_capa_t)47, + IWL_UCODE_TLV_CAPA_CS_MODIFY = (__force iwl_ucode_tlv_capa_t)49, /* set 2 */ IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, @@ -925,4 +944,20 @@ struct iwl_fw_dbg_conf_tlv { struct iwl_fw_dbg_conf_hcmd hcmd; } __packed; +#define IWL_FW_CMD_VER_UNKNOWN 99 + +/** + * struct iwl_fw_cmd_version - firmware command version entry + * @cmd: command ID + * @group: group ID + * @cmd_ver: command version + * @notif_ver: notification version + */ +struct iwl_fw_cmd_version { + u8 cmd; + u8 group; + u8 cmd_ver; + u8 notif_ver; +} __packed; + #endif /* __iwl_fw_file_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h index f4c5a4d73206..18ca5f152be6 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h @@ -8,7 +8,7 @@ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -109,6 +109,9 @@ struct iwl_ucode_capabilities { u32 error_log_size; unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)]; unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)]; + + const struct iwl_fw_cmd_version *cmd_versions; + u32 n_cmd_versions; }; static inline bool diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c index 7adf4e4e841a..4435c0ce3013 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/init.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c @@ -76,7 +76,8 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, fwrt->ops_ctx = ops_ctx; INIT_DELAYED_WORK(&fwrt->dump.wk, iwl_fw_error_dump_wk); iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir); - init_waitqueue_head(&fwrt->trans->fw_halt_waitq); + timer_setup(&fwrt->dump.periodic_trig, + iwl_fw_dbg_periodic_trig_handler, 0); } IWL_EXPORT_SYMBOL(iwl_fw_runtime_init); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index a5fe1a8ca426..a6402a0b3854 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -145,6 +145,8 @@ struct iwl_fw_runtime { u32 lmac_err_id[MAX_NUM_LMAC]; u32 umac_err_id; void *fifo_iter; + enum iwl_fw_ini_trigger_id ini_trig_id; + struct timer_list periodic_trig; } dump; #ifdef CONFIG_IWLWIFI_DEBUGFS struct { diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index f5f87773667b..f3e69edf8907 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -383,6 +383,9 @@ struct iwl_csr_params { * @bisr_workaround: BISR hardware workaround (for 22260 series devices) * @min_txq_size: minimum number of slots required in a TX queue * @umac_prph_offset: offset to add to UMAC periphery address + * @uhb_supported: ultra high band channels supported + * @min_256_ba_txq_size: minimum number of slots required in a TX queue which + * supports 256 BA aggregation * * We enable the driver to be backward compatible wrt. hardware features. * API differences in uCode shouldn't be handled here but through TLVs @@ -433,7 +436,8 @@ struct iwl_cfg { gen2:1, cdb:1, dbgc_supported:1, - bisr_workaround:1; + bisr_workaround:1, + uhb_supported:1; u8 valid_tx_ant; u8 valid_rx_ant; u8 non_shared_ant; @@ -450,6 +454,12 @@ struct iwl_cfg { u32 d3_debug_data_length; u32 min_txq_size; u32 umac_prph_offset; + u32 fw_mon_smem_write_ptr_addr; + u32 fw_mon_smem_write_ptr_msk; + u32 fw_mon_smem_cycle_cnt_ptr_addr; + u32 fw_mon_smem_cycle_cnt_ptr_msk; + u32 gp2_reg_addr; + u32 min_256_ba_txq_size; }; extern const struct iwl_csr_params iwl_csr_v1; @@ -549,8 +559,9 @@ extern const struct iwl_cfg iwl22000_2ac_cfg_hr; extern const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb; extern const struct iwl_cfg iwl22000_2ac_cfg_jf; extern const struct iwl_cfg iwl_ax101_cfg_qu_hr; +extern const struct iwl_cfg iwl_ax101_cfg_quz_hr; extern const struct iwl_cfg iwl22000_2ax_cfg_hr; -extern const struct iwl_cfg iwl22260_2ax_cfg; +extern const struct iwl_cfg iwl_ax200_cfg_cc; extern const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0; extern const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0; extern const struct iwl_cfg killer1650x_2ax_cfg; @@ -567,11 +578,11 @@ extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0_f0; extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0; extern const struct iwl_cfg iwl9560_2ac_cfg_qnj_jf_b0; extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0; -extern const struct iwl_cfg iwl22560_2ax_cfg_su_cdb; extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0; extern const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0; extern const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0; extern const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0; +extern const struct iwl_cfg iwlax210_2ax_cfg_so_gf4_a0; #endif /* CPTCFG_IWLMVM || CPTCFG_IWLFMAC */ #endif /* __IWL_CONFIG_H__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index aea6d03e545a..553554846009 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -8,7 +8,7 @@ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2016 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -290,6 +290,7 @@ /* HW REV */ #define CSR_HW_REV_DASH(_val) (((_val) & 0x0000003) >> 0) #define CSR_HW_REV_STEP(_val) (((_val) & 0x000000C) >> 2) +#define CSR_HW_REV_TYPE(_val) (((_val) & 0x000FFF0) >> 4) /* HW RFID */ #define CSR_HW_RFID_FLAVOR(_val) (((_val) & 0x000000F) >> 0) @@ -327,6 +328,7 @@ enum { #define CSR_HW_REV_TYPE_NONE (0x00001F0) #define CSR_HW_REV_TYPE_QNJ (0x0000360) #define CSR_HW_REV_TYPE_QNJ_B0 (0x0000364) +#define CSR_HW_REV_TYPE_QUZ (0x0000354) #define CSR_HW_REV_TYPE_HR_CDB (0x0000340) #define CSR_HW_REV_TYPE_SO (0x0000370) #define CSR_HW_REV_TYPE_TY (0x0000420) @@ -336,6 +338,7 @@ enum { #define CSR_HW_RF_ID_TYPE_HR (0x0010A000) #define CSR_HW_RF_ID_TYPE_HRCDB (0x00109F00) #define CSR_HW_RF_ID_TYPE_GF (0x0010D000) +#define CSR_HW_RF_ID_TYPE_GF4 (0x0010E000) /* HW_RF CHIP ID */ #define CSR_HW_RF_ID_TYPE_CHIP_ID(_val) (((_val) >> 12) & 0xFFF) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 5798f434f68f..ba66f7fba064 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,7 +28,7 @@ * * BSD LICENSE * - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -73,6 +73,9 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv, int copy_size = le32_to_cpu(tlv->length) + sizeof(*tlv); int offset_size = copy_size; + if (le32_to_cpu(header->tlv_version) != 1) + return; + if (WARN_ONCE(apply_point >= IWL_FW_INI_APPLY_NUM, "Invalid apply point id %d\n", apply_point)) return; @@ -126,13 +129,17 @@ void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data, len -= ALIGN(tlv_len, 4); data += sizeof(*tlv) + ALIGN(tlv_len, 4); - if (!(tlv_type & IWL_UCODE_INI_TLV_GROUP)) + if (tlv_type < IWL_UCODE_TLV_DEBUG_BASE || + tlv_type > IWL_UCODE_TLV_DEBUG_MAX) continue; hdr = (void *)&tlv->data[0]; apply = le32_to_cpu(hdr->apply_point); - IWL_DEBUG_FW(trans, "Read TLV %x, apply point %d\n", + if (le32_to_cpu(hdr->tlv_version) != 1) + continue; + + IWL_DEBUG_FW(trans, "WRT: read TLV 0x%x, apply point %d\n", le32_to_cpu(tlv->type), apply); if (WARN_ON(apply >= IWL_FW_INI_APPLY_NUM)) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-debug.h b/drivers/net/wireless/intel/iwlwifi/iwl-debug.h index 655ff5694560..d3ba6a1422ee 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-debug.h @@ -218,5 +218,7 @@ do { \ #define IWL_DEBUG_TPT(p, f, a...) IWL_DEBUG(p, IWL_DL_TPT, f, ## a) #define IWL_DEBUG_RPM(p, f, a...) IWL_DEBUG(p, IWL_DL_RPM, f, ## a) #define IWL_DEBUG_LAR(p, f, a...) IWL_DEBUG(p, IWL_DL_LAR, f, ## a) +#define IWL_DEBUG_FW_INFO(p, f, a...) \ + IWL_DEBUG(p, IWL_DL_INFO | IWL_DL_FW, f, ## a) #endif diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 689a65b11cc3..852d3cbfc719 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -179,6 +179,7 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv) kfree(drv->fw.dbg.trigger_tlv[i]); kfree(drv->fw.dbg.mem_tlv); kfree(drv->fw.iml); + kfree(drv->fw.ucode_capa.cmd_versions); for (i = 0; i < IWL_UCODE_TYPE_MAX; i++) iwl_free_fw_img(drv, drv->fw.img + i); @@ -252,8 +253,8 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) snprintf(drv->firmware_name, sizeof(drv->firmware_name), "%s%s.ucode", cfg->fw_name_pre, tag); - IWL_DEBUG_INFO(drv, "attempting to load firmware '%s'\n", - drv->firmware_name); + IWL_DEBUG_FW_INFO(drv, "attempting to load firmware '%s'\n", + drv->firmware_name); return request_firmware_nowait(THIS_MODULE, 1, drv->firmware_name, drv->trans->dev, @@ -1144,6 +1145,23 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, if (iwlwifi_mod_params.enable_ini) iwl_fw_dbg_copy_tlv(drv->trans, tlv, false); break; + case IWL_UCODE_TLV_CMD_VERSIONS: + if (tlv_len % sizeof(struct iwl_fw_cmd_version)) { + IWL_ERR(drv, + "Invalid length for command versions: %u\n", + tlv_len); + tlv_len /= sizeof(struct iwl_fw_cmd_version); + tlv_len *= sizeof(struct iwl_fw_cmd_version); + } + if (WARN_ON(capa->cmd_versions)) + return -EINVAL; + capa->cmd_versions = kmemdup(tlv_data, tlv_len, + GFP_KERNEL); + if (!capa->cmd_versions) + return -ENOMEM; + capa->n_cmd_versions = + tlv_len / sizeof(struct iwl_fw_cmd_version); + break; default: IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); break; @@ -1318,8 +1336,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) if (!ucode_raw) goto try_again; - IWL_DEBUG_INFO(drv, "Loaded firmware file '%s' (%zd bytes).\n", - drv->firmware_name, ucode_raw->size); + IWL_DEBUG_FW_INFO(drv, "Loaded firmware file '%s' (%zd bytes).\n", + drv->firmware_name, ucode_raw->size); /* Make sure that we got at least the API version number */ if (ucode_raw->size < 4) { diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 87d6de7efdd2..d87a6bb3e456 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -130,7 +130,7 @@ enum nvm_sku_bits { /* * These are the channel numbers in the order that they are stored in the NVM */ -static const u8 iwl_nvm_channels[] = { +static const u16 iwl_nvm_channels[] = { /* 2.4 GHz */ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 5 GHz */ @@ -139,7 +139,7 @@ static const u8 iwl_nvm_channels[] = { 149, 153, 157, 161, 165 }; -static const u8 iwl_ext_nvm_channels[] = { +static const u16 iwl_ext_nvm_channels[] = { /* 2.4 GHz */ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 5 GHz */ @@ -148,14 +148,27 @@ static const u8 iwl_ext_nvm_channels[] = { 149, 153, 157, 161, 165, 169, 173, 177, 181 }; +static const u16 iwl_uhb_nvm_channels[] = { + /* 2.4 GHz */ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + /* 5 GHz */ + 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, + 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, + 149, 153, 157, 161, 165, 169, 173, 177, 181, + /* 6-7 GHz */ + 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 237, 241, + 245, 249, 253, 257, 261, 265, 269, 273, 277, 281, 285, 289, 293, 297, + 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, + 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, + 413, 417, 421 +}; + #define IWL_NVM_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels) #define IWL_NVM_NUM_CHANNELS_EXT ARRAY_SIZE(iwl_ext_nvm_channels) +#define IWL_NVM_NUM_CHANNELS_UHB ARRAY_SIZE(iwl_uhb_nvm_channels) #define NUM_2GHZ_CHANNELS 14 -#define NUM_2GHZ_CHANNELS_EXT 14 #define FIRST_2GHZ_HT_MINUS 5 #define LAST_2GHZ_HT_PLUS 9 -#define LAST_5GHZ_HT 165 -#define LAST_5GHZ_HT_FAMILY_8000 181 #define N_HW_ADDR_MASK 0xF /* rate data (static) */ @@ -213,7 +226,7 @@ enum iwl_nvm_channel_flags { }; static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level, - int chan, u16 flags) + int chan, u32 flags) { #define CHECK_AND_PRINT_I(x) \ ((flags & NVM_CHANNEL_##x) ? " " #x : "") @@ -244,20 +257,16 @@ static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level, } static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz, - u16 nvm_flags, const struct iwl_cfg *cfg) + u32 nvm_flags, const struct iwl_cfg *cfg) { u32 flags = IEEE80211_CHAN_NO_HT40; - u32 last_5ghz_ht = LAST_5GHZ_HT; - - if (cfg->nvm_type == IWL_NVM_EXT) - last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000; if (!is_5ghz && (nvm_flags & NVM_CHANNEL_40MHZ)) { if (ch_num <= LAST_2GHZ_HT_PLUS) flags &= ~IEEE80211_CHAN_NO_HT40PLUS; if (ch_num >= FIRST_2GHZ_HT_MINUS) flags &= ~IEEE80211_CHAN_NO_HT40MINUS; - } else if (ch_num <= last_5ghz_ht && (nvm_flags & NVM_CHANNEL_40MHZ)) { + } else if (nvm_flags & NVM_CHANNEL_40MHZ) { if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0) flags &= ~IEEE80211_CHAN_NO_HT40PLUS; else @@ -292,30 +301,36 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz, static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, struct iwl_nvm_data *data, - const __le16 * const nvm_ch_flags, - u32 sbands_flags) + const void * const nvm_ch_flags, + u32 sbands_flags, bool v4) { int ch_idx; int n_channels = 0; struct ieee80211_channel *channel; - u16 ch_flags; - int num_of_ch, num_2ghz_channels; - const u8 *nvm_chan; - - if (cfg->nvm_type != IWL_NVM_EXT) { - num_of_ch = IWL_NVM_NUM_CHANNELS; - nvm_chan = &iwl_nvm_channels[0]; - num_2ghz_channels = NUM_2GHZ_CHANNELS; - } else { + u32 ch_flags; + int num_of_ch, num_2ghz_channels = NUM_2GHZ_CHANNELS; + const u16 *nvm_chan; + + if (cfg->uhb_supported) { + num_of_ch = IWL_NVM_NUM_CHANNELS_UHB; + nvm_chan = iwl_uhb_nvm_channels; + } else if (cfg->nvm_type == IWL_NVM_EXT) { num_of_ch = IWL_NVM_NUM_CHANNELS_EXT; - nvm_chan = &iwl_ext_nvm_channels[0]; - num_2ghz_channels = NUM_2GHZ_CHANNELS_EXT; + nvm_chan = iwl_ext_nvm_channels; + } else { + num_of_ch = IWL_NVM_NUM_CHANNELS; + nvm_chan = iwl_nvm_channels; } for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) { bool is_5ghz = (ch_idx >= num_2ghz_channels); - ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx); + if (v4) + ch_flags = + __le32_to_cpup((__le32 *)nvm_ch_flags + ch_idx); + else + ch_flags = + __le16_to_cpup((__le16 *)nvm_ch_flags + ch_idx); if (is_5ghz && !data->sku_cap_band_52ghz_enable) continue; @@ -636,12 +651,7 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = { static void iwl_init_he_hw_capab(struct ieee80211_supported_band *sband, u8 tx_chains, u8 rx_chains) { - if (sband->band == NL80211_BAND_2GHZ || - sband->band == NL80211_BAND_5GHZ) - sband->iftype_data = iwl_he_capa; - else - return; - + sband->iftype_data = iwl_he_capa; sband->n_iftype_data = ARRAY_SIZE(iwl_he_capa); /* If not 2x2, we need to indicate 1x1 in the Midamble RX Max NSTS */ @@ -661,15 +671,15 @@ static void iwl_init_he_hw_capab(struct ieee80211_supported_band *sband, static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, struct iwl_nvm_data *data, - const __le16 *nvm_ch_flags, u8 tx_chains, - u8 rx_chains, u32 sbands_flags) + const void *nvm_ch_flags, u8 tx_chains, + u8 rx_chains, u32 sbands_flags, bool v4) { int n_channels; int n_used = 0; struct ieee80211_supported_band *sband; n_channels = iwl_init_channel_map(dev, cfg, data, nvm_ch_flags, - sbands_flags); + sbands_flags, v4); sband = &data->bands[NL80211_BAND_2GHZ]; sband->band = NL80211_BAND_2GHZ; sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; @@ -1006,22 +1016,18 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg, sbands_flags |= IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ; iwl_init_sbands(dev, cfg, data, ch_section, tx_chains, rx_chains, - sbands_flags); + sbands_flags, false); data->calib_version = 255; return data; } IWL_EXPORT_SYMBOL(iwl_parse_nvm_data); -static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan, +static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan, int ch_idx, u16 nvm_flags, const struct iwl_cfg *cfg) { u32 flags = NL80211_RRF_NO_HT40; - u32 last_5ghz_ht = LAST_5GHZ_HT; - - if (cfg->nvm_type == IWL_NVM_EXT) - last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000; if (ch_idx < NUM_2GHZ_CHANNELS && (nvm_flags & NVM_CHANNEL_40MHZ)) { @@ -1029,8 +1035,7 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan, flags &= ~NL80211_RRF_NO_HT40PLUS; if (nvm_chan[ch_idx] >= FIRST_2GHZ_HT_MINUS) flags &= ~NL80211_RRF_NO_HT40MINUS; - } else if (nvm_chan[ch_idx] <= last_5ghz_ht && - (nvm_flags & NVM_CHANNEL_40MHZ)) { + } else if (nvm_flags & NVM_CHANNEL_40MHZ) { if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0) flags &= ~NL80211_RRF_NO_HT40PLUS; else @@ -1074,18 +1079,26 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, int ch_idx; u16 ch_flags; u32 reg_rule_flags, prev_reg_rule_flags = 0; - const u8 *nvm_chan = cfg->nvm_type == IWL_NVM_EXT ? - iwl_ext_nvm_channels : iwl_nvm_channels; + const u16 *nvm_chan; struct ieee80211_regdomain *regd, *copy_rd; - int size_of_regd, regd_to_copy; struct ieee80211_reg_rule *rule; struct regdb_ptrs *regdb_ptrs; enum nl80211_band band; int center_freq, prev_center_freq = 0; int valid_rules = 0; bool new_rule; - int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ? - IWL_NVM_NUM_CHANNELS_EXT : IWL_NVM_NUM_CHANNELS; + int max_num_ch; + + if (cfg->uhb_supported) { + max_num_ch = IWL_NVM_NUM_CHANNELS_UHB; + nvm_chan = iwl_uhb_nvm_channels; + } else if (cfg->nvm_type == IWL_NVM_EXT) { + max_num_ch = IWL_NVM_NUM_CHANNELS_EXT; + nvm_chan = iwl_ext_nvm_channels; + } else { + max_num_ch = IWL_NVM_NUM_CHANNELS; + nvm_chan = iwl_nvm_channels; + } if (WARN_ON(num_of_ch > max_num_ch)) num_of_ch = max_num_ch; @@ -1097,11 +1110,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, num_of_ch); /* build a regdomain rule for every valid channel */ - size_of_regd = - sizeof(struct ieee80211_regdomain) + - num_of_ch * sizeof(struct ieee80211_reg_rule); - - regd = kzalloc(size_of_regd, GFP_KERNEL); + regd = kzalloc(struct_size(regd, reg_rules, num_of_ch), GFP_KERNEL); if (!regd) return ERR_PTR(-ENOMEM); @@ -1177,14 +1186,10 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, * Narrow down regdom for unused regulatory rules to prevent hole * between reg rules to wmm rules. */ - regd_to_copy = sizeof(struct ieee80211_regdomain) + - valid_rules * sizeof(struct ieee80211_reg_rule); - - copy_rd = kmemdup(regd, regd_to_copy, GFP_KERNEL); - if (!copy_rd) { + copy_rd = kmemdup(regd, struct_size(regd, reg_rules, valid_rules), + GFP_KERNEL); + if (!copy_rd) copy_rd = ERR_PTR(-ENOMEM); - goto out; - } out: kfree(regdb_ptrs); @@ -1393,7 +1398,6 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, const struct iwl_fw *fw) { struct iwl_nvm_get_info cmd = {}; - struct iwl_nvm_get_info_rsp *rsp; struct iwl_nvm_data *nvm; struct iwl_host_cmd hcmd = { .flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL, @@ -1408,12 +1412,24 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, bool empty_otp; u32 mac_flags; u32 sbands_flags = 0; + /* + * All the values in iwl_nvm_get_info_rsp v4 are the same as + * in v3, except for the channel profile part of the + * regulatory. So we can just access the new struct, with the + * exception of the latter. + */ + struct iwl_nvm_get_info_rsp *rsp; + struct iwl_nvm_get_info_rsp_v3 *rsp_v3; + bool v4 = fw_has_api(&fw->ucode_capa, + IWL_UCODE_TLV_API_REGULATORY_NVM_INFO); + size_t rsp_size = v4 ? sizeof(*rsp) : sizeof(*rsp_v3); + void *channel_profile; ret = iwl_trans_send_cmd(trans, &hcmd); if (ret) return ERR_PTR(ret); - if (WARN(iwl_rx_packet_payload_len(hcmd.resp_pkt) != sizeof(*rsp), + if (WARN(iwl_rx_packet_payload_len(hcmd.resp_pkt) != rsp_size, "Invalid payload len in NVM response from FW %d", iwl_rx_packet_payload_len(hcmd.resp_pkt))) { ret = -EINVAL; @@ -1475,11 +1491,15 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, sbands_flags |= IWL_NVM_SBANDS_FLAGS_LAR; } + rsp_v3 = (void *)rsp; + channel_profile = v4 ? (void *)rsp->regulatory.channel_profile : + (void *)rsp_v3->regulatory.channel_profile; + iwl_init_sbands(trans->dev, trans->cfg, nvm, - rsp->regulatory.channel_profile, + channel_profile, nvm->valid_tx_ant & fw->valid_tx_ant, nvm->valid_rx_ant & fw->valid_rx_ant, - sbands_flags); + sbands_flags, v4); iwl_free_resp(&hcmd); return nvm; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index 1af9f9e1ecd4..8e6a0c363c0d 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h @@ -368,6 +368,12 @@ #define MON_BUFF_WRPTR_VER2 (0xa03c24) #define MON_BUFF_CYCLE_CNT_VER2 (0xa03c28) #define MON_BUFF_SHIFT_VER2 (0x8) +/* FW monitor familiy AX210 and on */ +#define DBGC_CUR_DBGBUF_BASE_ADDR_LSB (0xd03c20) +#define DBGC_CUR_DBGBUF_BASE_ADDR_MSB (0xd03c24) +#define DBGC_CUR_DBGBUF_STATUS (0xd03c1c) +#define DBGC_DBGBUF_WRAP_AROUND (0xd03c2c) +#define DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK (0x00ffffff) #define MON_DMARB_RD_CTL_ADDR (0xa03c60) #define MON_DMARB_RD_DATA_ADDR (0xa03c5c) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index bbebbf3efd57..1e4c9ef548cc 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -274,7 +274,6 @@ struct iwl_rx_cmd_buffer { bool _page_stolen; u32 _rx_page_order; unsigned int truesize; - u8 status; }; static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r) @@ -338,7 +337,6 @@ enum iwl_d3_status { * are sent * @STATUS_TRANS_IDLE: the trans is idle - general commands are not to be sent * @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation - * @STATUS_FW_WAIT_DUMP: if set, wait until cleared before collecting dump */ enum iwl_trans_status { STATUS_SYNC_HCMD_ACTIVE, @@ -351,7 +349,6 @@ enum iwl_trans_status { STATUS_TRANS_GOING_IDLE, STATUS_TRANS_IDLE, STATUS_TRANS_DEAD, - STATUS_FW_WAIT_DUMP, }; static inline int @@ -618,6 +615,7 @@ struct iwl_trans_ops { struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans, u32 dump_mask); void (*debugfs_cleanup)(struct iwl_trans *trans); + void (*sync_nmi)(struct iwl_trans *trans); }; /** @@ -769,6 +767,7 @@ struct iwl_self_init_dram { * @umac_error_event_table: addr of umac error table * @error_event_table_tlv_status: bitmap that indicates what error table * pointers was recevied via TLV. use enum &iwl_error_event_table_status + * @hw_error: equals true if hw error interrupt was received from the FW */ struct iwl_trans { const struct iwl_trans_ops *ops; @@ -831,7 +830,7 @@ struct iwl_trans { u32 lmac_error_event_table[2]; u32 umac_error_event_table; unsigned int error_event_table_tlv_status; - wait_queue_head_t fw_halt_waitq; + bool hw_error; /* pointer to trans specific struct */ /*Ensure that this pointer will always be aligned to sizeof pointer */ @@ -1239,10 +1238,12 @@ static inline void iwl_trans_fw_error(struct iwl_trans *trans) /* prevent double restarts due to the same erroneous FW */ if (!test_and_set_bit(STATUS_FW_ERROR, &trans->status)) iwl_op_mode_nic_error(trans->op_mode); +} - if (test_and_clear_bit(STATUS_FW_WAIT_DUMP, &trans->status)) - wake_up(&trans->fw_halt_waitq); - +static inline void iwl_trans_sync_nmi(struct iwl_trans *trans) +{ + if (trans->ops->sync_nmi) + trans->ops->sync_nmi(trans); } /***************************************************** diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 808bc6f363d0..60f5d337f16d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -385,10 +385,10 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, } } -static int iwl_mvm_send_patterns(struct iwl_mvm *mvm, - struct cfg80211_wowlan *wowlan) +static int iwl_mvm_send_patterns_v1(struct iwl_mvm *mvm, + struct cfg80211_wowlan *wowlan) { - struct iwl_wowlan_patterns_cmd *pattern_cmd; + struct iwl_wowlan_patterns_cmd_v1 *pattern_cmd; struct iwl_host_cmd cmd = { .id = WOWLAN_PATTERNS, .dataflags[0] = IWL_HCMD_DFL_NOCOPY, @@ -399,7 +399,7 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm, return 0; cmd.len[0] = sizeof(*pattern_cmd) + - wowlan->n_patterns * sizeof(struct iwl_wowlan_pattern); + wowlan->n_patterns * sizeof(struct iwl_wowlan_pattern_v1); pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL); if (!pattern_cmd) @@ -426,6 +426,50 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm, return err; } +static int iwl_mvm_send_patterns(struct iwl_mvm *mvm, + struct cfg80211_wowlan *wowlan) +{ + struct iwl_wowlan_patterns_cmd *pattern_cmd; + struct iwl_host_cmd cmd = { + .id = WOWLAN_PATTERNS, + .dataflags[0] = IWL_HCMD_DFL_NOCOPY, + }; + int i, err; + + if (!wowlan->n_patterns) + return 0; + + cmd.len[0] = sizeof(*pattern_cmd) + + wowlan->n_patterns * sizeof(struct iwl_wowlan_pattern_v2); + + pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL); + if (!pattern_cmd) + return -ENOMEM; + + pattern_cmd->n_patterns = cpu_to_le32(wowlan->n_patterns); + + for (i = 0; i < wowlan->n_patterns; i++) { + int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8); + + pattern_cmd->patterns[i].pattern_type = + WOWLAN_PATTERN_TYPE_BITMASK; + + memcpy(&pattern_cmd->patterns[i].u.bitmask.mask, + wowlan->patterns[i].mask, mask_len); + memcpy(&pattern_cmd->patterns[i].u.bitmask.pattern, + wowlan->patterns[i].pattern, + wowlan->patterns[i].pattern_len); + pattern_cmd->patterns[i].u.bitmask.mask_size = mask_len; + pattern_cmd->patterns[i].u.bitmask.pattern_size = + wowlan->patterns[i].pattern_len; + } + + cmd.data[0] = pattern_cmd; + err = iwl_mvm_send_cmd(mvm, &cmd); + kfree(pattern_cmd); + return err; +} + static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *ap_sta) { @@ -851,7 +895,11 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm, if (ret) return ret; - ret = iwl_mvm_send_patterns(mvm, wowlan); + if (fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE)) + ret = iwl_mvm_send_patterns(mvm, wowlan); + else + ret = iwl_mvm_send_patterns_v1(mvm, wowlan); if (ret) return ret; @@ -1728,9 +1776,12 @@ void iwl_mvm_d0i3_update_keys(struct iwl_mvm *mvm, iwl_mvm_iter_d0i3_ap_keys(mvm, vif, iwl_mvm_d3_update_keys, >kdata); } +#define ND_QUERY_BUF_LEN (sizeof(struct iwl_scan_offload_profile_match) * \ + IWL_SCAN_MAX_PROFILES) + struct iwl_mvm_nd_query_results { u32 matched_profiles; - struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES]; + u8 matches[ND_QUERY_BUF_LEN]; }; static int @@ -1743,6 +1794,7 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm, .flags = CMD_WANT_SKB, }; int ret, len; + size_t query_len, matches_len; ret = iwl_mvm_send_cmd(mvm, &cmd); if (ret) { @@ -1750,8 +1802,19 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm, return ret; } + if (fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) { + query_len = sizeof(struct iwl_scan_offload_profiles_query); + matches_len = sizeof(struct iwl_scan_offload_profile_match) * + IWL_SCAN_MAX_PROFILES; + } else { + query_len = sizeof(struct iwl_scan_offload_profiles_query_v1); + matches_len = sizeof(struct iwl_scan_offload_profile_match_v1) * + IWL_SCAN_MAX_PROFILES; + } + len = iwl_rx_packet_payload_len(cmd.resp_pkt); - if (len < sizeof(*query)) { + if (len < query_len) { IWL_ERR(mvm, "Invalid scan offload profiles query response!\n"); ret = -EIO; goto out_free_resp; @@ -1760,7 +1823,7 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm, query = (void *)cmd.resp_pkt->data; results->matched_profiles = le32_to_cpu(query->matched_profiles); - memcpy(results->matches, query->matches, sizeof(results->matches)); + memcpy(results->matches, query->matches, matches_len); #ifdef CONFIG_IWLWIFI_DEBUGFS mvm->last_netdetect_scans = le32_to_cpu(query->n_scans_done); @@ -1771,6 +1834,57 @@ out_free_resp: return ret; } +static int iwl_mvm_query_num_match_chans(struct iwl_mvm *mvm, + struct iwl_mvm_nd_query_results *query, + int idx) +{ + int n_chans = 0, i; + + if (fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) { + struct iwl_scan_offload_profile_match *matches = + (struct iwl_scan_offload_profile_match *)query->matches; + + for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; i++) + n_chans += hweight8(matches[idx].matching_channels[i]); + } else { + struct iwl_scan_offload_profile_match_v1 *matches = + (struct iwl_scan_offload_profile_match_v1 *)query->matches; + + for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1; i++) + n_chans += hweight8(matches[idx].matching_channels[i]); + } + + return n_chans; +} + +static void iwl_mvm_query_set_freqs(struct iwl_mvm *mvm, + struct iwl_mvm_nd_query_results *query, + struct cfg80211_wowlan_nd_match *match, + int idx) +{ + int i; + + if (fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) { + struct iwl_scan_offload_profile_match *matches = + (struct iwl_scan_offload_profile_match *)query->matches; + + for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8; i++) + if (matches[idx].matching_channels[i / 8] & (BIT(i % 8))) + match->channels[match->n_channels++] = + mvm->nd_channels[i]->center_freq; + } else { + struct iwl_scan_offload_profile_match_v1 *matches = + (struct iwl_scan_offload_profile_match_v1 *)query->matches; + + for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1 * 8; i++) + if (matches[idx].matching_channels[i / 8] & (BIT(i % 8))) + match->channels[match->n_channels++] = + mvm->nd_channels[i]->center_freq; + } +} + static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { @@ -1783,7 +1897,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm, struct iwl_wowlan_status *fw_status; unsigned long matched_profiles; u32 reasons = 0; - int i, j, n_matches, ret; + int i, n_matches, ret; fw_status = iwl_mvm_get_wakeup_status(mvm); if (!IS_ERR_OR_NULL(fw_status)) { @@ -1817,14 +1931,10 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm, goto out_report_nd; for_each_set_bit(i, &matched_profiles, mvm->n_nd_match_sets) { - struct iwl_scan_offload_profile_match *fw_match; struct cfg80211_wowlan_nd_match *match; int idx, n_channels = 0; - fw_match = &query.matches[i]; - - for (j = 0; j < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; j++) - n_channels += hweight8(fw_match->matching_channels[j]); + n_channels = iwl_mvm_query_num_match_chans(mvm, &query, i); match = kzalloc(struct_size(match, channels, n_channels), GFP_KERNEL); @@ -1844,10 +1954,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm, if (mvm->n_nd_channels < n_channels) continue; - for (j = 0; j < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8; j++) - if (fw_match->matching_channels[j / 8] & (BIT(j % 8))) - match->channels[match->n_channels++] = - mvm->nd_channels[j]->center_freq; + iwl_mvm_query_set_freqs(mvm, &query, match, i); } out_report_nd: @@ -2030,7 +2137,6 @@ out: * 2. We are using a unified image but had an error while exiting D3 */ set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status); - set_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status); /* * When switching images we return 1, which causes mac80211 * to do a reconfig with IEEE80211_RECONFIG_TYPE_RESTART. diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c index 2453ceabf00d..f043eefabb4e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c @@ -743,9 +743,8 @@ static ssize_t iwl_dbgfs_quota_min_read(struct file *file, #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif) #define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \ - if (!debugfs_create_file(#name, mode, parent, vif, \ - &iwl_dbgfs_##name##_ops)) \ - goto err; \ + debugfs_create_file(#name, mode, parent, vif, \ + &iwl_dbgfs_##name##_ops); \ } while (0) MVM_DEBUGFS_READ_FILE_OPS(mac_params); @@ -774,8 +773,7 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) return; mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir); - - if (!mvmvif->dbgfs_dir) { + if (IS_ERR_OR_NULL(mvmvif->dbgfs_dir)) { IWL_ERR(mvm, "Failed to create debugfs directory under %pd\n", dbgfs_dir); return; @@ -812,12 +810,6 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name, mvm->debugfs_dir, buf); - if (!mvmvif->dbgfs_slink) - IWL_ERR(mvm, "Can't create debugfs symbolic link under %pd\n", - dbgfs_dir); - return; -err: - IWL_ERR(mvm, "Can't create debugfs entity\n"); } void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 776b24f54200..d4ff6b44de2c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1349,7 +1349,7 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm, return 0; iwl_fw_dbg_collect(&mvm->fwrt, FW_DBG_TRIGGER_USER, buf, - (count - 1)); + (count - 1), NULL); iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE); @@ -1696,9 +1696,8 @@ static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf, #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm) #define MVM_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do { \ - if (!debugfs_create_file(alias, mode, parent, mvm, \ - &iwl_dbgfs_##name##_ops)) \ - goto err; \ + debugfs_create_file(alias, mode, parent, mvm, \ + &iwl_dbgfs_##name##_ops); \ } while (0) #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \ MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode) @@ -1709,9 +1708,8 @@ static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf, _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_sta) #define MVM_DEBUGFS_ADD_STA_FILE_ALIAS(alias, name, parent, mode) do { \ - if (!debugfs_create_file(alias, mode, parent, sta, \ - &iwl_dbgfs_##name##_ops)) \ - goto err; \ + debugfs_create_file(alias, mode, parent, sta, \ + &iwl_dbgfs_##name##_ops); \ } while (0) #define MVM_DEBUGFS_ADD_STA_FILE(name, parent, mode) \ MVM_DEBUGFS_ADD_STA_FILE_ALIAS(#name, name, parent, mode) @@ -2092,13 +2090,9 @@ void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw, if (iwl_mvm_has_tlc_offload(mvm)) MVM_DEBUGFS_ADD_STA_FILE(rs_data, dir, 0400); - - return; -err: - IWL_ERR(mvm, "Can't create the mvm station debugfs entry\n"); } -int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) +void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) { struct dentry *bcast_dir __maybe_unused; char buf[100]; @@ -2142,14 +2136,10 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) #endif MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600); - if (!debugfs_create_bool("enable_scan_iteration_notif", - 0600, - mvm->debugfs_dir, - &mvm->scan_iter_notif_enabled)) - goto err; - if (!debugfs_create_bool("drop_bcn_ap_mode", 0600, - mvm->debugfs_dir, &mvm->drop_bcn_ap_mode)) - goto err; + debugfs_create_bool("enable_scan_iteration_notif", 0600, + mvm->debugfs_dir, &mvm->scan_iter_notif_enabled); + debugfs_create_bool("drop_bcn_ap_mode", 0600, mvm->debugfs_dir, + &mvm->drop_bcn_ap_mode); MVM_DEBUGFS_ADD_FILE(uapsd_noagg_bssids, mvm->debugfs_dir, S_IRUSR); @@ -2157,13 +2147,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) { bcast_dir = debugfs_create_dir("bcast_filtering", mvm->debugfs_dir); - if (!bcast_dir) - goto err; - if (!debugfs_create_bool("override", 0600, - bcast_dir, - &mvm->dbgfs_bcast_filtering.override)) - goto err; + debugfs_create_bool("override", 0600, bcast_dir, + &mvm->dbgfs_bcast_filtering.override); MVM_DEBUGFS_ADD_FILE_ALIAS("filters", bcast_filters, bcast_dir, 0600); @@ -2175,35 +2161,26 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) #ifdef CONFIG_PM_SLEEP MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, 0600); MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, 0400); - if (!debugfs_create_bool("d3_wake_sysassert", 0600, - mvm->debugfs_dir, &mvm->d3_wake_sysassert)) - goto err; - if (!debugfs_create_u32("last_netdetect_scans", 0400, - mvm->debugfs_dir, &mvm->last_netdetect_scans)) - goto err; + debugfs_create_bool("d3_wake_sysassert", 0600, mvm->debugfs_dir, + &mvm->d3_wake_sysassert); + debugfs_create_u32("last_netdetect_scans", 0400, mvm->debugfs_dir, + &mvm->last_netdetect_scans); #endif - if (!debugfs_create_u8("ps_disabled", 0400, - mvm->debugfs_dir, &mvm->ps_disabled)) - goto err; - if (!debugfs_create_blob("nvm_hw", 0400, - mvm->debugfs_dir, &mvm->nvm_hw_blob)) - goto err; - if (!debugfs_create_blob("nvm_sw", 0400, - mvm->debugfs_dir, &mvm->nvm_sw_blob)) - goto err; - if (!debugfs_create_blob("nvm_calib", 0400, - mvm->debugfs_dir, &mvm->nvm_calib_blob)) - goto err; - if (!debugfs_create_blob("nvm_prod", 0400, - mvm->debugfs_dir, &mvm->nvm_prod_blob)) - goto err; - if (!debugfs_create_blob("nvm_phy_sku", 0400, - mvm->debugfs_dir, &mvm->nvm_phy_sku_blob)) - goto err; - if (!debugfs_create_blob("nvm_reg", S_IRUSR, - mvm->debugfs_dir, &mvm->nvm_reg_blob)) - goto err; + debugfs_create_u8("ps_disabled", 0400, mvm->debugfs_dir, + &mvm->ps_disabled); + debugfs_create_blob("nvm_hw", 0400, mvm->debugfs_dir, + &mvm->nvm_hw_blob); + debugfs_create_blob("nvm_sw", 0400, mvm->debugfs_dir, + &mvm->nvm_sw_blob); + debugfs_create_blob("nvm_calib", 0400, mvm->debugfs_dir, + &mvm->nvm_calib_blob); + debugfs_create_blob("nvm_prod", 0400, mvm->debugfs_dir, + &mvm->nvm_prod_blob); + debugfs_create_blob("nvm_phy_sku", 0400, mvm->debugfs_dir, + &mvm->nvm_phy_sku_blob); + debugfs_create_blob("nvm_reg", S_IRUSR, + mvm->debugfs_dir, &mvm->nvm_reg_blob); debugfs_create_file("mem", 0600, dbgfs_dir, mvm, &iwl_dbgfs_mem_ops); @@ -2212,11 +2189,5 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) * exists (before the opmode exists which removes the target.) */ snprintf(buf, 100, "../../%pd2", dbgfs_dir->d_parent); - if (!debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir, buf)) - goto err; - - return 0; -err: - IWL_ERR(mvm, "Can't create the mvm debugfs directory\n"); - return -ENOMEM; + debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir, buf); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c index e9822a3ec373..fec38a47696e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c @@ -187,12 +187,24 @@ static void iwl_mvm_ftm_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, for (i = 0; i < ETH_ALEN; i++) cmd->macaddr_mask[i] = ~req->mac_addr_mask[i]; - if (vif->bss_conf.assoc) + if (vif->bss_conf.assoc) { memcpy(cmd->range_req_bssid, vif->bss_conf.bssid, ETH_ALEN); - else + + /* AP's TSF is only relevant if associated */ + for (i = 0; i < req->n_peers; i++) { + if (req->peers[i].report_ap_tsf) { + struct iwl_mvm_vif *mvmvif = + iwl_mvm_vif_from_mac80211(vif); + + cmd->tsf_mac_id = cpu_to_le32(mvmvif->id); + return; + } + } + } else { eth_broadcast_addr(cmd->range_req_bssid); + } - /* TODO: fill in tsf_mac_id if needed */ + /* Don't report AP's TSF */ cmd->tsf_mac_id = cpu_to_le32(0xff); } @@ -460,9 +472,7 @@ static int iwl_mvm_ftm_range_resp_valid(struct iwl_mvm *mvm, u8 request_id, static void iwl_mvm_debug_range_resp(struct iwl_mvm *mvm, u8 index, struct cfg80211_pmsr_result *res) { - s64 rtt_avg = res->ftm.rtt_avg * 100; - - do_div(rtt_avg, 6666); + s64 rtt_avg = div_s64(res->ftm.rtt_avg * 100, 6666); IWL_DEBUG_INFO(mvm, "entry %d\n", index); IWL_DEBUG_INFO(mvm, "\tstatus: %d\n", res->status); @@ -482,6 +492,7 @@ void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_tof_range_rsp_ntfy_v5 *fw_resp_v5 = (void *)pkt->data; + struct iwl_tof_range_rsp_ntfy_v6 *fw_resp_v6 = (void *)pkt->data; struct iwl_tof_range_rsp_ntfy *fw_resp = (void *)pkt->data; int i; bool new_api = fw_has_api(&mvm->fw->ucode_capa, @@ -521,8 +532,15 @@ void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) int peer_idx; if (new_api) { - fw_ap = &fw_resp->ap[i]; + if (fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_FTM_RTT_ACCURACY)) + fw_ap = &fw_resp->ap[i]; + else + fw_ap = (void *)&fw_resp_v6->ap[i]; + result.final = fw_resp->ap[i].last_burst; + result.ap_tsf = le32_to_cpu(fw_ap->start_tsf); + result.ap_tsf_valid = 1; } else { /* the first part is the same for old and new APIs */ fw_ap = (void *)&fw_resp_v5->ap[i]; @@ -590,6 +608,11 @@ void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) mvm->ftm_initiator.req, &result, GFP_KERNEL); + if (fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_FTM_RTT_ACCURACY)) + IWL_DEBUG_INFO(mvm, "RTT confidence: %hhu\n", + fw_ap->rttConfidence); + iwl_mvm_debug_range_resp(mvm, i, &result); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 00a47f6f1d81..ab68b5d53ec9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -1121,7 +1121,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm) ret = iwl_mvm_load_rt_fw(mvm); if (ret) { IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret); - iwl_fw_dbg_error_collect(&mvm->fwrt, FW_DBG_TRIGGER_DRIVER); + if (ret != -ERFKILL) + iwl_fw_dbg_error_collect(&mvm->fwrt, + FW_DBG_TRIGGER_DRIVER); goto error; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 6a70dece447d..53c217af13c8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -262,9 +262,7 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) .preferred_tsf = NUM_TSF_IDS, .found_vif = false, }; - u32 ac; - int ret, i, queue_limit; - unsigned long used_hw_queues; + int ret, i; lockdep_assert_held(&mvm->mutex); @@ -341,37 +339,9 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) INIT_LIST_HEAD(&mvmvif->time_event_data.list); mvmvif->time_event_data.id = TE_MAX; - /* No need to allocate data queues to P2P Device MAC.*/ - if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) - vif->hw_queue[ac] = IEEE80211_INVAL_HW_QUEUE; - + /* No need to allocate data queues to P2P Device MAC and NAN.*/ + if (vif->type == NL80211_IFTYPE_P2P_DEVICE) return 0; - } - - /* - * queues in mac80211 almost entirely independent of - * the ones here - no real limit - */ - queue_limit = IEEE80211_MAX_QUEUES; - - /* - * Find available queues, and allocate them to the ACs. When in - * DQA-mode they aren't really used, and this is done only so the - * mac80211 ieee80211_check_queues() function won't fail - */ - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { - u8 queue = find_first_zero_bit(&used_hw_queues, queue_limit); - - if (queue >= queue_limit) { - IWL_ERR(mvm, "Failed to allocate queue\n"); - ret = -EIO; - goto exit_fail; - } - - __set_bit(queue, &used_hw_queues); - vif->hw_queue[ac] = queue; - } /* Allocate the CAB queue for softAP and GO interfaces */ if (vif->type == NL80211_IFTYPE_AP || @@ -1143,9 +1113,7 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm, ieee80211_tu_to_usec(data.beacon_int * rand / 100); } else { - mvmvif->ap_beacon_time = - iwl_read_prph(mvm->trans, - DEVICE_SYSTEM_TIME_REG); + mvmvif->ap_beacon_time = iwl_mvm_get_systime(mvm); } } @@ -1573,6 +1541,7 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm, rcu_read_lock(); vif = rcu_dereference(mvm->vif_id_to_mac[mac_id]); + mvmvif = iwl_mvm_vif_from_mac80211(vif); switch (vif->type) { case NL80211_IFTYPE_AP: @@ -1581,7 +1550,6 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm, csa_vif != vif)) goto out_unlock; - mvmvif = iwl_mvm_vif_from_mac80211(csa_vif); csa_id = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color); if (WARN(csa_id != id_n_color, "channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)", @@ -1602,6 +1570,7 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm, return; case NL80211_IFTYPE_STATION: iwl_mvm_csa_client_absent(mvm, vif); + cancel_delayed_work(&mvmvif->csa_work); ieee80211_chswitch_done(vif, true); break; default: diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 3a92c09d4692..5c52469288be 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -420,6 +420,7 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm) const static u8 he_if_types_ext_capa_sta[] = { [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING, + [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT, [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF, [9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT, }; @@ -597,6 +598,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; + wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS); + hw->wiphy->features |= NL80211_FEATURE_HT_IBSS; + hw->wiphy->regulatory_flags |= REGULATORY_ENABLE_RELAX_NO_IR; if (iwl_mvm_is_lar_supported(mvm)) hw->wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED; @@ -732,6 +736,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) hw->wiphy->iftype_ext_capab = he_iftypes_ext_capa; hw->wiphy->num_iftype_ext_capab = ARRAY_SIZE(he_iftypes_ext_capa); + + ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); + ieee80211_hw_set(hw, SUPPORTS_ONLY_HE_MULTI_BSSID); } mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; @@ -1191,15 +1198,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) { - /* clear the D3 reconfig, we only need it to avoid dumping a - * firmware coredump on reconfiguration, we shouldn't do that - * on D3->D0 transition - */ - if (!test_and_clear_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status)) { - mvm->fwrt.dump.desc = &iwl_dump_desc_assert; - iwl_fw_error_dump(&mvm->fwrt); - } - /* cleanup all stale references (scan, roc), but keep the * ucode_down ref until reconfig is complete */ @@ -1500,6 +1498,91 @@ static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd); } +static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + int ret; + + mutex_lock(&mvm->mutex); + + if (mvmvif->csa_failed) { + mvmvif->csa_failed = false; + ret = -EIO; + goto out_unlock; + } + + if (vif->type == NL80211_IFTYPE_STATION) { + struct iwl_mvm_sta *mvmsta; + + mvmvif->csa_bcn_pending = false; + mvmsta = iwl_mvm_sta_from_staid_protected(mvm, + mvmvif->ap_sta_id); + + if (WARN_ON(!mvmsta)) { + ret = -EIO; + goto out_unlock; + } + + iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false); + + iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); + + ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0); + if (ret) + goto out_unlock; + + iwl_mvm_stop_session_protection(mvm, vif); + } + + mvmvif->ps_disabled = false; + + ret = iwl_mvm_power_update_ps(mvm); + +out_unlock: + mutex_unlock(&mvm->mutex); + + return ret; +} + +static void iwl_mvm_abort_channel_switch(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_chan_switch_te_cmd cmd = { + .mac_id = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, + mvmvif->color)), + .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE), + }; + + IWL_DEBUG_MAC80211(mvm, "Abort CSA on mac %d\n", mvmvif->id); + + mutex_lock(&mvm->mutex); + WARN_ON(iwl_mvm_send_cmd_pdu(mvm, + WIDE_ID(MAC_CONF_GROUP, + CHANNEL_SWITCH_TIME_EVENT_CMD), + 0, sizeof(cmd), &cmd)); + mutex_unlock(&mvm->mutex); + + WARN_ON(iwl_mvm_post_channel_switch(hw, vif)); +} + +static void iwl_mvm_channel_switch_disconnect_wk(struct work_struct *wk) +{ + struct iwl_mvm *mvm; + struct iwl_mvm_vif *mvmvif; + struct ieee80211_vif *vif; + + mvmvif = container_of(wk, struct iwl_mvm_vif, csa_work.work); + vif = container_of((void *)mvmvif, struct ieee80211_vif, drv_priv); + mvm = mvmvif->mvm; + + iwl_mvm_abort_channel_switch(mvm->hw, vif); + ieee80211_chswitch_done(vif, false); +} + static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -1626,6 +1709,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, } iwl_mvm_tcm_add_vif(mvm, vif); + INIT_DELAYED_WORK(&mvmvif->csa_work, + iwl_mvm_channel_switch_disconnect_wk); if (vif->type == NL80211_IFTYPE_MONITOR) mvm->monitor_on = true; @@ -2127,6 +2212,10 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm, .frame_time_rts_th = cpu_to_le16(vif->bss_conf.frame_time_rts_th), }; + int size = fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_MBSSID_HE) ? + sizeof(sta_ctxt_cmd) : + sizeof(struct iwl_he_sta_context_cmd_v1); struct ieee80211_sta *sta; u32 flags; int i; @@ -2254,16 +2343,18 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm, /* Set the PPE thresholds accordingly */ if (low_th >= 0 && high_th >= 0) { - u8 ***pkt_ext_qam = - (void *)sta_ctxt_cmd.pkt_ext.pkt_ext_qam_th; + struct iwl_he_pkt_ext *pkt_ext = + (struct iwl_he_pkt_ext *)&sta_ctxt_cmd.pkt_ext; for (i = 0; i < MAX_HE_SUPP_NSS; i++) { u8 bw; for (bw = 0; bw < MAX_HE_CHANNEL_BW_INDX; bw++) { - pkt_ext_qam[i][bw][0] = low_th; - pkt_ext_qam[i][bw][1] = high_th; + pkt_ext->pkt_ext_qam_th[i][bw][0] = + low_th; + pkt_ext->pkt_ext_qam_th[i][bw][1] = + high_th; } } @@ -2308,13 +2399,23 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm, (vif->bss_conf.uora_ocw_range >> 3) & 0x7; } - /* TODO: support Multi BSSID IE */ + if (vif->bss_conf.nontransmitted) { + flags |= STA_CTXT_HE_REF_BSSID_VALID; + ether_addr_copy(sta_ctxt_cmd.ref_bssid_addr, + vif->bss_conf.transmitter_bssid); + sta_ctxt_cmd.max_bssid_indicator = + vif->bss_conf.bssid_indicator; + sta_ctxt_cmd.bssid_index = vif->bss_conf.bssid_index; + sta_ctxt_cmd.ema_ap = vif->bss_conf.ema_ap; + sta_ctxt_cmd.profile_periodicity = + vif->bss_conf.profile_periodicity; + } sta_ctxt_cmd.flags = cpu_to_le32(flags); if (iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(STA_HE_CTXT_CMD, DATA_PATH_GROUP, 0), - 0, sizeof(sta_ctxt_cmd), &sta_ctxt_cmd)) + 0, size, &sta_ctxt_cmd)) IWL_ERR(mvm, "Failed to config FW to work HE!\n"); } @@ -2714,9 +2815,6 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw, iwl_mvm_mac_ctxt_remove(mvm, vif); - kfree(mvmvif->ap_wep_key); - mvmvif->ap_wep_key = NULL; - mutex_unlock(&mvm->mutex); } @@ -3183,24 +3281,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, ret = iwl_mvm_update_sta(mvm, vif, sta); } else if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTHORIZED) { - /* if wep is used, need to set the key for the station now */ - if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key) { - mvm_sta->wep_key = - kmemdup(mvmvif->ap_wep_key, - sizeof(*mvmvif->ap_wep_key) + - mvmvif->ap_wep_key->keylen, - GFP_KERNEL); - if (!mvm_sta->wep_key) { - ret = -ENOMEM; - goto out_unlock; - } - - ret = iwl_mvm_set_sta_key(mvm, vif, sta, - mvm_sta->wep_key, - STA_KEY_IDX_INVALID); - } else { - ret = 0; - } + ret = 0; /* we don't support TDLS during DCM */ if (iwl_mvm_phy_ctx_count(mvm) > 1) @@ -3242,17 +3323,6 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, NL80211_TDLS_DISABLE_LINK); } - /* Remove STA key if this is an AP using WEP */ - if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key) { - int rm_ret = iwl_mvm_remove_sta_key(mvm, vif, sta, - mvm_sta->wep_key); - - if (!ret) - ret = rm_ret; - kfree(mvm_sta->wep_key); - mvm_sta->wep_key = NULL; - } - if (unlikely(ret && test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status))) @@ -3289,6 +3359,13 @@ static void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u32 changed) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + + if (changed & (IEEE80211_RC_BW_CHANGED | + IEEE80211_RC_SUPP_RATES_CHANGED | + IEEE80211_RC_NSS_CHANGED)) + iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band, + true); if (vif->type == NL80211_IFTYPE_STATION && changed & IEEE80211_RC_NSS_CHANGED) @@ -3439,20 +3516,12 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, break; case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: - if (vif->type == NL80211_IFTYPE_AP) { - struct iwl_mvm_vif *mvmvif = - iwl_mvm_vif_from_mac80211(vif); - - mvmvif->ap_wep_key = kmemdup(key, - sizeof(*key) + key->keylen, - GFP_KERNEL); - if (!mvmvif->ap_wep_key) - return -ENOMEM; - } - - if (vif->type != NL80211_IFTYPE_STATION) - return 0; - break; + if (vif->type == NL80211_IFTYPE_STATION) + break; + if (iwl_mvm_has_new_tx_api(mvm)) + return -EOPNOTSUPP; + /* support HW crypto on TX */ + return 0; default: /* currently FW supports only one optional cipher scheme */ if (hw->n_cipher_schemes && @@ -3540,12 +3609,17 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, key_offset); if (ret) { IWL_WARN(mvm, "set key failed\n"); + key->hw_key_idx = STA_KEY_IDX_INVALID; /* * can't add key for RX, but we don't need it - * in the device for TX so still return 0 + * in the device for TX so still return 0, + * unless we have new TX API where we cannot + * put key material into the TX_CMD */ - key->hw_key_idx = STA_KEY_IDX_INVALID; - ret = 0; + if (iwl_mvm_has_new_tx_api(mvm)) + ret = -EOPNOTSUPP; + else + ret = 0; } break; @@ -3639,7 +3713,7 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int duration) { - int res, time_reg = DEVICE_SYSTEM_TIME_REG; + int res; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_time_event_data *te_data = &mvmvif->hs_time_event_data; static const u16 time_event_response[] = { HOT_SPOT_CMD }; @@ -3665,7 +3739,7 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm, 0); /* Set the time and duration */ - tail->apply_time = cpu_to_le32(iwl_read_prph(mvm->trans, time_reg)); + tail->apply_time = cpu_to_le32(iwl_mvm_get_systime(mvm)); delay = AUX_ROC_MIN_DELAY; req_dur = MSEC_TO_TU(duration); @@ -4391,8 +4465,8 @@ static int __iwl_mvm_mac_testmode_cmd(struct iwl_mvm *mvm, int err; u32 noa_duration; - err = nla_parse(tb, IWL_MVM_TM_ATTR_MAX, data, len, iwl_mvm_tm_policy, - NULL); + err = nla_parse_deprecated(tb, IWL_MVM_TM_ATTR_MAX, data, len, + iwl_mvm_tm_policy, NULL); if (err) return err; @@ -4469,16 +4543,22 @@ static int iwl_mvm_schedule_client_csa(struct iwl_mvm *mvm, .action = cpu_to_le32(FW_CTXT_ACTION_ADD), .tsf = cpu_to_le32(chsw->timestamp), .cs_count = chsw->count, + .cs_mode = chsw->block_tx, }; lockdep_assert_held(&mvm->mutex); + if (chsw->delay) + cmd.cs_delayed_bcn_count = + DIV_ROUND_UP(chsw->delay, vif->bss_conf.beacon_int); + return iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(MAC_CONF_GROUP, CHANNEL_SWITCH_TIME_EVENT_CMD), 0, sizeof(cmd), &cmd); } +#define IWL_MAX_CSA_BLOCK_TX 1500 static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_channel_switch *chsw) @@ -4543,8 +4623,18 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, ((vif->bss_conf.beacon_int * (chsw->count - 1) - IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT) * 1024); - if (chsw->block_tx) + if (chsw->block_tx) { iwl_mvm_csa_client_absent(mvm, vif); + /* + * In case of undetermined / long time with immediate + * quiet monitor status to gracefully disconnect + */ + if (!chsw->count || + chsw->count * vif->bss_conf.beacon_int > + IWL_MAX_CSA_BLOCK_TX) + schedule_delayed_work(&mvmvif->csa_work, + msecs_to_jiffies(IWL_MAX_CSA_BLOCK_TX)); + } if (mvmvif->bf_data.bf_enabled) { ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); @@ -4559,6 +4649,9 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, iwl_mvm_schedule_csa_period(mvm, vif, vif->bss_conf.beacon_int, apply_time); + + mvmvif->csa_count = chsw->count; + mvmvif->csa_misbehave = false; break; default: break; @@ -4579,52 +4672,42 @@ out_unlock: return ret; } -static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static void iwl_mvm_channel_switch_rx_beacon(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_channel_switch *chsw) { - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - int ret; - - mutex_lock(&mvm->mutex); - - if (mvmvif->csa_failed) { - mvmvif->csa_failed = false; - ret = -EIO; - goto out_unlock; - } - - if (vif->type == NL80211_IFTYPE_STATION) { - struct iwl_mvm_sta *mvmsta; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_chan_switch_te_cmd cmd = { + .mac_id = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, + mvmvif->color)), + .action = cpu_to_le32(FW_CTXT_ACTION_MODIFY), + .tsf = cpu_to_le32(chsw->timestamp), + .cs_count = chsw->count, + .cs_mode = chsw->block_tx, + }; - mvmvif->csa_bcn_pending = false; - mvmsta = iwl_mvm_sta_from_staid_protected(mvm, - mvmvif->ap_sta_id); + if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_CS_MODIFY)) + return; - if (WARN_ON(!mvmsta)) { - ret = -EIO; - goto out_unlock; + if (chsw->count >= mvmvif->csa_count && chsw->block_tx) { + if (mvmvif->csa_misbehave) { + /* Second time, give up on this AP*/ + iwl_mvm_abort_channel_switch(hw, vif); + ieee80211_chswitch_done(vif, false); + mvmvif->csa_misbehave = false; + return; } - - iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false); - - iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); - - ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0); - if (ret) - goto out_unlock; - - iwl_mvm_stop_session_protection(mvm, vif); + mvmvif->csa_misbehave = true; } + mvmvif->csa_count = chsw->count; - mvmvif->ps_disabled = false; - - ret = iwl_mvm_power_update_ps(mvm); + IWL_DEBUG_MAC80211(mvm, "Modify CSA on mac %d\n", mvmvif->id); -out_unlock: - mutex_unlock(&mvm->mutex); - - return ret; + WARN_ON(iwl_mvm_send_cmd_pdu(mvm, + WIDE_ID(MAC_CONF_GROUP, + CHANNEL_SWITCH_TIME_EVENT_CMD), + CMD_ASYNC, sizeof(cmd), &cmd)); } static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop) @@ -5083,6 +5166,8 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { .channel_switch = iwl_mvm_channel_switch, .pre_channel_switch = iwl_mvm_pre_channel_switch, .post_channel_switch = iwl_mvm_post_channel_switch, + .abort_channel_switch = iwl_mvm_abort_channel_switch, + .channel_switch_rx_beacon = iwl_mvm_channel_switch_rx_beacon, .tdls_channel_switch = iwl_mvm_tdls_channel_switch, .tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index bca6f6b536d9..8dc2a9850bc5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -490,6 +490,9 @@ struct iwl_mvm_vif { bool csa_countdown; bool csa_failed; u16 csa_target_freq; + u16 csa_count; + u16 csa_misbehave; + struct delayed_work csa_work; /* Indicates that we are waiting for a beacon on a new channel */ bool csa_bcn_pending; @@ -498,7 +501,6 @@ struct iwl_mvm_vif { netdev_features_t features; struct iwl_probe_resp_data __rcu *probe_resp_data; - struct ieee80211_key_conf *ap_wep_key; }; static inline struct iwl_mvm_vif * @@ -1200,7 +1202,6 @@ struct iwl_mvm { * @IWL_MVM_STATUS_IN_HW_RESTART: HW restart is active * @IWL_MVM_STATUS_IN_D0I3: NIC is in D0i3 * @IWL_MVM_STATUS_ROC_AUX_RUNNING: AUX remain-on-channel is running - * @IWL_MVM_STATUS_D3_RECONFIG: D3 reconfiguration is being done * @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running * @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA */ @@ -1212,7 +1213,6 @@ enum iwl_mvm_status { IWL_MVM_STATUS_IN_HW_RESTART, IWL_MVM_STATUS_IN_D0I3, IWL_MVM_STATUS_ROC_AUX_RUNNING, - IWL_MVM_STATUS_D3_RECONFIG, IWL_MVM_STATUS_FIRMWARE_RUNNING, IWL_MVM_STATUS_NEED_FLUSH_P2P, }; @@ -1538,6 +1538,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); u8 first_antenna(u8 mask); u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx); void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, u32 *gp2, u64 *boottime); +u32 iwl_mvm_get_systime(struct iwl_mvm *mvm); /* Tx / Host Commands */ int __must_check iwl_mvm_send_cmd(struct iwl_mvm *mvm, @@ -1650,8 +1651,8 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, struct iwl_rx_cmd_buffer *rxb, int queue); -void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi, - struct iwl_rx_cmd_buffer *rxb, int queue); +void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi, + struct iwl_rx_cmd_buffer *rxb, int queue); void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi, struct iwl_rx_cmd_buffer *rxb, int queue); int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask, @@ -1785,14 +1786,13 @@ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm, /* MVM debugfs */ #ifdef CONFIG_IWLWIFI_DEBUGFS -int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir); +void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir); void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif); void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif); #else -static inline int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, - struct dentry *dbgfs_dir) +static inline void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, + struct dentry *dbgfs_dir) { - return 0; } static inline void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) @@ -2024,17 +2024,6 @@ static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm) static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm) { lockdep_assert_held(&mvm->mutex); - /* If IWL_MVM_STATUS_HW_RESTART_REQUESTED bit is set then we received - * an assert. Since we failed to bring the interface up, mac80211 - * will not attempt to reconfig the device, - * which handles the dump collection in assert flow, - * so trigger dump collection here. - */ - if (test_and_clear_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, - &mvm->status)) - iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert, - false, 0); - iwl_fw_cancel_timestamp(&mvm->fwrt); clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status); iwl_fwrt_stop_device(&mvm->fwrt); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index ba27dce4c2bb..acd2fda12466 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -834,7 +834,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, mutex_lock(&mvm->mutex); iwl_mvm_ref(mvm, IWL_MVM_REF_INIT_UCODE); err = iwl_run_init_mvm_ucode(mvm, true); - if (err) + if (err && err != -ERFKILL) iwl_fw_dbg_error_collect(&mvm->fwrt, FW_DBG_TRIGGER_DRIVER); if (!iwlmvm_mod_params.init_dbg || !err) iwl_mvm_stop_device(mvm); @@ -862,9 +862,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, min_backoff = iwl_mvm_min_backoff(mvm); iwl_mvm_thermal_initialize(mvm, min_backoff); - err = iwl_mvm_dbgfs_register(mvm, dbgfs_dir); - if (err) - goto out_unregister; + iwl_mvm_dbgfs_register(mvm, dbgfs_dir); if (!iwl_mvm_has_new_rx_stats_api(mvm)) memset(&mvm->rx_stats_v3, 0, @@ -881,14 +879,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, return op_mode; - out_unregister: - if (iwlmvm_mod_params.init_dbg) - return op_mode; - - ieee80211_unregister_hw(mvm->hw); - mvm->hw_registered = false; - iwl_mvm_leds_exit(mvm); - iwl_mvm_thermal_exit(mvm); out_free: iwl_fw_flush_dump(&mvm->fwrt); iwl_fw_runtime_free(&mvm->fwrt); @@ -1105,7 +1095,7 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode, else if (cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE)) iwl_mvm_rx_frame_release(mvm, napi, rxb, 0); else if (cmd == WIDE_ID(DATA_PATH_GROUP, RX_NO_DATA_NOTIF)) - iwl_mvm_rx_monitor_ndp(mvm, napi, rxb, 0); + iwl_mvm_rx_monitor_no_data(mvm, napi, rxb, 0); else iwl_mvm_rx_common(mvm, rxb, pkt); } @@ -1271,6 +1261,7 @@ static void iwl_mvm_reprobe_wk(struct work_struct *wk) void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) { iwl_abort_notification_waits(&mvm->notif_wait); + del_timer(&mvm->fwrt.dump.periodic_trig); /* * This is a bit racy, but worst case we tell mac80211 about @@ -1291,8 +1282,7 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) * can't recover this since we're already half suspended. */ if (!mvm->fw_restart && fw_error) { - iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert, - false, 0); + iwl_fw_error_collect(&mvm->fwrt); } else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { struct iwl_mvm_reprobe *reprobe; @@ -1340,6 +1330,8 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) } } + iwl_fw_error_collect(&mvm->fwrt); + if (fw_error && mvm->fw_restart > 0) mvm->fw_restart--; set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c index a28283ff7295..659e21b2d4e7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c @@ -6,7 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -27,7 +27,7 @@ * BSD LICENSE * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -116,8 +116,9 @@ static u8 rs_fw_sgi_cw_support(struct ieee80211_sta *sta) return supp; } -static u16 rs_fw_set_config_flags(struct iwl_mvm *mvm, - struct ieee80211_sta *sta) +static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm, + struct ieee80211_sta *sta, + struct ieee80211_supported_band *sband) { struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; @@ -147,6 +148,12 @@ static u16 rs_fw_set_config_flags(struct iwl_mvm *mvm, (vht_ena && (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC)))) flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; + /* consider our LDPC support in case of HE */ + if (sband->iftype_data && sband->iftype_data->he_cap.has_he && + !(sband->iftype_data->he_cap.he_cap_elem.phy_cap_info[1] & + IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) + flags &= ~IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; + if (he_cap && he_cap->has_he && (he_cap->he_cap_elem.phy_cap_info[3] & IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK)) @@ -223,19 +230,43 @@ static u16 rs_fw_he_ieee80211_mcs_to_rs_mcs(u16 mcs) static void rs_fw_he_set_enabled_rates(const struct ieee80211_sta *sta, - const struct ieee80211_sta_he_cap *he_cap, + struct ieee80211_supported_band *sband, struct iwl_tlc_config_cmd *cmd) { - u16 mcs_160 = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_160); - u16 mcs_80 = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_80); + const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap; + u16 mcs_160 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160); + u16 mcs_80 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80); + u16 tx_mcs_80 = + le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80); + u16 tx_mcs_160 = + le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160); int i; for (i = 0; i < sta->rx_nss && i < MAX_NSS; i++) { u16 _mcs_160 = (mcs_160 >> (2 * i)) & 0x3; u16 _mcs_80 = (mcs_80 >> (2 * i)) & 0x3; - + u16 _tx_mcs_160 = (tx_mcs_160 >> (2 * i)) & 0x3; + u16 _tx_mcs_80 = (tx_mcs_80 >> (2 * i)) & 0x3; + + /* If one side doesn't support - mark both as not supporting */ + if (_mcs_80 == IEEE80211_HE_MCS_NOT_SUPPORTED || + _tx_mcs_80 == IEEE80211_HE_MCS_NOT_SUPPORTED) { + _mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED; + _tx_mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED; + } + if (_mcs_80 > _tx_mcs_80) + _mcs_80 = _tx_mcs_80; cmd->ht_rates[i][0] = cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_80)); + + /* If one side doesn't support - mark both as not supporting */ + if (_mcs_160 == IEEE80211_HE_MCS_NOT_SUPPORTED || + _tx_mcs_160 == IEEE80211_HE_MCS_NOT_SUPPORTED) { + _mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED; + _tx_mcs_160 = IEEE80211_HE_MCS_NOT_SUPPORTED; + } + if (_mcs_160 > _tx_mcs_160) + _mcs_160 = _tx_mcs_160; cmd->ht_rates[i][1] = cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_160)); } @@ -264,7 +295,7 @@ static void rs_fw_set_supp_rates(struct ieee80211_sta *sta, /* HT/VHT rates */ if (he_cap && he_cap->has_he) { cmd->mode = IWL_TLC_MNG_MODE_HE; - rs_fw_he_set_enabled_rates(sta, he_cap, cmd); + rs_fw_he_set_enabled_rates(sta, sband, cmd); } else if (vht_cap && vht_cap->vht_supported) { cmd->mode = IWL_TLC_MNG_MODE_VHT; rs_fw_vht_set_enabled_rates(sta, vht_cap, cmd); @@ -345,6 +376,37 @@ out: rcu_read_unlock(); } +static u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta) +{ + const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; + const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; + + if (vht_cap && vht_cap->vht_supported) { + switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) { + case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454: + return IEEE80211_MAX_MPDU_LEN_VHT_11454; + case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991: + return IEEE80211_MAX_MPDU_LEN_VHT_7991; + default: + return IEEE80211_MAX_MPDU_LEN_VHT_3895; + } + + } else if (ht_cap && ht_cap->ht_supported) { + if (ht_cap->cap & IEEE80211_HT_CAP_MAX_AMSDU) + /* + * agg is offloaded so we need to assume that agg + * are enabled and max mpdu in ampdu is 4095 + * (spec 802.11-2016 9.3.2.1) + */ + return IEEE80211_MAX_MPDU_LEN_HT_BA; + else + return IEEE80211_MAX_MPDU_LEN_HT_3839; + } + + /* in legacy mode no amsdu is enabled so return zero */ + return 0; +} + void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, enum nl80211_band band, bool update) { @@ -352,15 +414,16 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw; u32 cmd_id = iwl_cmd_id(TLC_MNG_CONFIG_CMD, DATA_PATH_GROUP, 0); - struct ieee80211_supported_band *sband; + struct ieee80211_supported_band *sband = hw->wiphy->bands[band]; + u16 max_amsdu_len = rs_fw_get_max_amsdu_len(sta); struct iwl_tlc_config_cmd cfg_cmd = { .sta_id = mvmsta->sta_id, .max_ch_width = update ? rs_fw_bw_from_sta_bw(sta) : RATE_MCS_CHAN_WIDTH_20, - .flags = cpu_to_le16(rs_fw_set_config_flags(mvm, sta)), + .flags = cpu_to_le16(rs_fw_get_config_flags(mvm, sta, sband)), .chains = rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm)), - .max_mpdu_len = cpu_to_le16(sta->max_amsdu_len), .sgi_ch_width_supp = rs_fw_sgi_cw_support(sta), + .max_mpdu_len = cpu_to_le16(max_amsdu_len), .amsdu = iwl_mvm_is_csum_supported(mvm), }; int ret; @@ -370,9 +433,14 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, #ifdef CONFIG_IWLWIFI_DEBUGFS iwl_mvm_reset_frame_stats(mvm); #endif - sband = hw->wiphy->bands[band]; rs_fw_set_supp_rates(sta, sband, &cfg_cmd); + /* + * since TLC offload works with one mode we can assume + * that only vht/ht is used and also set it as station max amsdu + */ + sta->max_amsdu_len = max_amsdu_len; + ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cfg_cmd), &cfg_cmd); if (ret) IWL_ERR(mvm, "Failed to send rate scale config (%d)\n", ret); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index e231a44d2423..c182821ab22b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -4078,9 +4078,8 @@ static ssize_t iwl_dbgfs_ss_force_write(struct iwl_lq_sta *lq_sta, char *buf, #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_lq_sta) #define MVM_DEBUGFS_ADD_FILE_RS(name, parent, mode) do { \ - if (!debugfs_create_file(#name, mode, parent, lq_sta, \ - &iwl_dbgfs_##name##_ops)) \ - goto err; \ + debugfs_create_file(#name, mode, parent, lq_sta, \ + &iwl_dbgfs_##name##_ops); \ } while (0) MVM_DEBUGFS_READ_WRITE_FILE_OPS(ss_force, 32); @@ -4108,9 +4107,6 @@ static void rs_drv_add_sta_debugfs(void *mvm, void *priv_sta, &lq_sta->pers.dbg_fixed_txp_reduction); MVM_DEBUGFS_ADD_FILE_RS(ss_force, dir, 0600); - return; -err: - IWL_ERR((struct iwl_mvm *)mvm, "Can't create debugfs entity\n"); } void rs_remove_sta_debugfs(void *mvm, void *mvm_sta) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 1e03acf30762..1824566d08fc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -169,9 +169,9 @@ static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb, } /* iwl_mvm_create_skb Adds the rxb to a new skb */ -static void iwl_mvm_create_skb(struct sk_buff *skb, struct ieee80211_hdr *hdr, - u16 len, u8 crypt_len, - struct iwl_rx_cmd_buffer *rxb) +static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb, + struct ieee80211_hdr *hdr, u16 len, u8 crypt_len, + struct iwl_rx_cmd_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_mpdu_desc *desc = (void *)pkt->data; @@ -204,6 +204,20 @@ static void iwl_mvm_create_skb(struct sk_buff *skb, struct ieee80211_hdr *hdr, * present before copying packet data. */ hdrlen += crypt_len; + + if (WARN_ONCE(headlen < hdrlen, + "invalid packet lengths (hdrlen=%d, len=%d, crypt_len=%d)\n", + hdrlen, len, crypt_len)) { + /* + * We warn and trace because we want to be able to see + * it in trace-cmd as well. + */ + IWL_DEBUG_RX(mvm, + "invalid packet lengths (hdrlen=%d, len=%d, crypt_len=%d)\n", + hdrlen, len, crypt_len); + return -EINVAL; + } + skb_put_data(skb, hdr, hdrlen); skb_put_data(skb, (u8 *)hdr + hdrlen + pad_len, headlen - hdrlen); @@ -216,6 +230,8 @@ static void iwl_mvm_create_skb(struct sk_buff *skb, struct ieee80211_hdr *hdr, skb_add_rx_frag(skb, 0, rxb_steal_page(rxb), offset, fraglen, rxb->truesize); } + + return 0; } static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm, @@ -1671,7 +1687,11 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, rx_status->boottime_ns = ktime_get_boot_ns(); } - iwl_mvm_create_skb(skb, hdr, len, crypt_len, rxb); + if (iwl_mvm_create_skb(mvm, skb, hdr, len, crypt_len, rxb)) { + kfree_skb(skb); + goto out; + } + if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc)) iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta, csi); @@ -1679,8 +1699,8 @@ out: rcu_read_unlock(); } -void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi, - struct iwl_rx_cmd_buffer *rxb, int queue) +void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi, + struct iwl_rx_cmd_buffer *rxb, int queue) { struct ieee80211_rx_status *rx_status; struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -1701,10 +1721,6 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi, if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))) return; - /* Currently only NDP type is supported */ - if (info_type != RX_NO_DATA_INFO_TYPE_NDP) - return; - energy_a = (rssi & RX_NO_DATA_CHAIN_A_MSK) >> RX_NO_DATA_CHAIN_A_POS; energy_b = (rssi & RX_NO_DATA_CHAIN_B_MSK) >> RX_NO_DATA_CHAIN_B_POS; channel = (rssi & RX_NO_DATA_CHANNEL_MSK) >> RX_NO_DATA_CHANNEL_POS; @@ -1726,9 +1742,22 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi, /* 0-length PSDU */ rx_status->flag |= RX_FLAG_NO_PSDU; - /* currently this is the only type for which we get this notif */ - rx_status->zero_length_psdu_type = - IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING; + + switch (info_type) { + case RX_NO_DATA_INFO_TYPE_NDP: + rx_status->zero_length_psdu_type = + IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING; + break; + case RX_NO_DATA_INFO_TYPE_MU_UNMATCHED: + case RX_NO_DATA_INFO_TYPE_HE_TB_UNMATCHED: + rx_status->zero_length_psdu_type = + IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED; + break; + default: + rx_status->zero_length_psdu_type = + IEEE80211_RADIOTAP_ZERO_LEN_PSDU_VENDOR; + break; + } /* This may be overridden by iwl_mvm_rx_he() to HE_RU */ switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 78694bc38e76..d9ddf9ff6428 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -1082,21 +1082,23 @@ static void iwl_mvm_fill_scan_dwell(struct iwl_mvm *mvm, dwell->extended = IWL_SCAN_DWELL_EXTENDED; } -static void iwl_mvm_fill_channels(struct iwl_mvm *mvm, u8 *channels) +static void iwl_mvm_fill_channels(struct iwl_mvm *mvm, u8 *channels, + u32 max_channels) { struct ieee80211_supported_band *band; int i, j = 0; band = &mvm->nvm_data->bands[NL80211_BAND_2GHZ]; - for (i = 0; i < band->n_channels; i++, j++) + for (i = 0; i < band->n_channels && j < max_channels; i++, j++) channels[j] = band->channels[i].hw_value; band = &mvm->nvm_data->bands[NL80211_BAND_5GHZ]; - for (i = 0; i < band->n_channels; i++, j++) + for (i = 0; i < band->n_channels && j < max_channels; i++, j++) channels[j] = band->channels[i].hw_value; } static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config, - u32 flags, u8 channel_flags) + u32 flags, u8 channel_flags, + u32 max_channels) { enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, NULL); struct iwl_scan_config_v1 *cfg = config; @@ -1115,11 +1117,12 @@ static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config, cfg->bcast_sta_id = mvm->aux_sta.sta_id; cfg->channel_flags = channel_flags; - iwl_mvm_fill_channels(mvm, cfg->channel_array); + iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels); } static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config, - u32 flags, u8 channel_flags) + u32 flags, u8 channel_flags, + u32 max_channels) { struct iwl_scan_config *cfg = config; @@ -1162,7 +1165,7 @@ static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config, cfg->bcast_sta_id = mvm->aux_sta.sta_id; cfg->channel_flags = channel_flags; - iwl_mvm_fill_channels(mvm, cfg->channel_array); + iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels); } int iwl_mvm_config_scan(struct iwl_mvm *mvm) @@ -1181,7 +1184,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) u8 channel_flags; if (WARN_ON(num_channels > mvm->fw->ucode_capa.n_scan_channels)) - return -ENOBUFS; + num_channels = mvm->fw->ucode_capa.n_scan_channels; if (iwl_mvm_is_cdb_supported(mvm)) { type = iwl_mvm_get_scan_type_band(mvm, NULL, @@ -1234,9 +1237,11 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) flags |= (iwl_mvm_is_scan_fragmented(hb_type)) ? SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED : SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED; - iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags); + iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags, + num_channels); } else { - iwl_mvm_fill_scan_config_v1(mvm, cfg, flags, channel_flags); + iwl_mvm_fill_scan_config_v1(mvm, cfg, flags, channel_flags, + num_channels); } cmd.data[0] = cfg; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 498c315291cf..f545a737a92d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2015 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2015 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -746,7 +746,8 @@ static int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id, static int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, u8 sta_id, u8 tid, unsigned int timeout) { - int queue, size = IWL_DEFAULT_QUEUE_SIZE; + int queue, size = max_t(u32, IWL_DEFAULT_QUEUE_SIZE, + mvm->trans->cfg->min_256_ba_txq_size); if (tid == IWL_MAX_TID_COUNT) { tid = IWL_MGMT_TID; @@ -1399,7 +1400,9 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk) iwl_mvm_sta_alloc_queue(mvm, txq->sta, txq->ac, tid); list_del_init(&mvmtxq->list); + local_bh_disable(); iwl_mvm_mac_itxq_xmit(mvm->hw, txq); + local_bh_enable(); } mutex_unlock(&mvm->mutex); @@ -2107,12 +2110,14 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) if (!iwl_mvm_has_new_tx_api(mvm)) { if (vif->type == NL80211_IFTYPE_AP || - vif->type == NL80211_IFTYPE_ADHOC) + vif->type == NL80211_IFTYPE_ADHOC) { queue = mvm->probe_queue; - else if (vif->type == NL80211_IFTYPE_P2P_DEVICE) + } else if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { queue = mvm->p2p_dev_queue; - else if (WARN(1, "Missing required TXQ for adding bcast STA\n")) + } else { + WARN(1, "Missing required TXQ for adding bcast STA\n"); return -EINVAL; + } bsta->tfd_queue_msk |= BIT(queue); @@ -2275,7 +2280,8 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) static const u8 _maddr[] = {0x03, 0x00, 0x00, 0x00, 0x00, 0x00}; const u8 *maddr = _maddr; struct iwl_trans_txq_scd_cfg cfg = { - .fifo = IWL_MVM_TX_FIFO_MCAST, + .fifo = vif->type == NL80211_IFTYPE_AP ? + IWL_MVM_TX_FIFO_MCAST : IWL_MVM_TX_FIFO_BE, .sta_id = msta->sta_id, .tid = 0, .aggregate = false, @@ -2333,21 +2339,6 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) iwl_mvm_enable_txq(mvm, NULL, mvmvif->cab_queue, 0, &cfg, timeout); - if (mvmvif->ap_wep_key) { - u8 key_offset = iwl_mvm_set_fw_key_idx(mvm); - - __set_bit(key_offset, mvm->fw_key_table); - - if (key_offset == STA_KEY_IDX_INVALID) - return -ENOSPC; - - ret = iwl_mvm_send_sta_key(mvm, mvmvif->mcast_sta.sta_id, - mvmvif->ap_wep_key, true, 0, NULL, 0, - key_offset, 0); - if (ret) - return ret; - } - return 0; } @@ -2419,28 +2410,6 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) iwl_mvm_disable_txq(mvm, NULL, mvmvif->cab_queue, 0, 0); - if (mvmvif->ap_wep_key) { - int i; - - if (!__test_and_clear_bit(mvmvif->ap_wep_key->hw_key_idx, - mvm->fw_key_table)) { - IWL_ERR(mvm, "offset %d not used in fw key table.\n", - mvmvif->ap_wep_key->hw_key_idx); - return -ENOENT; - } - - /* track which key was deleted last */ - for (i = 0; i < STA_KEY_MAX_NUM; i++) { - if (mvm->fw_key_deleted[i] < U8_MAX) - mvm->fw_key_deleted[i]++; - } - mvm->fw_key_deleted[mvmvif->ap_wep_key->hw_key_idx] = 0; - ret = __iwl_mvm_remove_sta_key(mvm, mvmvif->mcast_sta.sta_id, - mvmvif->ap_wep_key, true); - if (ret) - return ret; - } - ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id); if (ret) IWL_WARN(mvm, "Failed sending remove station\n"); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index 79700c7310a1..b4d4071b865d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2016 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2016 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -394,7 +394,6 @@ struct iwl_mvm_rxq_dup_data { * the BA window. To be used for UAPSD only. * @ptk_pn: per-queue PTK PN data structures * @dup_data: per queue duplicate packet detection data - * @wep_key: used in AP mode. Is a duplicate of the WEP key. * @deferred_traffic_tid_map: indication bitmap of deferred traffic per-TID * @tx_ant: the index of the antenna to use for data tx to this station. Only * used during connection establishment (e.g. for the 4 way handshake @@ -426,8 +425,6 @@ struct iwl_mvm_sta { struct iwl_mvm_key_pn __rcu *ptk_pn[4]; struct iwl_mvm_rxq_dup_data *dup_data; - struct ieee80211_key_conf *wep_key; - u8 reserved_queue; /* Temporary, until the new TLC will control the Tx protection */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c index 859aa5a4e6b5..9df21a8d1fc1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c @@ -7,7 +7,7 @@ * * Copyright(c) 2014 Intel Mobile Communications GmbH * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(C) 2018 Intel Corporation + * Copyright(C) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -29,7 +29,7 @@ * * Copyright(c) 2014 Intel Mobile Communications GmbH * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(C) 2018 Intel Corporation + * Copyright(C) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -252,8 +252,7 @@ static void iwl_mvm_tdls_update_cs_state(struct iwl_mvm *mvm, /* we only send requests to our switching peer - update sent time */ if (state == IWL_MVM_TDLS_SW_REQ_SENT) - mvm->tdls_cs.peer.sent_timestamp = - iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG); + mvm->tdls_cs.peer.sent_timestamp = iwl_mvm_get_systime(mvm); if (state == IWL_MVM_TDLS_SW_IDLE) mvm->tdls_cs.cur_sta_id = IWL_MVM_INVALID_STA; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 9693fa4cdc39..4d34e5ab1bff 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -234,6 +234,7 @@ iwl_mvm_te_handle_notify_csa(struct iwl_mvm *mvm, break; } iwl_mvm_csa_client_absent(mvm, te_data->vif); + cancel_delayed_work(&mvmvif->csa_work); ieee80211_chswitch_done(te_data->vif, true); break; default: diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 4649327abb45..b9914efc55c4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -1418,6 +1418,16 @@ void iwl_mvm_tcm_rm_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif) cancel_delayed_work_sync(&mvmvif->uapsd_nonagg_detected_wk); } +u32 iwl_mvm_get_systime(struct iwl_mvm *mvm) +{ + u32 reg_addr = DEVICE_SYSTEM_TIME_REG; + + if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000 && + mvm->trans->cfg->gp2_reg_addr) + reg_addr = mvm->trans->cfg->gp2_reg_addr; + + return iwl_read_prph(mvm->trans, reg_addr); +} void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, u32 *gp2, u64 *boottime) { @@ -1432,7 +1442,7 @@ void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, u32 *gp2, u64 *boottime) iwl_mvm_power_update_device(mvm); } - *gp2 = iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG); + *gp2 = iwl_mvm_get_systime(mvm); *boottime = ktime_get_boot_ns(); if (!ps_disabled) { diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index 1e36459948db..f496d1bcb643 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -66,7 +66,8 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, void *iml_img; u32 control_flags = 0; int ret; - int cmdq_size = max_t(u32, TFD_CMD_SLOTS, trans->cfg->min_txq_size); + int cmdq_size = max_t(u32, IWL_CMD_QUEUE_SIZE, + trans->cfg->min_txq_size); /* Allocate prph scratch */ prph_scratch = dma_alloc_coherent(trans->dev, sizeof(*prph_scratch), diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c index 9274e317cc77..8969b47bacf2 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c @@ -6,7 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -20,7 +20,7 @@ * BSD LICENSE * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -210,7 +210,7 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans, ctxt_info->hcmd_cfg.cmd_queue_addr = cpu_to_le64(trans_pcie->txq[trans_pcie->cmd_queue]->dma_addr); ctxt_info->hcmd_cfg.cmd_queue_size = - TFD_QUEUE_CB_SIZE(TFD_CMD_SLOTS); + TFD_QUEUE_CB_SIZE(IWL_CMD_QUEUE_SIZE); /* allocate ucode sections in dram and set addresses */ ret = iwl_pcie_init_fw_sec(trans, fw, &ctxt_info->dram); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 2b94e4cef56c..cd035061cdd5 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -928,11 +928,6 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x34F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x4070, iwl_ax101_cfg_qu_hr)}, - {IWL_PCI_DEVICE(0x40C0, 0x0000, iwl22560_2ax_cfg_su_cdb)}, - {IWL_PCI_DEVICE(0x40C0, 0x0010, iwl22560_2ax_cfg_su_cdb)}, - {IWL_PCI_DEVICE(0x40c0, 0x0090, iwl22560_2ax_cfg_su_cdb)}, - {IWL_PCI_DEVICE(0x40C0, 0x0310, iwl22560_2ax_cfg_su_cdb)}, - {IWL_PCI_DEVICE(0x40C0, 0x0A10, iwl22560_2ax_cfg_su_cdb)}, {IWL_PCI_DEVICE(0x43F0, 0x0040, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x43F0, 0x0070, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x43F0, 0x0074, iwl_ax101_cfg_qu_hr)}, @@ -953,17 +948,15 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0xA0F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, {IWL_PCI_DEVICE(0xA0F0, 0x4070, iwl_ax101_cfg_qu_hr)}, - {IWL_PCI_DEVICE(0x2723, 0x0080, iwl22260_2ax_cfg)}, - {IWL_PCI_DEVICE(0x2723, 0x0084, iwl22260_2ax_cfg)}, - {IWL_PCI_DEVICE(0x2723, 0x0088, iwl22260_2ax_cfg)}, - {IWL_PCI_DEVICE(0x2723, 0x008C, iwl22260_2ax_cfg)}, + {IWL_PCI_DEVICE(0x2723, 0x0080, iwl_ax200_cfg_cc)}, + {IWL_PCI_DEVICE(0x2723, 0x0084, iwl_ax200_cfg_cc)}, + {IWL_PCI_DEVICE(0x2723, 0x0088, iwl_ax200_cfg_cc)}, + {IWL_PCI_DEVICE(0x2723, 0x008C, iwl_ax200_cfg_cc)}, {IWL_PCI_DEVICE(0x2723, 0x1653, killer1650w_2ax_cfg)}, {IWL_PCI_DEVICE(0x2723, 0x1654, killer1650x_2ax_cfg)}, - {IWL_PCI_DEVICE(0x2723, 0x4080, iwl22260_2ax_cfg)}, - {IWL_PCI_DEVICE(0x2723, 0x4088, iwl22260_2ax_cfg)}, - - {IWL_PCI_DEVICE(0x1a56, 0x1653, killer1650w_2ax_cfg)}, - {IWL_PCI_DEVICE(0x1a56, 0x1654, killer1650x_2ax_cfg)}, + {IWL_PCI_DEVICE(0x2723, 0x2080, iwl_ax200_cfg_cc)}, + {IWL_PCI_DEVICE(0x2723, 0x4080, iwl_ax200_cfg_cc)}, + {IWL_PCI_DEVICE(0x2723, 0x4088, iwl_ax200_cfg_cc)}, {IWL_PCI_DEVICE(0x2725, 0x0090, iwlax210_2ax_cfg_so_hr_a0)}, {IWL_PCI_DEVICE(0x7A70, 0x0090, iwlax210_2ax_cfg_so_hr_a0)}, @@ -1046,9 +1039,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } /* register transport layer debugfs here */ - ret = iwl_trans_pcie_dbgfs_register(iwl_trans); - if (ret) - goto out_free_drv; + iwl_trans_pcie_dbgfs_register(iwl_trans); /* if RTPM is in use, enable it in our device */ if (iwl_trans->runtime_pm_mode != IWL_PLAT_PM_MODE_DISABLED) { @@ -1077,8 +1068,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; -out_free_drv: - iwl_drv_stop(iwl_trans->drv); out_free_trans: iwl_trans_pcie_free(iwl_trans); return ret; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index bf8b61a476c5..b513037dc066 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -106,7 +106,6 @@ struct iwl_host_cmd; * @page: driver's pointer to the rxb page * @invalid: rxb is in driver ownership - not owned by HW * @vid: index of this rxb in the global table - * @size: size used from the buffer */ struct iwl_rx_mem_buffer { dma_addr_t page_dma; @@ -114,7 +113,6 @@ struct iwl_rx_mem_buffer { u16 vid; bool invalid; struct list_head list; - u32 size; }; /** @@ -135,46 +133,32 @@ struct isr_statistics { u32 unhandled; }; -#define IWL_RX_TD_TYPE_MSK 0xff000000 -#define IWL_RX_TD_SIZE_MSK 0x00ffffff -#define IWL_RX_TD_SIZE_2K BIT(11) -#define IWL_RX_TD_TYPE 0 - /** * struct iwl_rx_transfer_desc - transfer descriptor - * @type_n_size: buffer type (bit 0: external buff valid, - * bit 1: optional footer valid, bit 2-7: reserved) - * and buffer size * @addr: ptr to free buffer start address * @rbid: unique tag of the buffer * @reserved: reserved */ struct iwl_rx_transfer_desc { - __le32 type_n_size; - __le64 addr; __le16 rbid; - __le16 reserved; + __le16 reserved[3]; + __le64 addr; } __packed; -#define IWL_RX_CD_SIZE 0xffffff00 +#define IWL_RX_CD_FLAGS_FRAGMENTED BIT(0) /** * struct iwl_rx_completion_desc - completion descriptor - * @type: buffer type (bit 0: external buff valid, - * bit 1: optional footer valid, bit 2-7: reserved) - * @status: status of the completion * @reserved1: reserved * @rbid: unique tag of the received buffer - * @size: buffer size, masked by IWL_RX_CD_SIZE + * @flags: flags (0: fragmented, all others: reserved) * @reserved2: reserved */ struct iwl_rx_completion_desc { - u8 type; - u8 status; - __le16 reserved1; + __le32 reserved1; __le16 rbid; - __le32 size; - u8 reserved2[22]; + u8 flags; + u8 reserved2[25]; } __packed; /** @@ -306,10 +290,6 @@ struct iwl_cmd_meta { u32 tbs; }; - -#define TFD_TX_CMD_SLOTS 256 -#define TFD_CMD_SLOTS 32 - /* * The FH will write back to the first TB only, so we need to copy some data * into the buffer regardless of whether it should be mapped or not. @@ -556,7 +536,7 @@ struct iwl_trans_pcie { int ict_index; bool use_ict; bool is_down, opmode_down; - bool debug_rfkill; + s8 debug_rfkill; struct isr_statistics isr_stats; spinlock_t irq_lock; @@ -1002,7 +982,7 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans) lockdep_assert_held(&trans_pcie->mutex); - if (trans_pcie->debug_rfkill) + if (trans_pcie->debug_rfkill == 1) return true; return !(iwl_read32(trans, CSR_GP_CNTRL) & @@ -1043,15 +1023,12 @@ static inline bool iwl_pcie_dbg_on(struct iwl_trans *trans) void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state); void iwl_trans_pcie_dump_regs(struct iwl_trans *trans); -void iwl_trans_sync_nmi(struct iwl_trans *trans); +void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans); #ifdef CONFIG_IWLWIFI_DEBUGFS -int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans); +void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans); #else -static inline int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) -{ - return 0; -} +static inline void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) { } #endif int iwl_pci_fw_exit_d0i3(struct iwl_trans *trans); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 8d4f0628622b..31b3591f71d1 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -282,9 +282,8 @@ static void iwl_pcie_restock_bd(struct iwl_trans *trans, if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) { struct iwl_rx_transfer_desc *bd = rxq->bd; - bd[rxq->write].type_n_size = - cpu_to_le32((IWL_RX_TD_TYPE & IWL_RX_TD_TYPE_MSK) | - ((IWL_RX_TD_SIZE_2K >> 8) & IWL_RX_TD_SIZE_MSK)); + BUILD_BUG_ON(sizeof(*bd) != 2 * sizeof(u64)); + bd[rxq->write].addr = cpu_to_le64(rxb->page_dma); bd[rxq->write].rbid = cpu_to_le16(rxb->vid); } else { @@ -435,7 +434,7 @@ static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans, /* * Issue an error if we don't have enough pre-allocated * buffers. -` */ + */ if (!(gfp_mask & __GFP_NOWARN) && net_ratelimit()) IWL_CRIT(trans, "Failed to alloc_pages\n"); @@ -1265,9 +1264,6 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, .truesize = max_len, }; - if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) - rxcb.status = rxq->cd[i].status; - pkt = rxb_addr(&rxcb); if (pkt->len_n_flags == cpu_to_le32(FH_RSCSR_FRAME_INVALID)) { @@ -1394,6 +1390,8 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb; u16 vid; + BUILD_BUG_ON(sizeof(struct iwl_rx_completion_desc) != 32); + if (!trans->cfg->mq_rx_supported) { rxb = rxq->queue[i]; rxq->queue[i] = NULL; @@ -1415,9 +1413,6 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans, IWL_DEBUG_RX(trans, "Got virtual RB ID %u\n", (u32)rxb->vid); - if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) - rxb->size = le32_to_cpu(rxq->cd[i].size) & IWL_RX_CD_SIZE; - rxb->invalid = true; return rxb; @@ -1434,10 +1429,15 @@ out_err: static void iwl_pcie_rx_handle(struct iwl_trans *trans, int queue) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq[queue]; + struct iwl_rxq *rxq; u32 r, i, count = 0; bool emergency = false; + if (WARN_ON_ONCE(!trans_pcie->rxq || !trans_pcie->rxq[queue].bd)) + return; + + rxq = &trans_pcie->rxq[queue]; + restart: spin_lock(&rxq->lock); /* uCode's read index (stored in shared DRAM) indicates the last Rx @@ -2212,6 +2212,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) "Hardware error detected. Restarting.\n"); isr_stats->hw++; + trans->hw_error = true; iwl_pcie_irq_handle_error(trans); } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index 9c203ca75de9..8507a7bdcfdd 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -6,7 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -20,7 +20,7 @@ * BSD LICENSE * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -234,7 +234,8 @@ void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power) static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - int queue_size = max_t(u32, TFD_CMD_SLOTS, trans->cfg->min_txq_size); + int queue_size = max_t(u32, IWL_CMD_QUEUE_SIZE, + trans->cfg->min_txq_size); /* TODO: most of the logic can be removed in A0 - but not in Z0 */ spin_lock(&trans_pcie->irq_lock); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index fe8269d023de..803fcbac4152 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -896,6 +896,8 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans) if (!trans->num_blocks) return; + IWL_DEBUG_FW(trans, + "WRT: applying DRAM buffer[0] destination\n"); iwl_write_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2, trans->fw_mon[0].physical >> MON_BUFF_SHIFT_VER2); @@ -2067,7 +2069,6 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans, * MAC_ACCESS_REQ bit to be performed before any other writes * scheduled on different CPUs (after we drop reg_lock). */ - mmiowb(); out: spin_unlock_irqrestore(&trans_pcie->reg_lock, *flags); } @@ -2442,9 +2443,8 @@ void iwl_pcie_dump_csr(struct iwl_trans *trans) #ifdef CONFIG_IWLWIFI_DEBUGFS /* create and remove of files */ #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ - if (!debugfs_create_file(#name, mode, parent, trans, \ - &iwl_dbgfs_##name##_ops)) \ - goto err; \ + debugfs_create_file(#name, mode, parent, trans, \ + &iwl_dbgfs_##name##_ops); \ } while (0) /* file operation */ @@ -2687,16 +2687,17 @@ static ssize_t iwl_dbgfs_rfkill_write(struct file *file, { struct iwl_trans *trans = file->private_data; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - bool old = trans_pcie->debug_rfkill; + bool new_value; int ret; - ret = kstrtobool_from_user(user_buf, count, &trans_pcie->debug_rfkill); + ret = kstrtobool_from_user(user_buf, count, &new_value); if (ret) return ret; - if (old == trans_pcie->debug_rfkill) + if (new_value == trans_pcie->debug_rfkill) return count; IWL_WARN(trans, "changing debug rfkill %d->%d\n", - old, trans_pcie->debug_rfkill); + trans_pcie->debug_rfkill, new_value); + trans_pcie->debug_rfkill = new_value; iwl_pcie_handle_rfkill_irq(trans); return count; @@ -2847,7 +2848,7 @@ static const struct file_operations iwl_dbgfs_monitor_data_ops = { }; /* Create the debugfs files and directories */ -int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) +void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) { struct dentry *dir = trans->dbgfs_dir; @@ -2858,11 +2859,6 @@ int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) DEBUGFS_ADD_FILE(fh_reg, dir, 0400); DEBUGFS_ADD_FILE(rfkill, dir, 0600); DEBUGFS_ADD_FILE(monitor_data, dir, 0400); - return 0; - -err: - IWL_ERR(trans, "failed to create the trans debugfs entry\n"); - return -ENOMEM; } static void iwl_trans_pcie_debugfs_cleanup(struct iwl_trans *trans) @@ -3012,10 +3008,14 @@ static void iwl_trans_pcie_dump_pointers(struct iwl_trans *trans, struct iwl_fw_error_dump_fw_mon *fw_mon_data) { - u32 base, write_ptr, wrap_cnt; + u32 base, base_high, write_ptr, write_ptr_val, wrap_cnt; - /* If there was a dest TLV - use the values from there */ - if (trans->ini_valid) { + if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { + base = DBGC_CUR_DBGBUF_BASE_ADDR_LSB; + base_high = DBGC_CUR_DBGBUF_BASE_ADDR_MSB; + write_ptr = DBGC_CUR_DBGBUF_STATUS; + wrap_cnt = DBGC_DBGBUF_WRAP_AROUND; + } else if (trans->ini_valid) { base = iwl_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2); write_ptr = iwl_umac_prph(trans, MON_BUFF_WRPTR_VER2); wrap_cnt = iwl_umac_prph(trans, MON_BUFF_CYCLE_CNT_VER2); @@ -3028,12 +3028,18 @@ iwl_trans_pcie_dump_pointers(struct iwl_trans *trans, write_ptr = MON_BUFF_WRPTR; wrap_cnt = MON_BUFF_CYCLE_CNT; } - fw_mon_data->fw_mon_wr_ptr = - cpu_to_le32(iwl_read_prph(trans, write_ptr)); + + write_ptr_val = iwl_read_prph(trans, write_ptr); fw_mon_data->fw_mon_cycle_cnt = cpu_to_le32(iwl_read_prph(trans, wrap_cnt)); fw_mon_data->fw_mon_base_ptr = cpu_to_le32(iwl_read_prph(trans, base)); + if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { + fw_mon_data->fw_mon_base_high_ptr = + cpu_to_le32(iwl_read_prph(trans, base_high)); + write_ptr_val &= DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK; + } + fw_mon_data->fw_mon_wr_ptr = cpu_to_le32(write_ptr_val); } static u32 @@ -3044,9 +3050,10 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans, u32 len = 0; if ((trans->num_blocks && - trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) || - (trans->dbg_dest_tlv && !trans->ini_valid) || - (trans->ini_valid && trans->num_blocks)) { + (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000 || + trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210 || + trans->ini_valid)) || + (trans->dbg_dest_tlv && !trans->ini_valid)) { struct iwl_fw_error_dump_fw_mon *fw_mon_data; (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR); @@ -3165,8 +3172,10 @@ static struct iwl_trans_dump_data len = sizeof(*dump_data); /* host commands */ - len += sizeof(*data) + - cmdq->n_window * (sizeof(*txcmd) + TFD_MAX_PAYLOAD_SIZE); + if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD)) + len += sizeof(*data) + + cmdq->n_window * (sizeof(*txcmd) + + TFD_MAX_PAYLOAD_SIZE); /* FW monitor */ if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FW_MONITOR)) @@ -3318,7 +3327,8 @@ static void iwl_trans_pcie_resume(struct iwl_trans *trans) .unref = iwl_trans_pcie_unref, \ .dump_data = iwl_trans_pcie_dump_data, \ .d3_suspend = iwl_trans_pcie_d3_suspend, \ - .d3_resume = iwl_trans_pcie_d3_resume + .d3_resume = iwl_trans_pcie_d3_resume, \ + .sync_nmi = iwl_trans_pcie_sync_nmi #ifdef CONFIG_PM_SLEEP #define IWL_TRANS_PM_OPS \ @@ -3411,7 +3421,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, ret = -ENOMEM; goto out_no_pci; } - + trans_pcie->debug_rfkill = -1; if (!cfg->base_params->pcie_l1_allowed) { /* @@ -3539,9 +3549,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) { trans->cfg = &iwlax210_2ax_cfg_so_gf_a0; + } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == + CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF4)) { + trans->cfg = &iwlax210_2ax_cfg_so_gf4_a0; } } else if (cfg == &iwl_ax101_cfg_qu_hr) { if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == + CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) && + trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0) { + trans->cfg = &iwl22000_2ax_cfg_qnj_hr_b0; + } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) { trans->cfg = &iwl_ax101_cfg_qu_hr; } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == @@ -3560,7 +3577,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, } } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) && - (trans->cfg != &iwl22260_2ax_cfg || + (trans->cfg != &iwl_ax200_cfg_cc || trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0)) { u32 hw_status; @@ -3637,22 +3654,29 @@ out_no_pci: return ERR_PTR(ret); } -void iwl_trans_sync_nmi(struct iwl_trans *trans) +void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans) { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT; + u32 inta_addr, sw_err_bit; + + if (trans_pcie->msix_enabled) { + inta_addr = CSR_MSIX_HW_INT_CAUSES_AD; + sw_err_bit = MSIX_HW_INT_CAUSES_REG_SW_ERR; + } else { + inta_addr = CSR_INT; + sw_err_bit = CSR_INT_BIT_SW_ERR; + } iwl_disable_interrupts(trans); iwl_force_nmi(trans); while (time_after(timeout, jiffies)) { - u32 inta_hw = iwl_read32(trans, - CSR_MSIX_HW_INT_CAUSES_AD); + u32 inta_hw = iwl_read32(trans, inta_addr); /* Error detected by uCode */ - if (inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR) { + if (inta_hw & sw_err_bit) { /* Clear causes register */ - iwl_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD, - inta_hw & - MSIX_HW_INT_CAUSES_REG_SW_ERR); + iwl_write32(trans, inta_addr, inta_hw & sw_err_bit); break; } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index 88530d9f4a54..38d110338987 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -965,7 +965,7 @@ static int iwl_pcie_gen2_send_hcmd_sync(struct iwl_trans *trans, cmd_str); ret = -ETIMEDOUT; - iwl_trans_sync_nmi(trans); + iwl_trans_pcie_sync_nmi(trans); goto cancel; } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 9fbd37d23e85..fa4245d0d4a8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -996,10 +996,11 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans) bool cmd_queue = (txq_id == trans_pcie->cmd_queue); if (cmd_queue) - slots_num = max_t(u32, TFD_CMD_SLOTS, + slots_num = max_t(u32, IWL_CMD_QUEUE_SIZE, trans->cfg->min_txq_size); else - slots_num = TFD_TX_CMD_SLOTS; + slots_num = max_t(u32, IWL_DEFAULT_QUEUE_SIZE, + trans->cfg->min_256_ba_txq_size); trans_pcie->txq[txq_id] = &trans_pcie->txq_memory[txq_id]; ret = iwl_pcie_txq_alloc(trans, trans_pcie->txq[txq_id], slots_num, cmd_queue); @@ -1049,10 +1050,11 @@ int iwl_pcie_tx_init(struct iwl_trans *trans) bool cmd_queue = (txq_id == trans_pcie->cmd_queue); if (cmd_queue) - slots_num = max_t(u32, TFD_CMD_SLOTS, + slots_num = max_t(u32, IWL_CMD_QUEUE_SIZE, trans->cfg->min_txq_size); else - slots_num = TFD_TX_CMD_SLOTS; + slots_num = max_t(u32, IWL_DEFAULT_QUEUE_SIZE, + trans->cfg->min_256_ba_txq_size); ret = iwl_pcie_txq_init(trans, trans_pcie->txq[txq_id], slots_num, cmd_queue); if (ret) { @@ -1960,7 +1962,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, iwl_get_cmd_string(trans, cmd->id)); ret = -ETIMEDOUT; - iwl_trans_sync_nmi(trans); + iwl_trans_pcie_sync_nmi(trans); goto cancel; } diff --git a/drivers/net/wireless/intersil/orinoco/mic.c b/drivers/net/wireless/intersil/orinoco/mic.c index 67b0c05afbdb..a324bc4b7938 100644 --- a/drivers/net/wireless/intersil/orinoco/mic.c +++ b/drivers/net/wireless/intersil/orinoco/mic.c @@ -65,7 +65,6 @@ int orinoco_mic(struct crypto_shash *tfm_michael, u8 *key, hdr[ETH_ALEN * 2 + 3] = 0; desc->tfm = tfm_michael; - desc->flags = 0; err = crypto_shash_setkey(tfm_michael, key, MIC_KEYLEN); if (err) diff --git a/drivers/net/wireless/intersil/p54/p54pci.c b/drivers/net/wireless/intersil/p54/p54pci.c index 27a49068d32d..57ad56435dda 100644 --- a/drivers/net/wireless/intersil/p54/p54pci.c +++ b/drivers/net/wireless/intersil/p54/p54pci.c @@ -554,7 +554,7 @@ static int p54p_probe(struct pci_dev *pdev, err = pci_enable_device(pdev); if (err) { dev_err(&pdev->dev, "Cannot enable new PCI device\n"); - return err; + goto err_put; } mem_addr = pci_resource_start(pdev, 0); @@ -639,6 +639,7 @@ static int p54p_probe(struct pci_dev *pdev, pci_release_regions(pdev); err_disable_dev: pci_disable_device(pdev); +err_put: pci_dev_put(pdev); return err; } diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 0838af04d681..60ca13e0f15b 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -409,8 +409,8 @@ static int mac80211_hwsim_vendor_cmd_test(struct wiphy *wiphy, int err; u32 val; - err = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, - hwsim_vendor_test_policy, NULL); + err = nla_parse_deprecated(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, + data_len, hwsim_vendor_test_policy, NULL); if (err) return err; if (!tb[QCA_WLAN_VENDOR_ATTR_TEST]) @@ -521,7 +521,7 @@ struct mac80211_hwsim_data { unsigned int rx_filter; bool started, idle, scanning; struct mutex mutex; - struct tasklet_hrtimer beacon_timer; + struct hrtimer beacon_timer; enum ps_mode { PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL } ps; @@ -1460,7 +1460,7 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw) { struct mac80211_hwsim_data *data = hw->priv; data->started = false; - tasklet_hrtimer_cancel(&data->beacon_timer); + hrtimer_cancel(&data->beacon_timer); wiphy_dbg(hw->wiphy, "%s\n", __func__); } @@ -1583,14 +1583,12 @@ static enum hrtimer_restart mac80211_hwsim_beacon(struct hrtimer *timer) { struct mac80211_hwsim_data *data = - container_of(timer, struct mac80211_hwsim_data, - beacon_timer.timer); + container_of(timer, struct mac80211_hwsim_data, beacon_timer); struct ieee80211_hw *hw = data->hw; u64 bcn_int = data->beacon_int; - ktime_t next_bcn; if (!data->started) - goto out; + return HRTIMER_NORESTART; ieee80211_iterate_active_interfaces_atomic( hw, IEEE80211_IFACE_ITER_NORMAL, @@ -1601,12 +1599,9 @@ mac80211_hwsim_beacon(struct hrtimer *timer) bcn_int -= data->bcn_delta; data->bcn_delta = 0; } - - next_bcn = ktime_add(hrtimer_get_expires(timer), - ns_to_ktime(bcn_int * 1000)); - tasklet_hrtimer_start(&data->beacon_timer, next_bcn, HRTIMER_MODE_ABS); -out: - return HRTIMER_NORESTART; + hrtimer_forward(&data->beacon_timer, hrtimer_get_expires(timer), + ns_to_ktime(bcn_int * NSEC_PER_USEC)); + return HRTIMER_RESTART; } static const char * const hwsim_chanwidths[] = { @@ -1680,15 +1675,15 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) mutex_unlock(&data->mutex); if (!data->started || !data->beacon_int) - tasklet_hrtimer_cancel(&data->beacon_timer); - else if (!hrtimer_is_queued(&data->beacon_timer.timer)) { + hrtimer_cancel(&data->beacon_timer); + else if (!hrtimer_is_queued(&data->beacon_timer)) { u64 tsf = mac80211_hwsim_get_tsf(hw, NULL); u32 bcn_int = data->beacon_int; u64 until_tbtt = bcn_int - do_div(tsf, bcn_int); - tasklet_hrtimer_start(&data->beacon_timer, - ns_to_ktime(until_tbtt * 1000), - HRTIMER_MODE_REL); + hrtimer_start(&data->beacon_timer, + ns_to_ktime(until_tbtt * NSEC_PER_USEC), + HRTIMER_MODE_REL_SOFT); } return 0; @@ -1751,7 +1746,7 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, info->enable_beacon, info->beacon_int); vp->bcn_en = info->enable_beacon; if (data->started && - !hrtimer_is_queued(&data->beacon_timer.timer) && + !hrtimer_is_queued(&data->beacon_timer) && info->enable_beacon) { u64 tsf, until_tbtt; u32 bcn_int; @@ -1759,9 +1754,10 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, tsf = mac80211_hwsim_get_tsf(hw, vif); bcn_int = data->beacon_int; until_tbtt = bcn_int - do_div(tsf, bcn_int); - tasklet_hrtimer_start(&data->beacon_timer, - ns_to_ktime(until_tbtt * 1000), - HRTIMER_MODE_REL); + + hrtimer_start(&data->beacon_timer, + ns_to_ktime(until_tbtt * NSEC_PER_USEC), + HRTIMER_MODE_REL_SOFT); } else if (!info->enable_beacon) { unsigned int count = 0; ieee80211_iterate_active_interfaces_atomic( @@ -1770,7 +1766,7 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, wiphy_dbg(hw->wiphy, " beaconing vifs remaining: %u", count); if (count == 0) { - tasklet_hrtimer_cancel(&data->beacon_timer); + hrtimer_cancel(&data->beacon_timer); data->beacon_int = 0; } } @@ -1936,8 +1932,8 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw, struct sk_buff *skb; int err, ps; - err = nla_parse(tb, HWSIM_TM_ATTR_MAX, data, len, - hwsim_testmode_policy, NULL); + err = nla_parse_deprecated(tb, HWSIM_TM_ATTR_MAX, data, len, + hwsim_testmode_policy, NULL); if (err) return err; @@ -2644,7 +2640,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, enum nl80211_band band; const struct ieee80211_ops *ops = &mac80211_hwsim_ops; struct net *net; - int idx; + int idx, i; int n_limits = 0; if (WARN_ON(param->channels > 1 && !param->use_chanctx)) @@ -2768,12 +2764,23 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, goto failed_hw; } + data->if_combination.max_interfaces = 0; + for (i = 0; i < n_limits; i++) + data->if_combination.max_interfaces += + data->if_limits[i].max; + data->if_combination.n_limits = n_limits; - data->if_combination.max_interfaces = 2048; data->if_combination.limits = data->if_limits; - hw->wiphy->iface_combinations = &data->if_combination; - hw->wiphy->n_iface_combinations = 1; + /* + * If we actually were asked to support combinations, + * advertise them - if there's only a single thing like + * only IBSS then don't advertise it as combinations. + */ + if (data->if_combination.max_interfaces > 1) { + hw->wiphy->iface_combinations = &data->if_combination; + hw->wiphy->n_iface_combinations = 1; + } if (param->ciphers) { memcpy(data->ciphers, param->ciphers, @@ -2799,6 +2806,12 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, ieee80211_hw_set(hw, SIGNAL_DBM); ieee80211_hw_set(hw, SUPPORTS_PS); ieee80211_hw_set(hw, TDLS_WIDER_BW); + + /* We only have SW crypto and only implement the A-MPDU API + * (but don't really build A-MPDUs) so can have extended key + * support + */ + ieee80211_hw_set(hw, EXT_KEY_ID_NATIVE); if (rctbl) ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); @@ -2922,9 +2935,9 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); - tasklet_hrtimer_init(&data->beacon_timer, - mac80211_hwsim_beacon, - CLOCK_MONOTONIC, HRTIMER_MODE_ABS); + hrtimer_init(&data->beacon_timer, CLOCK_MONOTONIC, + HRTIMER_MODE_ABS_SOFT); + data->beacon_timer.function = mac80211_hwsim_beacon; err = ieee80211_register_hw(hw); if (err < 0) { @@ -3620,35 +3633,35 @@ done: static const struct genl_ops hwsim_ops[] = { { .cmd = HWSIM_CMD_REGISTER, - .policy = hwsim_genl_policy, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = hwsim_register_received_nl, .flags = GENL_UNS_ADMIN_PERM, }, { .cmd = HWSIM_CMD_FRAME, - .policy = hwsim_genl_policy, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = hwsim_cloned_frame_received_nl, }, { .cmd = HWSIM_CMD_TX_INFO_FRAME, - .policy = hwsim_genl_policy, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = hwsim_tx_info_frame_received_nl, }, { .cmd = HWSIM_CMD_NEW_RADIO, - .policy = hwsim_genl_policy, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = hwsim_new_radio_nl, .flags = GENL_UNS_ADMIN_PERM, }, { .cmd = HWSIM_CMD_DEL_RADIO, - .policy = hwsim_genl_policy, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = hwsim_del_radio_nl, .flags = GENL_UNS_ADMIN_PERM, }, { .cmd = HWSIM_CMD_GET_RADIO, - .policy = hwsim_genl_policy, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = hwsim_get_radio_nl, .dumpit = hwsim_dump_radio_nl, }, @@ -3658,6 +3671,7 @@ static struct genl_family hwsim_genl_family __ro_after_init = { .name = "MAC80211_HWSIM", .version = 1, .maxattr = HWSIM_ATTR_MAX, + .policy = hwsim_genl_policy, .netnsok = true, .module = THIS_MODULE, .ops = hwsim_ops, @@ -3894,6 +3908,8 @@ static int __init init_mac80211_hwsim(void) param.p2p_device = support_p2p_device; param.use_chanctx = channels > 1; param.iftypes = HWSIM_IFTYPE_SUPPORT_MASK; + if (param.p2p_device) + param.iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE); err = mac80211_hwsim_new_radio(NULL, ¶m); if (err < 0) diff --git a/drivers/net/wireless/marvell/mwifiex/Kconfig b/drivers/net/wireless/marvell/mwifiex/Kconfig index 524fd565cb2a..572d187a99f4 100644 --- a/drivers/net/wireless/marvell/mwifiex/Kconfig +++ b/drivers/net/wireless/marvell/mwifiex/Kconfig @@ -9,13 +9,13 @@ config MWIFIEX mwifiex. config MWIFIEX_SDIO - tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797/SD8887/SD8897/SD8977/SD8997" + tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797/SD8887/SD8897/SD8977/SD8987/SD8997" depends on MWIFIEX && MMC select FW_LOADER select WANT_DEV_COREDUMP ---help--- This adds support for wireless adapters based on Marvell - 8786/8787/8797/8887/8897/8997 chipsets with SDIO interface. + 8786/8787/8797/8887/8897/8977/8987/8997 chipsets with SDIO interface. If you choose to build it as a module, it will be called mwifiex_sdio. diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index c46f0a54a0c7..e11a4bb67172 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -4059,8 +4059,8 @@ static int mwifiex_tm_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, if (!priv) return -EINVAL; - err = nla_parse(tb, MWIFIEX_TM_ATTR_MAX, data, len, mwifiex_tm_policy, - NULL); + err = nla_parse_deprecated(tb, MWIFIEX_TM_ATTR_MAX, data, len, + mwifiex_tm_policy, NULL); if (err) return err; @@ -4082,16 +4082,20 @@ static int mwifiex_tm_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, if (mwifiex_send_cmd(priv, 0, 0, 0, hostcmd, true)) { dev_err(priv->adapter->dev, "Failed to process hostcmd\n"); + kfree(hostcmd); return -EFAULT; } /* process hostcmd response*/ skb = cfg80211_testmode_alloc_reply_skb(wiphy, hostcmd->len); - if (!skb) + if (!skb) { + kfree(hostcmd); return -ENOMEM; + } err = nla_put(skb, MWIFIEX_TM_ATTR_DATA, hostcmd->len, hostcmd->cmd); if (err) { + kfree(hostcmd); kfree_skb(skb); return -EMSGSIZE; } diff --git a/drivers/net/wireless/marvell/mwifiex/cfp.c b/drivers/net/wireless/marvell/mwifiex/cfp.c index bfe84e55df77..f1522fb1c1e8 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfp.c +++ b/drivers/net/wireless/marvell/mwifiex/cfp.c @@ -531,5 +531,8 @@ u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv, rate_index = (rx_rate > MWIFIEX_RATE_INDEX_OFDM0) ? rx_rate - 1 : rx_rate; + if (rate_index >= MWIFIEX_MAX_AC_RX_RATES) + rate_index = MWIFIEX_MAX_AC_RX_RATES - 1; + return rate_index; } diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c index 60db2b969e20..8c35441fd9b7 100644 --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c @@ -341,6 +341,12 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) sleep_cfm_tmp = dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm) + MWIFIEX_TYPE_LEN); + if (!sleep_cfm_tmp) { + mwifiex_dbg(adapter, ERROR, + "SLEEP_CFM: dev_alloc_skb failed\n"); + return -ENOMEM; + } + skb_put(sleep_cfm_tmp, sizeof(struct mwifiex_opt_sleep_confirm) + MWIFIEX_TYPE_LEN); put_unaligned_le32(MWIFIEX_USB_TYPE_CMD, sleep_cfm_tmp->data); diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index 20cee5c397fb..f6da8edab7f1 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -1282,8 +1282,7 @@ static struct net_device_stats *mwifiex_get_stats(struct net_device *dev) static u16 mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb, - struct net_device *sb_dev, - select_queue_fallback_t fallback) + struct net_device *sb_dev) { skb->priority = cfg80211_classify8021d(skb, NULL); return mwifiex_1d_to_wmm_queue[skb->priority]; diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index a85648342d15..24c041dad9f6 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -181,7 +181,7 @@ static int mwifiex_sdio_resume(struct device *dev) adapter = card->adapter; - if (test_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags)) { + if (!test_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags)) { mwifiex_dbg(adapter, WARN, "device already resumed\n"); return 0; @@ -491,6 +491,8 @@ static void mwifiex_sdio_coredump(struct device *dev) #define SDIO_DEVICE_ID_MARVELL_8801 (0x9139) /* Device ID for SD8977 */ #define SDIO_DEVICE_ID_MARVELL_8977 (0x9145) +/* Device ID for SD8987 */ +#define SDIO_DEVICE_ID_MARVELL_8987 (0x9149) /* Device ID for SD8997 */ #define SDIO_DEVICE_ID_MARVELL_8997 (0x9141) @@ -511,6 +513,8 @@ static const struct sdio_device_id mwifiex_ids[] = { .driver_data = (unsigned long)&mwifiex_sdio_sd8801}, {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8977), .driver_data = (unsigned long)&mwifiex_sdio_sd8977}, + {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8987), + .driver_data = (unsigned long)&mwifiex_sdio_sd8987}, {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8997), .driver_data = (unsigned long)&mwifiex_sdio_sd8997}, {}, @@ -2731,4 +2735,5 @@ MODULE_FIRMWARE(SD8797_DEFAULT_FW_NAME); MODULE_FIRMWARE(SD8897_DEFAULT_FW_NAME); MODULE_FIRMWARE(SD8887_DEFAULT_FW_NAME); MODULE_FIRMWARE(SD8977_DEFAULT_FW_NAME); +MODULE_FIRMWARE(SD8987_DEFAULT_FW_NAME); MODULE_FIRMWARE(SD8997_DEFAULT_FW_NAME); diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h b/drivers/net/wireless/marvell/mwifiex/sdio.h index 912de2cde8d9..f672bdf52cc1 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.h +++ b/drivers/net/wireless/marvell/mwifiex/sdio.h @@ -37,6 +37,7 @@ #define SD8887_DEFAULT_FW_NAME "mrvl/sd8887_uapsta.bin" #define SD8801_DEFAULT_FW_NAME "mrvl/sd8801_uapsta.bin" #define SD8977_DEFAULT_FW_NAME "mrvl/sd8977_uapsta.bin" +#define SD8987_DEFAULT_FW_NAME "mrvl/sd8987_uapsta.bin" #define SD8997_DEFAULT_FW_NAME "mrvl/sd8997_uapsta.bin" #define BLOCK_MODE 1 @@ -526,6 +527,58 @@ static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8887 = { 0x68, 0x69, 0x6a}, }; +static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8987 = { + .start_rd_port = 0, + .start_wr_port = 0, + .base_0_reg = 0xF8, + .base_1_reg = 0xF9, + .poll_reg = 0x5C, + .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK | + CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK, + .host_int_rsr_reg = 0x4, + .host_int_status_reg = 0x0C, + .host_int_mask_reg = 0x08, + .status_reg_0 = 0xE8, + .status_reg_1 = 0xE9, + .sdio_int_mask = 0xff, + .data_port_mask = 0xffffffff, + .io_port_0_reg = 0xE4, + .io_port_1_reg = 0xE5, + .io_port_2_reg = 0xE6, + .max_mp_regs = 196, + .rd_bitmap_l = 0x10, + .rd_bitmap_u = 0x11, + .rd_bitmap_1l = 0x12, + .rd_bitmap_1u = 0x13, + .wr_bitmap_l = 0x14, + .wr_bitmap_u = 0x15, + .wr_bitmap_1l = 0x16, + .wr_bitmap_1u = 0x17, + .rd_len_p0_l = 0x18, + .rd_len_p0_u = 0x19, + .card_misc_cfg_reg = 0xd8, + .card_cfg_2_1_reg = 0xd9, + .cmd_rd_len_0 = 0xc0, + .cmd_rd_len_1 = 0xc1, + .cmd_rd_len_2 = 0xc2, + .cmd_rd_len_3 = 0xc3, + .cmd_cfg_0 = 0xc4, + .cmd_cfg_1 = 0xc5, + .cmd_cfg_2 = 0xc6, + .cmd_cfg_3 = 0xc7, + .fw_dump_host_ready = 0xcc, + .fw_dump_ctrl = 0xf9, + .fw_dump_start = 0xf1, + .fw_dump_end = 0xf8, + .func1_dump_reg_start = 0x10, + .func1_dump_reg_end = 0x17, + .func1_scratch_reg = 0xE8, + .func1_spec_reg_num = 13, + .func1_spec_reg_table = {0x08, 0x58, 0x5C, 0x5D, 0x60, + 0x61, 0x62, 0x64, 0x65, 0x66, + 0x68, 0x69, 0x6a}, +}; + static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = { .firmware = SD8786_DEFAULT_FW_NAME, .reg = &mwifiex_reg_sd87xx, @@ -633,6 +686,22 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = { .can_ext_scan = true, }; +static const struct mwifiex_sdio_device mwifiex_sdio_sd8987 = { + .firmware = SD8987_DEFAULT_FW_NAME, + .reg = &mwifiex_reg_sd8987, + .max_ports = 32, + .mp_agg_pkt_limit = 16, + .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, + .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX, + .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX, + .supports_sdio_new_mode = true, + .has_control_mask = false, + .can_dump_fw = true, + .fw_dump_enh = true, + .can_auto_tdls = true, + .can_ext_scan = true, +}; + static const struct mwifiex_sdio_device mwifiex_sdio_sd8801 = { .firmware = SD8801_DEFAULT_FW_NAME, .reg = &mwifiex_reg_sd87xx, diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c index 69e3b624adbb..24b33e20e7a9 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c @@ -1025,17 +1025,14 @@ mwifiex_create_custom_regdomain(struct mwifiex_private *priv, struct ieee80211_regdomain *regd; struct ieee80211_reg_rule *rule; bool new_rule; - int regd_size, idx, freq, prev_freq = 0; + int idx, freq, prev_freq = 0; u32 bw, prev_bw = 0; u8 chflags, prev_chflags = 0, valid_rules = 0; if (WARN_ON_ONCE(num_chan > NL80211_MAX_SUPP_REG_RULES)) return ERR_PTR(-EINVAL); - regd_size = sizeof(struct ieee80211_regdomain) + - num_chan * sizeof(struct ieee80211_reg_rule); - - regd = kzalloc(regd_size, GFP_KERNEL); + regd = kzalloc(struct_size(regd, reg_rules, num_chan), GFP_KERNEL); if (!regd) return ERR_PTR(-ENOMEM); diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c index a327fc5b36e3..8b3123cb84c8 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c @@ -27,9 +27,9 @@ #define MWIFIEX_IBSS_CONNECT_EVT_FIX_SIZE 12 -static int mwifiex_check_ibss_peer_capabilties(struct mwifiex_private *priv, - struct mwifiex_sta_node *sta_ptr, - struct sk_buff *event) +static int mwifiex_check_ibss_peer_capabilities(struct mwifiex_private *priv, + struct mwifiex_sta_node *sta_ptr, + struct sk_buff *event) { int evt_len, ele_len; u8 *curr; @@ -42,7 +42,7 @@ static int mwifiex_check_ibss_peer_capabilties(struct mwifiex_private *priv, evt_len = event->len; curr = event->data; - mwifiex_dbg_dump(priv->adapter, EVT_D, "ibss peer capabilties:", + mwifiex_dbg_dump(priv->adapter, EVT_D, "ibss peer capabilities:", event->data, event->len); skb_push(event, MWIFIEX_IBSS_CONNECT_EVT_FIX_SIZE); @@ -937,8 +937,8 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) ibss_sta_addr); sta_ptr = mwifiex_add_sta_entry(priv, ibss_sta_addr); if (sta_ptr && adapter->adhoc_11n_enabled) { - mwifiex_check_ibss_peer_capabilties(priv, sta_ptr, - adapter->event_skb); + mwifiex_check_ibss_peer_capabilities(priv, sta_ptr, + adapter->event_skb); if (sta_ptr->is_11n_enabled) for (i = 0; i < MAX_NUM_TID; i++) sta_ptr->ampdu_sta[i] = diff --git a/drivers/net/wireless/marvell/mwifiex/sta_rx.c b/drivers/net/wireless/marvell/mwifiex/sta_rx.c index fb28a5c7f441..52a2ce2e78b0 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_rx.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_rx.c @@ -250,7 +250,8 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, local_rx_pd->nf); } } else { - if (rx_pkt_type != PKT_TYPE_BAR) + if (rx_pkt_type != PKT_TYPE_BAR && + local_rx_pd->priority < MAX_NUM_TID) priv->rx_seq[local_rx_pd->priority] = seq_num; memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN); diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c index ca759d9c0253..86bfa1b9ef9d 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_event.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c @@ -23,8 +23,8 @@ #define MWIFIEX_BSS_START_EVT_FIX_SIZE 12 -static int mwifiex_check_uap_capabilties(struct mwifiex_private *priv, - struct sk_buff *event) +static int mwifiex_check_uap_capabilities(struct mwifiex_private *priv, + struct sk_buff *event) { int evt_len; u8 *curr; @@ -38,7 +38,7 @@ static int mwifiex_check_uap_capabilties(struct mwifiex_private *priv, evt_len = event->len; curr = event->data; - mwifiex_dbg_dump(priv->adapter, EVT_D, "uap capabilties:", + mwifiex_dbg_dump(priv->adapter, EVT_D, "uap capabilities:", event->data, event->len); skb_push(event, MWIFIEX_BSS_START_EVT_FIX_SIZE); @@ -201,7 +201,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) ETH_ALEN); if (priv->hist_data) mwifiex_hist_data_reset(priv); - mwifiex_check_uap_capabilties(priv, adapter->event_skb); + mwifiex_check_uap_capabilities(priv, adapter->event_skb); break; case EVENT_UAP_MIC_COUNTERMEASURES: /* For future development */ diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c index 8e4e9b6919e0..c4db6417748f 100644 --- a/drivers/net/wireless/marvell/mwl8k.c +++ b/drivers/net/wireless/marvell/mwl8k.c @@ -441,6 +441,9 @@ static const struct ieee80211_rate mwl8k_rates_50[] = { #define MWL8K_CMD_UPDATE_STADB 0x1123 #define MWL8K_CMD_BASTREAM 0x1125 +#define MWL8K_LEGACY_5G_RATE_OFFSET \ + (ARRAY_SIZE(mwl8k_rates_24) - ARRAY_SIZE(mwl8k_rates_50)) + static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize) { u16 command = le16_to_cpu(cmd); @@ -1016,8 +1019,9 @@ mwl8k_rxd_ap_process(void *_rxd, struct ieee80211_rx_status *status, if (rxd->channel > 14) { status->band = NL80211_BAND_5GHZ; - if (!(status->encoding == RX_ENC_HT)) - status->rate_idx -= 5; + if (!(status->encoding == RX_ENC_HT) && + status->rate_idx >= MWL8K_LEGACY_5G_RATE_OFFSET) + status->rate_idx -= MWL8K_LEGACY_5G_RATE_OFFSET; } else { status->band = NL80211_BAND_2GHZ; } @@ -1124,8 +1128,9 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status, if (rxd->channel > 14) { status->band = NL80211_BAND_5GHZ; - if (!(status->encoding == RX_ENC_HT)) - status->rate_idx -= 5; + if (!(status->encoding == RX_ENC_HT) && + status->rate_idx >= MWL8K_LEGACY_5G_RATE_OFFSET) + status->rate_idx -= MWL8K_LEGACY_5G_RATE_OFFSET; } else { status->band = NL80211_BAND_2GHZ; } @@ -2234,8 +2239,10 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) dma_size = le16_to_cpu(cmd->length); dma_addr = pci_map_single(priv->pdev, cmd, dma_size, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(priv->pdev, dma_addr)) - return -ENOMEM; + if (pci_dma_mapping_error(priv->pdev, dma_addr)) { + rc = -ENOMEM; + goto exit; + } priv->hostcmd_wait = &cmd_wait; iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR); @@ -2275,6 +2282,7 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) ms); } +exit: if (bitmap) mwl8k_enable_bsses(hw, true, bitmap); @@ -4631,7 +4639,7 @@ static void mwl8k_tx_poll(unsigned long data) limit = 32; - spin_lock_bh(&priv->tx_lock); + spin_lock(&priv->tx_lock); for (i = 0; i < mwl8k_tx_queues(priv); i++) limit -= mwl8k_txq_reclaim(hw, i, limit, 0); @@ -4641,7 +4649,7 @@ static void mwl8k_tx_poll(unsigned long data) priv->tx_wait = NULL; } - spin_unlock_bh(&priv->tx_lock); + spin_unlock(&priv->tx_lock); if (limit) { writel(~MWL8K_A2H_INT_TX_DONE, diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig index dbe8c70a8f73..30e44e4c3c7d 100644 --- a/drivers/net/wireless/mediatek/mt76/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/Kconfig @@ -22,3 +22,4 @@ config MT76x02_USB source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt7603/Kconfig" +source "drivers/net/wireless/mediatek/mt76/mt7615/Kconfig" diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index 3fd1b64b4aa7..7beae2354a24 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -16,10 +16,11 @@ CFLAGS_mt76x02_trace.o := -I$(src) mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o \ mt76x02_eeprom.o mt76x02_phy.o mt76x02_mmio.o \ mt76x02_txrx.o mt76x02_trace.o mt76x02_debugfs.o \ - mt76x02_dfs.o + mt76x02_dfs.o mt76x02_beacon.o mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o obj-$(CONFIG_MT76x0_COMMON) += mt76x0/ obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ obj-$(CONFIG_MT7603E) += mt7603/ +obj-$(CONFIG_MT7615E) += mt7615/ diff --git a/drivers/net/wireless/mediatek/mt76/agg-rx.c b/drivers/net/wireless/mediatek/mt76/agg-rx.c index 73c8b2805c97..27e3ff039c48 100644 --- a/drivers/net/wireless/mediatek/mt76/agg-rx.c +++ b/drivers/net/wireless/mediatek/mt76/agg-rx.c @@ -135,7 +135,7 @@ mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames) return; status->tid = le16_to_cpu(bar->control) >> 12; - seqno = le16_to_cpu(bar->start_seq_num) >> 4; + seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(bar->start_seq_num)); tid = rcu_dereference(wcid->aggr[status->tid]); if (!tid) return; diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c index a5adf22c3ffa..c6a9fe2aef9d 100644 --- a/drivers/net/wireless/mediatek/mt76/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/debugfs.c @@ -43,14 +43,15 @@ mt76_queues_read(struct seq_file *s, void *data) int i; for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) { - struct mt76_queue *q = &dev->q_tx[i]; + struct mt76_sw_queue *q = &dev->q_tx[i]; - if (!q->ndesc) + if (!q->q) continue; seq_printf(s, "%d: queued=%d head=%d tail=%d swq_queued=%d\n", - i, q->queued, q->head, q->tail, q->swq_queued); + i, q->q->queued, q->q->head, q->q->tail, + q->swq_queued); } return 0; diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 6eedc0ec7661..4381155375e1 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -18,16 +18,20 @@ #include "mt76.h" #include "dma.h" -#define DMA_DUMMY_TXWI ((void *) ~0) - static int -mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q) +mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, + int idx, int n_desc, int bufsize, + u32 ring_base) { int size; int i; spin_lock_init(&q->lock); - INIT_LIST_HEAD(&q->swq); + + q->regs = dev->mmio.regs + ring_base + idx * MT_RING_SIZE; + q->ndesc = n_desc; + q->buf_size = bufsize; + q->hw_idx = idx; size = q->ndesc * sizeof(struct mt76_desc); q->desc = dmam_alloc_coherent(dev->dev, size, &q->desc_dma, GFP_KERNEL); @@ -43,10 +47,10 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q) for (i = 0; i < q->ndesc; i++) q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); - iowrite32(q->desc_dma, &q->regs->desc_base); - iowrite32(0, &q->regs->cpu_idx); - iowrite32(0, &q->regs->dma_idx); - iowrite32(q->ndesc, &q->regs->ring_size); + writel(q->desc_dma, &q->regs->desc_base); + writel(0, &q->regs->cpu_idx); + writel(0, &q->regs->dma_idx); + writel(q->ndesc, &q->regs->ring_size); return 0; } @@ -61,7 +65,7 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q, int i, idx = -1; if (txwi) - q->entry[q->head].txwi = DMA_DUMMY_TXWI; + q->entry[q->head].txwi = DMA_DUMMY_DATA; for (i = 0; i < nbufs; i += 2, buf += 2) { u32 buf0 = buf[0].addr, buf1 = 0; @@ -120,9 +124,12 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx, DMA_TO_DEVICE); } - if (e->txwi == DMA_DUMMY_TXWI) + if (e->txwi == DMA_DUMMY_DATA) e->txwi = NULL; + if (e->skb == DMA_DUMMY_DATA) + e->skb = NULL; + *prev_e = *e; memset(e, 0, sizeof(*e)); } @@ -130,57 +137,70 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx, static void mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) { - q->head = ioread32(&q->regs->dma_idx); + writel(q->desc_dma, &q->regs->desc_base); + writel(q->ndesc, &q->regs->ring_size); + q->head = readl(&q->regs->dma_idx); q->tail = q->head; - iowrite32(q->head, &q->regs->cpu_idx); + writel(q->head, &q->regs->cpu_idx); } static void mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush) { - struct mt76_queue *q = &dev->q_tx[qid]; + struct mt76_sw_queue *sq = &dev->q_tx[qid]; + struct mt76_queue *q = sq->q; struct mt76_queue_entry entry; + unsigned int n_swq_queued[4] = {}; + unsigned int n_queued = 0; bool wake = false; - int last; + int i, last; - if (!q->ndesc) + if (!q) return; - spin_lock_bh(&q->lock); if (flush) last = -1; else - last = ioread32(&q->regs->dma_idx); + last = readl(&q->regs->dma_idx); - while (q->queued && q->tail != last) { + while ((q->queued > n_queued) && q->tail != last) { mt76_dma_tx_cleanup_idx(dev, q, q->tail, &entry); if (entry.schedule) - q->swq_queued--; + n_swq_queued[entry.qid]++; q->tail = (q->tail + 1) % q->ndesc; - q->queued--; + n_queued++; - if (entry.skb) { - spin_unlock_bh(&q->lock); - dev->drv->tx_complete_skb(dev, q, &entry, flush); - spin_lock_bh(&q->lock); - } + if (entry.skb) + dev->drv->tx_complete_skb(dev, qid, &entry); if (entry.txwi) { - mt76_put_txwi(dev, entry.txwi); + if (!(dev->drv->txwi_flags & MT_TXWI_NO_FREE)) + mt76_put_txwi(dev, entry.txwi); wake = !flush; } if (!flush && q->tail == last) - last = ioread32(&q->regs->dma_idx); + last = readl(&q->regs->dma_idx); } - if (!flush) - mt76_txq_schedule(dev, q); - else + spin_lock_bh(&q->lock); + + q->queued -= n_queued; + for (i = 0; i < ARRAY_SIZE(n_swq_queued); i++) { + if (!n_swq_queued[i]) + continue; + + dev->q_tx[i].swq_queued -= n_swq_queued[i]; + } + + if (flush) mt76_dma_sync_idx(dev, q); - wake = wake && qid < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8; + wake = wake && q->stopped && + qid < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8; + if (wake) + q->stopped = false; if (!q->queued) wake_up(&dev->tx_wait); @@ -239,20 +259,20 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush, static void mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q) { - iowrite32(q->head, &q->regs->cpu_idx); + writel(q->head, &q->regs->cpu_idx); } static int mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, struct sk_buff *skb, u32 tx_info) { - struct mt76_queue *q = &dev->q_tx[qid]; + struct mt76_queue *q = dev->q_tx[qid].q; struct mt76_queue_buf buf; dma_addr_t addr; addr = dma_map_single(dev->dev, skb->data, skb->len, DMA_TO_DEVICE); - if (dma_mapping_error(dev->dev, addr)) + if (unlikely(dma_mapping_error(dev->dev, addr))) return -ENOMEM; buf.addr = addr; @@ -266,80 +286,85 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, return 0; } -int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, - struct sk_buff *skb, struct mt76_wcid *wcid, - struct ieee80211_sta *sta) +static int +mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, + struct sk_buff *skb, struct mt76_wcid *wcid, + struct ieee80211_sta *sta) { + struct mt76_queue *q = dev->q_tx[qid].q; + struct mt76_tx_info tx_info = { + .skb = skb, + }; + int len, n = 0, ret = -ENOMEM; struct mt76_queue_entry e; struct mt76_txwi_cache *t; - struct mt76_queue_buf buf[32]; struct sk_buff *iter; dma_addr_t addr; - int len; - u32 tx_info = 0; - int n, ret; + u8 *txwi; t = mt76_get_txwi(dev); if (!t) { ieee80211_free_txskb(dev->hw, skb); return -ENOMEM; } + txwi = mt76_get_txwi_ptr(dev, t); skb->prev = skb->next = NULL; - dma_sync_single_for_cpu(dev->dev, t->dma_addr, sizeof(t->txwi), - DMA_TO_DEVICE); - ret = dev->drv->tx_prepare_skb(dev, &t->txwi, skb, q, wcid, sta, - &tx_info); - dma_sync_single_for_device(dev->dev, t->dma_addr, sizeof(t->txwi), - DMA_TO_DEVICE); - if (ret < 0) - goto free; + if (dev->drv->tx_aligned4_skbs) + mt76_insert_hdr_pad(skb); - len = skb->len - skb->data_len; + len = skb_headlen(skb); addr = dma_map_single(dev->dev, skb->data, len, DMA_TO_DEVICE); - if (dma_mapping_error(dev->dev, addr)) { - ret = -ENOMEM; + if (unlikely(dma_mapping_error(dev->dev, addr))) goto free; - } - n = 0; - buf[n].addr = t->dma_addr; - buf[n++].len = dev->drv->txwi_size; - buf[n].addr = addr; - buf[n++].len = len; + tx_info.buf[n].addr = t->dma_addr; + tx_info.buf[n++].len = dev->drv->txwi_size; + tx_info.buf[n].addr = addr; + tx_info.buf[n++].len = len; skb_walk_frags(skb, iter) { - if (n == ARRAY_SIZE(buf)) + if (n == ARRAY_SIZE(tx_info.buf)) goto unmap; addr = dma_map_single(dev->dev, iter->data, iter->len, DMA_TO_DEVICE); - if (dma_mapping_error(dev->dev, addr)) + if (unlikely(dma_mapping_error(dev->dev, addr))) goto unmap; - buf[n].addr = addr; - buf[n++].len = iter->len; + tx_info.buf[n].addr = addr; + tx_info.buf[n++].len = iter->len; } + tx_info.nbuf = n; + + dma_sync_single_for_cpu(dev->dev, t->dma_addr, dev->drv->txwi_size, + DMA_TO_DEVICE); + ret = dev->drv->tx_prepare_skb(dev, txwi, qid, wcid, sta, &tx_info); + dma_sync_single_for_device(dev->dev, t->dma_addr, dev->drv->txwi_size, + DMA_TO_DEVICE); + if (ret < 0) + goto unmap; - if (q->queued + (n + 1) / 2 >= q->ndesc - 1) + if (q->queued + (tx_info.nbuf + 1) / 2 >= q->ndesc - 1) { + ret = -ENOMEM; goto unmap; + } - return mt76_dma_add_buf(dev, q, buf, n, tx_info, skb, t); + return mt76_dma_add_buf(dev, q, tx_info.buf, tx_info.nbuf, + tx_info.info, tx_info.skb, t); unmap: - ret = -ENOMEM; for (n--; n > 0; n--) - dma_unmap_single(dev->dev, buf[n].addr, buf[n].len, - DMA_TO_DEVICE); + dma_unmap_single(dev->dev, tx_info.buf[n].addr, + tx_info.buf[n].len, DMA_TO_DEVICE); free: - e.skb = skb; + e.skb = tx_info.skb; e.txwi = t; - dev->drv->tx_complete_skb(dev, q, &e, true); + dev->drv->tx_complete_skb(dev, qid, &e); mt76_put_txwi(dev, t); return ret; } -EXPORT_SYMBOL_GPL(mt76_dma_tx_queue_skb); static int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) @@ -361,7 +386,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) break; addr = dma_map_single(dev->dev, buf, len, DMA_FROM_DEVICE); - if (dma_mapping_error(dev->dev, addr)) { + if (unlikely(dma_mapping_error(dev->dev, addr))) { skb_free_frag(buf); break; } diff --git a/drivers/net/wireless/mediatek/mt76/dma.h b/drivers/net/wireless/mediatek/mt76/dma.h index e3292df5e9b2..03dd2bafa4e8 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.h +++ b/drivers/net/wireless/mediatek/mt76/dma.h @@ -16,6 +16,8 @@ #ifndef __MT76_DMA_H #define __MT76_DMA_H +#define DMA_DUMMY_DATA ((void *)~0) + #define MT_RING_SIZE 0x10 #define MT_DMA_CTL_SD_LEN1 GENMASK(13, 0) diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index a1529920d877..b7a49ae6b327 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -94,8 +94,8 @@ mt76_eeprom_override(struct mt76_dev *dev) return; mac = of_get_mac_address(np); - if (mac) - memcpy(dev->macaddr, mac, ETH_ALEN); + if (!IS_ERR(mac)) + ether_addr_copy(dev->macaddr, mac); #endif if (!is_valid_ether_addr(dev->macaddr)) { diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index a033745adb2f..5b6a81ee457e 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -214,6 +214,8 @@ mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband, vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC | IEEE80211_VHT_CAP_RXSTBC_1 | IEEE80211_VHT_CAP_SHORT_GI_80 | + IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | + IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | (3 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT); return 0; @@ -369,10 +371,16 @@ void mt76_unregister_device(struct mt76_dev *dev) mt76_tx_status_check(dev, NULL, true); ieee80211_unregister_hw(hw); - mt76_tx_free(dev); } EXPORT_SYMBOL_GPL(mt76_unregister_device); +void mt76_free_device(struct mt76_dev *dev) +{ + mt76_tx_free(dev); + ieee80211_free_hw(dev->hw); +} +EXPORT_SYMBOL_GPL(mt76_free_device); + void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb) { if (!test_bit(MT76_STATE_RUNNING, &dev->state)) { @@ -384,17 +392,20 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb) } EXPORT_SYMBOL_GPL(mt76_rx); -static bool mt76_has_tx_pending(struct mt76_dev *dev) +bool mt76_has_tx_pending(struct mt76_dev *dev) { + struct mt76_queue *q; int i; for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) { - if (dev->q_tx[i].queued) + q = dev->q_tx[i].q; + if (q && q->queued) return true; } return false; } +EXPORT_SYMBOL_GPL(mt76_has_tx_pending); void mt76_set_channel(struct mt76_dev *dev) { @@ -560,6 +571,7 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) struct ieee80211_sta *sta; struct mt76_wcid *wcid = status->wcid; bool ps; + int i; if (ieee80211_is_pspoll(hdr->frame_control) && !wcid) { sta = ieee80211_find_sta_by_ifaddr(dev->hw, hdr->addr2, NULL); @@ -606,6 +618,20 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) dev->drv->sta_ps(dev, sta, ps); ieee80211_sta_ps_transition(sta, ps); + + if (ps) + return; + + for (i = 0; i < ARRAY_SIZE(sta->txq); i++) { + struct mt76_txq *mtxq; + + if (!sta->txq[i]) + continue; + + mtxq = (struct mt76_txq *) sta->txq[i]->drv_priv; + if (!skb_queue_empty(&mtxq->retry_q)) + ieee80211_schedule_txq(dev->hw, sta->txq[i]); + } } void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, @@ -679,19 +705,15 @@ out: return ret; } -static void -mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; - int idx = wcid->idx; - int i; + int i, idx = wcid->idx; rcu_assign_pointer(dev->wcid[idx], NULL); synchronize_rcu(); - mutex_lock(&dev->mutex); - if (dev->drv->sta_remove) dev->drv->sta_remove(dev, vif, sta); @@ -699,7 +721,15 @@ mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, for (i = 0; i < ARRAY_SIZE(sta->txq); i++) mt76_txq_remove(dev, sta->txq[i]); mt76_wcid_free(dev->wcid_mask, idx); +} +EXPORT_SYMBOL_GPL(__mt76_sta_remove); +static void +mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + mutex_lock(&dev->mutex); + __mt76_sta_remove(dev, vif, sta); mutex_unlock(&dev->mutex); } @@ -733,7 +763,7 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt76_dev *dev = hw->priv; int n_chains = hweight8(dev->antenna_mask); - *dbm = dev->txpower_cur / 2; + *dbm = DIV_ROUND_UP(dev->txpower_cur, 2); /* convert from per-chain power to combined * output on 2x2 devices @@ -783,3 +813,10 @@ void mt76_csa_check(struct mt76_dev *dev) __mt76_csa_check, dev); } EXPORT_SYMBOL_GPL(mt76_csa_check); + +int +mt76_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) +{ + return 0; +} +EXPORT_SYMBOL_GPL(mt76_set_tim); diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c index 1d6bbce76041..38368d19aa6f 100644 --- a/drivers/net/wireless/mediatek/mt76/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mmio.c @@ -21,7 +21,7 @@ static u32 mt76_mmio_rr(struct mt76_dev *dev, u32 offset) { u32 val; - val = ioread32(dev->mmio.regs + offset); + val = readl(dev->mmio.regs + offset); trace_reg_rr(dev, offset, val); return val; @@ -30,7 +30,7 @@ static u32 mt76_mmio_rr(struct mt76_dev *dev, u32 offset) static void mt76_mmio_wr(struct mt76_dev *dev, u32 offset, u32 val) { trace_reg_wr(dev, offset, val); - iowrite32(val, dev->mmio.regs + offset); + writel(val, dev->mmio.regs + offset); } static u32 mt76_mmio_rmw(struct mt76_dev *dev, u32 offset, u32 mask, u32 val) @@ -70,6 +70,19 @@ static int mt76_mmio_rd_rp(struct mt76_dev *dev, u32 base, return 0; } +void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, + u32 clear, u32 set) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->mmio.irq_lock, flags); + dev->mmio.irqmask &= ~clear; + dev->mmio.irqmask |= set; + mt76_mmio_wr(dev, addr, dev->mmio.irqmask); + spin_unlock_irqrestore(&dev->mmio.irq_lock, flags); +} +EXPORT_SYMBOL_GPL(mt76_set_irq_mask); + void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs) { static const struct mt76_bus_ops mt76_mmio_ops = { diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 5dfb0601f101..8ecbf81a906f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -69,6 +69,7 @@ enum mt76_txq_id { MT_TXQ_MCU, MT_TXQ_BEACON, MT_TXQ_CAB, + MT_TXQ_FWDL, __MT_TXQ_MAX }; @@ -83,12 +84,11 @@ struct mt76_queue_buf { int len; }; -struct mt76u_buf { - struct mt76_dev *dev; - struct urb *urb; - size_t len; - void *buf; - bool done; +struct mt76_tx_info { + struct mt76_queue_buf buf[32]; + struct sk_buff *skb; + int nbuf; + u32 info; }; struct mt76_queue_entry { @@ -98,9 +98,11 @@ struct mt76_queue_entry { }; union { struct mt76_txwi_cache *txwi; - struct mt76u_buf ubuf; + struct urb *urb; }; + enum mt76_txq_id qid; bool schedule; + bool done; }; struct mt76_queue_regs { @@ -117,15 +119,13 @@ struct mt76_queue { struct mt76_queue_entry *entry; struct mt76_desc *desc; - struct list_head swq; - int swq_queued; - u16 first; u16 head; u16 tail; int ndesc; int queued; int buf_size; + bool stopped; u8 buf_offset; u8 hw_idx; @@ -133,7 +133,13 @@ struct mt76_queue { dma_addr_t desc_dma; struct sk_buff *rx_head; struct page_frag_cache rx_page; - spinlock_t rx_page_lock; +}; + +struct mt76_sw_queue { + struct mt76_queue *q; + + struct list_head swq; + int swq_queued; }; struct mt76_mcu_ops { @@ -143,18 +149,21 @@ struct mt76_mcu_ops { const struct mt76_reg_pair *rp, int len); int (*mcu_rd_rp)(struct mt76_dev *dev, u32 base, struct mt76_reg_pair *rp, int len); + int (*mcu_restart)(struct mt76_dev *dev); }; struct mt76_queue_ops { int (*init)(struct mt76_dev *dev); - int (*alloc)(struct mt76_dev *dev, struct mt76_queue *q); + int (*alloc)(struct mt76_dev *dev, struct mt76_queue *q, + int idx, int n_desc, int bufsize, + u32 ring_base); int (*add_buf)(struct mt76_dev *dev, struct mt76_queue *q, struct mt76_queue_buf *buf, int nbufs, u32 info, struct sk_buff *skb, void *txwi); - int (*tx_queue_skb)(struct mt76_dev *dev, struct mt76_queue *q, + int (*tx_queue_skb)(struct mt76_dev *dev, enum mt76_txq_id qid, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta); @@ -181,6 +190,11 @@ enum mt76_wcid_flags { DECLARE_EWMA(signal, 10, 8); +#define MT_WCID_TX_INFO_RATE GENMASK(15, 0) +#define MT_WCID_TX_INFO_NSS GENMASK(17, 16) +#define MT_WCID_TX_INFO_TXPWR_ADJ GENMASK(25, 18) +#define MT_WCID_TX_INFO_SET BIT(31) + struct mt76_wcid { struct mt76_rx_tid __rcu *aggr[IEEE80211_NUM_TIDS]; @@ -199,18 +213,14 @@ struct mt76_wcid { u8 rx_check_pn; u8 rx_key_pn[IEEE80211_NUM_TIDS][6]; - __le16 tx_rate; - bool tx_rate_set; - u8 tx_rate_nss; - s8 max_txpwr_adj; + u32 tx_info; bool sw_iv; u8 packet_id; }; struct mt76_txq { - struct list_head list; - struct mt76_queue *hwq; + struct mt76_sw_queue *swq; struct mt76_wcid *wcid; struct sk_buff_head retry_q; @@ -221,11 +231,11 @@ struct mt76_txq { }; struct mt76_txwi_cache { - u32 txwi[8]; - dma_addr_t dma_addr; struct list_head list; -}; + dma_addr_t dma_addr; + struct sk_buff *skb; +}; struct mt76_rx_tid { struct rcu_head rcu_head; @@ -278,18 +288,22 @@ struct mt76_hw_cap { bool has_5ghz; }; +#define MT_TXWI_NO_FREE BIT(0) + struct mt76_driver_ops { + bool tx_aligned4_skbs; + u32 txwi_flags; u16 txwi_size; void (*update_survey)(struct mt76_dev *dev); int (*tx_prepare_skb)(struct mt76_dev *dev, void *txwi_ptr, - struct sk_buff *skb, struct mt76_queue *q, - struct mt76_wcid *wcid, - struct ieee80211_sta *sta, u32 *tx_info); + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info); - void (*tx_complete_skb)(struct mt76_dev *dev, struct mt76_queue *q, - struct mt76_queue_entry *e, bool flush); + void (*tx_complete_skb)(struct mt76_dev *dev, enum mt76_txq_id qid, + struct mt76_queue_entry *e); bool (*tx_status_data)(struct mt76_dev *dev, u8 *update); @@ -376,7 +390,6 @@ struct mt76_usb { u8 data[32]; struct tasklet_struct rx_tasklet; - struct tasklet_struct tx_tasklet; struct delayed_work stat_work; u8 out_ep[__MT_EP_OUT_MAX]; @@ -433,11 +446,14 @@ struct mt76_dev { struct sk_buff_head rx_skb[__MT_RXQ_MAX]; struct list_head txwi_cache; - struct mt76_queue q_tx[__MT_TXQ_MAX]; + struct mt76_sw_queue q_tx[__MT_TXQ_MAX]; struct mt76_queue q_rx[__MT_RXQ_MAX]; const struct mt76_queue_ops *queue_ops; int tx_dma_idx[4]; + struct tasklet_struct tx_tasklet; + struct delayed_work mac_work; + wait_queue_head_t tx_wait; struct sk_buff_head status_list; @@ -453,6 +469,10 @@ struct mt76_dev { u8 antenna_mask; u16 chainmask; + struct tasklet_struct pre_tbtt_tasklet; + int beacon_int; + u8 beacon_mask; + struct mt76_sband sband_2g; struct mt76_sband sband_5g; struct debugfs_blob_wrapper eeprom; @@ -527,6 +547,9 @@ struct mt76_rx_status { #define mt76_rd_rp(dev, ...) (dev)->mt76.bus->rd_rp(&((dev)->mt76), __VA_ARGS__) #define mt76_mcu_send_msg(dev, ...) (dev)->mt76.mcu_ops->mcu_send_msg(&((dev)->mt76), __VA_ARGS__) +#define __mt76_mcu_send_msg(dev, ...) (dev)->mcu_ops->mcu_send_msg((dev), __VA_ARGS__) +#define mt76_mcu_restart(dev, ...) (dev)->mt76.mcu_ops->mcu_restart(&((dev)->mt76)) +#define __mt76_mcu_restart(dev, ...) (dev)->mcu_ops->mcu_restart((dev)) #define mt76_set(dev, offset, val) mt76_rmw(dev, offset, 0, val) #define mt76_clear(dev, offset, val) mt76_rmw(dev, offset, val, 0) @@ -570,6 +593,7 @@ static inline u16 mt76_rev(struct mt76_dev *dev) #define mt76_init_queues(dev) (dev)->mt76.queue_ops->init(&((dev)->mt76)) #define mt76_queue_alloc(dev, ...) (dev)->mt76.queue_ops->alloc(&((dev)->mt76), __VA_ARGS__) #define mt76_tx_queue_skb_raw(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb_raw(&((dev)->mt76), __VA_ARGS__) +#define mt76_tx_queue_skb(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__) @@ -595,6 +619,7 @@ struct mt76_dev *mt76_alloc_device(struct device *pdev, unsigned int size, int mt76_register_device(struct mt76_dev *dev, bool vht, struct ieee80211_rate *rates, int n_rates); void mt76_unregister_device(struct mt76_dev *dev); +void mt76_free_device(struct mt76_dev *dev); struct dentry *mt76_register_debugfs(struct mt76_dev *dev); void mt76_seq_puts_array(struct seq_file *file, const char *str, @@ -603,6 +628,12 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str, int mt76_eeprom_init(struct mt76_dev *dev, int len); void mt76_eeprom_override(struct mt76_dev *dev); +static inline u8 * +mt76_get_txwi_ptr(struct mt76_dev *dev, struct mt76_txwi_cache *t) +{ + return (u8 *)t - dev->drv->txwi_size; +} + /* increment with wrap-around */ static inline int mt76_incr(int val, int size) { @@ -643,9 +674,19 @@ static inline struct mt76_tx_cb *mt76_tx_skb_cb(struct sk_buff *skb) return ((void *) IEEE80211_SKB_CB(skb)->status.status_driver_data); } -int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, - struct sk_buff *skb, struct mt76_wcid *wcid, - struct ieee80211_sta *sta); +static inline void mt76_insert_hdr_pad(struct sk_buff *skb) +{ + int len = ieee80211_get_hdrlen_from_skb(skb); + + if (len % 4 == 0) + return; + + skb_push(skb, 2); + memmove(skb->data, skb->data + 2, len); + + skb->data[len] = 0; + skb->data[len + 1] = 0; +} void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb); void mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, @@ -655,13 +696,14 @@ void mt76_txq_remove(struct mt76_dev *dev, struct ieee80211_txq *txq); void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq); void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta, bool send_bar); -void mt76_txq_schedule(struct mt76_dev *dev, struct mt76_queue *hwq); +void mt76_txq_schedule(struct mt76_dev *dev, enum mt76_txq_id qid); void mt76_txq_schedule_all(struct mt76_dev *dev); void mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u16 tids, int nframes, enum ieee80211_frame_release_type reason, bool more_data); +bool mt76_has_tx_pending(struct mt76_dev *dev); void mt76_set_channel(struct mt76_dev *dev); int mt76_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey); @@ -693,6 +735,8 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state); +void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb); @@ -704,6 +748,8 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void mt76_csa_check(struct mt76_dev *dev); void mt76_csa_finish(struct mt76_dev *dev); +int mt76_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set); + /* internal */ void mt76_tx_free(struct mt76_dev *dev); struct mt76_txwi_cache *mt76_get_txwi(struct mt76_dev *dev); @@ -734,8 +780,7 @@ static inline int mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len, int timeout) { - struct usb_interface *intf = to_usb_interface(dev->dev); - struct usb_device *udev = interface_to_usbdev(intf); + struct usb_device *udev = to_usb_device(dev->dev); struct mt76_usb *usb = &dev->usb; unsigned int pipe; @@ -753,10 +798,10 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req, void mt76u_single_wr(struct mt76_dev *dev, const u8 req, const u16 offset, const u32 val); int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf); -int mt76u_submit_rx_buffers(struct mt76_dev *dev); int mt76u_alloc_queues(struct mt76_dev *dev); -void mt76u_stop_queues(struct mt76_dev *dev); -void mt76u_stop_stat_wk(struct mt76_dev *dev); +void mt76u_stop_tx(struct mt76_dev *dev); +void mt76u_stop_rx(struct mt76_dev *dev); +int mt76u_resume_rx(struct mt76_dev *dev); void mt76u_queues_deinit(struct mt76_dev *dev); struct sk_buff * @@ -766,4 +811,6 @@ void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb); struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, unsigned long expires); +void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, u32 clear, u32 set); + #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c index afcd86f735b4..58e68fbdbf75 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c @@ -16,21 +16,20 @@ mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; struct sk_buff *skb = NULL; - if (!(dev->beacon_mask & BIT(mvif->idx))) + if (!(dev->mt76.beacon_mask & BIT(mvif->idx))) return; skb = ieee80211_beacon_get(mt76_hw(dev), vif); if (!skb) return; - mt76_dma_tx_queue_skb(&dev->mt76, &dev->mt76.q_tx[MT_TXQ_BEACON], skb, - &mvif->sta.wcid, NULL); + mt76_tx_queue_skb(dev, MT_TXQ_BEACON, skb, &mvif->sta.wcid, NULL); spin_lock_bh(&dev->ps_lock); mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY | FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, mvif->sta.wcid.idx) | FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, - dev->mt76.q_tx[MT_TXQ_CAB].hw_idx) | + dev->mt76.q_tx[MT_TXQ_CAB].q->hw_idx) | FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) | FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8)); @@ -49,7 +48,7 @@ mt7603_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif) struct ieee80211_tx_info *info; struct sk_buff *skb; - if (!(dev->beacon_mask & BIT(mvif->idx))) + if (!(dev->mt76.beacon_mask & BIT(mvif->idx))) return; skb = ieee80211_get_buffered_bc(mt76_hw(dev), vif); @@ -73,10 +72,13 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg) struct sk_buff *skb; int i, nframes; + if (mt76_hw(dev)->conf.flags & IEEE80211_CONF_OFFCHANNEL) + return; + data.dev = dev; __skb_queue_head_init(&data.q); - q = &dev->mt76.q_tx[MT_TXQ_BEACON]; + q = dev->mt76.q_tx[MT_TXQ_BEACON].q; spin_lock_bh(&q->lock); ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), IEEE80211_IFACE_ITER_RESUME_ALL, @@ -93,7 +95,7 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg) if (dev->mt76.csa_complete) goto out; - q = &dev->mt76.q_tx[MT_TXQ_CAB]; + q = dev->mt76.q_tx[MT_TXQ_CAB].q; do { nframes = skb_queue_len(&data.q); ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), @@ -118,8 +120,7 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg) struct ieee80211_vif *vif = info->control.vif; struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; - mt76_dma_tx_queue_skb(&dev->mt76, q, skb, &mvif->sta.wcid, - NULL); + mt76_tx_queue_skb(dev, MT_TXQ_CAB, skb, &mvif->sta.wcid, NULL); } mt76_queue_kick(dev, q); spin_unlock_bh(&q->lock); @@ -135,8 +136,8 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg) out: mt76_queue_tx_cleanup(dev, MT_TXQ_BEACON, false); - if (dev->mt76.q_tx[MT_TXQ_BEACON].queued > - __sw_hweight8(dev->beacon_mask)) + if (dev->mt76.q_tx[MT_TXQ_BEACON].q->queued > + hweight8(dev->mt76.beacon_mask)) dev->beacon_check++; } @@ -146,19 +147,19 @@ void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval) if (idx >= 0) { if (intval) - dev->beacon_mask |= BIT(idx); + dev->mt76.beacon_mask |= BIT(idx); else - dev->beacon_mask &= ~BIT(idx); + dev->mt76.beacon_mask &= ~BIT(idx); } - if (!dev->beacon_mask || (!intval && idx < 0)) { + if (!dev->mt76.beacon_mask || (!intval && idx < 0)) { mt7603_irq_disable(dev, MT_INT_MAC_IRQ3); mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_BCNQ_OPMODE_MASK); mt76_wr(dev, MT_HW_INT_MASK(3), 0); return; } - dev->beacon_int = intval; + dev->mt76.beacon_int = intval; mt76_wr(dev, MT_TBTT, FIELD_PREP(MT_TBTT_PERIOD, intval) | MT_TBTT_CAL_ENABLE); @@ -176,10 +177,11 @@ void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval) mt76_set(dev, MT_WF_ARB_BCN_START, MT_WF_ARB_BCN_START_BSSn(0) | - ((dev->beacon_mask >> 1) * MT_WF_ARB_BCN_START_BSS0n(1))); + ((dev->mt76.beacon_mask >> 1) * + MT_WF_ARB_BCN_START_BSS0n(1))); mt7603_irq_enable(dev, MT_INT_MAC_IRQ3); - if (dev->beacon_mask & ~BIT(0)) + if (dev->mt76.beacon_mask & ~BIT(0)) mt76_set(dev, MT_LPON_SBTOR(0), MT_LPON_SBTOR_SUB_BSS_EN); else mt76_clear(dev, MT_LPON_SBTOR(0), MT_LPON_SBTOR_SUB_BSS_EN); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/core.c b/drivers/net/wireless/mediatek/mt76/mt7603/core.c index 1086dcd376a0..37e5644b45ef 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/core.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/core.c @@ -2,17 +2,6 @@ #include "mt7603.h" -void mt7603_set_irq_mask(struct mt7603_dev *dev, u32 clear, u32 set) -{ - unsigned long flags; - - spin_lock_irqsave(&dev->mt76.mmio.irq_lock, flags); - dev->mt76.mmio.irqmask &= ~clear; - dev->mt76.mmio.irqmask |= set; - mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask); - spin_unlock_irqrestore(&dev->mt76.mmio.irq_lock, flags); -} - void mt7603_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) { struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); @@ -38,7 +27,7 @@ irqreturn_t mt7603_irq_handler(int irq, void *dev_instance) mt76_wr(dev, MT_HW_INT_STATUS(3), hwintr); if (hwintr & MT_HW_INT3_PRE_TBTT0) - tasklet_schedule(&dev->pre_tbtt_tasklet); + tasklet_schedule(&dev->mt76.pre_tbtt_tasklet); if ((hwintr & MT_HW_INT3_TBTT0) && dev->mt76.csa_complete) mt76_csa_finish(&dev->mt76); @@ -46,7 +35,7 @@ irqreturn_t mt7603_irq_handler(int irq, void *dev_instance) if (intr & MT_INT_TX_DONE_ALL) { mt7603_irq_disable(dev, MT_INT_TX_DONE_ALL); - tasklet_schedule(&dev->tx_tasklet); + tasklet_schedule(&dev->mt76.tx_tasklet); } if (intr & MT_INT_RX_DONE(0)) { @@ -64,8 +53,8 @@ irqreturn_t mt7603_irq_handler(int irq, void *dev_instance) u32 mt7603_reg_map(struct mt7603_dev *dev, u32 addr) { - u32 base = addr & GENMASK(31, 19); - u32 offset = addr & GENMASK(18, 0); + u32 base = addr & MT_MCU_PCIE_REMAP_2_BASE; + u32 offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET; dev->bus_ops->wr(&dev->mt76, MT_MCU_PCIE_REMAP_2, base); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index d69e82c66ab2..27e2d9f90553 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -5,18 +5,22 @@ #include "../dma.h" static int -mt7603_init_tx_queue(struct mt7603_dev *dev, struct mt76_queue *q, +mt7603_init_tx_queue(struct mt7603_dev *dev, struct mt76_sw_queue *q, int idx, int n_desc) { - int ret; + struct mt76_queue *hwq; + int err; - q->hw_idx = idx; - q->regs = dev->mt76.mmio.regs + MT_TX_RING_BASE + idx * MT_RING_SIZE; - q->ndesc = n_desc; + hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); + if (!hwq) + return -ENOMEM; - ret = mt76_queue_alloc(dev, q); - if (ret) - return ret; + err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE); + if (err < 0) + return err; + + INIT_LIST_HEAD(&q->swq); + q->q = hwq; mt7603_irq_enable(dev, MT_INT_TX_DONE(idx)); @@ -27,12 +31,16 @@ static void mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) { __le32 *txd = (__le32 *)skb->data; + struct ieee80211_hdr *hdr; + struct ieee80211_sta *sta; struct mt7603_sta *msta; struct mt76_wcid *wcid; + void *priv; int idx; u32 val; + u8 tid; - if (skb->len < sizeof(MT_TXD_SIZE) + sizeof(struct ieee80211_hdr)) + if (skb->len < MT_TXD_SIZE + sizeof(struct ieee80211_hdr)) goto free; val = le32_to_cpu(txd[1]); @@ -46,10 +54,19 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) if (!wcid) goto free; - msta = container_of(wcid, struct mt7603_sta, wcid); + priv = msta = container_of(wcid, struct mt7603_sta, wcid); val = le32_to_cpu(txd[0]); skb_set_queue_mapping(skb, FIELD_GET(MT_TXD0_Q_IDX, val)); + val &= ~(MT_TXD0_P_IDX | MT_TXD0_Q_IDX); + val |= FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_HW_QUEUE_MGMT); + txd[0] = cpu_to_le32(val); + + sta = container_of(priv, struct ieee80211_sta, drv_priv); + hdr = (struct ieee80211_hdr *) &skb->data[MT_TXD_SIZE]; + tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; + ieee80211_sta_set_buffered(sta, tid, true); + spin_lock_bh(&dev->ps_lock); __skb_queue_tail(&msta->psq, skb); if (skb_queue_len(&msta->psq) >= 64) { @@ -106,15 +123,12 @@ static int mt7603_init_rx_queue(struct mt7603_dev *dev, struct mt76_queue *q, int idx, int n_desc, int bufsize) { - int ret; + int err; - q->regs = dev->mt76.mmio.regs + MT_RX_RING_BASE + idx * MT_RING_SIZE; - q->ndesc = n_desc; - q->buf_size = bufsize; - - ret = mt76_queue_alloc(dev, q); - if (ret) - return ret; + err = mt76_queue_alloc(dev, q, idx, n_desc, bufsize, + MT_RX_RING_BASE); + if (err < 0) + return err; mt7603_irq_enable(dev, MT_INT_RX_DONE(idx)); @@ -131,6 +145,8 @@ mt7603_tx_tasklet(unsigned long data) for (i = MT_TXQ_MCU; i >= 0; i--) mt76_queue_tx_cleanup(dev, i, false); + mt76_txq_schedule_all(&dev->mt76); + mt7603_irq_enable(dev, MT_INT_TX_DONE_ALL); } @@ -150,7 +166,7 @@ int mt7603_dma_init(struct mt7603_dev *dev) init_waitqueue_head(&dev->mt76.mmio.mcu.wait); skb_queue_head_init(&dev->mt76.mmio.mcu.res_q); - tasklet_init(&dev->tx_tasklet, mt7603_tx_tasklet, (unsigned long)dev); + tasklet_init(&dev->mt76.tx_tasklet, mt7603_tx_tasklet, (unsigned long)dev); mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN | @@ -210,6 +226,6 @@ void mt7603_dma_cleanup(struct mt7603_dev *dev) MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); - tasklet_kill(&dev->tx_tasklet); + tasklet_kill(&dev->mt76.tx_tasklet); mt76_dma_cleanup(&dev->mt76); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 15cc8f33b34d..78cdbb70e178 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -112,7 +112,7 @@ static void mt7603_phy_init(struct mt7603_dev *dev) { int rx_chains = dev->mt76.antenna_mask; - int tx_chains = __sw_hweight8(rx_chains) - 1; + int tx_chains = hweight8(rx_chains) - 1; mt76_rmw(dev, MT_WF_RMAC_RMCR, (MT_WF_RMAC_RMCR_SMPS_MODE | @@ -167,7 +167,8 @@ mt7603_mac_init(struct mt7603_dev *dev) FIELD_PREP(MT_AGG_RETRY_CONTROL_BAR_LIMIT, 1) | FIELD_PREP(MT_AGG_RETRY_CONTROL_RTS_LIMIT, 15)); - mt76_rmw(dev, MT_DMA_DCR0, ~0xfffc, 4096); + mt76_wr(dev, MT_DMA_DCR0, MT_DMA_DCR0_RX_VEC_DROP | + FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 4096)); mt76_rmw(dev, MT_DMA_VCFR0, BIT(0), BIT(13)); mt76_rmw(dev, MT_DMA_TMCFR0, BIT(0) | BIT(1), BIT(13)); @@ -488,6 +489,7 @@ mt7603_init_txpower(struct mt7603_dev *dev, for (i = 0; i < sband->n_channels; i++) { chan = &sband->channels[i]; chan->max_power = target_power; + chan->orig_mpwr = target_power; } } @@ -510,8 +512,10 @@ int mt7603_register_device(struct mt7603_dev *dev) bus_ops->rmw = mt7603_rmw; dev->mt76.bus = bus_ops; - INIT_DELAYED_WORK(&dev->mac_work, mt7603_mac_work); - tasklet_init(&dev->pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet, + spin_lock_init(&dev->ps_lock); + + INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7603_mac_work); + tasklet_init(&dev->mt76.pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet, (unsigned long)dev); /* Check for 7688, which only has 1SS */ @@ -570,9 +574,9 @@ int mt7603_register_device(struct mt7603_dev *dev) void mt7603_unregister_device(struct mt7603_dev *dev) { - tasklet_disable(&dev->pre_tbtt_tasklet); + tasklet_disable(&dev->mt76.pre_tbtt_tasklet); mt76_unregister_device(&dev->mt76); mt7603_mcu_exit(dev); mt7603_dma_cleanup(dev); - ieee80211_free_hw(mt76_hw(dev)); + mt76_free_device(&dev->mt76); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 0a0115861b51..6d506e34c3ee 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -343,7 +343,7 @@ void mt7603_mac_rx_ba_reset(struct mt7603_dev *dev, void *addr, u8 tid) MT_BA_CONTROL_1_RESET)); } -void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ssn, +void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ba_size) { u32 addr = mt7603_wtbl2_addr(wcid); @@ -358,43 +358,6 @@ void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ssn, mt76_clear(dev, addr + (15 * 4), tid_mask); return; } - mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); - - mt7603_mac_stop(dev); - switch (tid) { - case 0: - mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID0_SN, ssn); - break; - case 1: - mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID1_SN, ssn); - break; - case 2: - mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID2_SN_LO, - ssn); - mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID2_SN_HI, - ssn >> 8); - break; - case 3: - mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID3_SN, ssn); - break; - case 4: - mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID4_SN, ssn); - break; - case 5: - mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID5_SN_LO, - ssn); - mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID5_SN_HI, - ssn >> 4); - break; - case 6: - mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID6_SN, ssn); - break; - case 7: - mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID7_SN, ssn); - break; - } - mt7603_wtbl_update(dev, wcid, MT_WTBL_UPDATE_WTBL2); - mt7603_mac_start(dev); for (i = 7; i > 0; i--) { if (ba_size >= MT_AGG_SIZE_LIMIT(i)) @@ -627,7 +590,7 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) status->aggr = unicast && !ieee80211_is_qos_nullfunc(hdr->frame_control); status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; - status->seqno = hdr->seq_ctrl >> 4; + status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); return 0; } @@ -754,11 +717,11 @@ void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta, MT_WTBL_UPDATE_RATE_UPDATE | MT_WTBL_UPDATE_TX_COUNT_CLEAR); - if (!sta->wcid.tx_rate_set) + if (!(sta->wcid.tx_info & MT_WCID_TX_INFO_SET)) mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); sta->rate_count = 2 * MT7603_RATE_RETRY * n_rates; - sta->wcid.tx_rate_set = true; + sta->wcid.tx_info |= MT_WCID_TX_INFO_SET; } static enum mt7603_cipher_type @@ -820,20 +783,23 @@ int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid, static int mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi, - struct sk_buff *skb, struct mt76_queue *q, + struct sk_buff *skb, enum mt76_txq_id qid, struct mt76_wcid *wcid, struct ieee80211_sta *sta, int pid, struct ieee80211_key_conf *key) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *rate = &info->control.rates[0]; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data; struct ieee80211_vif *vif = info->control.vif; + struct mt76_queue *q = dev->mt76.q_tx[qid].q; struct mt7603_vif *mvif; int wlan_idx; int hdr_len = ieee80211_get_hdrlen_from_skb(skb); int tx_count = 8; u8 frame_type, frame_subtype; u16 fc = le16_to_cpu(hdr->frame_control); + u16 seqno = 0; u8 vif_idx = 0; u32 val; u8 bw; @@ -841,7 +807,7 @@ mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi, if (vif) { mvif = (struct mt7603_vif *)vif->drv_priv; vif_idx = mvif->idx; - if (vif_idx && q >= &dev->mt76.q_tx[MT_TXQ_BEACON]) + if (vif_idx && qid >= MT_TXQ_BEACON) vif_idx += 0x10; } @@ -915,11 +881,21 @@ mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi, } /* use maximum tx count for beacons and buffered multicast */ - if (q >= &dev->mt76.q_tx[MT_TXQ_BEACON]) + if (qid >= MT_TXQ_BEACON) tx_count = 0x1f; val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count) | - FIELD_PREP(MT_TXD3_SEQ, le16_to_cpu(hdr->seq_ctrl)); + MT_TXD3_SN_VALID; + + if (ieee80211_is_data_qos(hdr->frame_control)) + seqno = le16_to_cpu(hdr->seq_ctrl); + else if (ieee80211_is_back_req(hdr->frame_control)) + seqno = le16_to_cpu(bar->start_seq_num); + else + val &= ~MT_TXD3_SN_VALID; + + val |= FIELD_PREP(MT_TXD3_SEQ, seqno >> 4); + txwi[3] = cpu_to_le32(val); if (key) { @@ -936,13 +912,13 @@ mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi, } int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, - struct sk_buff *skb, struct mt76_queue *q, - struct mt76_wcid *wcid, struct ieee80211_sta *sta, - u32 *tx_info) + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info) { struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); struct mt7603_sta *msta = container_of(wcid, struct mt7603_sta, wcid); - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); struct ieee80211_key_conf *key = info->control.hw_key; int pid; @@ -958,7 +934,7 @@ int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, mt7603_wtbl_set_ps(dev, msta, false); } - pid = mt76_tx_status_skb_add(mdev, wcid, skb); + pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { spin_lock_bh(&dev->mt76.lock); @@ -968,7 +944,8 @@ int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, spin_unlock_bh(&dev->mt76.lock); } - mt7603_mac_write_txwi(dev, txwi_ptr, skb, q, wcid, sta, pid, key); + mt7603_mac_write_txwi(dev, txwi_ptr, tx_info->skb, qid, wcid, + sta, pid, key); return 0; } @@ -1072,7 +1049,7 @@ out: case MT_PHY_TYPE_HT: final_rate_flags |= IEEE80211_TX_RC_MCS; final_rate &= GENMASK(5, 0); - if (i > 15) + if (final_rate > 15) return false; break; default: @@ -1167,8 +1144,8 @@ out: rcu_read_unlock(); } -void mt7603_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, - struct mt76_queue_entry *e, bool flush) +void mt7603_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, + struct mt76_queue_entry *e) { struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); struct sk_buff *skb = e->skb; @@ -1178,7 +1155,7 @@ void mt7603_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, return; } - if (q - dev->mt76.q_tx < 4) + if (qid < 4) dev->tx_hang_check = 0; mt76_tx_complete_skb(mdev, skb); @@ -1291,7 +1268,7 @@ static void mt7603_dma_sched_reset(struct mt7603_dev *dev) static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) { - int beacon_int = dev->beacon_int; + int beacon_int = dev->mt76.beacon_int; u32 mask = dev->mt76.mmio.irqmask; int i; @@ -1301,8 +1278,8 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) /* lock/unlock all queues to ensure that no tx is pending */ mt76_txq_schedule_all(&dev->mt76); - tasklet_disable(&dev->tx_tasklet); - tasklet_disable(&dev->pre_tbtt_tasklet); + tasklet_disable(&dev->mt76.tx_tasklet); + tasklet_disable(&dev->mt76.pre_tbtt_tasklet); napi_disable(&dev->mt76.napi[0]); napi_disable(&dev->mt76.napi[1]); @@ -1348,10 +1325,10 @@ skip_dma_reset: clear_bit(MT76_RESET, &dev->mt76.state); mutex_unlock(&dev->mt76.mutex); - tasklet_enable(&dev->tx_tasklet); - tasklet_schedule(&dev->tx_tasklet); + tasklet_enable(&dev->mt76.tx_tasklet); + tasklet_schedule(&dev->mt76.tx_tasklet); - tasklet_enable(&dev->pre_tbtt_tasklet); + tasklet_enable(&dev->mt76.pre_tbtt_tasklet); mt7603_beacon_set_timer(dev, -1, beacon_int); napi_enable(&dev->mt76.napi[0]); @@ -1410,17 +1387,17 @@ static bool mt7603_tx_hang(struct mt7603_dev *dev) int i; for (i = 0; i < 4; i++) { - q = &dev->mt76.q_tx[i]; + q = dev->mt76.q_tx[i].q; if (!q->queued) continue; prev_dma_idx = dev->tx_dma_idx[i]; - dma_idx = ioread32(&q->regs->dma_idx); + dma_idx = readl(&q->regs->dma_idx); dev->tx_dma_idx[i] = dma_idx; if (dma_idx == prev_dma_idx && - dma_idx != ioread32(&q->regs->cpu_idx)) + dma_idx != readl(&q->regs->cpu_idx)) break; } @@ -1691,7 +1668,7 @@ out: void mt7603_mac_work(struct work_struct *work) { struct mt7603_dev *dev = container_of(work, struct mt7603_dev, - mac_work.work); + mt76.mac_work.work); bool reset = false; mt76_tx_status_check(&dev->mt76, NULL, false); @@ -1744,6 +1721,6 @@ void mt7603_mac_work(struct work_struct *work) if (reset) mt7603_mac_watchdog_reset(dev); - ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, msecs_to_jiffies(MT7603_WATCHDOG_TIME)); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index b10775ed92e6..0a0334dc40d5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -5,6 +5,7 @@ #include <linux/pci.h> #include <linux/module.h> #include "mt7603.h" +#include "mac.h" #include "eeprom.h" static int @@ -15,7 +16,7 @@ mt7603_start(struct ieee80211_hw *hw) mt7603_mac_start(dev); dev->survey_time = ktime_get_boottime(); set_bit(MT76_STATE_RUNNING, &dev->mt76.state); - mt7603_mac_work(&dev->mac_work.work); + mt7603_mac_work(&dev->mt76.mac_work.work); return 0; } @@ -26,7 +27,7 @@ mt7603_stop(struct ieee80211_hw *hw) struct mt7603_dev *dev = hw->priv; clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); - cancel_delayed_work_sync(&dev->mac_work); + cancel_delayed_work_sync(&dev->mt76.mac_work); mt7603_mac_stop(dev); } @@ -131,11 +132,13 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) u8 bw = MT_BW_20; bool failed = false; - cancel_delayed_work_sync(&dev->mac_work); + cancel_delayed_work_sync(&dev->mt76.mac_work); + tasklet_disable(&dev->mt76.pre_tbtt_tasklet); mutex_lock(&dev->mt76.mutex); set_bit(MT76_RESET, &dev->mt76.state); + mt7603_beacon_set_timer(dev, -1, 0); mt76_set_channel(&dev->mt76); mt7603_mac_stop(dev); @@ -170,7 +173,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) mt76_txq_schedule_all(&dev->mt76); - ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, MT7603_WATCHDOG_TIME); /* reset channel stats */ @@ -185,10 +188,14 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) mt7603_init_edcca(dev); out: + if (!(mt76_hw(dev)->conf.flags & IEEE80211_CONF_OFFCHANNEL)) + mt7603_beacon_set_timer(dev, -1, dev->mt76.beacon_int); mutex_unlock(&dev->mt76.mutex); + tasklet_enable(&dev->mt76.pre_tbtt_tasklet); + if (failed) - mt7603_mac_work(&dev->mac_work.work); + mt7603_mac_work(&dev->mt76.mac_work.work); return ret; } @@ -293,9 +300,9 @@ mt7603_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON_INT)) { int beacon_int = !!info->enable_beacon * info->beacon_int; - tasklet_disable(&dev->pre_tbtt_tasklet); + tasklet_disable(&dev->mt76.pre_tbtt_tasklet); mt7603_beacon_set_timer(dev, mvif->idx, beacon_int); - tasklet_enable(&dev->pre_tbtt_tasklet); + tasklet_enable(&dev->mt76.pre_tbtt_tasklet); } mutex_unlock(&dev->mt76.mutex); @@ -371,7 +378,7 @@ mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; struct sk_buff_head list; - mt76_stop_tx_queues(&dev->mt76, sta, false); + mt76_stop_tx_queues(&dev->mt76, sta, true); mt7603_wtbl_set_ps(dev, msta, ps); if (ps) return; @@ -386,6 +393,15 @@ mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) } static void +mt7603_ps_set_more_data(struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr; + + hdr = (struct ieee80211_hdr *) &skb->data[MT_TXD_SIZE]; + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); +} + +static void mt7603_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u16 tids, int nframes, @@ -399,6 +415,8 @@ mt7603_release_buffered_frames(struct ieee80211_hw *hw, __skb_queue_head_init(&list); + mt7603_wtbl_set_ps(dev, msta, false); + spin_lock_bh(&dev->ps_lock); skb_queue_walk_safe(&msta->psq, skb, tmp) { if (!nframes) @@ -409,11 +427,15 @@ mt7603_release_buffered_frames(struct ieee80211_hw *hw, skb_set_queue_mapping(skb, MT_TXQ_PSD); __skb_unlink(skb, &msta->psq); + mt7603_ps_set_more_data(skb); __skb_queue_tail(&list, skb); nframes--; } spin_unlock_bh(&dev->ps_lock); + if (!skb_queue_empty(&list)) + ieee80211_sta_eosp(sta); + mt7603_ps_tx_list(dev, &list); if (nframes) @@ -476,7 +498,7 @@ mt7603_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, u16 cw_max = (1 << 10) - 1; u32 val; - queue = dev->mt76.q_tx[queue].hw_idx; + queue = dev->mt76.q_tx[queue].q->hw_idx; if (params->cw_min) cw_min = params->cw_min; @@ -519,7 +541,6 @@ mt7603_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt7603_dev *dev = hw->priv; set_bit(MT76_SCANNING, &dev->mt76.state); - mt7603_beacon_set_timer(dev, -1, 0); } static void @@ -528,7 +549,6 @@ mt7603_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) struct mt7603_dev *dev = hw->priv; clear_bit(MT76_SCANNING, &dev->mt76.state); - mt7603_beacon_set_timer(dev, -1, dev->beacon_int); } static void @@ -568,21 +588,21 @@ mt7603_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_TX_OPERATIONAL: mtxq->aggr = true; mtxq->send_bar = false; - mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, ba_size); + mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, ba_size); break; case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: mtxq->aggr = false; ieee80211_send_bar(vif, sta->addr, tid, mtxq->agg_ssn); - mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, -1); + mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, -1); break; case IEEE80211_AMPDU_TX_START: - mtxq->agg_ssn = *ssn << 4; + mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(*ssn); ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; case IEEE80211_AMPDU_TX_STOP_CONT: mtxq->aggr = false; - mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, -1); + mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, -1); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; } @@ -648,12 +668,6 @@ static void mt7603_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *cont mt76_tx(&dev->mt76, control->sta, wcid, skb); } -static int -mt7603_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) -{ - return 0; -} - const struct ieee80211_ops mt7603_ops = { .tx = mt7603_tx, .start = mt7603_start, @@ -675,7 +689,7 @@ const struct ieee80211_ops mt7603_ops = { .sta_rate_tbl_update = mt7603_sta_rate_tbl_update, .release_buffered_frames = mt7603_release_buffered_frames, .set_coverage_class = mt7603_set_coverage_class, - .set_tim = mt7603_set_tim, + .set_tim = mt76_set_tim, .get_survey = mt76_get_survey, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c index 4b0713f1fd5e..6357b5658a32 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c @@ -14,17 +14,14 @@ struct mt7603_fw_trailer { } __packed; static int -__mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd, - int query, int *wait_seq) +__mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, + int cmd, int *wait_seq) { int hdrlen = dev->mcu_running ? sizeof(struct mt7603_mcu_txd) : 12; struct mt76_dev *mdev = &dev->mt76; struct mt7603_mcu_txd *txd; u8 seq; - if (!skb) - return -EINVAL; - seq = ++mdev->mmio.mcu.msg_seq & 0xf; if (!seq) seq = ++mdev->mmio.mcu.msg_seq & 0xf; @@ -42,15 +39,14 @@ __mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd, if (cmd < 0) { txd->cid = -cmd; + txd->set_query = MCU_Q_NA; } else { txd->cid = MCU_CMD_EXT_CID; txd->ext_cid = cmd; - if (query != MCU_Q_NA) - txd->ext_cid_ack = 1; + txd->set_query = MCU_Q_SET; + txd->ext_cid_ack = 1; } - txd->set_query = query; - if (wait_seq) *wait_seq = seq; @@ -58,21 +54,26 @@ __mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd, } static int -mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd, - int query) +mt7603_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, + int len, bool wait_resp) { - struct mt76_dev *mdev = &dev->mt76; + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); unsigned long expires = jiffies + 3 * HZ; struct mt7603_mcu_rxd *rxd; + struct sk_buff *skb; int ret, seq; + skb = mt7603_mcu_msg_alloc(data, len); + if (!skb) + return -ENOMEM; + mutex_lock(&mdev->mmio.mcu.mutex); - ret = __mt7603_mcu_msg_send(dev, skb, cmd, query, &seq); + ret = __mt7603_mcu_msg_send(dev, skb, cmd, &seq); if (ret) goto out; - while (1) { + while (wait_resp) { bool check_seq = false; skb = mt76_mcu_get_response(&dev->mt76, expires); @@ -113,28 +114,22 @@ mt7603_mcu_init_download(struct mt7603_dev *dev, u32 addr, u32 len) .len = cpu_to_le32(len), .mode = cpu_to_le32(BIT(31)), }; - struct sk_buff *skb = mt7603_mcu_msg_alloc(&req, sizeof(req)); - return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, - MCU_Q_NA); + return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, + &req, sizeof(req), true); } static int mt7603_mcu_send_firmware(struct mt7603_dev *dev, const void *data, int len) { - struct sk_buff *skb; - int ret = 0; + int cur_len, ret = 0; while (len > 0) { - int cur_len = min_t(int, 4096 - sizeof(struct mt7603_mcu_txd), - len); - - skb = mt7603_mcu_msg_alloc(data, cur_len); - if (!skb) - return -ENOMEM; + cur_len = min_t(int, 4096 - sizeof(struct mt7603_mcu_txd), + len); - ret = __mt7603_mcu_msg_send(dev, skb, -MCU_CMD_FW_SCATTER, - MCU_Q_NA, NULL); + ret = __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_SCATTER, + data, cur_len, false); if (ret) break; @@ -155,23 +150,19 @@ mt7603_mcu_start_firmware(struct mt7603_dev *dev, u32 addr) .override = cpu_to_le32(addr ? 1 : 0), .addr = cpu_to_le32(addr), }; - struct sk_buff *skb = mt7603_mcu_msg_alloc(&req, sizeof(req)); - return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ, - MCU_Q_NA); + return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_START_REQ, + &req, sizeof(req), true); } static int -mt7603_mcu_restart(struct mt7603_dev *dev) +mt7603_mcu_restart(struct mt76_dev *dev) { - struct sk_buff *skb = mt7603_mcu_msg_alloc(NULL, 0); - - return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ, - MCU_Q_NA); + return __mt76_mcu_send_msg(dev, -MCU_CMD_RESTART_DL_REQ, + NULL, 0, true); } -static int -mt7603_load_firmware(struct mt7603_dev *dev) +static int mt7603_load_firmware(struct mt7603_dev *dev) { const struct firmware *fw; const struct mt7603_fw_trailer *hdr; @@ -261,6 +252,9 @@ running: mt76_clear(dev, MT_SCH_4, BIT(8)); dev->mcu_running = true; + snprintf(dev->mt76.hw->wiphy->fw_version, + sizeof(dev->mt76.hw->wiphy->fw_version), + "%.10s-%.15s", hdr->fw_ver, hdr->build_date); dev_info(dev->mt76.dev, "firmware init done\n"); out: @@ -271,14 +265,18 @@ out: int mt7603_mcu_init(struct mt7603_dev *dev) { - mutex_init(&dev->mt76.mmio.mcu.mutex); + static const struct mt76_mcu_ops mt7603_mcu_ops = { + .mcu_send_msg = mt7603_mcu_msg_send, + .mcu_restart = mt7603_mcu_restart, + }; + dev->mt76.mcu_ops = &mt7603_mcu_ops; return mt7603_load_firmware(dev); } void mt7603_mcu_exit(struct mt7603_dev *dev) { - mt7603_mcu_restart(dev); + __mt76_mcu_restart(&dev->mt76); skb_queue_purge(&dev->mt76.mmio.mcu.res_q); } @@ -360,27 +358,30 @@ int mt7603_mcu_set_eeprom(struct mt7603_dev *dev) .buffer_mode = 1, .len = ARRAY_SIZE(req_fields) - 1, }; - struct sk_buff *skb; - struct req_data *data; const int size = 0xff * sizeof(struct req_data); - u8 *eep = (u8 *)dev->mt76.eeprom.data; - int i; + u8 *req, *eep = (u8 *)dev->mt76.eeprom.data; + int i, ret, len = sizeof(req_hdr) + size; + struct req_data *data; BUILD_BUG_ON(ARRAY_SIZE(req_fields) * sizeof(*data) > size); - skb = mt7603_mcu_msg_alloc(NULL, size + sizeof(req_hdr)); - memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); - data = (struct req_data *)skb_put(skb, size); - memset(data, 0, size); + req = kmalloc(len, GFP_KERNEL); + if (!req) + return -ENOMEM; + memcpy(req, &req_hdr, sizeof(req_hdr)); + data = (struct req_data *)(req + sizeof(req_hdr)); + memset(data, 0, size); for (i = 0; i < ARRAY_SIZE(req_fields); i++) { data[i].addr = cpu_to_le16(req_fields[i]); data[i].val = eep[req_fields[i]]; - data[i].pad = 0; } - return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_EFUSE_BUFFER_MODE, - MCU_Q_SET); + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, + req, len, true); + kfree(req); + + return ret; } static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev) @@ -415,7 +416,6 @@ static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev) }, #undef EEP_VAL }; - struct sk_buff *skb; u8 *eep = (u8 *)dev->mt76.eeprom.data; memcpy(req.rate_power_delta, eep + MT_EE_TX_POWER_CCK, @@ -424,16 +424,15 @@ static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev) memcpy(req.temp_comp_power, eep + MT_EE_STEP_NUM_NEG_6_7, sizeof(req.temp_comp_power)); - skb = mt7603_mcu_msg_alloc(&req, sizeof(req)); - return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_TX_POWER_CTRL, - MCU_Q_SET); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_TX_POWER_CTRL, + &req, sizeof(req), true); } int mt7603_mcu_set_channel(struct mt7603_dev *dev) { struct cfg80211_chan_def *chandef = &dev->mt76.chandef; struct ieee80211_hw *hw = mt76_hw(dev); - int n_chains = __sw_hweight8(dev->mt76.antenna_mask); + int n_chains = hweight8(dev->mt76.antenna_mask); struct { u8 control_chan; u8 center_chan; @@ -450,10 +449,8 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev) .tx_streams = n_chains, .rx_streams = n_chains, }; - struct sk_buff *skb; s8 tx_power; - int ret; - int i; + int i, ret; if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_40) { req.bw = MT_BW_40; @@ -473,9 +470,8 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev) for (i = 0; i < ARRAY_SIZE(req.txpower); i++) req.txpower[i] = tx_power; - skb = mt7603_mcu_msg_alloc(&req, sizeof(req)); - ret = mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH, - MCU_Q_SET); + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_CHANNEL_SWITCH, + &req, sizeof(req), true); if (ret) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index 79f332429432..fa64bbaab0d2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -109,7 +109,6 @@ struct mt7603_dev { ktime_t survey_time; ktime_t ed_time; - int beacon_int; struct mt76_queue q_rx; @@ -126,8 +125,6 @@ struct mt7603_dev { s8 sensitivity; - u8 beacon_mask; - u8 beacon_check; u8 tx_hang_check; u8 tx_dma_check; @@ -143,10 +140,6 @@ struct mt7603_dev { u32 reset_test; unsigned int reset_cause[__RESET_CAUSE_MAX]; - - struct delayed_work mac_work; - struct tasklet_struct tx_tasklet; - struct tasklet_struct pre_tbtt_tasklet; }; extern const struct mt76_driver_ops mt7603_drv_ops; @@ -179,16 +172,14 @@ void mt7603_dma_cleanup(struct mt7603_dev *dev); int mt7603_mcu_init(struct mt7603_dev *dev); void mt7603_init_debugfs(struct mt7603_dev *dev); -void mt7603_set_irq_mask(struct mt7603_dev *dev, u32 clear, u32 set); - static inline void mt7603_irq_enable(struct mt7603_dev *dev, u32 mask) { - mt7603_set_irq_mask(dev, 0, mask); + mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, 0, mask); } static inline void mt7603_irq_disable(struct mt7603_dev *dev, u32 mask) { - mt7603_set_irq_mask(dev, mask, 0); + mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0); } void mt7603_mac_dma_start(struct mt7603_dev *dev); @@ -200,7 +191,7 @@ void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval); int mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb); void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data); void mt7603_mac_rx_ba_reset(struct mt7603_dev *dev, void *addr, u8 tid); -void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ssn, +void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ba_size); void mt7603_pse_client_reset(struct mt7603_dev *dev); @@ -225,12 +216,12 @@ void mt7603_wtbl_set_smps(struct mt7603_dev *dev, struct mt7603_sta *sta, void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort); int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, - struct sk_buff *skb, struct mt76_queue *q, - struct mt76_wcid *wcid, struct ieee80211_sta *sta, - u32 *tx_info); + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info); -void mt7603_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, - struct mt76_queue_entry *e, bool flush); +void mt7603_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, + struct mt76_queue_entry *e); void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h index da6827ae6cee..9d257d5c309d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h @@ -233,6 +233,10 @@ #define MT_WF_DMA(ofs) (MT_WF_DMA_BASE + (ofs)) #define MT_DMA_DCR0 MT_WF_DMA(0x000) +#define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 0) +#define MT_DMA_DCR0_DAMSDU BIT(16) +#define MT_DMA_DCR0_RX_VEC_DROP BIT(17) + #define MT_DMA_DCR1 MT_WF_DMA(0x004) #define MT_DMA_FQCR0 MT_WF_DMA(0x008) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/soc.c b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c index e13fea80d970..b920be1f5718 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c @@ -23,9 +23,9 @@ mt76_wmac_probe(struct platform_device *pdev) } mem_base = devm_ioremap_resource(&pdev->dev, res); - if (!mem_base) { + if (IS_ERR(mem_base)) { dev_err(&pdev->dev, "Failed to get memory resource\n"); - return -EINVAL; + return PTR_ERR(mem_base); } mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7603_ops, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig new file mode 100644 index 000000000000..3b8aba09bd5e --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig @@ -0,0 +1,7 @@ +config MT7615E + tristate "MediaTek MT7615E (PCIe) support" + select MT76_CORE + depends on MAC80211 + depends on PCI + help + This adds support for MT7615-based wireless PCIe devices. diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/Makefile b/drivers/net/wireless/mediatek/mt76/mt7615/Makefile new file mode 100644 index 000000000000..6397552f6ee3 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/Makefile @@ -0,0 +1,5 @@ +#SPDX-License-Identifier: ISC + +obj-$(CONFIG_MT7615E) += mt7615e.o + +mt7615e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c new file mode 100644 index 000000000000..3ec6582afd8f --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2019 MediaTek Inc. + * + * Author: Ryder Lee <ryder.lee@mediatek.com> + * Roy Luo <royluo@google.com> + * Lorenzo Bianconi <lorenzo@kernel.org> + * Felix Fietkau <nbd@nbd.name> + */ + +#include "mt7615.h" +#include "../dma.h" +#include "mac.h" + +static int +mt7615_init_tx_queues(struct mt7615_dev *dev, int n_desc) +{ + struct mt76_sw_queue *q; + struct mt76_queue *hwq; + int err, i; + + hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); + if (!hwq) + return -ENOMEM; + + err = mt76_queue_alloc(dev, hwq, 0, n_desc, 0, MT_TX_RING_BASE); + if (err < 0) + return err; + + for (i = 0; i < MT_TXQ_MCU; i++) { + q = &dev->mt76.q_tx[i]; + INIT_LIST_HEAD(&q->swq); + q->q = hwq; + } + + return 0; +} + +static int +mt7615_init_mcu_queue(struct mt7615_dev *dev, struct mt76_sw_queue *q, + int idx, int n_desc) +{ + struct mt76_queue *hwq; + int err; + + hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); + if (!hwq) + return -ENOMEM; + + err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE); + if (err < 0) + return err; + + INIT_LIST_HEAD(&q->swq); + q->q = hwq; + + return 0; +} + +void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, + struct sk_buff *skb) +{ + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + __le32 *rxd = (__le32 *)skb->data; + __le32 *end = (__le32 *)&skb->data[skb->len]; + enum rx_pkt_type type; + + type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); + + switch (type) { + case PKT_TYPE_TXS: + for (rxd++; rxd + 7 <= end; rxd += 7) + mt7615_mac_add_txs(dev, rxd); + dev_kfree_skb(skb); + break; + case PKT_TYPE_TXRX_NOTIFY: + mt7615_mac_tx_free(dev, skb); + break; + case PKT_TYPE_RX_EVENT: + mt76_mcu_rx_event(&dev->mt76, skb); + break; + case PKT_TYPE_NORMAL: + if (!mt7615_mac_fill_rx(dev, skb)) { + mt76_rx(&dev->mt76, q, skb); + return; + } + /* fall through */ + default: + dev_kfree_skb(skb); + break; + } +} + +static void mt7615_tx_tasklet(unsigned long data) +{ + struct mt7615_dev *dev = (struct mt7615_dev *)data; + static const u8 queue_map[] = { + MT_TXQ_MCU, + MT_TXQ_BE + }; + int i; + + for (i = 0; i < ARRAY_SIZE(queue_map); i++) + mt76_queue_tx_cleanup(dev, queue_map[i], false); + + mt76_txq_schedule_all(&dev->mt76); + + mt7615_irq_enable(dev, MT_INT_TX_DONE_ALL); +} + +int mt7615_dma_init(struct mt7615_dev *dev) +{ + int ret; + + mt76_dma_attach(&dev->mt76); + + tasklet_init(&dev->mt76.tx_tasklet, mt7615_tx_tasklet, + (unsigned long)dev); + + mt76_wr(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE | + MT_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN | + MT_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY | + MT_WPDMA_GLO_CFG_OMIT_TX_INFO); + + mt76_rmw_field(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_TX_BT_SIZE_BIT0, 0x1); + + mt76_rmw_field(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_TX_BT_SIZE_BIT21, 0x1); + + mt76_rmw_field(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_DMA_BURST_SIZE, 0x3); + + mt76_rmw_field(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_MULTI_DMA_EN, 0x3); + + mt76_wr(dev, MT_WPDMA_GLO_CFG1, 0x1); + mt76_wr(dev, MT_WPDMA_TX_PRE_CFG, 0xf0000); + mt76_wr(dev, MT_WPDMA_RX_PRE_CFG, 0xf7f0000); + mt76_wr(dev, MT_WPDMA_ABT_CFG, 0x4000026); + mt76_wr(dev, MT_WPDMA_ABT_CFG1, 0x18811881); + mt76_set(dev, 0x7158, BIT(16)); + mt76_clear(dev, 0x7000, BIT(23)); + mt76_wr(dev, MT_WPDMA_RST_IDX, ~0); + + ret = mt7615_init_tx_queues(dev, MT7615_TX_RING_SIZE); + if (ret) + return ret; + + ret = mt7615_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU], + MT7615_TXQ_MCU, + MT7615_TX_MCU_RING_SIZE); + if (ret) + return ret; + + ret = mt7615_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_FWDL], + MT7615_TXQ_FWDL, + MT7615_TX_FWDL_RING_SIZE); + if (ret) + return ret; + + /* init rx queues */ + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1, + MT7615_RX_MCU_RING_SIZE, MT_RX_BUF_SIZE, + MT_RX_RING_BASE); + if (ret) + return ret; + + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0, + MT7615_RX_RING_SIZE, MT_RX_BUF_SIZE, + MT_RX_RING_BASE); + if (ret) + return ret; + + mt76_wr(dev, MT_DELAY_INT_CFG, 0); + + ret = mt76_init_queues(dev); + if (ret < 0) + return ret; + + mt76_poll(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_TX_DMA_BUSY | + MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 1000); + + /* start dma engine */ + mt76_set(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_TX_DMA_EN | + MT_WPDMA_GLO_CFG_RX_DMA_EN); + + /* enable interrupts for TX/RX rings */ + mt7615_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL); + + return 0; +} + +void mt7615_dma_cleanup(struct mt7615_dev *dev) +{ + mt76_clear(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_TX_DMA_EN | + MT_WPDMA_GLO_CFG_RX_DMA_EN); + mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_SW_RESET); + + tasklet_kill(&dev->mt76.tx_tasklet); + mt76_dma_cleanup(&dev->mt76); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c new file mode 100644 index 000000000000..dd5ab46a4f66 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2019 MediaTek Inc. + * + * Author: Ryder Lee <ryder.lee@mediatek.com> + * Felix Fietkau <nbd@nbd.name> + */ + +#include "mt7615.h" +#include "eeprom.h" + +static int mt7615_efuse_read(struct mt7615_dev *dev, u32 base, + u16 addr, u8 *data) +{ + u32 val; + int i; + + val = mt76_rr(dev, base + MT_EFUSE_CTRL); + val &= ~(MT_EFUSE_CTRL_AIN | MT_EFUSE_CTRL_MODE); + val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf); + val |= MT_EFUSE_CTRL_KICK; + mt76_wr(dev, base + MT_EFUSE_CTRL, val); + + if (!mt76_poll(dev, base + MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000)) + return -ETIMEDOUT; + + udelay(2); + + val = mt76_rr(dev, base + MT_EFUSE_CTRL); + if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT || + WARN_ON_ONCE(!(val & MT_EFUSE_CTRL_VALID))) { + memset(data, 0x0, 16); + return 0; + } + + for (i = 0; i < 4; i++) { + val = mt76_rr(dev, base + MT_EFUSE_RDATA(i)); + put_unaligned_le32(val, data + 4 * i); + } + + return 0; +} + +static int mt7615_efuse_init(struct mt7615_dev *dev) +{ + u32 base = mt7615_reg_map(dev, MT_EFUSE_BASE); + int len = MT7615_EEPROM_SIZE; + int ret, i; + void *buf; + + if (mt76_rr(dev, base + MT_EFUSE_BASE_CTRL) & MT_EFUSE_BASE_CTRL_EMPTY) + return -EINVAL; + + dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL); + dev->mt76.otp.size = len; + if (!dev->mt76.otp.data) + return -ENOMEM; + + buf = dev->mt76.otp.data; + for (i = 0; i + 16 <= len; i += 16) { + ret = mt7615_efuse_read(dev, base, i, buf + i); + if (ret) + return ret; + } + + return 0; +} + +static int mt7615_eeprom_load(struct mt7615_dev *dev) +{ + int ret; + + ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_SIZE); + if (ret < 0) + return ret; + + return mt7615_efuse_init(dev); +} + +int mt7615_eeprom_init(struct mt7615_dev *dev) +{ + int ret; + + ret = mt7615_eeprom_load(dev); + if (ret < 0) + return ret; + + memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, MT7615_EEPROM_SIZE); + + dev->mt76.cap.has_2ghz = true; + dev->mt76.cap.has_5ghz = true; + + memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, + ETH_ALEN); + + mt76_eeprom_override(&dev->mt76); + + return 0; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h new file mode 100644 index 000000000000..a4cf16688171 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2019 MediaTek Inc. */ + +#ifndef __MT7615_EEPROM_H +#define __MT7615_EEPROM_H + +#include "mt7615.h" + +enum mt7615_eeprom_field { + MT_EE_CHIP_ID = 0x000, + MT_EE_VERSION = 0x002, + MT_EE_MAC_ADDR = 0x004, + MT_EE_NIC_CONF_0 = 0x034, + + __MT_EE_MAX = 0x3bf +}; + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c new file mode 100644 index 000000000000..3ab3ff553ef2 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2019 MediaTek Inc. + * + * Author: Roy Luo <royluo@google.com> + * Ryder Lee <ryder.lee@mediatek.com> + * Felix Fietkau <nbd@nbd.name> + */ + +#include <linux/etherdevice.h> +#include "mt7615.h" +#include "mac.h" + +static void mt7615_phy_init(struct mt7615_dev *dev) +{ + /* disable band 0 rf low power beacon mode */ + mt76_rmw(dev, MT_WF_PHY_WF2_RFCTRL0, MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN, + MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN); +} + +static void mt7615_mac_init(struct mt7615_dev *dev) +{ + /* enable band 0 clk */ + mt76_rmw(dev, MT_CFG_CCR, + MT_CFG_CCR_MAC_D0_1X_GC_EN | MT_CFG_CCR_MAC_D0_2X_GC_EN, + MT_CFG_CCR_MAC_D0_1X_GC_EN | MT_CFG_CCR_MAC_D0_2X_GC_EN); + + mt76_rmw_field(dev, MT_TMAC_CTCR0, + MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f); + mt76_rmw_field(dev, MT_TMAC_CTCR0, + MT_TMAC_CTCR0_INS_DDLMT_DENSITY, 0x3); + mt76_rmw(dev, MT_TMAC_CTCR0, + MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | + MT_TMAC_CTCR0_INS_DDLMT_EN, + MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | + MT_TMAC_CTCR0_INS_DDLMT_EN); + + mt7615_mcu_set_rts_thresh(dev, 0x92b); + + mt76_rmw(dev, MT_AGG_SCR, MT_AGG_SCR_NLNAV_MID_PTEC_DIS, + MT_AGG_SCR_NLNAV_MID_PTEC_DIS); + + mt7615_mcu_init_mac(dev); + + mt76_wr(dev, MT_DMA_DCR0, MT_DMA_DCR0_RX_VEC_DROP | + FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 3072)); + + mt76_wr(dev, MT_AGG_ARUCR, FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7)); + mt76_wr(dev, MT_AGG_ARDCR, + FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 0) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), + max_t(int, 0, MT7615_RATE_RETRY - 2)) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), MT7615_RATE_RETRY - 1)); + + mt76_wr(dev, MT_AGG_ARCR, + (MT_AGG_ARCR_INIT_RATE1 | + FIELD_PREP(MT_AGG_ARCR_RTS_RATE_THR, 2) | + MT_AGG_ARCR_RATE_DOWN_RATIO_EN | + FIELD_PREP(MT_AGG_ARCR_RATE_DOWN_RATIO, 1) | + FIELD_PREP(MT_AGG_ARCR_RATE_UP_EXTRA_TH, 4))); + + dev->mt76.global_wcid.idx = MT7615_WTBL_RESERVED; + dev->mt76.global_wcid.hw_key_idx = -1; + rcu_assign_pointer(dev->mt76.wcid[MT7615_WTBL_RESERVED], + &dev->mt76.global_wcid); +} + +static int mt7615_init_hardware(struct mt7615_dev *dev) +{ + int ret; + + mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); + + spin_lock_init(&dev->token_lock); + idr_init(&dev->token); + + ret = mt7615_eeprom_init(dev); + if (ret < 0) + return ret; + + ret = mt7615_dma_init(dev); + if (ret) + return ret; + + set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + + ret = mt7615_mcu_init(dev); + if (ret) + return ret; + + mt7615_mcu_set_eeprom(dev); + mt7615_mac_init(dev); + mt7615_phy_init(dev); + mt7615_mcu_ctrl_pm_state(dev, 0); + mt7615_mcu_del_wtbl_all(dev); + + return 0; +} + +#define CCK_RATE(_idx, _rate) { \ + .bitrate = _rate, \ + .flags = IEEE80211_RATE_SHORT_PREAMBLE, \ + .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx), \ + .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + (_idx)), \ +} + +#define OFDM_RATE(_idx, _rate) { \ + .bitrate = _rate, \ + .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx), \ + .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx), \ +} + +static struct ieee80211_rate mt7615_rates[] = { + CCK_RATE(0, 10), + CCK_RATE(1, 20), + CCK_RATE(2, 55), + CCK_RATE(3, 110), + OFDM_RATE(11, 60), + OFDM_RATE(15, 90), + OFDM_RATE(10, 120), + OFDM_RATE(14, 180), + OFDM_RATE(9, 240), + OFDM_RATE(13, 360), + OFDM_RATE(8, 480), + OFDM_RATE(12, 540), +}; + +static const struct ieee80211_iface_limit if_limits[] = { + { + .max = MT7615_MAX_INTERFACES, + .types = BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) + } +}; + +static const struct ieee80211_iface_combination if_comb[] = { + { + .limits = if_limits, + .n_limits = ARRAY_SIZE(if_limits), + .max_interfaces = 4, + .num_different_channels = 1, + .beacon_int_infra_match = true, + } +}; + +static int mt7615_init_debugfs(struct mt7615_dev *dev) +{ + struct dentry *dir; + + dir = mt76_register_debugfs(&dev->mt76); + if (!dir) + return -ENOMEM; + + return 0; +} + +int mt7615_register_device(struct mt7615_dev *dev) +{ + struct ieee80211_hw *hw = mt76_hw(dev); + struct wiphy *wiphy = hw->wiphy; + int ret; + + ret = mt7615_init_hardware(dev); + if (ret) + return ret; + + INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7615_mac_work); + + hw->queues = 4; + hw->max_rates = 3; + hw->max_report_rates = 7; + hw->max_rate_tries = 11; + + hw->sta_data_size = sizeof(struct mt7615_sta); + hw->vif_data_size = sizeof(struct mt7615_vif); + + wiphy->iface_combinations = if_comb; + wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); + + ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER); + ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); + + dev->mt76.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; + dev->mt76.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; + dev->mt76.sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_SHORT_GI_160 | + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; + dev->mt76.chainmask = 0x404; + dev->mt76.antenna_mask = 0xf; + + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP); + + ret = mt76_register_device(&dev->mt76, true, mt7615_rates, + ARRAY_SIZE(mt7615_rates)); + if (ret) + return ret; + + hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; + + return mt7615_init_debugfs(dev); +} + +void mt7615_unregister_device(struct mt7615_dev *dev) +{ + struct mt76_txwi_cache *txwi; + int id; + + spin_lock_bh(&dev->token_lock); + idr_for_each_entry(&dev->token, txwi, id) { + mt7615_txp_skb_unmap(&dev->mt76, txwi); + if (txwi->skb) + dev_kfree_skb_any(txwi->skb); + mt76_put_txwi(&dev->mt76, txwi); + } + spin_unlock_bh(&dev->token_lock); + idr_destroy(&dev->token); + mt76_unregister_device(&dev->mt76); + mt7615_mcu_exit(dev); + mt7615_dma_cleanup(dev); + + ieee80211_free_hw(mt76_hw(dev)); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c new file mode 100644 index 000000000000..b8f48d10f27a --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -0,0 +1,775 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2019 MediaTek Inc. + * + * Author: Ryder Lee <ryder.lee@mediatek.com> + * Roy Luo <royluo@google.com> + * Felix Fietkau <nbd@nbd.name> + * Lorenzo Bianconi <lorenzo@kernel.org> + */ + +#include <linux/etherdevice.h> +#include <linux/timekeeping.h> +#include "mt7615.h" +#include "../dma.h" +#include "mac.h" + +static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev, + u8 idx, bool unicast) +{ + struct mt7615_sta *sta; + struct mt76_wcid *wcid; + + if (idx >= ARRAY_SIZE(dev->mt76.wcid)) + return NULL; + + wcid = rcu_dereference(dev->mt76.wcid[idx]); + if (unicast || !wcid) + return wcid; + + if (!wcid->sta) + return NULL; + + sta = container_of(wcid, struct mt7615_sta, wcid); + if (!sta->vif) + return NULL; + + return &sta->vif->sta.wcid; +} + +static int mt7615_get_rate(struct mt7615_dev *dev, + struct ieee80211_supported_band *sband, + int idx, bool cck) +{ + int offset = 0; + int len = sband->n_bitrates; + int i; + + if (cck) { + if (sband == &dev->mt76.sband_5g.sband) + return 0; + + idx &= ~BIT(2); /* short preamble */ + } else if (sband == &dev->mt76.sband_2g.sband) { + offset = 4; + } + + for (i = offset; i < len; i++) { + if ((sband->bitrates[i].hw_value & GENMASK(7, 0)) == idx) + return i; + } + + return 0; +} + +static void mt7615_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + int hdr_len = ieee80211_get_hdrlen_from_skb(skb); + u8 *pn = status->iv; + u8 *hdr; + + __skb_push(skb, 8); + memmove(skb->data, skb->data + 8, hdr_len); + hdr = skb->data + hdr_len; + + hdr[0] = pn[5]; + hdr[1] = pn[4]; + hdr[2] = 0; + hdr[3] = 0x20 | (key_id << 6); + hdr[4] = pn[3]; + hdr[5] = pn[2]; + hdr[6] = pn[1]; + hdr[7] = pn[0]; + + status->flag &= ~RX_FLAG_IV_STRIPPED; +} + +int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct ieee80211_supported_band *sband; + struct ieee80211_hdr *hdr; + __le32 *rxd = (__le32 *)skb->data; + u32 rxd0 = le32_to_cpu(rxd[0]); + u32 rxd1 = le32_to_cpu(rxd[1]); + u32 rxd2 = le32_to_cpu(rxd[2]); + bool unicast, remove_pad, insert_ccmp_hdr = false; + int i, idx; + + memset(status, 0, sizeof(*status)); + + unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M; + idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2); + status->wcid = mt7615_rx_get_wcid(dev, idx, unicast); + + /* TODO: properly support DBDC */ + status->freq = dev->mt76.chandef.chan->center_freq; + status->band = dev->mt76.chandef.chan->band; + if (status->band == NL80211_BAND_5GHZ) + sband = &dev->mt76.sband_5g.sband; + else + sband = &dev->mt76.sband_2g.sband; + + if (rxd2 & MT_RXD2_NORMAL_FCS_ERR) + status->flag |= RX_FLAG_FAILED_FCS_CRC; + + if (rxd2 & MT_RXD2_NORMAL_TKIP_MIC_ERR) + status->flag |= RX_FLAG_MMIC_ERROR; + + if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 && + !(rxd2 & (MT_RXD2_NORMAL_CLM | MT_RXD2_NORMAL_CM))) { + status->flag |= RX_FLAG_DECRYPTED; + status->flag |= RX_FLAG_IV_STRIPPED; + status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED; + } + + remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET; + + if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) + return -EINVAL; + + if (!sband->channels) + return -EINVAL; + + rxd += 4; + if (rxd0 & MT_RXD0_NORMAL_GROUP_4) { + rxd += 4; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + } + + if (rxd0 & MT_RXD0_NORMAL_GROUP_1) { + u8 *data = (u8 *)rxd; + + if (status->flag & RX_FLAG_DECRYPTED) { + status->iv[0] = data[5]; + status->iv[1] = data[4]; + status->iv[2] = data[3]; + status->iv[3] = data[2]; + status->iv[4] = data[1]; + status->iv[5] = data[0]; + + insert_ccmp_hdr = FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); + } + rxd += 4; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + } + + if (rxd0 & MT_RXD0_NORMAL_GROUP_2) { + rxd += 2; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + } + + if (rxd0 & MT_RXD0_NORMAL_GROUP_3) { + u32 rxdg0 = le32_to_cpu(rxd[0]); + u32 rxdg1 = le32_to_cpu(rxd[1]); + u8 stbc = FIELD_GET(MT_RXV1_HT_STBC, rxdg0); + bool cck = false; + + i = FIELD_GET(MT_RXV1_TX_RATE, rxdg0); + switch (FIELD_GET(MT_RXV1_TX_MODE, rxdg0)) { + case MT_PHY_TYPE_CCK: + cck = true; + /* fall through */ + case MT_PHY_TYPE_OFDM: + i = mt7615_get_rate(dev, sband, i, cck); + break; + case MT_PHY_TYPE_HT_GF: + case MT_PHY_TYPE_HT: + status->encoding = RX_ENC_HT; + if (i > 31) + return -EINVAL; + break; + case MT_PHY_TYPE_VHT: + status->nss = FIELD_GET(MT_RXV2_NSTS, rxdg1) + 1; + status->encoding = RX_ENC_VHT; + break; + default: + return -EINVAL; + } + status->rate_idx = i; + + switch (FIELD_GET(MT_RXV1_FRAME_MODE, rxdg0)) { + case MT_PHY_BW_20: + break; + case MT_PHY_BW_40: + status->bw = RATE_INFO_BW_40; + break; + case MT_PHY_BW_80: + status->bw = RATE_INFO_BW_80; + break; + case MT_PHY_BW_160: + status->bw = RATE_INFO_BW_160; + break; + default: + return -EINVAL; + } + + if (rxdg0 & MT_RXV1_HT_SHORT_GI) + status->enc_flags |= RX_ENC_FLAG_SHORT_GI; + if (rxdg0 & MT_RXV1_HT_AD_CODE) + status->enc_flags |= RX_ENC_FLAG_LDPC; + + status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; + + /* TODO: RSSI */ + rxd += 6; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + } + + skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad); + + if (insert_ccmp_hdr) { + u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); + + mt7615_insert_ccmp_hdr(skb, key_id); + } + + hdr = (struct ieee80211_hdr *)skb->data; + if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control)) + return 0; + + status->aggr = unicast && + !ieee80211_is_qos_nullfunc(hdr->frame_control); + status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; + status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); + + return 0; +} + +void mt7615_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) +{ +} + +void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, + struct mt76_queue_entry *e) +{ + if (!e->txwi) { + dev_kfree_skb_any(e->skb); + return; + } + + /* error path */ + if (e->skb == DMA_DUMMY_DATA) { + struct mt76_txwi_cache *t; + struct mt7615_dev *dev; + struct mt7615_txp *txp; + u8 *txwi_ptr; + + txwi_ptr = mt76_get_txwi_ptr(mdev, e->txwi); + txp = (struct mt7615_txp *)(txwi_ptr + MT_TXD_SIZE); + dev = container_of(mdev, struct mt7615_dev, mt76); + + spin_lock_bh(&dev->token_lock); + t = idr_remove(&dev->token, le16_to_cpu(txp->token)); + spin_unlock_bh(&dev->token_lock); + e->skb = t ? t->skb : NULL; + } + + if (e->skb) + mt76_tx_complete_skb(mdev, e->skb); +} + +u16 mt7615_mac_tx_rate_val(struct mt7615_dev *dev, + const struct ieee80211_tx_rate *rate, + bool stbc, u8 *bw) +{ + u8 phy, nss, rate_idx; + u16 rateval; + + *bw = 0; + + if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { + rate_idx = ieee80211_rate_get_vht_mcs(rate); + nss = ieee80211_rate_get_vht_nss(rate); + phy = MT_PHY_TYPE_VHT; + if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + *bw = 1; + else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) + *bw = 2; + else if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH) + *bw = 3; + } else if (rate->flags & IEEE80211_TX_RC_MCS) { + rate_idx = rate->idx; + nss = 1 + (rate->idx >> 3); + phy = MT_PHY_TYPE_HT; + if (rate->flags & IEEE80211_TX_RC_GREEN_FIELD) + phy = MT_PHY_TYPE_HT_GF; + if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + *bw = 1; + } else { + const struct ieee80211_rate *r; + int band = dev->mt76.chandef.chan->band; + u16 val; + + nss = 1; + r = &mt76_hw(dev)->wiphy->bands[band]->bitrates[rate->idx]; + if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + val = r->hw_value_short; + else + val = r->hw_value; + + phy = val >> 8; + rate_idx = val & 0xff; + } + + rateval = (FIELD_PREP(MT_TX_RATE_IDX, rate_idx) | + FIELD_PREP(MT_TX_RATE_MODE, phy) | + FIELD_PREP(MT_TX_RATE_NSS, nss - 1)); + + if (stbc && nss == 1) + rateval |= MT_TX_RATE_STBC; + + return rateval; +} + +int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, + struct sk_buff *skb, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, int pid, + struct ieee80211_key_conf *key) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_rate *rate = &info->control.rates[0]; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_vif *vif = info->control.vif; + int tx_count = 8; + u8 fc_type, fc_stype, p_fmt, q_idx, omac_idx = 0; + __le16 fc = hdr->frame_control; + u16 seqno = 0; + u32 val; + + if (vif) { + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + + omac_idx = mvif->omac_idx; + } + + if (sta) { + struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + + tx_count = msta->rate_count; + } + + fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; + fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; + + if (ieee80211_is_data(fc)) { + q_idx = skb_get_queue_mapping(skb); + p_fmt = MT_TX_TYPE_CT; + } else if (ieee80211_is_beacon(fc)) { + q_idx = MT_LMAC_BCN0; + p_fmt = MT_TX_TYPE_FW; + } else { + q_idx = MT_LMAC_ALTX0; + p_fmt = MT_TX_TYPE_CT; + } + + val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) | + FIELD_PREP(MT_TXD0_P_IDX, MT_TX_PORT_IDX_LMAC) | + FIELD_PREP(MT_TXD0_Q_IDX, q_idx); + txwi[0] = cpu_to_le32(val); + + val = MT_TXD1_LONG_FORMAT | + FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) | + FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | + FIELD_PREP(MT_TXD1_HDR_INFO, + ieee80211_get_hdrlen_from_skb(skb) / 2) | + FIELD_PREP(MT_TXD1_TID, + skb->priority & IEEE80211_QOS_CTL_TID_MASK) | + FIELD_PREP(MT_TXD1_PKT_FMT, p_fmt) | + FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx); + txwi[1] = cpu_to_le32(val); + + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) | + FIELD_PREP(MT_TXD2_MULTICAST, + is_multicast_ether_addr(hdr->addr1)); + txwi[2] = cpu_to_le32(val); + + if (!(info->flags & IEEE80211_TX_CTL_AMPDU)) + txwi[2] |= cpu_to_le32(MT_TXD2_BA_DISABLE); + + txwi[4] = 0; + txwi[6] = 0; + + if (rate->idx >= 0 && rate->count && + !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) { + bool stbc = info->flags & IEEE80211_TX_CTL_STBC; + u8 bw; + u16 rateval = mt7615_mac_tx_rate_val(dev, rate, stbc, &bw); + + txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE); + + val = MT_TXD6_FIXED_BW | + FIELD_PREP(MT_TXD6_BW, bw) | + FIELD_PREP(MT_TXD6_TX_RATE, rateval); + txwi[6] |= cpu_to_le32(val); + + if (rate->flags & IEEE80211_TX_RC_SHORT_GI) + txwi[6] |= cpu_to_le32(MT_TXD6_SGI); + + if (info->flags & IEEE80211_TX_CTL_LDPC) + txwi[6] |= cpu_to_le32(MT_TXD6_LDPC); + + if (!(rate->flags & (IEEE80211_TX_RC_MCS | + IEEE80211_TX_RC_VHT_MCS))) + txwi[2] |= cpu_to_le32(MT_TXD2_BA_DISABLE); + + tx_count = rate->count; + } + + if (!ieee80211_is_beacon(fc)) { + val = MT_TXD5_TX_STATUS_HOST | MT_TXD5_SW_POWER_MGMT | + FIELD_PREP(MT_TXD5_PID, pid); + txwi[5] = cpu_to_le32(val); + } else { + txwi[5] = 0; + /* use maximum tx count for beacons */ + tx_count = 0x1f; + } + + val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count); + if (ieee80211_is_data_qos(hdr->frame_control)) { + seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); + val |= MT_TXD3_SN_VALID; + } else if (ieee80211_is_back_req(hdr->frame_control)) { + struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data; + + seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(bar->start_seq_num)); + val |= MT_TXD3_SN_VALID; + } + val |= FIELD_PREP(MT_TXD3_SEQ, seqno); + + txwi[3] = cpu_to_le32(val); + + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + txwi[3] |= cpu_to_le32(MT_TXD3_NO_ACK); + + if (key) + txwi[3] |= cpu_to_le32(MT_TXD3_PROTECT_FRAME); + + txwi[7] = FIELD_PREP(MT_TXD7_TYPE, fc_type) | + FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype); + + return 0; +} + +void mt7615_txp_skb_unmap(struct mt76_dev *dev, + struct mt76_txwi_cache *t) +{ + struct mt7615_txp *txp; + u8 *txwi; + int i; + + txwi = mt76_get_txwi_ptr(dev, t); + txp = (struct mt7615_txp *)(txwi + MT_TXD_SIZE); + for (i = 1; i < txp->nbuf; i++) + dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]), + le16_to_cpu(txp->len[i]), DMA_TO_DEVICE); +} + +int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + struct mt7615_sta *msta = container_of(wcid, struct mt7615_sta, wcid); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); + struct ieee80211_key_conf *key = info->control.hw_key; + struct ieee80211_vif *vif = info->control.vif; + int i, pid, id, nbuf = tx_info->nbuf - 1; + u8 *txwi = (u8 *)txwi_ptr; + struct mt76_txwi_cache *t; + struct mt7615_txp *txp; + + if (!wcid) + wcid = &dev->mt76.global_wcid; + + pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); + + if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { + spin_lock_bh(&dev->mt76.lock); + msta->rate_probe = true; + mt7615_mcu_set_rates(dev, msta, &info->control.rates[0], + msta->rates); + spin_unlock_bh(&dev->mt76.lock); + } + + mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta, + pid, key); + + txp = (struct mt7615_txp *)(txwi + MT_TXD_SIZE); + for (i = 0; i < nbuf; i++) { + txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr); + txp->len[i] = cpu_to_le16(tx_info->buf[i + 1].len); + } + txp->nbuf = nbuf; + + /* pass partial skb header to fw */ + tx_info->buf[1].len = MT_CT_PARSE_LEN; + tx_info->nbuf = MT_CT_DMA_BUF_NUM; + + txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD); + + if (!key) + txp->flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME); + + if (ieee80211_is_mgmt(hdr->frame_control)) + txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME); + + if (vif) { + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + + txp->bss_idx = mvif->idx; + } + + t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); + t->skb = tx_info->skb; + + spin_lock_bh(&dev->token_lock); + id = idr_alloc(&dev->token, t, 0, MT7615_TOKEN_SIZE, GFP_ATOMIC); + spin_unlock_bh(&dev->token_lock); + if (id < 0) + return id; + + txp->token = cpu_to_le16(id); + txp->rept_wds_wcid = 0xff; + tx_info->skb = DMA_DUMMY_DATA; + + return 0; +} + +static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, + struct ieee80211_tx_info *info, __le32 *txs_data) +{ + struct ieee80211_supported_band *sband; + int i, idx, count, final_idx = 0; + bool fixed_rate, final_mpdu, ack_timeout; + bool probe, ampdu, cck = false; + u32 final_rate, final_rate_flags, final_nss, txs; + u8 pid; + + fixed_rate = info->status.rates[0].count; + probe = !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); + + txs = le32_to_cpu(txs_data[1]); + final_mpdu = txs & MT_TXS1_ACKED_MPDU; + ampdu = !fixed_rate && (txs & MT_TXS1_AMPDU); + + txs = le32_to_cpu(txs_data[3]); + count = FIELD_GET(MT_TXS3_TX_COUNT, txs); + + txs = le32_to_cpu(txs_data[0]); + pid = FIELD_GET(MT_TXS0_PID, txs); + final_rate = FIELD_GET(MT_TXS0_TX_RATE, txs); + ack_timeout = txs & MT_TXS0_ACK_TIMEOUT; + + if (!ampdu && (txs & MT_TXS0_RTS_TIMEOUT)) + return false; + + if (txs & MT_TXS0_QUEUE_TIMEOUT) + return false; + + if (!ack_timeout) + info->flags |= IEEE80211_TX_STAT_ACK; + + info->status.ampdu_len = 1; + info->status.ampdu_ack_len = !!(info->flags & + IEEE80211_TX_STAT_ACK); + + if (ampdu || (info->flags & IEEE80211_TX_CTL_AMPDU)) + info->flags |= IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_CTL_AMPDU; + + if (fixed_rate && !probe) { + info->status.rates[0].count = count; + goto out; + } + + for (i = 0, idx = 0; i < ARRAY_SIZE(info->status.rates); i++) { + int cur_count = min_t(int, count, 2 * MT7615_RATE_RETRY); + + if (!i && probe) { + cur_count = 1; + } else { + info->status.rates[i] = sta->rates[idx]; + idx++; + } + + if (i && info->status.rates[i].idx < 0) { + info->status.rates[i - 1].count += count; + break; + } + + if (!count) { + info->status.rates[i].idx = -1; + break; + } + + info->status.rates[i].count = cur_count; + final_idx = i; + count -= cur_count; + } + +out: + final_rate_flags = info->status.rates[final_idx].flags; + + switch (FIELD_GET(MT_TX_RATE_MODE, final_rate)) { + case MT_PHY_TYPE_CCK: + cck = true; + /* fall through */ + case MT_PHY_TYPE_OFDM: + if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) + sband = &dev->mt76.sband_5g.sband; + else + sband = &dev->mt76.sband_2g.sband; + final_rate &= MT_TX_RATE_IDX; + final_rate = mt7615_get_rate(dev, sband, final_rate, cck); + final_rate_flags = 0; + break; + case MT_PHY_TYPE_HT_GF: + case MT_PHY_TYPE_HT: + final_rate_flags |= IEEE80211_TX_RC_MCS; + final_rate &= MT_TX_RATE_IDX; + if (final_rate > 31) + return false; + break; + case MT_PHY_TYPE_VHT: + final_nss = FIELD_GET(MT_TX_RATE_NSS, final_rate); + final_rate_flags |= IEEE80211_TX_RC_VHT_MCS; + final_rate = (final_rate & MT_TX_RATE_IDX) | (final_nss << 4); + break; + default: + return false; + } + + info->status.rates[final_idx].idx = final_rate; + info->status.rates[final_idx].flags = final_rate_flags; + + return true; +} + +static bool mt7615_mac_add_txs_skb(struct mt7615_dev *dev, + struct mt7615_sta *sta, int pid, + __le32 *txs_data) +{ + struct mt76_dev *mdev = &dev->mt76; + struct sk_buff_head list; + struct sk_buff *skb; + + if (pid < MT_PACKET_ID_FIRST) + return false; + + mt76_tx_status_lock(mdev, &list); + skb = mt76_tx_status_skb_get(mdev, &sta->wcid, pid, &list); + if (skb) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + + if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { + spin_lock_bh(&dev->mt76.lock); + if (sta->rate_probe) { + mt7615_mcu_set_rates(dev, sta, NULL, + sta->rates); + sta->rate_probe = false; + } + spin_unlock_bh(&dev->mt76.lock); + } + + if (!mt7615_fill_txs(dev, sta, info, txs_data)) { + ieee80211_tx_info_clear_status(info); + info->status.rates[0].idx = -1; + } + + mt76_tx_status_skb_done(mdev, skb, &list); + } + mt76_tx_status_unlock(mdev, &list); + + return !!skb; +} + +void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) +{ + struct ieee80211_tx_info info = {}; + struct ieee80211_sta *sta = NULL; + struct mt7615_sta *msta = NULL; + struct mt76_wcid *wcid; + __le32 *txs_data = data; + u32 txs; + u8 wcidx; + u8 pid; + + txs = le32_to_cpu(txs_data[0]); + pid = FIELD_GET(MT_TXS0_PID, txs); + txs = le32_to_cpu(txs_data[2]); + wcidx = FIELD_GET(MT_TXS2_WCID, txs); + + if (pid == MT_PACKET_ID_NO_ACK) + return; + + if (wcidx >= ARRAY_SIZE(dev->mt76.wcid)) + return; + + rcu_read_lock(); + + wcid = rcu_dereference(dev->mt76.wcid[wcidx]); + if (!wcid) + goto out; + + msta = container_of(wcid, struct mt7615_sta, wcid); + sta = wcid_to_sta(wcid); + + if (mt7615_mac_add_txs_skb(dev, msta, pid, txs_data)) + goto out; + + if (wcidx >= MT7615_WTBL_STA || !sta) + goto out; + + if (mt7615_fill_txs(dev, msta, &info, txs_data)) + ieee80211_tx_status_noskb(mt76_hw(dev), sta, &info); + +out: + rcu_read_unlock(); +} + +void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb) +{ + struct mt7615_tx_free *free = (struct mt7615_tx_free *)skb->data; + struct mt76_dev *mdev = &dev->mt76; + struct mt76_txwi_cache *txwi; + u8 i, count; + + count = FIELD_GET(MT_TX_FREE_MSDU_ID_CNT, le16_to_cpu(free->ctrl)); + for (i = 0; i < count; i++) { + spin_lock_bh(&dev->token_lock); + txwi = idr_remove(&dev->token, le16_to_cpu(free->token[i])); + spin_unlock_bh(&dev->token_lock); + + if (!txwi) + continue; + + mt7615_txp_skb_unmap(mdev, txwi); + if (txwi->skb) { + mt76_tx_complete_skb(mdev, txwi->skb); + txwi->skb = NULL; + } + + mt76_put_txwi(mdev, txwi); + } + dev_kfree_skb(skb); +} + +void mt7615_mac_work(struct work_struct *work) +{ + struct mt7615_dev *dev; + + dev = (struct mt7615_dev *)container_of(work, struct mt76_dev, + mac_work.work); + + mt76_tx_status_check(&dev->mt76, NULL, false); + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, + MT7615_WATCHDOG_TIME); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h new file mode 100644 index 000000000000..18ad4b8a3807 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -0,0 +1,300 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2019 MediaTek Inc. */ + +#ifndef __MT7615_MAC_H +#define __MT7615_MAC_H + +#define MT_CT_PARSE_LEN 72 +#define MT_CT_DMA_BUF_NUM 2 + +#define MT_RXD0_LENGTH GENMASK(15, 0) +#define MT_RXD0_PKT_TYPE GENMASK(31, 29) + +#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) +#define MT_RXD0_NORMAL_IP_SUM BIT(23) +#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24) +#define MT_RXD0_NORMAL_GROUP_1 BIT(25) +#define MT_RXD0_NORMAL_GROUP_2 BIT(26) +#define MT_RXD0_NORMAL_GROUP_3 BIT(27) +#define MT_RXD0_NORMAL_GROUP_4 BIT(28) + +enum rx_pkt_type { + PKT_TYPE_TXS, + PKT_TYPE_TXRXV, + PKT_TYPE_NORMAL, + PKT_TYPE_RX_DUP_RFB, + PKT_TYPE_RX_TMR, + PKT_TYPE_RETRIEVE, + PKT_TYPE_TXRX_NOTIFY, + PKT_TYPE_RX_EVENT +}; + +#define MT_RXD1_NORMAL_BSSID GENMASK(31, 26) +#define MT_RXD1_NORMAL_PAYLOAD_FORMAT GENMASK(25, 24) +#define MT_RXD1_NORMAL_HDR_TRANS BIT(23) +#define MT_RXD1_NORMAL_HDR_OFFSET BIT(22) +#define MT_RXD1_NORMAL_MAC_HDR_LEN GENMASK(21, 16) +#define MT_RXD1_NORMAL_CH_FREQ GENMASK(15, 8) +#define MT_RXD1_NORMAL_KEY_ID GENMASK(7, 6) +#define MT_RXD1_NORMAL_BEACON_UC BIT(5) +#define MT_RXD1_NORMAL_BEACON_MC BIT(4) +#define MT_RXD1_NORMAL_BF_REPORT BIT(3) +#define MT_RXD1_NORMAL_ADDR_TYPE GENMASK(2, 1) +#define MT_RXD1_NORMAL_BCAST GENMASK(2, 1) +#define MT_RXD1_NORMAL_MCAST BIT(2) +#define MT_RXD1_NORMAL_U2M BIT(1) +#define MT_RXD1_NORMAL_HTC_VLD BIT(0) + +#define MT_RXD2_NORMAL_NON_AMPDU BIT(31) +#define MT_RXD2_NORMAL_NON_AMPDU_SUB BIT(30) +#define MT_RXD2_NORMAL_NDATA BIT(29) +#define MT_RXD2_NORMAL_NULL_FRAME BIT(28) +#define MT_RXD2_NORMAL_FRAG BIT(27) +#define MT_RXD2_NORMAL_INT_FRAME BIT(26) +#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25) +#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24) +#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23) +#define MT_RXD2_NORMAL_LEN_MISMATCH BIT(22) +#define MT_RXD2_NORMAL_TKIP_MIC_ERR BIT(21) +#define MT_RXD2_NORMAL_ICV_ERR BIT(20) +#define MT_RXD2_NORMAL_CLM BIT(19) +#define MT_RXD2_NORMAL_CM BIT(18) +#define MT_RXD2_NORMAL_FCS_ERR BIT(17) +#define MT_RXD2_NORMAL_SW_BIT BIT(16) +#define MT_RXD2_NORMAL_SEC_MODE GENMASK(15, 12) +#define MT_RXD2_NORMAL_TID GENMASK(11, 8) +#define MT_RXD2_NORMAL_WLAN_IDX GENMASK(7, 0) + +#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30) +#define MT_RXD3_NORMAL_PF_MODE BIT(29) +#define MT_RXD3_NORMAL_CLS_BITMAP GENMASK(28, 19) +#define MT_RXD3_NORMAL_WOL GENMASK(18, 14) +#define MT_RXD3_NORMAL_MAGIC_PKT BIT(13) +#define MT_RXD3_NORMAL_OFLD GENMASK(12, 11) +#define MT_RXD3_NORMAL_CLS BIT(10) +#define MT_RXD3_NORMAL_PATTERN_DROP BIT(9) +#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(8) +#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0) + +#define MT_RXV1_ACID_DET_H BIT(31) +#define MT_RXV1_ACID_DET_L BIT(30) +#define MT_RXV1_VHTA2_B8_B3 GENMASK(29, 24) +#define MT_RXV1_NUM_RX GENMASK(23, 22) +#define MT_RXV1_HT_NO_SOUND BIT(21) +#define MT_RXV1_HT_SMOOTH BIT(20) +#define MT_RXV1_HT_SHORT_GI BIT(19) +#define MT_RXV1_HT_AGGR BIT(18) +#define MT_RXV1_VHTA1_B22 BIT(17) +#define MT_RXV1_FRAME_MODE GENMASK(16, 15) +#define MT_RXV1_TX_MODE GENMASK(14, 12) +#define MT_RXV1_HT_EXT_LTF GENMASK(11, 10) +#define MT_RXV1_HT_AD_CODE BIT(9) +#define MT_RXV1_HT_STBC GENMASK(8, 7) +#define MT_RXV1_TX_RATE GENMASK(6, 0) + +#define MT_RXV2_SEL_ANT BIT(31) +#define MT_RXV2_VALID_BIT BIT(30) +#define MT_RXV2_NSTS GENMASK(29, 27) +#define MT_RXV2_GROUP_ID GENMASK(26, 21) +#define MT_RXV2_LENGTH GENMASK(20, 0) + +enum tx_header_format { + MT_HDR_FORMAT_802_3, + MT_HDR_FORMAT_CMD, + MT_HDR_FORMAT_802_11, + MT_HDR_FORMAT_802_11_EXT, +}; + +enum tx_pkt_type { + MT_TX_TYPE_CT, + MT_TX_TYPE_SF, + MT_TX_TYPE_CMD, + MT_TX_TYPE_FW, +}; + +enum tx_pkt_queue_idx { + MT_LMAC_AC00, + MT_LMAC_AC01, + MT_LMAC_AC02, + MT_LMAC_AC03, + MT_LMAC_ALTX0 = 0x10, + MT_LMAC_BMC0, + MT_LMAC_BCN0, + MT_LMAC_PSMP0, +}; + +enum tx_port_idx { + MT_TX_PORT_IDX_LMAC, + MT_TX_PORT_IDX_MCU +}; + +enum tx_mcu_port_q_idx { + MT_TX_MCU_PORT_RX_Q0 = 0, + MT_TX_MCU_PORT_RX_Q1, + MT_TX_MCU_PORT_RX_Q2, + MT_TX_MCU_PORT_RX_Q3, + MT_TX_MCU_PORT_RX_FWDL = 0x1e +}; + +enum tx_phy_bandwidth { + MT_PHY_BW_20, + MT_PHY_BW_40, + MT_PHY_BW_80, + MT_PHY_BW_160, +}; + +#define MT_CT_INFO_APPLY_TXD BIT(0) +#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1) +#define MT_CT_INFO_MGMT_FRAME BIT(2) +#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3) +#define MT_CT_INFO_HSR2_TX BIT(4) + +#define MT_TXD_SIZE (8 * 4) + +#define MT_TXD0_P_IDX BIT(31) +#define MT_TXD0_Q_IDX GENMASK(30, 26) +#define MT_TXD0_UDP_TCP_SUM BIT(24) +#define MT_TXD0_IP_SUM BIT(23) +#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16) +#define MT_TXD0_TX_BYTES GENMASK(15, 0) + +#define MT_TXD1_OWN_MAC GENMASK(31, 26) +#define MT_TXD1_PKT_FMT GENMASK(25, 24) +#define MT_TXD1_TID GENMASK(23, 21) +#define MT_TXD1_AMSDU BIT(20) +#define MT_TXD1_UNXV BIT(19) +#define MT_TXD1_HDR_PAD GENMASK(18, 17) +#define MT_TXD1_TXD_LEN BIT(16) +#define MT_TXD1_LONG_FORMAT BIT(15) +#define MT_TXD1_HDR_FORMAT GENMASK(14, 13) +#define MT_TXD1_HDR_INFO GENMASK(12, 8) +#define MT_TXD1_WLAN_IDX GENMASK(7, 0) + +#define MT_TXD2_FIX_RATE BIT(31) +#define MT_TXD2_TIMING_MEASURE BIT(30) +#define MT_TXD2_BA_DISABLE BIT(29) +#define MT_TXD2_POWER_OFFSET GENMASK(28, 24) +#define MT_TXD2_MAX_TX_TIME GENMASK(23, 16) +#define MT_TXD2_FRAG GENMASK(15, 14) +#define MT_TXD2_HTC_VLD BIT(13) +#define MT_TXD2_DURATION BIT(12) +#define MT_TXD2_BIP BIT(11) +#define MT_TXD2_MULTICAST BIT(10) +#define MT_TXD2_RTS BIT(9) +#define MT_TXD2_SOUNDING BIT(8) +#define MT_TXD2_NDPA BIT(7) +#define MT_TXD2_NDP BIT(6) +#define MT_TXD2_FRAME_TYPE GENMASK(5, 4) +#define MT_TXD2_SUB_TYPE GENMASK(3, 0) + +#define MT_TXD3_SN_VALID BIT(31) +#define MT_TXD3_PN_VALID BIT(30) +#define MT_TXD3_SEQ GENMASK(27, 16) +#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11) +#define MT_TXD3_TX_COUNT GENMASK(10, 6) +#define MT_TXD3_PROTECT_FRAME BIT(1) +#define MT_TXD3_NO_ACK BIT(0) + +#define MT_TXD4_PN_LOW GENMASK(31, 0) + +#define MT_TXD5_PN_HIGH GENMASK(31, 16) +#define MT_TXD5_SW_POWER_MGMT BIT(13) +#define MT_TXD5_DA_SELECT BIT(11) +#define MT_TXD5_TX_STATUS_HOST BIT(10) +#define MT_TXD5_TX_STATUS_MCU BIT(9) +#define MT_TXD5_TX_STATUS_FMT BIT(8) +#define MT_TXD5_PID GENMASK(7, 0) + +#define MT_TXD6_FIXED_RATE BIT(31) +#define MT_TXD6_SGI BIT(30) +#define MT_TXD6_LDPC BIT(29) +#define MT_TXD6_TX_BF BIT(28) +#define MT_TXD6_TX_RATE GENMASK(27, 16) +#define MT_TXD6_ANT_ID GENMASK(15, 4) +#define MT_TXD6_DYN_BW BIT(3) +#define MT_TXD6_FIXED_BW BIT(2) +#define MT_TXD6_BW GENMASK(1, 0) + +#define MT_TXD7_TYPE GENMASK(21, 20) +#define MT_TXD7_SUB_TYPE GENMASK(19, 16) + +#define MT_TX_RATE_STBC BIT(11) +#define MT_TX_RATE_NSS GENMASK(10, 9) +#define MT_TX_RATE_MODE GENMASK(8, 6) +#define MT_TX_RATE_IDX GENMASK(5, 0) + +#define MT_TXP_MAX_BUF_NUM 6 + +struct mt7615_txp { + __le16 flags; + __le16 token; + u8 bss_idx; + u8 rept_wds_wcid; + u8 rsv; + u8 nbuf; + __le32 buf[MT_TXP_MAX_BUF_NUM]; + __le16 len[MT_TXP_MAX_BUF_NUM]; +} __packed; + +struct mt7615_tx_free { + __le16 rx_byte_cnt; + __le16 ctrl; + u8 txd_cnt; + u8 rsv[3]; + __le16 token[]; +} __packed; + +#define MT_TX_FREE_MSDU_ID_CNT GENMASK(6, 0) + +#define MT_TXS0_PID GENMASK(31, 24) +#define MT_TXS0_BA_ERROR BIT(22) +#define MT_TXS0_PS_FLAG BIT(21) +#define MT_TXS0_TXOP_TIMEOUT BIT(20) +#define MT_TXS0_BIP_ERROR BIT(19) + +#define MT_TXS0_QUEUE_TIMEOUT BIT(18) +#define MT_TXS0_RTS_TIMEOUT BIT(17) +#define MT_TXS0_ACK_TIMEOUT BIT(16) +#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16) + +#define MT_TXS0_TX_STATUS_HOST BIT(15) +#define MT_TXS0_TX_STATUS_MCU BIT(14) +#define MT_TXS0_TXS_FORMAT BIT(13) +#define MT_TXS0_FIXED_RATE BIT(12) +#define MT_TXS0_TX_RATE GENMASK(11, 0) + +#define MT_TXS1_ANT_ID GENMASK(31, 20) +#define MT_TXS1_RESP_RATE GENMASK(19, 16) +#define MT_TXS1_BW GENMASK(15, 14) +#define MT_TXS1_I_TXBF BIT(13) +#define MT_TXS1_E_TXBF BIT(12) +#define MT_TXS1_TID GENMASK(11, 9) +#define MT_TXS1_AMPDU BIT(8) +#define MT_TXS1_ACKED_MPDU BIT(7) +#define MT_TXS1_TX_POWER_DBM GENMASK(6, 0) + +#define MT_TXS2_WCID GENMASK(31, 24) +#define MT_TXS2_RXV_SEQNO GENMASK(23, 16) +#define MT_TXS2_TX_DELAY GENMASK(15, 0) + +#define MT_TXS3_LAST_TX_RATE GENMASK(31, 29) +#define MT_TXS3_TX_COUNT GENMASK(28, 24) +#define MT_TXS3_F1_TSSI1 GENMASK(23, 12) +#define MT_TXS3_F1_TSSI0 GENMASK(11, 0) +#define MT_TXS3_F0_SEQNO GENMASK(11, 0) + +#define MT_TXS4_F0_TIMESTAMP GENMASK(31, 0) +#define MT_TXS4_F1_TSSI3 GENMASK(23, 12) +#define MT_TXS4_F1_TSSI2 GENMASK(11, 0) + +#define MT_TXS5_F0_FRONT_TIME GENMASK(24, 0) +#define MT_TXS5_F1_NOISE_2 GENMASK(23, 16) +#define MT_TXS5_F1_NOISE_1 GENMASK(15, 8) +#define MT_TXS5_F1_NOISE_0 GENMASK(7, 0) + +#define MT_TXS6_F1_RCPI_3 GENMASK(31, 24) +#define MT_TXS6_F1_RCPI_2 GENMASK(23, 16) +#define MT_TXS6_F1_RCPI_1 GENMASK(15, 8) +#define MT_TXS6_F1_RCPI_0 GENMASK(7, 0) + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c new file mode 100644 index 000000000000..80e6b211f60b --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -0,0 +1,499 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2019 MediaTek Inc. + * + * Author: Roy Luo <royluo@google.com> + * Ryder Lee <ryder.lee@mediatek.com> + * Felix Fietkau <nbd@nbd.name> + */ + +#include <linux/etherdevice.h> +#include <linux/platform_device.h> +#include <linux/pci.h> +#include <linux/module.h> +#include "mt7615.h" + +static int mt7615_start(struct ieee80211_hw *hw) +{ + struct mt7615_dev *dev = hw->priv; + + set_bit(MT76_STATE_RUNNING, &dev->mt76.state); + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, + MT7615_WATCHDOG_TIME); + + return 0; +} + +static void mt7615_stop(struct ieee80211_hw *hw) +{ + struct mt7615_dev *dev = hw->priv; + + clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + cancel_delayed_work_sync(&dev->mt76.mac_work); +} + +static int get_omac_idx(enum nl80211_iftype type, u32 mask) +{ + int i; + + switch (type) { + case NL80211_IFTYPE_AP: + /* ap use hw bssid 0 and ext bssid */ + if (~mask & BIT(HW_BSSID_0)) + return HW_BSSID_0; + + for (i = EXT_BSSID_1; i < EXT_BSSID_END; i++) + if (~mask & BIT(i)) + return i; + + break; + case NL80211_IFTYPE_STATION: + /* sta use hw bssid other than 0 */ + for (i = HW_BSSID_1; i < HW_BSSID_MAX; i++) + if (~mask & BIT(i)) + return i; + + break; + default: + WARN_ON(1); + break; + }; + + return -1; +} + +static int mt7615_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt7615_dev *dev = hw->priv; + struct mt76_txq *mtxq; + int idx, ret = 0; + + mutex_lock(&dev->mt76.mutex); + + mvif->idx = ffs(~dev->vif_mask) - 1; + if (mvif->idx >= MT7615_MAX_INTERFACES) { + ret = -ENOSPC; + goto out; + } + + mvif->omac_idx = get_omac_idx(vif->type, dev->omac_mask); + if (mvif->omac_idx < 0) { + ret = -ENOSPC; + goto out; + } + + /* TODO: DBDC support. Use band 0 and wmm 0 for now */ + mvif->band_idx = 0; + mvif->wmm_idx = 0; + + ret = mt7615_mcu_set_dev_info(dev, vif, 1); + if (ret) + goto out; + + dev->vif_mask |= BIT(mvif->idx); + dev->omac_mask |= BIT(mvif->omac_idx); + idx = MT7615_WTBL_RESERVED - 1 - mvif->idx; + mvif->sta.wcid.idx = idx; + mvif->sta.wcid.hw_key_idx = -1; + + rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); + mtxq = (struct mt76_txq *)vif->txq->drv_priv; + mtxq->wcid = &mvif->sta.wcid; + mt76_txq_init(&dev->mt76, vif->txq); + +out: + mutex_unlock(&dev->mt76.mutex); + + return ret; +} + +static void mt7615_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt7615_dev *dev = hw->priv; + int idx = mvif->sta.wcid.idx; + + /* TODO: disable beacon for the bss */ + + mt7615_mcu_set_dev_info(dev, vif, 0); + + rcu_assign_pointer(dev->mt76.wcid[idx], NULL); + mt76_txq_remove(&dev->mt76, vif->txq); + + mutex_lock(&dev->mt76.mutex); + dev->vif_mask &= ~BIT(mvif->idx); + dev->omac_mask &= ~BIT(mvif->omac_idx); + mutex_unlock(&dev->mt76.mutex); +} + +static int mt7615_set_channel(struct mt7615_dev *dev, + struct cfg80211_chan_def *def) +{ + int ret; + + cancel_delayed_work_sync(&dev->mt76.mac_work); + set_bit(MT76_RESET, &dev->mt76.state); + + mt76_set_channel(&dev->mt76); + + ret = mt7615_mcu_set_channel(dev); + if (ret) + return ret; + + clear_bit(MT76_RESET, &dev->mt76.state); + + mt76_txq_schedule_all(&dev->mt76); + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, + MT7615_WATCHDOG_TIME); + return 0; +} + +static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct mt7615_dev *dev = hw->priv; + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt7615_sta *msta = sta ? (struct mt7615_sta *)sta->drv_priv : + &mvif->sta; + struct mt76_wcid *wcid = &msta->wcid; + int idx = key->keyidx; + + /* The hardware does not support per-STA RX GTK, fallback + * to software mode for these. + */ + if ((vif->type == NL80211_IFTYPE_ADHOC || + vif->type == NL80211_IFTYPE_MESH_POINT) && + (key->cipher == WLAN_CIPHER_SUITE_TKIP || + key->cipher == WLAN_CIPHER_SUITE_CCMP) && + !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + return -EOPNOTSUPP; + + if (cmd == SET_KEY) { + key->hw_key_idx = wcid->idx; + wcid->hw_key_idx = idx; + } else { + if (idx == wcid->hw_key_idx) + wcid->hw_key_idx = -1; + + key = NULL; + } + mt76_wcid_key_setup(&dev->mt76, wcid, key); + + return mt7615_mcu_set_wtbl_key(dev, wcid->idx, key, cmd); +} + +static int mt7615_config(struct ieee80211_hw *hw, u32 changed) +{ + struct mt7615_dev *dev = hw->priv; + int ret = 0; + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + mutex_lock(&dev->mt76.mutex); + + ieee80211_stop_queues(hw); + ret = mt7615_set_channel(dev, &hw->conf.chandef); + ieee80211_wake_queues(hw); + + mutex_unlock(&dev->mt76.mutex); + } + + if (changed & IEEE80211_CONF_CHANGE_MONITOR) { + mutex_lock(&dev->mt76.mutex); + + if (!(hw->conf.flags & IEEE80211_CONF_MONITOR)) + dev->mt76.rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; + else + dev->mt76.rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; + + mt76_wr(dev, MT_WF_RFCR, dev->mt76.rxfilter); + + mutex_unlock(&dev->mt76.mutex); + } + return ret; +} + +static int +mt7615_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + struct mt7615_dev *dev = hw->priv; + static const u8 wmm_queue_map[] = { + [IEEE80211_AC_BK] = 0, + [IEEE80211_AC_BE] = 1, + [IEEE80211_AC_VI] = 2, + [IEEE80211_AC_VO] = 3, + }; + + /* TODO: hw wmm_set 1~3 */ + return mt7615_mcu_set_wmm(dev, wmm_queue_map[queue], params); +} + +static void mt7615_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) +{ + struct mt7615_dev *dev = hw->priv; + u32 flags = 0; + +#define MT76_FILTER(_flag, _hw) do { \ + flags |= *total_flags & FIF_##_flag; \ + dev->mt76.rxfilter &= ~(_hw); \ + dev->mt76.rxfilter |= !(flags & FIF_##_flag) * (_hw); \ + } while (0) + + dev->mt76.rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | + MT_WF_RFCR_DROP_OTHER_BEACON | + MT_WF_RFCR_DROP_FRAME_REPORT | + MT_WF_RFCR_DROP_PROBEREQ | + MT_WF_RFCR_DROP_MCAST_FILTERED | + MT_WF_RFCR_DROP_MCAST | + MT_WF_RFCR_DROP_BCAST | + MT_WF_RFCR_DROP_DUPLICATE | + MT_WF_RFCR_DROP_A2_BSSID | + MT_WF_RFCR_DROP_UNWANTED_CTL | + MT_WF_RFCR_DROP_STBC_MULTI); + + MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM | + MT_WF_RFCR_DROP_A3_MAC | + MT_WF_RFCR_DROP_A3_BSSID); + + MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL); + + MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS | + MT_WF_RFCR_DROP_RTS | + MT_WF_RFCR_DROP_CTL_RSV | + MT_WF_RFCR_DROP_NDPA); + + *total_flags = flags; + mt76_wr(dev, MT_WF_RFCR, dev->mt76.rxfilter); +} + +static void mt7615_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed) +{ + struct mt7615_dev *dev = hw->priv; + + mutex_lock(&dev->mt76.mutex); + + /* TODO: sta mode connect/disconnect + * BSS_CHANGED_ASSOC | BSS_CHANGED_BSSID + */ + + /* TODO: update beacon content + * BSS_CHANGED_BEACON + */ + + if (changed & BSS_CHANGED_BEACON_ENABLED) { + if (info->enable_beacon) { + mt7615_mcu_set_bss_info(dev, vif, 1); + mt7615_mcu_add_wtbl_bmc(dev, vif); + mt7615_mcu_set_sta_rec_bmc(dev, vif, 1); + mt7615_mcu_set_bcn(dev, vif, 1); + } else { + mt7615_mcu_set_sta_rec_bmc(dev, vif, 0); + mt7615_mcu_del_wtbl_bmc(dev, vif); + mt7615_mcu_set_bss_info(dev, vif, 0); + mt7615_mcu_set_bcn(dev, vif, 0); + } + } + + mutex_unlock(&dev->mt76.mutex); +} + +int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + int idx; + + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7615_WTBL_STA - 1); + if (idx < 0) + return -ENOSPC; + + msta->vif = mvif; + msta->wcid.sta = 1; + msta->wcid.idx = idx; + + mt7615_mcu_add_wtbl(dev, vif, sta); + mt7615_mcu_set_sta_rec(dev, vif, sta, 1); + + return 0; +} + +void mt7615_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + + if (sta->ht_cap.ht_supported) + mt7615_mcu_set_ht_cap(dev, vif, sta); +} + +void mt7615_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + + mt7615_mcu_set_sta_rec(dev, vif, sta, 0); + mt7615_mcu_del_wtbl(dev, vif, sta); +} + +static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7615_dev *dev = hw->priv; + struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + struct ieee80211_sta_rates *sta_rates = rcu_dereference(sta->rates); + int i; + + spin_lock_bh(&dev->mt76.lock); + for (i = 0; i < ARRAY_SIZE(msta->rates); i++) { + msta->rates[i].idx = sta_rates->rate[i].idx; + msta->rates[i].count = sta_rates->rate[i].count; + msta->rates[i].flags = sta_rates->rate[i].flags; + + if (msta->rates[i].idx < 0 || !msta->rates[i].count) + break; + } + msta->n_rates = i; + mt7615_mcu_set_rates(dev, msta, NULL, msta->rates); + msta->rate_probe = false; + spin_unlock_bh(&dev->mt76.lock); +} + +static void mt7615_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct mt7615_dev *dev = hw->priv; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; + struct mt76_wcid *wcid = &dev->mt76.global_wcid; + + if (control->sta) { + struct mt7615_sta *sta; + + sta = (struct mt7615_sta *)control->sta->drv_priv; + wcid = &sta->wcid; + } + + if (vif && !control->sta) { + struct mt7615_vif *mvif; + + mvif = (struct mt7615_vif *)vif->drv_priv; + wcid = &mvif->sta.wcid; + } + + mt76_tx(&dev->mt76, control->sta, wcid, skb); +} + +static int mt7615_set_rts_threshold(struct ieee80211_hw *hw, u32 val) +{ + struct mt7615_dev *dev = hw->priv; + + mutex_lock(&dev->mt76.mutex); + mt7615_mcu_set_rts_thresh(dev, val); + mutex_unlock(&dev->mt76.mutex); + + return 0; +} + +static int +mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_ampdu_params *params) +{ + enum ieee80211_ampdu_mlme_action action = params->action; + struct mt7615_dev *dev = hw->priv; + struct ieee80211_sta *sta = params->sta; + struct ieee80211_txq *txq = sta->txq[params->tid]; + struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; + struct mt76_txq *mtxq; + + if (!txq) + return -EINVAL; + + mtxq = (struct mt76_txq *)txq->drv_priv; + + switch (action) { + case IEEE80211_AMPDU_RX_START: + mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, *ssn, + params->buf_size); + mt7615_mcu_set_rx_ba(dev, params, 1); + break; + case IEEE80211_AMPDU_RX_STOP: + mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); + mt7615_mcu_set_rx_ba(dev, params, 0); + break; + case IEEE80211_AMPDU_TX_OPERATIONAL: + mtxq->aggr = true; + mtxq->send_bar = false; + mt7615_mcu_set_tx_ba(dev, params, 1); + break; + case IEEE80211_AMPDU_TX_STOP_FLUSH: + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: + mtxq->aggr = false; + ieee80211_send_bar(vif, sta->addr, tid, mtxq->agg_ssn); + mt7615_mcu_set_tx_ba(dev, params, 0); + break; + case IEEE80211_AMPDU_TX_START: + mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(*ssn); + ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); + break; + case IEEE80211_AMPDU_TX_STOP_CONT: + mtxq->aggr = false; + mt7615_mcu_set_tx_ba(dev, params, 0); + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + break; + } + + return 0; +} + +static void +mt7615_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + const u8 *mac) +{ + struct mt7615_dev *dev = hw->priv; + + set_bit(MT76_SCANNING, &dev->mt76.state); +} + +static void +mt7615_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct mt7615_dev *dev = hw->priv; + + clear_bit(MT76_SCANNING, &dev->mt76.state); +} + +const struct ieee80211_ops mt7615_ops = { + .tx = mt7615_tx, + .start = mt7615_start, + .stop = mt7615_stop, + .add_interface = mt7615_add_interface, + .remove_interface = mt7615_remove_interface, + .config = mt7615_config, + .conf_tx = mt7615_conf_tx, + .configure_filter = mt7615_configure_filter, + .bss_info_changed = mt7615_bss_info_changed, + .sta_state = mt76_sta_state, + .set_key = mt7615_set_key, + .ampdu_action = mt7615_ampdu_action, + .set_rts_threshold = mt7615_set_rts_threshold, + .wake_tx_queue = mt76_wake_tx_queue, + .sta_rate_tbl_update = mt7615_sta_rate_tbl_update, + .sw_scan_start = mt7615_sw_scan, + .sw_scan_complete = mt7615_sw_scan_complete, + .release_buffered_frames = mt76_release_buffered_frames, +}; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c new file mode 100644 index 000000000000..ea67c6022fe6 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -0,0 +1,1655 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2019 MediaTek Inc. + * + * Author: Roy Luo <royluo@google.com> + * Ryder Lee <ryder.lee@mediatek.com> + */ + +#include <linux/firmware.h> +#include "mt7615.h" +#include "mcu.h" +#include "mac.h" +#include "eeprom.h" + +struct mt7615_patch_hdr { + char build_date[16]; + char platform[4]; + __be32 hw_sw_ver; + __be32 patch_ver; + __be16 checksum; +} __packed; + +struct mt7615_fw_trailer { + __le32 addr; + u8 chip_id; + u8 feature_set; + u8 eco_code; + char fw_ver[10]; + char build_date[15]; + __le32 len; +} __packed; + +#define MCU_PATCH_ADDRESS 0x80000 + +#define N9_REGION_NUM 2 +#define CR4_REGION_NUM 1 + +#define IMG_CRC_LEN 4 + +#define FW_FEATURE_SET_ENCRYPT BIT(0) +#define FW_FEATURE_SET_KEY_IDX GENMASK(2, 1) + +#define DL_MODE_ENCRYPT BIT(0) +#define DL_MODE_KEY_IDX GENMASK(2, 1) +#define DL_MODE_RESET_SEC_IV BIT(3) +#define DL_MODE_WORKING_PDA_CR4 BIT(4) +#define DL_MODE_NEED_RSP BIT(31) + +#define FW_START_OVERRIDE BIT(0) +#define FW_START_WORKING_PDA_CR4 BIT(2) + +static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, + int cmd, int query, int dest, int *wait_seq) +{ + struct mt7615_mcu_txd *mcu_txd; + u8 seq, q_idx, pkt_fmt; + enum mt76_txq_id qid; + u32 val; + __le32 *txd; + + if (!skb) + return -EINVAL; + + seq = ++dev->mt76.mmio.mcu.msg_seq & 0xf; + if (!seq) + seq = ++dev->mt76.mmio.mcu.msg_seq & 0xf; + + mcu_txd = (struct mt7615_mcu_txd *)skb_push(skb, + sizeof(struct mt7615_mcu_txd)); + memset(mcu_txd, 0, sizeof(struct mt7615_mcu_txd)); + + if (cmd != -MCU_CMD_FW_SCATTER) { + q_idx = MT_TX_MCU_PORT_RX_Q0; + pkt_fmt = MT_TX_TYPE_CMD; + } else { + q_idx = MT_TX_MCU_PORT_RX_FWDL; + pkt_fmt = MT_TX_TYPE_FW; + } + + txd = mcu_txd->txd; + + val = FIELD_PREP(MT_TXD0_TX_BYTES, cpu_to_le16(skb->len)) | + FIELD_PREP(MT_TXD0_P_IDX, MT_TX_PORT_IDX_MCU) | + FIELD_PREP(MT_TXD0_Q_IDX, q_idx); + txd[0] = cpu_to_le32(val); + + val = MT_TXD1_LONG_FORMAT | + FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_CMD) | + FIELD_PREP(MT_TXD1_PKT_FMT, pkt_fmt); + txd[1] = cpu_to_le32(val); + + mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd)); + mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU, q_idx)); + mcu_txd->pkt_type = MCU_PKT_ID; + mcu_txd->seq = seq; + + if (cmd < 0) { + mcu_txd->cid = -cmd; + } else { + mcu_txd->cid = MCU_CMD_EXT_CID; + mcu_txd->ext_cid = cmd; + if (query != MCU_Q_NA) + mcu_txd->ext_cid_ack = 1; + } + + mcu_txd->set_query = query; + mcu_txd->s2d_index = dest; + + if (wait_seq) + *wait_seq = seq; + + if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state)) + qid = MT_TXQ_MCU; + else + qid = MT_TXQ_FWDL; + + return mt76_tx_queue_skb_raw(dev, qid, skb, 0); +} + +static int mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, + int cmd, int query, int dest, + struct sk_buff **skb_ret) +{ + unsigned long expires = jiffies + 10 * HZ; + struct mt7615_mcu_rxd *rxd; + int ret, seq; + + mutex_lock(&dev->mt76.mmio.mcu.mutex); + + ret = __mt7615_mcu_msg_send(dev, skb, cmd, query, dest, &seq); + if (ret) + goto out; + + while (1) { + skb = mt76_mcu_get_response(&dev->mt76, expires); + if (!skb) { + dev_err(dev->mt76.dev, "Message %d (seq %d) timeout\n", + cmd, seq); + ret = -ETIMEDOUT; + break; + } + + rxd = (struct mt7615_mcu_rxd *)skb->data; + if (seq != rxd->seq) + continue; + + if (skb_ret) { + int hdr_len = sizeof(*rxd); + + if (!test_bit(MT76_STATE_MCU_RUNNING, + &dev->mt76.state)) + hdr_len -= 4; + skb_pull(skb, hdr_len); + *skb_ret = skb; + } else { + dev_kfree_skb(skb); + } + + break; + } + +out: + mutex_unlock(&dev->mt76.mmio.mcu.mutex); + + return ret; +} + +static int mt7615_mcu_init_download(struct mt7615_dev *dev, u32 addr, + u32 len, u32 mode) +{ + struct { + __le32 addr; + __le32 len; + __le32 mode; + } req = { + .addr = cpu_to_le32(addr), + .len = cpu_to_le32(len), + .mode = cpu_to_le32(mode), + }; + struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); + + return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, + MCU_Q_NA, MCU_S2D_H2N, NULL); +} + +static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data, + int len) +{ + struct sk_buff *skb; + int ret = 0; + + while (len > 0) { + int cur_len = min_t(int, 4096 - sizeof(struct mt7615_mcu_txd), + len); + + skb = mt7615_mcu_msg_alloc(data, cur_len); + if (!skb) + return -ENOMEM; + + ret = __mt7615_mcu_msg_send(dev, skb, -MCU_CMD_FW_SCATTER, + MCU_Q_NA, MCU_S2D_H2N, NULL); + if (ret) + break; + + data += cur_len; + len -= cur_len; + } + + return ret; +} + +static int mt7615_mcu_start_firmware(struct mt7615_dev *dev, u32 addr, + u32 option) +{ + struct { + __le32 option; + __le32 addr; + } req = { + .option = cpu_to_le32(option), + .addr = cpu_to_le32(addr), + }; + struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); + + return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ, + MCU_Q_NA, MCU_S2D_H2N, NULL); +} + +static int mt7615_mcu_restart(struct mt7615_dev *dev) +{ + struct sk_buff *skb = mt7615_mcu_msg_alloc(NULL, 0); + + return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ, + MCU_Q_NA, MCU_S2D_H2N, NULL); +} + +static int mt7615_mcu_patch_sem_ctrl(struct mt7615_dev *dev, bool get) +{ + struct { + __le32 operation; + } req = { + .operation = cpu_to_le32(get ? PATCH_SEM_GET : + PATCH_SEM_RELEASE), + }; + struct event { + u8 status; + u8 reserved[3]; + } *resp; + struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); + struct sk_buff *skb_ret; + int ret; + + ret = mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_SEM_CONTROL, + MCU_Q_NA, MCU_S2D_H2N, &skb_ret); + if (ret) + goto out; + + resp = (struct event *)(skb_ret->data); + ret = resp->status; + dev_kfree_skb(skb_ret); + +out: + return ret; +} + +static int mt7615_mcu_start_patch(struct mt7615_dev *dev) +{ + struct { + u8 check_crc; + u8 reserved[3]; + } req = { + .check_crc = 0, + }; + struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); + + return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_FINISH_REQ, + MCU_Q_NA, MCU_S2D_H2N, NULL); +} + +static int mt7615_driver_own(struct mt7615_dev *dev) +{ + mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_DRV_OWN); + if (!mt76_poll_msec(dev, MT_CFG_LPCR_HOST, + MT_CFG_LPCR_HOST_FW_OWN, 0, 500)) { + dev_err(dev->mt76.dev, "Timeout for driver own\n"); + return -EIO; + } + + return 0; +} + +static int mt7615_load_patch(struct mt7615_dev *dev) +{ + const struct firmware *fw; + const struct mt7615_patch_hdr *hdr; + const char *firmware = MT7615_ROM_PATCH; + int len, ret, sem; + + sem = mt7615_mcu_patch_sem_ctrl(dev, 1); + switch (sem) { + case PATCH_IS_DL: + return 0; + case PATCH_NOT_DL_SEM_SUCCESS: + break; + default: + dev_err(dev->mt76.dev, "Failed to get patch semaphore\n"); + return -EAGAIN; + } + + ret = request_firmware(&fw, firmware, dev->mt76.dev); + if (ret) + return ret; + + if (!fw || !fw->data || fw->size < sizeof(*hdr)) { + dev_err(dev->mt76.dev, "Invalid firmware\n"); + ret = -EINVAL; + goto out; + } + + hdr = (const struct mt7615_patch_hdr *)(fw->data); + + dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n", + be32_to_cpu(hdr->hw_sw_ver), hdr->build_date); + + len = fw->size - sizeof(*hdr); + + ret = mt7615_mcu_init_download(dev, MCU_PATCH_ADDRESS, len, + DL_MODE_NEED_RSP); + if (ret) { + dev_err(dev->mt76.dev, "Download request failed\n"); + goto out; + } + + ret = mt7615_mcu_send_firmware(dev, fw->data + sizeof(*hdr), len); + if (ret) { + dev_err(dev->mt76.dev, "Failed to send firmware to device\n"); + goto out; + } + + ret = mt7615_mcu_start_patch(dev); + if (ret) + dev_err(dev->mt76.dev, "Failed to start patch\n"); + +out: + release_firmware(fw); + + sem = mt7615_mcu_patch_sem_ctrl(dev, 0); + switch (sem) { + case PATCH_REL_SEM_SUCCESS: + break; + default: + ret = -EAGAIN; + dev_err(dev->mt76.dev, "Failed to release patch semaphore\n"); + break; + } + + return ret; +} + +static u32 gen_dl_mode(u8 feature_set, bool is_cr4) +{ + u32 ret = 0; + + ret |= (feature_set & FW_FEATURE_SET_ENCRYPT) ? + (DL_MODE_ENCRYPT | DL_MODE_RESET_SEC_IV) : 0; + ret |= FIELD_PREP(DL_MODE_KEY_IDX, + FIELD_GET(FW_FEATURE_SET_KEY_IDX, feature_set)); + ret |= DL_MODE_NEED_RSP; + ret |= is_cr4 ? DL_MODE_WORKING_PDA_CR4 : 0; + + return ret; +} + +static int mt7615_load_ram(struct mt7615_dev *dev) +{ + const struct firmware *fw; + const struct mt7615_fw_trailer *hdr; + const char *n9_firmware = MT7615_FIRMWARE_N9; + const char *cr4_firmware = MT7615_FIRMWARE_CR4; + u32 n9_ilm_addr, offset; + int i, ret; + + ret = request_firmware(&fw, n9_firmware, dev->mt76.dev); + if (ret) + return ret; + + if (!fw || !fw->data || fw->size < N9_REGION_NUM * sizeof(*hdr)) { + dev_err(dev->mt76.dev, "Invalid firmware\n"); + ret = -EINVAL; + goto out; + } + + hdr = (const struct mt7615_fw_trailer *)(fw->data + fw->size - + N9_REGION_NUM * sizeof(*hdr)); + + dev_info(dev->mt76.dev, "N9 Firmware Version: %.10s, Build Time: %.15s\n", + hdr->fw_ver, hdr->build_date); + + n9_ilm_addr = le32_to_cpu(hdr->addr); + + for (offset = 0, i = 0; i < N9_REGION_NUM; i++) { + u32 len, addr, mode; + + len = le32_to_cpu(hdr[i].len) + IMG_CRC_LEN; + addr = le32_to_cpu(hdr[i].addr); + mode = gen_dl_mode(hdr[i].feature_set, false); + + ret = mt7615_mcu_init_download(dev, addr, len, mode); + if (ret) { + dev_err(dev->mt76.dev, "Download request failed\n"); + goto out; + } + + ret = mt7615_mcu_send_firmware(dev, fw->data + offset, len); + if (ret) { + dev_err(dev->mt76.dev, "Failed to send firmware to device\n"); + goto out; + } + + offset += len; + } + + ret = mt7615_mcu_start_firmware(dev, n9_ilm_addr, FW_START_OVERRIDE); + if (ret) { + dev_err(dev->mt76.dev, "Failed to start N9 firmware\n"); + goto out; + } + + release_firmware(fw); + + ret = request_firmware(&fw, cr4_firmware, dev->mt76.dev); + if (ret) + return ret; + + if (!fw || !fw->data || fw->size < CR4_REGION_NUM * sizeof(*hdr)) { + dev_err(dev->mt76.dev, "Invalid firmware\n"); + ret = -EINVAL; + goto out; + } + + hdr = (const struct mt7615_fw_trailer *)(fw->data + fw->size - + CR4_REGION_NUM * sizeof(*hdr)); + + dev_info(dev->mt76.dev, "CR4 Firmware Version: %.10s, Build Time: %.15s\n", + hdr->fw_ver, hdr->build_date); + + for (offset = 0, i = 0; i < CR4_REGION_NUM; i++) { + u32 len, addr, mode; + + len = le32_to_cpu(hdr[i].len) + IMG_CRC_LEN; + addr = le32_to_cpu(hdr[i].addr); + mode = gen_dl_mode(hdr[i].feature_set, true); + + ret = mt7615_mcu_init_download(dev, addr, len, mode); + if (ret) { + dev_err(dev->mt76.dev, "Download request failed\n"); + goto out; + } + + ret = mt7615_mcu_send_firmware(dev, fw->data + offset, len); + if (ret) { + dev_err(dev->mt76.dev, "Failed to send firmware to device\n"); + goto out; + } + + offset += len; + } + + ret = mt7615_mcu_start_firmware(dev, 0, FW_START_WORKING_PDA_CR4); + if (ret) + dev_err(dev->mt76.dev, "Failed to start CR4 firmware\n"); + +out: + release_firmware(fw); + + return ret; +} + +static int mt7615_load_firmware(struct mt7615_dev *dev) +{ + int ret; + u32 val; + + val = mt76_get_field(dev, MT_TOP_MISC2, MT_TOP_MISC2_FW_STATE); + + if (val != FW_STATE_FW_DOWNLOAD) { + dev_err(dev->mt76.dev, "Firmware is not ready for download\n"); + return -EIO; + } + + ret = mt7615_load_patch(dev); + if (ret) + return ret; + + ret = mt7615_load_ram(dev); + if (ret) + return ret; + + if (!mt76_poll_msec(dev, MT_TOP_MISC2, MT_TOP_MISC2_FW_STATE, + FIELD_PREP(MT_TOP_MISC2_FW_STATE, + FW_STATE_CR4_RDY), 500)) { + dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); + return -EIO; + } + + dev_dbg(dev->mt76.dev, "Firmware init done\n"); + + return 0; +} + +int mt7615_mcu_init(struct mt7615_dev *dev) +{ + int ret; + + ret = mt7615_driver_own(dev); + if (ret) + return ret; + + ret = mt7615_load_firmware(dev); + if (ret) + return ret; + + set_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state); + + return 0; +} + +void mt7615_mcu_exit(struct mt7615_dev *dev) +{ + mt7615_mcu_restart(dev); + mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_FW_OWN); + skb_queue_purge(&dev->mt76.mmio.mcu.res_q); +} + +int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) +{ + struct req_data { + u8 val; + } __packed; + struct { + u8 buffer_mode; + u8 pad; + u16 len; + } __packed req_hdr = { + .buffer_mode = 1, + .len = __MT_EE_MAX - MT_EE_NIC_CONF_0, + }; + struct sk_buff *skb; + struct req_data *data; + const int size = (__MT_EE_MAX - MT_EE_NIC_CONF_0) * + sizeof(struct req_data); + u8 *eep = (u8 *)dev->mt76.eeprom.data; + u16 off; + + skb = mt7615_mcu_msg_alloc(NULL, size + sizeof(req_hdr)); + memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); + data = (struct req_data *)skb_put(skb, size); + memset(data, 0, size); + + for (off = MT_EE_NIC_CONF_0; off < __MT_EE_MAX; off++) + data[off - MT_EE_NIC_CONF_0].val = eep[off]; + + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EFUSE_BUFFER_MODE, + MCU_Q_SET, MCU_S2D_H2N, NULL); +} + +int mt7615_mcu_init_mac(struct mt7615_dev *dev) +{ + struct { + u8 enable; + u8 band; + u8 rsv[2]; + } __packed req = { + .enable = 1, + .band = 0, + }; + struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); + + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_MAC_INIT_CTRL, + MCU_Q_SET, MCU_S2D_H2N, NULL); +} + +int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) +{ + struct { + u8 prot_idx; + u8 band; + u8 rsv[2]; + __le32 len_thresh; + __le32 pkt_thresh; + } __packed req = { + .prot_idx = 1, + .band = 0, + .len_thresh = cpu_to_le32(val), + .pkt_thresh = cpu_to_le32(0x2), + }; + struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); + + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PROTECT_CTRL, + MCU_Q_SET, MCU_S2D_H2N, NULL); +} + +int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, + const struct ieee80211_tx_queue_params *params) +{ +#define WMM_AIFS_SET BIT(0) +#define WMM_CW_MIN_SET BIT(1) +#define WMM_CW_MAX_SET BIT(2) +#define WMM_TXOP_SET BIT(3) + struct req_data { + u8 number; + u8 rsv[3]; + u8 queue; + u8 valid; + u8 aifs; + u8 cw_min; + __le16 cw_max; + __le16 txop; + } __packed req = { + .number = 1, + .queue = queue, + .valid = WMM_AIFS_SET | WMM_TXOP_SET, + .aifs = params->aifs, + .txop = cpu_to_le16(params->txop), + }; + struct sk_buff *skb; + + if (params->cw_min) { + req.valid |= WMM_CW_MIN_SET; + req.cw_min = params->cw_min; + } + if (params->cw_max) { + req.valid |= WMM_CW_MAX_SET; + req.cw_max = cpu_to_le16(params->cw_max); + } + + skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EDCA_UPDATE, + MCU_Q_SET, MCU_S2D_H2N, NULL); +} + +int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) +{ +#define ENTER_PM_STATE 1 +#define EXIT_PM_STATE 2 + struct { + u8 pm_number; + u8 pm_state; + u8 bssid[ETH_ALEN]; + u8 dtim_period; + u8 wlan_idx; + __le16 bcn_interval; + __le32 aid; + __le32 rx_filter; + u8 band_idx; + u8 rsv[3]; + __le32 feature; + u8 omac_idx; + u8 wmm_idx; + u8 bcn_loss_cnt; + u8 bcn_sp_duration; + } __packed req = { + .pm_number = 5, + .pm_state = (enter) ? ENTER_PM_STATE : EXIT_PM_STATE, + .band_idx = 0, + }; + struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); + + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PM_STATE_CTRL, + MCU_Q_SET, MCU_S2D_H2N, NULL); +} + +static int __mt7615_mcu_set_dev_info(struct mt7615_dev *dev, + struct dev_info *dev_info) +{ + struct req_hdr { + u8 omac_idx; + u8 band_idx; + __le16 tlv_num; + u8 is_tlv_append; + u8 rsv[3]; + } __packed req_hdr = {0}; + struct req_tlv { + __le16 tag; + __le16 len; + u8 active; + u8 band_idx; + u8 omac_addr[ETH_ALEN]; + } __packed; + struct sk_buff *skb; + u16 tlv_num = 0; + + skb = mt7615_mcu_msg_alloc(NULL, sizeof(req_hdr) + + sizeof(struct req_tlv)); + skb_reserve(skb, sizeof(req_hdr)); + + if (dev_info->feature & BIT(DEV_INFO_ACTIVE)) { + struct req_tlv req_tlv = { + .tag = cpu_to_le16(DEV_INFO_ACTIVE), + .len = cpu_to_le16(sizeof(req_tlv)), + .active = dev_info->enable, + .band_idx = dev_info->band_idx, + }; + memcpy(req_tlv.omac_addr, dev_info->omac_addr, ETH_ALEN); + memcpy(skb_put(skb, sizeof(req_tlv)), &req_tlv, + sizeof(req_tlv)); + tlv_num++; + } + + req_hdr.omac_idx = dev_info->omac_idx; + req_hdr.band_idx = dev_info->band_idx; + req_hdr.tlv_num = cpu_to_le16(tlv_num); + req_hdr.is_tlv_append = tlv_num ? 1 : 0; + + memcpy(skb_push(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); + + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_DEV_INFO_UPDATE, + MCU_Q_SET, MCU_S2D_H2N, NULL); +} + +int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, + int en) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct dev_info dev_info = {0}; + + dev_info.omac_idx = mvif->omac_idx; + memcpy(dev_info.omac_addr, vif->addr, ETH_ALEN); + dev_info.band_idx = mvif->band_idx; + dev_info.enable = en; + dev_info.feature = BIT(DEV_INFO_ACTIVE); + + return __mt7615_mcu_set_dev_info(dev, &dev_info); +} + +static void bss_info_omac_handler (struct mt7615_dev *dev, + struct bss_info *bss_info, + struct sk_buff *skb) +{ + struct bss_info_omac tlv = {0}; + + tlv.tag = cpu_to_le16(BSS_INFO_OMAC); + tlv.len = cpu_to_le16(sizeof(tlv)); + tlv.hw_bss_idx = (bss_info->omac_idx > EXT_BSSID_START) ? + HW_BSSID_0 : bss_info->omac_idx; + tlv.omac_idx = bss_info->omac_idx; + tlv.band_idx = bss_info->band_idx; + tlv.conn_type = cpu_to_le32(bss_info->conn_type); + + memcpy(skb_put(skb, sizeof(tlv)), &tlv, sizeof(tlv)); +} + +static void bss_info_basic_handler (struct mt7615_dev *dev, + struct bss_info *bss_info, + struct sk_buff *skb) +{ + struct bss_info_basic tlv = {0}; + + tlv.tag = cpu_to_le16(BSS_INFO_BASIC); + tlv.len = cpu_to_le16(sizeof(tlv)); + tlv.network_type = cpu_to_le32(bss_info->network_type); + tlv.active = bss_info->enable; + tlv.bcn_interval = cpu_to_le16(bss_info->bcn_interval); + memcpy(tlv.bssid, bss_info->bssid, ETH_ALEN); + tlv.wmm_idx = bss_info->wmm_idx; + tlv.dtim_period = bss_info->dtim_period; + tlv.bmc_tx_wlan_idx = bss_info->bmc_tx_wlan_idx; + + memcpy(skb_put(skb, sizeof(tlv)), &tlv, sizeof(tlv)); +} + +static void bss_info_ext_bss_handler (struct mt7615_dev *dev, + struct bss_info *bss_info, + struct sk_buff *skb) +{ +/* SIFS 20us + 512 byte beacon tranmitted by 1Mbps (3906us) */ +#define BCN_TX_ESTIMATE_TIME (4096 + 20) + struct bss_info_ext_bss tlv = {0}; + int ext_bss_idx; + + ext_bss_idx = bss_info->omac_idx - EXT_BSSID_START; + + if (ext_bss_idx < 0) + return; + + tlv.tag = cpu_to_le16(BSS_INFO_EXT_BSS); + tlv.len = cpu_to_le16(sizeof(tlv)); + tlv.mbss_tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME; + + memcpy(skb_put(skb, sizeof(tlv)), &tlv, sizeof(tlv)); +} + +static struct bss_info_tag_handler bss_info_tag_handler[] = { + {BSS_INFO_OMAC, sizeof(struct bss_info_omac), bss_info_omac_handler}, + {BSS_INFO_BASIC, sizeof(struct bss_info_basic), bss_info_basic_handler}, + {BSS_INFO_RF_CH, sizeof(struct bss_info_rf_ch), NULL}, + {BSS_INFO_PM, 0, NULL}, + {BSS_INFO_UAPSD, 0, NULL}, + {BSS_INFO_ROAM_DETECTION, 0, NULL}, + {BSS_INFO_LQ_RM, 0, NULL}, + {BSS_INFO_EXT_BSS, sizeof(struct bss_info_ext_bss), bss_info_ext_bss_handler}, + {BSS_INFO_BMC_INFO, 0, NULL}, + {BSS_INFO_SYNC_MODE, 0, NULL}, + {BSS_INFO_RA, 0, NULL}, + {BSS_INFO_MAX_NUM, 0, NULL}, +}; + +static int __mt7615_mcu_set_bss_info(struct mt7615_dev *dev, + struct bss_info *bss_info) +{ + struct req_hdr { + u8 bss_idx; + u8 rsv0; + __le16 tlv_num; + u8 is_tlv_append; + u8 rsv1[3]; + } __packed req_hdr = {0}; + struct sk_buff *skb; + u16 tlv_num = 0; + u32 size = 0; + int i; + + for (i = 0; i < BSS_INFO_MAX_NUM; i++) + if ((BIT(bss_info_tag_handler[i].tag) & bss_info->feature) && + bss_info_tag_handler[i].handler) { + tlv_num++; + size += bss_info_tag_handler[i].len; + } + + skb = mt7615_mcu_msg_alloc(NULL, sizeof(req_hdr) + size); + + req_hdr.bss_idx = bss_info->bss_idx; + req_hdr.tlv_num = cpu_to_le16(tlv_num); + req_hdr.is_tlv_append = tlv_num ? 1 : 0; + + memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); + + for (i = 0; i < BSS_INFO_MAX_NUM; i++) + if ((BIT(bss_info_tag_handler[i].tag) & bss_info->feature) && + bss_info_tag_handler[i].handler) + bss_info_tag_handler[i].handler(dev, bss_info, skb); + + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BSS_INFO_UPDATE, + MCU_Q_SET, MCU_S2D_H2N, NULL); +} + +static void bss_info_convert_vif_type(enum nl80211_iftype type, + u32 *network_type, u32 *conn_type) +{ + switch (type) { + case NL80211_IFTYPE_AP: + if (network_type) + *network_type = NETWORK_INFRA; + if (conn_type) + *conn_type = CONNECTION_INFRA_AP; + break; + case NL80211_IFTYPE_STATION: + if (network_type) + *network_type = NETWORK_INFRA; + if (conn_type) + *conn_type = CONNECTION_INFRA_STA; + break; + default: + WARN_ON(1); + break; + }; +} + +int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, + int en) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct bss_info bss_info = {0}; + u8 bmc_tx_wlan_idx = 0; + u32 network_type = 0, conn_type = 0; + + if (vif->type == NL80211_IFTYPE_AP) { + bmc_tx_wlan_idx = mvif->sta.wcid.idx; + } else if (vif->type == NL80211_IFTYPE_STATION) { + /* find the unicast entry for sta mode bmc tx */ + struct ieee80211_sta *ap_sta; + struct mt7615_sta *msta; + + rcu_read_lock(); + + ap_sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); + if (!ap_sta) { + rcu_read_unlock(); + return -EINVAL; + } + + msta = (struct mt7615_sta *)ap_sta->drv_priv; + bmc_tx_wlan_idx = msta->wcid.idx; + + rcu_read_unlock(); + } else { + WARN_ON(1); + } + + bss_info_convert_vif_type(vif->type, &network_type, &conn_type); + + bss_info.bss_idx = mvif->idx; + memcpy(bss_info.bssid, vif->bss_conf.bssid, ETH_ALEN); + bss_info.omac_idx = mvif->omac_idx; + bss_info.band_idx = mvif->band_idx; + bss_info.bmc_tx_wlan_idx = bmc_tx_wlan_idx; + bss_info.wmm_idx = mvif->wmm_idx; + bss_info.network_type = network_type; + bss_info.conn_type = conn_type; + bss_info.bcn_interval = vif->bss_conf.beacon_int; + bss_info.dtim_period = vif->bss_conf.dtim_period; + bss_info.enable = en; + bss_info.feature = BIT(BSS_INFO_BASIC); + if (en) { + bss_info.feature |= BIT(BSS_INFO_OMAC); + if (mvif->omac_idx > EXT_BSSID_START) + bss_info.feature |= BIT(BSS_INFO_EXT_BSS); + } + + return __mt7615_mcu_set_bss_info(dev, &bss_info); +} + +static int __mt7615_mcu_set_wtbl(struct mt7615_dev *dev, int wlan_idx, + int operation, void *buf, int buf_len) +{ + struct req_hdr { + u8 wlan_idx; + u8 operation; + __le16 tlv_num; + u8 rsv[4]; + } __packed req_hdr = {0}; + struct tlv { + __le16 tag; + __le16 len; + u8 buf[0]; + } __packed; + struct sk_buff *skb; + u16 tlv_num = 0; + int offset = 0; + + while (offset < buf_len) { + struct tlv *tlv = (struct tlv *)((u8 *)buf + offset); + + tlv_num++; + offset += tlv->len; + } + + skb = mt7615_mcu_msg_alloc(NULL, sizeof(req_hdr) + buf_len); + + req_hdr.wlan_idx = wlan_idx; + req_hdr.operation = operation; + req_hdr.tlv_num = cpu_to_le16(tlv_num); + + memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); + + if (buf && buf_len) + memcpy(skb_put(skb, buf_len), buf, buf_len); + + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_WTBL_UPDATE, + MCU_Q_SET, MCU_S2D_H2N, NULL); +} + +static enum mt7615_cipher_type +mt7615_get_key_info(struct ieee80211_key_conf *key, u8 *key_data) +{ + if (!key || key->keylen > 32) + return MT_CIPHER_NONE; + + memcpy(key_data, key->key, key->keylen); + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + return MT_CIPHER_WEP40; + case WLAN_CIPHER_SUITE_WEP104: + return MT_CIPHER_WEP104; + case WLAN_CIPHER_SUITE_TKIP: + /* Rx/Tx MIC keys are swapped */ + memcpy(key_data + 16, key->key + 24, 8); + memcpy(key_data + 24, key->key + 16, 8); + return MT_CIPHER_TKIP; + case WLAN_CIPHER_SUITE_CCMP: + return MT_CIPHER_AES_CCMP; + case WLAN_CIPHER_SUITE_CCMP_256: + return MT_CIPHER_CCMP_256; + case WLAN_CIPHER_SUITE_GCMP: + return MT_CIPHER_GCMP; + case WLAN_CIPHER_SUITE_GCMP_256: + return MT_CIPHER_GCMP_256; + case WLAN_CIPHER_SUITE_SMS4: + return MT_CIPHER_WAPI; + default: + return MT_CIPHER_NONE; + } +} + +int mt7615_mcu_set_wtbl_key(struct mt7615_dev *dev, int wcid, + struct ieee80211_key_conf *key, + enum set_key_cmd cmd) +{ + struct wtbl_sec_key wtbl_sec_key = {0}; + int buf_len = sizeof(struct wtbl_sec_key); + u8 cipher; + + wtbl_sec_key.tag = cpu_to_le16(WTBL_SEC_KEY); + wtbl_sec_key.len = cpu_to_le16(buf_len); + wtbl_sec_key.add = cmd; + + if (cmd == SET_KEY) { + cipher = mt7615_get_key_info(key, wtbl_sec_key.key_material); + if (cipher == MT_CIPHER_NONE && key) + return -EOPNOTSUPP; + + wtbl_sec_key.cipher_id = cipher; + wtbl_sec_key.key_id = key->keyidx; + wtbl_sec_key.key_len = key->keylen; + } else { + wtbl_sec_key.key_len = sizeof(wtbl_sec_key.key_material); + } + + return __mt7615_mcu_set_wtbl(dev, wcid, WTBL_SET, &wtbl_sec_key, + buf_len); +} + +int mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct wtbl_generic *wtbl_generic; + struct wtbl_rx *wtbl_rx; + int buf_len, ret; + u8 *buf; + + buf = kzalloc(MT7615_WTBL_UPDATE_MAX_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + wtbl_generic = (struct wtbl_generic *)buf; + buf_len = sizeof(*wtbl_generic); + wtbl_generic->tag = cpu_to_le16(WTBL_GENERIC); + wtbl_generic->len = cpu_to_le16(buf_len); + eth_broadcast_addr(wtbl_generic->peer_addr); + wtbl_generic->muar_idx = 0xe; + + wtbl_rx = (struct wtbl_rx *)(buf + buf_len); + buf_len += sizeof(*wtbl_rx); + wtbl_rx->tag = cpu_to_le16(WTBL_RX); + wtbl_rx->len = cpu_to_le16(sizeof(*wtbl_rx)); + wtbl_rx->rca1 = 1; + wtbl_rx->rca2 = 1; + wtbl_rx->rv = 1; + + ret = __mt7615_mcu_set_wtbl(dev, mvif->sta.wcid.idx, + WTBL_RESET_AND_SET, buf, buf_len); + + kfree(buf); + return ret; +} + +int mt7615_mcu_del_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + + return __mt7615_mcu_set_wtbl(dev, mvif->sta.wcid.idx, + WTBL_RESET_AND_SET, NULL, 0); +} + +int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + struct wtbl_generic *wtbl_generic; + struct wtbl_rx *wtbl_rx; + int buf_len, ret; + u8 *buf; + + buf = kzalloc(MT7615_WTBL_UPDATE_MAX_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + wtbl_generic = (struct wtbl_generic *)buf; + buf_len = sizeof(*wtbl_generic); + wtbl_generic->tag = cpu_to_le16(WTBL_GENERIC); + wtbl_generic->len = cpu_to_le16(buf_len); + memcpy(wtbl_generic->peer_addr, sta->addr, ETH_ALEN); + wtbl_generic->muar_idx = mvif->omac_idx; + wtbl_generic->qos = sta->wme; + wtbl_generic->partial_aid = cpu_to_le16(sta->aid); + + wtbl_rx = (struct wtbl_rx *)(buf + buf_len); + buf_len += sizeof(*wtbl_rx); + wtbl_rx->tag = cpu_to_le16(WTBL_RX); + wtbl_rx->len = cpu_to_le16(sizeof(*wtbl_rx)); + wtbl_rx->rca1 = (vif->type == NL80211_IFTYPE_AP) ? 0 : 1; + wtbl_rx->rca2 = 1; + wtbl_rx->rv = 1; + + ret = __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, + WTBL_RESET_AND_SET, buf, buf_len); + + kfree(buf); + return ret; +} + +int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + + return __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, + WTBL_RESET_AND_SET, NULL, 0); +} + +int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) +{ + return __mt7615_mcu_set_wtbl(dev, 0, WTBL_RESET_ALL, NULL, 0); +} + +static int __mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, int bss_idx, + int wlan_idx, int muar_idx, void *buf, + int buf_len) +{ + struct req_hdr { + u8 bss_idx; + u8 wlan_idx; + __le16 tlv_num; + u8 is_tlv_append; + u8 muar_idx; + u8 rsv[2]; + } __packed req_hdr = {0}; + struct tlv { + __le16 tag; + __le16 len; + u8 buf[0]; + } __packed; + struct sk_buff *skb; + u16 tlv_num = 0; + int offset = 0; + + while (offset < buf_len) { + struct tlv *tlv = (struct tlv *)((u8 *)buf + offset); + + tlv_num++; + offset += tlv->len; + } + + skb = mt7615_mcu_msg_alloc(NULL, sizeof(req_hdr) + buf_len); + + req_hdr.bss_idx = bss_idx; + req_hdr.wlan_idx = wlan_idx; + req_hdr.tlv_num = cpu_to_le16(tlv_num); + req_hdr.is_tlv_append = tlv_num ? 1 : 0; + req_hdr.muar_idx = muar_idx; + + memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); + + if (buf && buf_len) + memcpy(skb_put(skb, buf_len), buf, buf_len); + + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_STA_REC_UPDATE, + MCU_Q_SET, MCU_S2D_H2N, NULL); +} + +int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, + struct ieee80211_vif *vif, bool en) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct sta_rec_basic sta_rec_basic = {0}; + int buf_len = sizeof(struct sta_rec_basic); + + sta_rec_basic.tag = cpu_to_le16(STA_REC_BASIC); + sta_rec_basic.len = cpu_to_le16(buf_len); + sta_rec_basic.conn_type = cpu_to_le32(CONNECTION_INFRA_BC); + eth_broadcast_addr(sta_rec_basic.peer_addr); + if (en) { + sta_rec_basic.conn_state = CONN_STATE_PORT_SECURE; + sta_rec_basic.extra_info = + cpu_to_le16(EXTRA_INFO_VER | EXTRA_INFO_NEW); + } else { + sta_rec_basic.conn_state = CONN_STATE_DISCONNECT; + sta_rec_basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); + } + + return __mt7615_mcu_set_sta_rec(dev, mvif->idx, mvif->sta.wcid.idx, + mvif->omac_idx, &sta_rec_basic, + buf_len); +} + +static void sta_rec_convert_vif_type(enum nl80211_iftype type, u32 *conn_type) +{ + switch (type) { + case NL80211_IFTYPE_AP: + if (conn_type) + *conn_type = CONNECTION_INFRA_STA; + break; + case NL80211_IFTYPE_STATION: + if (conn_type) + *conn_type = CONNECTION_INFRA_AP; + break; + default: + WARN_ON(1); + break; + }; +} + +int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool en) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + struct sta_rec_basic sta_rec_basic = {0}; + int buf_len = sizeof(struct sta_rec_basic); + u32 conn_type = 0; + + sta_rec_convert_vif_type(vif->type, &conn_type); + + sta_rec_basic.tag = cpu_to_le16(STA_REC_BASIC); + sta_rec_basic.len = cpu_to_le16(buf_len); + sta_rec_basic.conn_type = cpu_to_le32(conn_type); + sta_rec_basic.qos = sta->wme; + sta_rec_basic.aid = cpu_to_le16(sta->aid); + memcpy(sta_rec_basic.peer_addr, sta->addr, ETH_ALEN); + + if (en) { + sta_rec_basic.conn_state = CONN_STATE_PORT_SECURE; + sta_rec_basic.extra_info = + cpu_to_le16(EXTRA_INFO_VER | EXTRA_INFO_NEW); + } else { + sta_rec_basic.conn_state = CONN_STATE_DISCONNECT; + sta_rec_basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); + } + + return __mt7615_mcu_set_sta_rec(dev, mvif->idx, msta->wcid.idx, + mvif->omac_idx, &sta_rec_basic, + buf_len); +} + +int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, + int en) +{ + struct req { + u8 omac_idx; + u8 enable; + u8 wlan_idx; + u8 band_idx; + u8 pkt_type; + u8 need_pre_tbtt_int; + __le16 csa_ie_pos; + __le16 pkt_len; + __le16 tim_ie_pos; + u8 pkt[512]; + u8 csa_cnt; + /* bss color change */ + u8 bcc_cnt; + __le16 bcc_ie_pos; + } __packed req = {0}; + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt76_wcid *wcid = &dev->mt76.global_wcid; + struct sk_buff *skb; + u16 tim_off, tim_len; + + skb = ieee80211_beacon_get_tim(mt76_hw(dev), vif, &tim_off, &tim_len); + + if (!skb) + return -EINVAL; + + if (skb->len > 512 - MT_TXD_SIZE) { + dev_err(dev->mt76.dev, "Bcn size limit exceed\n"); + dev_kfree_skb(skb); + return -EINVAL; + } + + mt7615_mac_write_txwi(dev, (__le32 *)(req.pkt), skb, wcid, NULL, + 0, NULL); + memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len); + dev_kfree_skb(skb); + + req.omac_idx = mvif->omac_idx; + req.enable = en; + req.wlan_idx = wcid->idx; + req.band_idx = mvif->band_idx; + /* pky_type: 0 for bcn, 1 for tim */ + req.pkt_type = 0; + req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); + req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + tim_off); + + skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); + + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BCN_OFFLOAD, + MCU_Q_SET, MCU_S2D_H2N, NULL); +} + +int mt7615_mcu_set_channel(struct mt7615_dev *dev) +{ + struct cfg80211_chan_def *chdef = &dev->mt76.chandef; + struct { + u8 control_chan; + u8 center_chan; + u8 bw; + u8 tx_streams; + u8 rx_streams_mask; + u8 switch_reason; + u8 band_idx; + /* for 80+80 only */ + u8 center_chan2; + __le16 cac_case; + u8 channel_band; + u8 rsv0; + __le32 outband_freq; + u8 txpower_drop; + u8 rsv1[3]; + u8 txpower_sku[53]; + u8 rsv2[3]; + } req = {0}; + struct sk_buff *skb; + int ret; + + req.control_chan = chdef->chan->hw_value; + req.center_chan = ieee80211_frequency_to_channel(chdef->center_freq1); + req.tx_streams = (dev->mt76.chainmask >> 8) & 0xf; + req.rx_streams_mask = dev->mt76.antenna_mask; + req.switch_reason = CH_SWITCH_NORMAL; + req.band_idx = 0; + req.center_chan2 = ieee80211_frequency_to_channel(chdef->center_freq2); + req.txpower_drop = 0; + + switch (dev->mt76.chandef.width) { + case NL80211_CHAN_WIDTH_40: + req.bw = CMD_CBW_40MHZ; + break; + case NL80211_CHAN_WIDTH_80: + req.bw = CMD_CBW_80MHZ; + break; + case NL80211_CHAN_WIDTH_80P80: + req.bw = CMD_CBW_8080MHZ; + break; + case NL80211_CHAN_WIDTH_160: + req.bw = CMD_CBW_160MHZ; + break; + case NL80211_CHAN_WIDTH_5: + req.bw = CMD_CBW_5MHZ; + break; + case NL80211_CHAN_WIDTH_10: + req.bw = CMD_CBW_10MHZ; + break; + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + default: + req.bw = CMD_CBW_20MHZ; + } + + memset(req.txpower_sku, 0x3f, 49); + + skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); + ret = mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH, + MCU_Q_SET, MCU_S2D_H2N, NULL); + if (ret) + return ret; + + skb = mt7615_mcu_msg_alloc(&req, sizeof(req)); + return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_RX_PATH, + MCU_Q_SET, MCU_S2D_H2N, NULL); +} + +int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct wtbl_ht *wtbl_ht; + struct wtbl_raw *wtbl_raw; + struct sta_rec_ht *sta_rec_ht; + int buf_len, ret; + u32 msk, val = 0; + u8 *buf; + + buf = kzalloc(MT7615_WTBL_UPDATE_MAX_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + /* ht basic */ + buf_len = sizeof(*wtbl_ht); + wtbl_ht = (struct wtbl_ht *)buf; + wtbl_ht->tag = cpu_to_le16(WTBL_HT); + wtbl_ht->len = cpu_to_le16(sizeof(*wtbl_ht)); + wtbl_ht->ht = 1; + wtbl_ht->ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING; + wtbl_ht->af = sta->ht_cap.ampdu_factor; + wtbl_ht->mm = sta->ht_cap.ampdu_density; + + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) + val |= MT_WTBL_W5_SHORT_GI_20; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) + val |= MT_WTBL_W5_SHORT_GI_40; + + /* vht basic */ + if (sta->vht_cap.vht_supported) { + struct wtbl_vht *wtbl_vht; + + wtbl_vht = (struct wtbl_vht *)(buf + buf_len); + buf_len += sizeof(*wtbl_vht); + wtbl_vht->tag = cpu_to_le16(WTBL_VHT); + wtbl_vht->len = cpu_to_le16(sizeof(*wtbl_vht)); + wtbl_vht->ldpc = sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC; + wtbl_vht->vht = 1; + + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) + val |= MT_WTBL_W5_SHORT_GI_80; + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160) + val |= MT_WTBL_W5_SHORT_GI_160; + } + + /* smps */ + if (sta->smps_mode == IEEE80211_SMPS_DYNAMIC) { + struct wtbl_smps *wtbl_smps; + + wtbl_smps = (struct wtbl_smps *)(buf + buf_len); + buf_len += sizeof(*wtbl_smps); + wtbl_smps->tag = cpu_to_le16(WTBL_SMPS); + wtbl_smps->len = cpu_to_le16(sizeof(*wtbl_smps)); + wtbl_smps->smps = 1; + } + + /* sgi */ + msk = MT_WTBL_W5_SHORT_GI_20 | MT_WTBL_W5_SHORT_GI_40 | + MT_WTBL_W5_SHORT_GI_80 | MT_WTBL_W5_SHORT_GI_160; + + wtbl_raw = (struct wtbl_raw *)(buf + buf_len); + buf_len += sizeof(*wtbl_raw); + wtbl_raw->tag = cpu_to_le16(WTBL_RAW_DATA); + wtbl_raw->len = cpu_to_le16(sizeof(*wtbl_raw)); + wtbl_raw->wtbl_idx = 1; + wtbl_raw->dw = 5; + wtbl_raw->msk = cpu_to_le32(~msk); + wtbl_raw->val = cpu_to_le32(val); + + ret = __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, WTBL_SET, buf, + buf_len); + if (ret) { + kfree(buf); + return ret; + } + + memset(buf, 0, MT7615_WTBL_UPDATE_MAX_SIZE); + + buf_len = sizeof(*sta_rec_ht); + sta_rec_ht = (struct sta_rec_ht *)buf; + sta_rec_ht->tag = cpu_to_le16(STA_REC_HT); + sta_rec_ht->len = cpu_to_le16(sizeof(*sta_rec_ht)); + sta_rec_ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); + + if (sta->vht_cap.vht_supported) { + struct sta_rec_vht *sta_rec_vht; + + sta_rec_vht = (struct sta_rec_vht *)(buf + buf_len); + buf_len += sizeof(*sta_rec_vht); + sta_rec_vht->tag = cpu_to_le16(STA_REC_VHT); + sta_rec_vht->len = cpu_to_le16(sizeof(*sta_rec_vht)); + sta_rec_vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); + sta_rec_vht->vht_rx_mcs_map = + cpu_to_le16(sta->vht_cap.vht_mcs.rx_mcs_map); + sta_rec_vht->vht_tx_mcs_map = + cpu_to_le16(sta->vht_cap.vht_mcs.tx_mcs_map); + } + + ret = __mt7615_mcu_set_sta_rec(dev, mvif->idx, msta->wcid.idx, + mvif->omac_idx, buf, buf_len); + kfree(buf); + return ret; +} + +int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool add) +{ + struct ieee80211_sta *sta = params->sta; + struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + struct mt7615_vif *mvif = msta->vif; + u8 ba_range[8] = {4, 8, 12, 24, 36, 48, 54, 64}; + u16 tid = params->tid; + u16 ba_size = params->buf_size; + u16 ssn = params->ssn; + struct wtbl_ba wtbl_ba = {0}; + struct sta_rec_ba sta_rec_ba = {0}; + int ret, buf_len; + + buf_len = sizeof(struct wtbl_ba); + + wtbl_ba.tag = cpu_to_le16(WTBL_BA); + wtbl_ba.len = cpu_to_le16(buf_len); + wtbl_ba.tid = tid; + wtbl_ba.ba_type = MT_BA_TYPE_ORIGINATOR; + + if (add) { + u8 idx; + + for (idx = 7; idx > 0; idx--) { + if (ba_size >= ba_range[idx]) + break; + } + + wtbl_ba.sn = cpu_to_le16(ssn); + wtbl_ba.ba_en = 1; + wtbl_ba.ba_winsize_idx = idx; + } + + ret = __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, WTBL_SET, &wtbl_ba, + buf_len); + if (ret) + return ret; + + buf_len = sizeof(struct sta_rec_ba); + + sta_rec_ba.tag = cpu_to_le16(STA_REC_BA); + sta_rec_ba.len = cpu_to_le16(buf_len); + sta_rec_ba.tid = tid; + sta_rec_ba.ba_type = MT_BA_TYPE_ORIGINATOR; + sta_rec_ba.amsdu = params->amsdu; + sta_rec_ba.ba_en = add << tid; + sta_rec_ba.ssn = cpu_to_le16(ssn); + sta_rec_ba.winsize = cpu_to_le16(ba_size); + + return __mt7615_mcu_set_sta_rec(dev, mvif->idx, msta->wcid.idx, + mvif->omac_idx, &sta_rec_ba, buf_len); +} + +int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool add) +{ + struct ieee80211_sta *sta = params->sta; + struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + struct mt7615_vif *mvif = msta->vif; + u16 tid = params->tid; + struct wtbl_ba wtbl_ba = {0}; + struct sta_rec_ba sta_rec_ba = {0}; + int ret, buf_len; + + buf_len = sizeof(struct sta_rec_ba); + + sta_rec_ba.tag = cpu_to_le16(STA_REC_BA); + sta_rec_ba.len = cpu_to_le16(buf_len); + sta_rec_ba.tid = tid; + sta_rec_ba.ba_type = MT_BA_TYPE_RECIPIENT; + sta_rec_ba.amsdu = params->amsdu; + sta_rec_ba.ba_en = add << tid; + sta_rec_ba.ssn = cpu_to_le16(params->ssn); + sta_rec_ba.winsize = cpu_to_le16(params->buf_size); + + ret = __mt7615_mcu_set_sta_rec(dev, mvif->idx, msta->wcid.idx, + mvif->omac_idx, &sta_rec_ba, buf_len); + if (ret || !add) + return ret; + + buf_len = sizeof(struct wtbl_ba); + + wtbl_ba.tag = cpu_to_le16(WTBL_BA); + wtbl_ba.len = cpu_to_le16(buf_len); + wtbl_ba.tid = tid; + wtbl_ba.ba_type = MT_BA_TYPE_RECIPIENT; + memcpy(wtbl_ba.peer_addr, sta->addr, ETH_ALEN); + wtbl_ba.rst_ba_tid = tid; + wtbl_ba.rst_ba_sel = RST_BA_MAC_TID_MATCH; + wtbl_ba.rst_ba_sb = 1; + + return __mt7615_mcu_set_wtbl(dev, msta->wcid.idx, WTBL_SET, + &wtbl_ba, buf_len); +} + +void mt7615_mcu_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, + struct ieee80211_tx_rate *probe_rate, + struct ieee80211_tx_rate *rates) +{ + int wcid = sta->wcid.idx; + u32 addr = MT_WTBL_BASE + wcid * MT_WTBL_ENTRY_SIZE; + bool stbc = false; + int n_rates = sta->n_rates; + u8 bw, bw_prev, bw_idx = 0; + u16 val[4]; + u16 probe_val; + u32 w5, w27; + int i; + + if (!mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000)) + return; + + for (i = n_rates; i < 4; i++) + rates[i] = rates[n_rates - 1]; + + val[0] = mt7615_mac_tx_rate_val(dev, &rates[0], stbc, &bw); + bw_prev = bw; + + if (probe_rate) { + probe_val = mt7615_mac_tx_rate_val(dev, probe_rate, stbc, &bw); + if (bw) + bw_idx = 1; + else + bw_prev = 0; + } else { + probe_val = val[0]; + } + + val[1] = mt7615_mac_tx_rate_val(dev, &rates[1], stbc, &bw); + if (bw_prev) { + bw_idx = 3; + bw_prev = bw; + } + + val[2] = mt7615_mac_tx_rate_val(dev, &rates[2], stbc, &bw); + if (bw_prev) { + bw_idx = 5; + bw_prev = bw; + } + + val[3] = mt7615_mac_tx_rate_val(dev, &rates[3], stbc, &bw); + if (bw_prev) + bw_idx = 7; + + w27 = mt76_rr(dev, addr + 27 * 4); + w27 &= ~MT_WTBL_W27_CC_BW_SEL; + w27 |= FIELD_PREP(MT_WTBL_W27_CC_BW_SEL, bw); + + w5 = mt76_rr(dev, addr + 5 * 4); + w5 &= ~(MT_WTBL_W5_BW_CAP | MT_WTBL_W5_CHANGE_BW_RATE); + w5 |= FIELD_PREP(MT_WTBL_W5_BW_CAP, bw) | + FIELD_PREP(MT_WTBL_W5_CHANGE_BW_RATE, bw_idx ? bw_idx - 1 : 7); + + mt76_wr(dev, MT_WTBL_RIUCR0, w5); + + mt76_wr(dev, MT_WTBL_RIUCR1, + FIELD_PREP(MT_WTBL_RIUCR1_RATE0, probe_val) | + FIELD_PREP(MT_WTBL_RIUCR1_RATE1, val[0]) | + FIELD_PREP(MT_WTBL_RIUCR1_RATE2_LO, val[0])); + + mt76_wr(dev, MT_WTBL_RIUCR2, + FIELD_PREP(MT_WTBL_RIUCR2_RATE2_HI, val[0] >> 8) | + FIELD_PREP(MT_WTBL_RIUCR2_RATE3, val[1]) | + FIELD_PREP(MT_WTBL_RIUCR2_RATE4, val[1]) | + FIELD_PREP(MT_WTBL_RIUCR2_RATE5_LO, val[2])); + + mt76_wr(dev, MT_WTBL_RIUCR3, + FIELD_PREP(MT_WTBL_RIUCR3_RATE5_HI, val[2] >> 4) | + FIELD_PREP(MT_WTBL_RIUCR3_RATE6, val[2]) | + FIELD_PREP(MT_WTBL_RIUCR3_RATE7, val[3])); + + mt76_wr(dev, MT_WTBL_UPDATE, + FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, wcid) | + MT_WTBL_UPDATE_RATE_UPDATE | + MT_WTBL_UPDATE_TX_COUNT_CLEAR); + + mt76_wr(dev, addr + 27 * 4, w27); + + if (!(sta->wcid.tx_info & MT_WCID_TX_INFO_SET)) + mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); + + sta->rate_count = 2 * MT7615_RATE_RETRY * n_rates; + sta->wcid.tx_info |= MT_WCID_TX_INFO_SET; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h new file mode 100644 index 000000000000..9455f8fa475d --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -0,0 +1,520 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2019 MediaTek Inc. */ + +#ifndef __MT7615_MCU_H +#define __MT7615_MCU_H + +struct mt7615_mcu_txd { + __le32 txd[8]; + + __le16 len; + __le16 pq_id; + + u8 cid; + u8 pkt_type; + u8 set_query; /* FW don't care */ + u8 seq; + + u8 uc_d2b0_rev; + u8 ext_cid; + u8 s2d_index; + u8 ext_cid_ack; + + u32 reserved[5]; +} __packed __aligned(4); + +struct mt7615_mcu_rxd { + __le32 rxd[4]; + + __le16 len; + __le16 pkt_type_id; + + u8 eid; + u8 seq; + __le16 __rsv; + + u8 ext_eid; + u8 __rsv1[2]; + u8 s2d_index; +}; + +#define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10)) +#define MCU_PKT_ID 0xa0 + +enum { + MCU_Q_QUERY, + MCU_Q_SET, + MCU_Q_RESERVED, + MCU_Q_NA +}; + +enum { + MCU_S2D_H2N, + MCU_S2D_C2N, + MCU_S2D_H2C, + MCU_S2D_H2CN +}; + +enum { + MCU_CMD_TARGET_ADDRESS_LEN_REQ = 0x01, + MCU_CMD_FW_START_REQ = 0x02, + MCU_CMD_INIT_ACCESS_REG = 0x3, + MCU_CMD_PATCH_START_REQ = 0x05, + MCU_CMD_PATCH_FINISH_REQ = 0x07, + MCU_CMD_PATCH_SEM_CONTROL = 0x10, + MCU_CMD_EXT_CID = 0xED, + MCU_CMD_FW_SCATTER = 0xEE, + MCU_CMD_RESTART_DL_REQ = 0xEF, +}; + +enum { + MCU_EXT_CMD_PM_STATE_CTRL = 0x07, + MCU_EXT_CMD_CHANNEL_SWITCH = 0x08, + MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21, + MCU_EXT_CMD_STA_REC_UPDATE = 0x25, + MCU_EXT_CMD_BSS_INFO_UPDATE = 0x26, + MCU_EXT_CMD_EDCA_UPDATE = 0x27, + MCU_EXT_CMD_DEV_INFO_UPDATE = 0x2A, + MCU_EXT_CMD_WTBL_UPDATE = 0x32, + MCU_EXT_CMD_PROTECT_CTRL = 0x3e, + MCU_EXT_CMD_MAC_INIT_CTRL = 0x46, + MCU_EXT_CMD_BCN_OFFLOAD = 0x49, + MCU_EXT_CMD_SET_RX_PATH = 0x4e, +}; + +enum { + PATCH_SEM_RELEASE = 0x0, + PATCH_SEM_GET = 0x1 +}; + +enum { + PATCH_NOT_DL_SEM_FAIL = 0x0, + PATCH_IS_DL = 0x1, + PATCH_NOT_DL_SEM_SUCCESS = 0x2, + PATCH_REL_SEM_SUCCESS = 0x3 +}; + +enum { + FW_STATE_INITIAL = 0, + FW_STATE_FW_DOWNLOAD = 1, + FW_STATE_NORMAL_OPERATION = 2, + FW_STATE_NORMAL_TRX = 3, + FW_STATE_CR4_RDY = 7 +}; + +#define STA_TYPE_STA BIT(0) +#define STA_TYPE_AP BIT(1) +#define STA_TYPE_ADHOC BIT(2) +#define STA_TYPE_TDLS BIT(3) +#define STA_TYPE_WDS BIT(4) +#define STA_TYPE_BC BIT(5) + +#define NETWORK_INFRA BIT(16) +#define NETWORK_P2P BIT(17) +#define NETWORK_IBSS BIT(18) +#define NETWORK_MESH BIT(19) +#define NETWORK_BOW BIT(20) +#define NETWORK_WDS BIT(21) + +#define CONNECTION_INFRA_STA (STA_TYPE_STA | NETWORK_INFRA) +#define CONNECTION_INFRA_AP (STA_TYPE_AP | NETWORK_INFRA) +#define CONNECTION_P2P_GC (STA_TYPE_STA | NETWORK_P2P) +#define CONNECTION_P2P_GO (STA_TYPE_AP | NETWORK_P2P) +#define CONNECTION_MESH_STA (STA_TYPE_STA | NETWORK_MESH) +#define CONNECTION_MESH_AP (STA_TYPE_AP | NETWORK_MESH) +#define CONNECTION_IBSS_ADHOC (STA_TYPE_ADHOC | NETWORK_IBSS) +#define CONNECTION_TDLS (STA_TYPE_STA | NETWORK_INFRA | STA_TYPE_TDLS) +#define CONNECTION_WDS (STA_TYPE_WDS | NETWORK_WDS) +#define CONNECTION_INFRA_BC (STA_TYPE_BC | NETWORK_INFRA) + +#define CONN_STATE_DISCONNECT 0 +#define CONN_STATE_CONNECT 1 +#define CONN_STATE_PORT_SECURE 2 + +struct dev_info { + u8 omac_idx; + u8 omac_addr[ETH_ALEN]; + u8 band_idx; + u8 enable; + u32 feature; +}; + +enum { + DEV_INFO_ACTIVE, + DEV_INFO_MAX_NUM +}; + +struct bss_info { + u8 bss_idx; + u8 bssid[ETH_ALEN]; + u8 omac_idx; + u8 band_idx; + u8 bmc_tx_wlan_idx; /* for bmc tx (sta mode use uc entry) */ + u8 wmm_idx; + u32 network_type; + u32 conn_type; + u16 bcn_interval; + u8 dtim_period; + u8 enable; + u32 feature; +}; + +struct bss_info_tag_handler { + u32 tag; + u32 len; + void (*handler)(struct mt7615_dev *dev, + struct bss_info *bss_info, struct sk_buff *skb); +}; + +struct bss_info_omac { + __le16 tag; + __le16 len; + u8 hw_bss_idx; + u8 omac_idx; + u8 band_idx; + u8 rsv0; + __le32 conn_type; + u32 rsv1; +} __packed; + +struct bss_info_basic { + __le16 tag; + __le16 len; + __le32 network_type; + u8 active; + u8 rsv0; + __le16 bcn_interval; + u8 bssid[ETH_ALEN]; + u8 wmm_idx; + u8 dtim_period; + u8 bmc_tx_wlan_idx; + u8 cipher; /* not used */ + u8 phymode; /* not used */ + u8 rsv1[5]; +} __packed; + +struct bss_info_rf_ch { + __le16 tag; + __le16 len; + u8 pri_ch; + u8 central_ch0; + u8 central_ch1; + u8 bw; +} __packed; + +struct bss_info_ext_bss { + __le16 tag; + __le16 len; + __le32 mbss_tsf_offset; /* in unit of us */ + u8 rsv[8]; +} __packed; + +enum { + BSS_INFO_OMAC, + BSS_INFO_BASIC, + BSS_INFO_RF_CH, /* optional, for BT/LTE coex */ + BSS_INFO_PM, /* sta only */ + BSS_INFO_UAPSD, /* sta only */ + BSS_INFO_ROAM_DETECTION, /* obsoleted */ + BSS_INFO_LQ_RM, /* obsoleted */ + BSS_INFO_EXT_BSS, + BSS_INFO_BMC_INFO, /* for bmc rate control in CR4 */ + BSS_INFO_SYNC_MODE, /* obsoleted */ + BSS_INFO_RA, + BSS_INFO_MAX_NUM +}; + +enum { + WTBL_RESET_AND_SET = 1, + WTBL_SET, + WTBL_QUERY, + WTBL_RESET_ALL +}; + +struct wtbl_generic { + __le16 tag; + __le16 len; + u8 peer_addr[ETH_ALEN]; + u8 muar_idx; + u8 skip_tx; + u8 cf_ack; + u8 qos; + u8 mesh; + u8 adm; + __le16 partial_aid; + u8 baf_en; + u8 aad_om; +} __packed; + +struct wtbl_rx { + __le16 tag; + __le16 len; + u8 rcid; + u8 rca1; + u8 rca2; + u8 rv; + u8 rsv[4]; +} __packed; + +struct wtbl_ht { + __le16 tag; + __le16 len; + u8 ht; + u8 ldpc; + u8 af; + u8 mm; + u8 rsv[4]; +} __packed; + +struct wtbl_vht { + __le16 tag; + __le16 len; + u8 ldpc; + u8 dyn_bw; + u8 vht; + u8 txop_ps; + u8 rsv[4]; +} __packed; + +struct wtbl_tx_ps { + __le16 tag; + __le16 len; + u8 txps; + u8 rsv[3]; +} __packed; + +struct wtbl_hdr_trans { + __le16 tag; + __le16 len; + u8 to_ds; + u8 from_ds; + u8 disable_rx_trans; + u8 rsv; +} __packed; + +enum mt7615_cipher_type { + MT_CIPHER_NONE, + MT_CIPHER_WEP40, + MT_CIPHER_TKIP, + MT_CIPHER_TKIP_NO_MIC, + MT_CIPHER_AES_CCMP, + MT_CIPHER_WEP104, + MT_CIPHER_BIP_CMAC_128, + MT_CIPHER_WEP128, + MT_CIPHER_WAPI, + MT_CIPHER_CCMP_256 = 10, + MT_CIPHER_GCMP, + MT_CIPHER_GCMP_256, +}; + +struct wtbl_sec_key { + __le16 tag; + __le16 len; + u8 add; /* 0: add, 1: remove */ + u8 rkv; + u8 ikv; + u8 cipher_id; + u8 key_id; + u8 key_len; + u8 rsv[2]; + u8 key_material[32]; +} __packed; + +enum { + MT_BA_TYPE_INVALID, + MT_BA_TYPE_ORIGINATOR, + MT_BA_TYPE_RECIPIENT +}; + +enum { + RST_BA_MAC_TID_MATCH, + RST_BA_MAC_MATCH, + RST_BA_NO_MATCH +}; + +struct wtbl_ba { + __le16 tag; + __le16 len; + /* common */ + u8 tid; + u8 ba_type; + u8 rsv0[2]; + /* originator only */ + __le16 sn; + u8 ba_en; + u8 ba_winsize_idx; + __le16 ba_winsize; + /* recipient only */ + u8 peer_addr[ETH_ALEN]; + u8 rst_ba_tid; + u8 rst_ba_sel; + u8 rst_ba_sb; + u8 band_idx; + u8 rsv1[4]; +} __packed; + +struct wtbl_bf { + __le16 tag; + __le16 len; + u8 ibf; + u8 ebf; + u8 ibf_vht; + u8 ebf_vht; + u8 gid; + u8 pfmu_idx; + u8 rsv[2]; +} __packed; + +struct wtbl_smps { + __le16 tag; + __le16 len; + u8 smps; + u8 rsv[3]; +} __packed; + +struct wtbl_pn { + __le16 tag; + __le16 len; + u8 pn[6]; + u8 rsv[2]; +} __packed; + +struct wtbl_spe { + __le16 tag; + __le16 len; + u8 spe_idx; + u8 rsv[3]; +} __packed; + +struct wtbl_raw { + __le16 tag; + __le16 len; + u8 wtbl_idx; + u8 dw; + u8 rsv[2]; + __le32 msk; + __le32 val; +} __packed; + +#define MT7615_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_generic) + \ + sizeof(struct wtbl_rx) + \ + sizeof(struct wtbl_ht) + \ + sizeof(struct wtbl_vht) + \ + sizeof(struct wtbl_tx_ps) + \ + sizeof(struct wtbl_hdr_trans) + \ + sizeof(struct wtbl_sec_key) + \ + sizeof(struct wtbl_ba) + \ + sizeof(struct wtbl_bf) + \ + sizeof(struct wtbl_smps) + \ + sizeof(struct wtbl_pn) + \ + sizeof(struct wtbl_spe)) + +enum { + WTBL_GENERIC, + WTBL_RX, + WTBL_HT, + WTBL_VHT, + WTBL_PEER_PS, /* not used */ + WTBL_TX_PS, + WTBL_HDR_TRANS, + WTBL_SEC_KEY, + WTBL_BA, + WTBL_RDG, /* obsoleted */ + WTBL_PROTECT, /* not used */ + WTBL_CLEAR, /* not used */ + WTBL_BF, + WTBL_SMPS, + WTBL_RAW_DATA, /* debug only */ + WTBL_PN, + WTBL_SPE, + WTBL_MAX_NUM +}; + +struct sta_rec_basic { + __le16 tag; + __le16 len; + __le32 conn_type; + u8 conn_state; + u8 qos; + __le16 aid; + u8 peer_addr[ETH_ALEN]; +#define EXTRA_INFO_VER BIT(0) +#define EXTRA_INFO_NEW BIT(1) + __le16 extra_info; +} __packed; + +struct sta_rec_ht { + __le16 tag; + __le16 len; + __le16 ht_cap; + u16 rsv; +} __packed; + +struct sta_rec_vht { + __le16 tag; + __le16 len; + __le32 vht_cap; + __le16 vht_rx_mcs_map; + __le16 vht_tx_mcs_map; +} __packed; + +struct sta_rec_ba { + __le16 tag; + __le16 len; + u8 tid; + u8 ba_type; + u8 amsdu; + u8 ba_en; + __le16 ssn; + __le16 winsize; +} __packed; + +#define MT7615_STA_REC_UPDATE_MAX_SIZE (sizeof(struct sta_rec_basic) + \ + sizeof(struct sta_rec_ht) + \ + sizeof(struct sta_rec_vht)) + +enum { + STA_REC_BASIC, + STA_REC_RA, + STA_REC_RA_CMM_INFO, + STA_REC_RA_UPDATE, + STA_REC_BF, + STA_REC_AMSDU, /* for CR4 */ + STA_REC_BA, + STA_REC_RED, /* not used */ + STA_REC_TX_PROC, /* for hdr trans and CSO in CR4 */ + STA_REC_HT, + STA_REC_VHT, + STA_REC_APPS, + STA_REC_MAX_NUM +}; + +enum { + CMD_CBW_20MHZ, + CMD_CBW_40MHZ, + CMD_CBW_80MHZ, + CMD_CBW_160MHZ, + CMD_CBW_10MHZ, + CMD_CBW_5MHZ, + CMD_CBW_8080MHZ +}; + +enum { + CH_SWITCH_NORMAL = 0, + CH_SWITCH_SCAN = 3, + CH_SWITCH_MCC = 4, + CH_SWITCH_DFS = 5, + CH_SWITCH_BACKGROUND_SCAN_START = 6, + CH_SWITCH_BACKGROUND_SCAN_RUNNING = 7, + CH_SWITCH_BACKGROUND_SCAN_STOP = 8, + CH_SWITCH_SCAN_BYPASS_DPD = 9 +}; + +static inline struct sk_buff * +mt7615_mcu_msg_alloc(const void *data, int len) +{ + return mt76_mcu_msg_alloc(data, sizeof(struct mt7615_mcu_txd), + len, 0); +} + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h new file mode 100644 index 000000000000..895c2904d7eb --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -0,0 +1,195 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2019 MediaTek Inc. */ + +#ifndef __MT7615_H +#define __MT7615_H + +#include <linux/interrupt.h> +#include <linux/ktime.h> +#include "../mt76.h" +#include "regs.h" + +#define MT7615_MAX_INTERFACES 4 +#define MT7615_WTBL_SIZE 128 +#define MT7615_WTBL_RESERVED (MT7615_WTBL_SIZE - 1) +#define MT7615_WTBL_STA (MT7615_WTBL_RESERVED - \ + MT7615_MAX_INTERFACES) + +#define MT7615_WATCHDOG_TIME 100 /* ms */ +#define MT7615_RATE_RETRY 2 + +#define MT7615_TX_RING_SIZE 1024 +#define MT7615_TX_MCU_RING_SIZE 128 +#define MT7615_TX_FWDL_RING_SIZE 128 + +#define MT7615_RX_RING_SIZE 1024 +#define MT7615_RX_MCU_RING_SIZE 512 + +#define MT7615_FIRMWARE_CR4 "mt7615_cr4.bin" +#define MT7615_FIRMWARE_N9 "mt7615_n9.bin" +#define MT7615_ROM_PATCH "mt7615_rom_patch.bin" + +#define MT7615_EEPROM_SIZE 1024 +#define MT7615_TOKEN_SIZE 4096 + +struct mt7615_vif; +struct mt7615_sta; + +enum mt7615_hw_txq_id { + MT7615_TXQ_MAIN, + MT7615_TXQ_EXT, + MT7615_TXQ_MCU, + MT7615_TXQ_FWDL, +}; + +struct mt7615_sta { + struct mt76_wcid wcid; /* must be first */ + + struct mt7615_vif *vif; + + struct ieee80211_tx_rate rates[8]; + u8 rate_count; + u8 n_rates; + + u8 rate_probe; +}; + +struct mt7615_vif { + u8 idx; + u8 omac_idx; + u8 band_idx; + u8 wmm_idx; + + struct mt7615_sta sta; +}; + +struct mt7615_dev { + struct mt76_dev mt76; /* must be first */ + u32 vif_mask; + u32 omac_mask; + + spinlock_t token_lock; + struct idr token; +}; + +enum { + HW_BSSID_0 = 0x0, + HW_BSSID_1, + HW_BSSID_2, + HW_BSSID_3, + HW_BSSID_MAX, + EXT_BSSID_START = 0x10, + EXT_BSSID_1, + EXT_BSSID_2, + EXT_BSSID_3, + EXT_BSSID_4, + EXT_BSSID_5, + EXT_BSSID_6, + EXT_BSSID_7, + EXT_BSSID_8, + EXT_BSSID_9, + EXT_BSSID_10, + EXT_BSSID_11, + EXT_BSSID_12, + EXT_BSSID_13, + EXT_BSSID_14, + EXT_BSSID_15, + EXT_BSSID_END +}; + +extern const struct ieee80211_ops mt7615_ops; +extern struct pci_driver mt7615_pci_driver; + +u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr); + +int mt7615_register_device(struct mt7615_dev *dev); +void mt7615_unregister_device(struct mt7615_dev *dev); +int mt7615_eeprom_init(struct mt7615_dev *dev); +int mt7615_dma_init(struct mt7615_dev *dev); +void mt7615_dma_cleanup(struct mt7615_dev *dev); +int mt7615_mcu_init(struct mt7615_dev *dev); +int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, + int en); +int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, + int en); +int mt7615_mcu_set_wtbl_key(struct mt7615_dev *dev, int wcid, + struct ieee80211_key_conf *key, + enum set_key_cmd cmd); +void mt7615_mcu_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, + struct ieee80211_tx_rate *probe_rate, + struct ieee80211_tx_rate *rates); +int mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif); +int mt7615_mcu_del_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif); +int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev); +int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, + struct ieee80211_vif *vif, bool en); +int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool en); +int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, + int en); +int mt7615_mcu_set_channel(struct mt7615_dev *dev); +int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, + const struct ieee80211_tx_queue_params *params); +int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool add); +int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool add); +int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); + +static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask) +{ + mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, 0, mask); +} + +static inline void mt7615_irq_disable(struct mt7615_dev *dev, u32 mask) +{ + mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0); +} + +u16 mt7615_mac_tx_rate_val(struct mt7615_dev *dev, + const struct ieee80211_tx_rate *rate, + bool stbc, u8 *bw); +int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, + struct sk_buff *skb, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, int pid, + struct ieee80211_key_conf *key); +int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb); +void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data); +void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb); + +int mt7615_mcu_set_eeprom(struct mt7615_dev *dev); +int mt7615_mcu_init_mac(struct mt7615_dev *dev); +int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val); +int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter); +void mt7615_mcu_exit(struct mt7615_dev *dev); + +int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info); + +void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, + struct mt76_queue_entry *e); + +void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, + struct sk_buff *skb); +void mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q); +void mt7615_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); +int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void mt7615_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void mt7615_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void mt7615_mac_work(struct work_struct *work); +void mt7615_txp_skb_unmap(struct mt76_dev *dev, + struct mt76_txwi_cache *txwi); + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c new file mode 100644 index 000000000000..11122bd2d727 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2019 MediaTek Inc. + * + * Author: Ryder Lee <ryder.lee@mediatek.com> + * Felix Fietkau <nbd@nbd.name> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pci.h> + +#include "mt7615.h" +#include "mac.h" + +static const struct pci_device_id mt7615_pci_device_table[] = { + { PCI_DEVICE(0x14c3, 0x7615) }, + { }, +}; + +u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr) +{ + u32 base = addr & MT_MCU_PCIE_REMAP_2_BASE; + u32 offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET; + + mt76_wr(dev, MT_MCU_PCIE_REMAP_2, base); + + return MT_PCIE_REMAP_BASE_2 + offset; +} + +void mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) +{ + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + + mt7615_irq_enable(dev, MT_INT_RX_DONE(q)); +} + +irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) +{ + struct mt7615_dev *dev = dev_instance; + u32 intr; + + intr = mt76_rr(dev, MT_INT_SOURCE_CSR); + mt76_wr(dev, MT_INT_SOURCE_CSR, intr); + + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state)) + return IRQ_NONE; + + intr &= dev->mt76.mmio.irqmask; + + if (intr & MT_INT_TX_DONE_ALL) { + mt7615_irq_disable(dev, MT_INT_TX_DONE_ALL); + tasklet_schedule(&dev->mt76.tx_tasklet); + } + + if (intr & MT_INT_RX_DONE(0)) { + mt7615_irq_disable(dev, MT_INT_RX_DONE(0)); + napi_schedule(&dev->mt76.napi[0]); + } + + if (intr & MT_INT_RX_DONE(1)) { + mt7615_irq_disable(dev, MT_INT_RX_DONE(1)); + napi_schedule(&dev->mt76.napi[1]); + } + + return IRQ_HANDLED; +} + +static int mt7615_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + static const struct mt76_driver_ops drv_ops = { + /* txwi_size = txd size + txp size */ + .txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp), + .txwi_flags = MT_TXWI_NO_FREE, + .tx_prepare_skb = mt7615_tx_prepare_skb, + .tx_complete_skb = mt7615_tx_complete_skb, + .rx_skb = mt7615_queue_rx_skb, + .rx_poll_complete = mt7615_rx_poll_complete, + .sta_ps = mt7615_sta_ps, + .sta_add = mt7615_sta_add, + .sta_assoc = mt7615_sta_assoc, + .sta_remove = mt7615_sta_remove, + }; + struct mt7615_dev *dev; + struct mt76_dev *mdev; + int ret; + + ret = pcim_enable_device(pdev); + if (ret) + return ret; + + ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev)); + if (ret) + return ret; + + pci_set_master(pdev); + + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7615_ops, + &drv_ops); + if (!mdev) + return -ENOMEM; + + dev = container_of(mdev, struct mt7615_dev, mt76); + mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); + + mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | + (mt76_rr(dev, MT_HW_REV) & 0xff); + dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); + + ret = devm_request_irq(mdev->dev, pdev->irq, mt7615_irq_handler, + IRQF_SHARED, KBUILD_MODNAME, dev); + if (ret) + goto error; + + ret = mt7615_register_device(dev); + if (ret) + goto error; + + return 0; +error: + ieee80211_free_hw(mt76_hw(dev)); + return ret; +} + +static void mt7615_pci_remove(struct pci_dev *pdev) +{ + struct mt76_dev *mdev = pci_get_drvdata(pdev); + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + + mt7615_unregister_device(dev); +} + +struct pci_driver mt7615_pci_driver = { + .name = KBUILD_MODNAME, + .id_table = mt7615_pci_device_table, + .probe = mt7615_pci_probe, + .remove = mt7615_pci_remove, +}; + +module_pci_driver(mt7615_pci_driver); + +MODULE_DEVICE_TABLE(pci, mt7615_pci_device_table); +MODULE_FIRMWARE(MT7615_FIRMWARE_CR4); +MODULE_FIRMWARE(MT7615_FIRMWARE_N9); +MODULE_FIRMWARE(MT7615_ROM_PATCH); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h new file mode 100644 index 000000000000..70e5ace33cc3 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -0,0 +1,203 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2019 MediaTek Inc. */ + +#ifndef __MT7615_REGS_H +#define __MT7615_REGS_H + +#define MT_HW_REV 0x1000 +#define MT_HW_CHIPID 0x1008 +#define MT_TOP_MISC2 0x1134 +#define MT_TOP_MISC2_FW_STATE GENMASK(2, 0) + +#define MT_MCU_BASE 0x2000 +#define MT_MCU(ofs) (MT_MCU_BASE + (ofs)) + +#define MT_MCU_PCIE_REMAP_1 MT_MCU(0x500) +#define MT_MCU_PCIE_REMAP_1_OFFSET GENMASK(17, 0) +#define MT_MCU_PCIE_REMAP_1_BASE GENMASK(31, 18) +#define MT_PCIE_REMAP_BASE_1 0x40000 + +#define MT_MCU_PCIE_REMAP_2 MT_MCU(0x504) +#define MT_MCU_PCIE_REMAP_2_OFFSET GENMASK(18, 0) +#define MT_MCU_PCIE_REMAP_2_BASE GENMASK(31, 19) +#define MT_PCIE_REMAP_BASE_2 0x80000 + +#define MT_HIF_BASE 0x4000 +#define MT_HIF(ofs) (MT_HIF_BASE + (ofs)) + +#define MT_CFG_LPCR_HOST MT_HIF(0x1f0) +#define MT_CFG_LPCR_HOST_FW_OWN BIT(0) +#define MT_CFG_LPCR_HOST_DRV_OWN BIT(1) + +#define MT_INT_SOURCE_CSR MT_HIF(0x200) +#define MT_INT_MASK_CSR MT_HIF(0x204) +#define MT_DELAY_INT_CFG MT_HIF(0x210) + +#define MT_INT_RX_DONE(_n) BIT(_n) +#define MT_INT_RX_DONE_ALL GENMASK(1, 0) +#define MT_INT_TX_DONE_ALL GENMASK(7, 4) +#define MT_INT_TX_DONE(_n) BIT((_n) + 4) + +#define MT_WPDMA_GLO_CFG MT_HIF(0x208) +#define MT_WPDMA_GLO_CFG_TX_DMA_EN BIT(0) +#define MT_WPDMA_GLO_CFG_TX_DMA_BUSY BIT(1) +#define MT_WPDMA_GLO_CFG_RX_DMA_EN BIT(2) +#define MT_WPDMA_GLO_CFG_RX_DMA_BUSY BIT(3) +#define MT_WPDMA_GLO_CFG_DMA_BURST_SIZE GENMASK(5, 4) +#define MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE BIT(6) +#define MT_WPDMA_GLO_CFG_BIG_ENDIAN BIT(7) +#define MT_WPDMA_GLO_CFG_TX_BT_SIZE_BIT0 BIT(9) +#define MT_WPDMA_GLO_CFG_MULTI_DMA_EN GENMASK(11, 10) +#define MT_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12) +#define MT_WPDMA_GLO_CFG_TX_BT_SIZE_BIT21 GENMASK(23, 22) +#define MT_WPDMA_GLO_CFG_SW_RESET BIT(24) +#define MT_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY BIT(26) +#define MT_WPDMA_GLO_CFG_OMIT_TX_INFO BIT(28) + +#define MT_WPDMA_RST_IDX MT_HIF(0x20c) + +#define MT_TX_RING_BASE MT_HIF(0x300) +#define MT_RX_RING_BASE MT_HIF(0x400) + +#define MT_WPDMA_GLO_CFG1 MT_HIF(0x500) +#define MT_WPDMA_TX_PRE_CFG MT_HIF(0x510) +#define MT_WPDMA_RX_PRE_CFG MT_HIF(0x520) +#define MT_WPDMA_ABT_CFG MT_HIF(0x530) +#define MT_WPDMA_ABT_CFG1 MT_HIF(0x534) + +#define MT_WF_PHY_BASE 0x10000 +#define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs)) + +#define MT_WF_PHY_WF2_RFCTRL0 MT_WF_PHY(0x1900) +#define MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN BIT(9) + +#define MT_WF_CFG_BASE 0x20200 +#define MT_WF_CFG(ofs) (MT_WF_CFG_BASE + (ofs)) + +#define MT_CFG_CCR MT_WF_CFG(0x000) +#define MT_CFG_CCR_MAC_D1_1X_GC_EN BIT(24) +#define MT_CFG_CCR_MAC_D0_1X_GC_EN BIT(25) +#define MT_CFG_CCR_MAC_D1_2X_GC_EN BIT(30) +#define MT_CFG_CCR_MAC_D0_2X_GC_EN BIT(31) + +#define MT_WF_AGG_BASE 0x20a00 +#define MT_WF_AGG(ofs) (MT_WF_AGG_BASE + (ofs)) + +#define MT_AGG_ARCR MT_WF_AGG(0x010) +#define MT_AGG_ARCR_INIT_RATE1 BIT(0) +#define MT_AGG_ARCR_RTS_RATE_THR GENMASK(12, 8) +#define MT_AGG_ARCR_RATE_DOWN_RATIO GENMASK(17, 16) +#define MT_AGG_ARCR_RATE_DOWN_RATIO_EN BIT(19) +#define MT_AGG_ARCR_RATE_UP_EXTRA_TH GENMASK(22, 20) + +#define MT_AGG_ARUCR MT_WF_AGG(0x018) +#define MT_AGG_ARDCR MT_WF_AGG(0x01c) +#define MT_AGG_ARxCR_LIMIT_SHIFT(_n) (4 * (_n)) +#define MT_AGG_ARxCR_LIMIT(_n) GENMASK(2 + \ + MT_AGG_ARxCR_LIMIT_SHIFT(_n), \ + MT_AGG_ARxCR_LIMIT_SHIFT(_n)) + +#define MT_AGG_SCR MT_WF_AGG(0x0fc) +#define MT_AGG_SCR_NLNAV_MID_PTEC_DIS BIT(3) + +#define MT_WF_TMAC_BASE 0x21000 +#define MT_WF_TMAC(ofs) (MT_WF_TMAC_BASE + (ofs)) + +#define MT_TMAC_CTCR0 MT_WF_TMAC(0x0f4) +#define MT_TMAC_CTCR0_INS_DDLMT_REFTIME GENMASK(5, 0) +#define MT_TMAC_CTCR0_INS_DDLMT_DENSITY GENMASK(15, 12) +#define MT_TMAC_CTCR0_INS_DDLMT_EN BIT(17) +#define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN BIT(18) + +#define MT_WF_RMAC_BASE 0x21200 +#define MT_WF_RMAC(ofs) (MT_WF_RMAC_BASE + (ofs)) + +#define MT_WF_RFCR MT_WF_RMAC(0x000) +#define MT_WF_RFCR_DROP_STBC_MULTI BIT(0) +#define MT_WF_RFCR_DROP_FCSFAIL BIT(1) +#define MT_WF_RFCR_DROP_VERSION BIT(3) +#define MT_WF_RFCR_DROP_PROBEREQ BIT(4) +#define MT_WF_RFCR_DROP_MCAST BIT(5) +#define MT_WF_RFCR_DROP_BCAST BIT(6) +#define MT_WF_RFCR_DROP_MCAST_FILTERED BIT(7) +#define MT_WF_RFCR_DROP_A3_MAC BIT(8) +#define MT_WF_RFCR_DROP_A3_BSSID BIT(9) +#define MT_WF_RFCR_DROP_A2_BSSID BIT(10) +#define MT_WF_RFCR_DROP_OTHER_BEACON BIT(11) +#define MT_WF_RFCR_DROP_FRAME_REPORT BIT(12) +#define MT_WF_RFCR_DROP_CTL_RSV BIT(13) +#define MT_WF_RFCR_DROP_CTS BIT(14) +#define MT_WF_RFCR_DROP_RTS BIT(15) +#define MT_WF_RFCR_DROP_DUPLICATE BIT(16) +#define MT_WF_RFCR_DROP_OTHER_BSS BIT(17) +#define MT_WF_RFCR_DROP_OTHER_UC BIT(18) +#define MT_WF_RFCR_DROP_OTHER_TIM BIT(19) +#define MT_WF_RFCR_DROP_NDPA BIT(20) +#define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21) + +#define MT_WF_DMA_BASE 0x21800 +#define MT_WF_DMA(ofs) (MT_WF_DMA_BASE + (ofs)) + +#define MT_DMA_DCR0 MT_WF_DMA(0x000) +#define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 2) +#define MT_DMA_DCR0_RX_VEC_DROP BIT(17) + +#define MT_WTBL_BASE 0x30000 +#define MT_WTBL_ENTRY_SIZE 256 + +#define MT_WTBL_OFF_BASE 0x23400 +#define MT_WTBL_OFF(n) (MT_WTBL_OFF_BASE + (n)) + +#define MT_WTBL_UPDATE MT_WTBL_OFF(0x030) +#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(7, 0) +#define MT_WTBL_UPDATE_RATE_UPDATE BIT(13) +#define MT_WTBL_UPDATE_TX_COUNT_CLEAR BIT(14) +#define MT_WTBL_UPDATE_BUSY BIT(31) + +#define MT_WTBL_ON_BASE 0x23000 +#define MT_WTBL_ON(_n) (MT_WTBL_ON_BASE + (_n)) + +#define MT_WTBL_RIUCR0 MT_WTBL_ON(0x020) + +#define MT_WTBL_RIUCR1 MT_WTBL_ON(0x024) +#define MT_WTBL_RIUCR1_RATE0 GENMASK(11, 0) +#define MT_WTBL_RIUCR1_RATE1 GENMASK(23, 12) +#define MT_WTBL_RIUCR1_RATE2_LO GENMASK(31, 24) + +#define MT_WTBL_RIUCR2 MT_WTBL_ON(0x028) +#define MT_WTBL_RIUCR2_RATE2_HI GENMASK(3, 0) +#define MT_WTBL_RIUCR2_RATE3 GENMASK(15, 4) +#define MT_WTBL_RIUCR2_RATE4 GENMASK(27, 16) +#define MT_WTBL_RIUCR2_RATE5_LO GENMASK(31, 28) + +#define MT_WTBL_RIUCR3 MT_WTBL_ON(0x02c) +#define MT_WTBL_RIUCR3_RATE5_HI GENMASK(7, 0) +#define MT_WTBL_RIUCR3_RATE6 GENMASK(19, 8) +#define MT_WTBL_RIUCR3_RATE7 GENMASK(31, 20) + +#define MT_WTBL_W5_CHANGE_BW_RATE GENMASK(7, 5) +#define MT_WTBL_W5_SHORT_GI_20 BIT(8) +#define MT_WTBL_W5_SHORT_GI_40 BIT(9) +#define MT_WTBL_W5_SHORT_GI_80 BIT(10) +#define MT_WTBL_W5_SHORT_GI_160 BIT(11) +#define MT_WTBL_W5_BW_CAP GENMASK(13, 12) +#define MT_WTBL_W27_CC_BW_SEL GENMASK(6, 5) + +#define MT_EFUSE_BASE 0x81070000 +#define MT_EFUSE_BASE_CTRL 0x000 +#define MT_EFUSE_BASE_CTRL_EMPTY BIT(30) + +#define MT_EFUSE_CTRL 0x008 +#define MT_EFUSE_CTRL_AOUT GENMASK(5, 0) +#define MT_EFUSE_CTRL_MODE GENMASK(7, 6) +#define MT_EFUSE_CTRL_LDO_OFF_TIME GENMASK(13, 8) +#define MT_EFUSE_CTRL_LDO_ON_TIME GENMASK(15, 14) +#define MT_EFUSE_CTRL_AIN GENMASK(25, 16) +#define MT_EFUSE_CTRL_VALID BIT(29) +#define MT_EFUSE_CTRL_KICK BIT(30) +#define MT_EFUSE_CTRL_SEL BIT(31) + +#define MT_EFUSE_WDATA(_i) (0x010 + ((_i) * 4)) +#define MT_EFUSE_RDATA(_i) (0x030 + ((_i) * 4)) + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c index bcb72e019fd2..57e46d57b449 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c @@ -259,7 +259,6 @@ int mt76x0_init_hardware(struct mt76x02_dev *dev) return ret; mt76x0_phy_init(dev); - mt76x02_init_beacon_config(dev); return 0; } @@ -281,6 +280,7 @@ mt76x0_init_txpower(struct mt76x02_dev *dev, mt76x0_get_power_info(dev, chan, &tp); chan->max_power = (mt76x02_get_max_rate_power(&t) + tp) / 2; + chan->orig_mpwr = chan->max_power; } } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h b/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h index 0290ba5869a5..736f81752b5b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h @@ -46,7 +46,7 @@ static const struct mt76_reg_pair common_mac_reg_table[] = { { MT_MM20_PROT_CFG, 0x01742004 }, { MT_MM40_PROT_CFG, 0x03f42084 }, { MT_TXOP_CTRL_CFG, 0x0000583f }, - { MT_TX_RTS_CFG, 0x00092b20 }, + { MT_TX_RTS_CFG, 0x00ffff20 }, { MT_EXP_ACK_TIME, 0x002400ca }, { MT_TXOP_HLDR_ET, 0x00000002 }, { MT_XIFS_TIME_CFG, 0x33a41010 }, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c index fee16ab21edb..691984037f98 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c @@ -22,10 +22,9 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) int ret; cancel_delayed_work_sync(&dev->cal_work); - if (mt76_is_mmio(dev)) { - tasklet_disable(&dev->pre_tbtt_tasklet); + dev->beacon_ops->pre_tbtt_enable(dev, false); + if (mt76_is_mmio(dev)) tasklet_disable(&dev->dfs_pd.dfs_tasklet); - } mt76_set_channel(&dev->mt76); ret = mt76x0_phy_set_channel(dev, chandef); @@ -38,9 +37,10 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) if (mt76_is_mmio(dev)) { mt76x02_dfs_init_params(dev); - tasklet_enable(&dev->pre_tbtt_tasklet); tasklet_enable(&dev->dfs_pd.dfs_tasklet); } + dev->beacon_ops->pre_tbtt_enable(dev, true); + mt76_txq_schedule_all(&dev->mt76); return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c index f302162036d0..4585e1b756c2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c @@ -25,25 +25,21 @@ static int mt76x0e_start(struct ieee80211_hw *hw) { struct mt76x02_dev *dev = hw->priv; - mutex_lock(&dev->mt76.mutex); - mt76x02_mac_start(dev); mt76x0_phy_calibrate(dev, true); - ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work, + ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mt76.mac_work, MT_MAC_WORK_INTERVAL); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, MT_CALIBRATE_INTERVAL); set_bit(MT76_STATE_RUNNING, &dev->mt76.state); - mutex_unlock(&dev->mt76.mutex); - return 0; } static void mt76x0e_stop_hw(struct mt76x02_dev *dev) { cancel_delayed_work_sync(&dev->cal_work); - cancel_delayed_work_sync(&dev->mac_work); + cancel_delayed_work_sync(&dev->mt76.mac_work); if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY, 0, 1000)) @@ -62,10 +58,8 @@ static void mt76x0e_stop(struct ieee80211_hw *hw) { struct mt76x02_dev *dev = hw->priv; - mutex_lock(&dev->mt76.mutex); clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); mt76x0e_stop_hw(dev); - mutex_unlock(&dev->mt76.mutex); } static void @@ -74,13 +68,6 @@ mt76x0e_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { } -static int -mt76x0e_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, - bool set) -{ - return 0; -} - static const struct ieee80211_ops mt76x0e_ops = { .tx = mt76x02_tx, .start = mt76x0e_start, @@ -101,7 +88,7 @@ static const struct ieee80211_ops mt76x0e_ops = { .get_survey = mt76_get_survey, .get_txpower = mt76_get_txpower, .flush = mt76x0e_flush, - .set_tim = mt76x0e_set_tim, + .set_tim = mt76_set_tim, .release_buffered_frames = mt76_release_buffered_frames, .set_coverage_class = mt76x02_set_coverage_class, .set_rts_threshold = mt76x02_set_rts_threshold, @@ -128,6 +115,8 @@ static int mt76x0e_register_device(struct mt76x02_dev *dev) if (err < 0) return err; + mt76x02e_init_beacon_config(dev); + if (mt76_chip(&dev->mt76) == 0x7610) { u16 val; @@ -164,6 +153,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct mt76_driver_ops drv_ops = { .txwi_size = sizeof(struct mt76x02_txwi), + .tx_aligned4_skbs = true, .update_survey = mt76x02_update_channel, .tx_prepare_skb = mt76x02_tx_prepare_skb, .tx_complete_skb = mt76x02_tx_complete_skb, @@ -223,7 +213,7 @@ error: static void mt76x0e_cleanup(struct mt76x02_dev *dev) { clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); - tasklet_disable(&dev->pre_tbtt_tasklet); + tasklet_disable(&dev->mt76.pre_tbtt_tasklet); mt76x0_chip_onoff(dev, false, false); mt76x0e_stop_hw(dev); mt76x02_dma_cleanup(dev); @@ -238,7 +228,7 @@ mt76x0e_remove(struct pci_dev *pdev) mt76_unregister_device(mdev); mt76x0e_cleanup(dev); - ieee80211_free_hw(mdev->hw); + mt76_free_device(mdev); } static const struct pci_device_id mt76x0e_device_table[] = { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index 91718647da02..7c38ec4418db 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -81,20 +81,19 @@ static void mt76x0u_cleanup(struct mt76x02_dev *dev) mt76u_queues_deinit(&dev->mt76); } -static void mt76x0u_mac_stop(struct mt76x02_dev *dev) +static void mt76x0u_stop(struct ieee80211_hw *hw) { + struct mt76x02_dev *dev = hw->priv; + clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); cancel_delayed_work_sync(&dev->cal_work); - cancel_delayed_work_sync(&dev->mac_work); - mt76u_stop_stat_wk(&dev->mt76); + cancel_delayed_work_sync(&dev->mt76.mac_work); + mt76u_stop_tx(&dev->mt76); + mt76x02u_exit_beacon_config(dev); if (test_bit(MT76_REMOVED, &dev->mt76.state)) return; - mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN | - MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN | - MT_BEACON_TIME_CFG_BEACON_TX); - if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_BUSY, 0, 1000)) dev_warn(dev->mt76.dev, "TX DMA did not stop\n"); @@ -109,31 +108,17 @@ static int mt76x0u_start(struct ieee80211_hw *hw) struct mt76x02_dev *dev = hw->priv; int ret; - mutex_lock(&dev->mt76.mutex); - ret = mt76x0_mac_start(dev); if (ret) - goto out; + return ret; mt76x0_phy_calibrate(dev, true); - ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work, + ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mt76.mac_work, MT_MAC_WORK_INTERVAL); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, MT_CALIBRATE_INTERVAL); set_bit(MT76_STATE_RUNNING, &dev->mt76.state); - -out: - mutex_unlock(&dev->mt76.mutex); - return ret; -} - -static void mt76x0u_stop(struct ieee80211_hw *hw) -{ - struct mt76x02_dev *dev = hw->priv; - - mutex_lock(&dev->mt76.mutex); - mt76x0u_mac_stop(dev); - mutex_unlock(&dev->mt76.mutex); + return 0; } static const struct ieee80211_ops mt76x0u_ops = { @@ -155,6 +140,8 @@ static const struct ieee80211_ops mt76x0u_ops = { .set_rts_threshold = mt76x02_set_rts_threshold, .wake_tx_queue = mt76_wake_tx_queue, .get_txpower = mt76_get_txpower, + .set_tim = mt76_set_tim, + .release_buffered_frames = mt76_release_buffered_frames, }; static int mt76x0u_init_hardware(struct mt76x02_dev *dev) @@ -175,6 +162,8 @@ static int mt76x0u_init_hardware(struct mt76x02_dev *dev) if (err < 0) return err; + mt76x02u_init_beacon_config(dev); + mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e); mt76_wr(dev, MT_TXOP_CTRL_CFG, FIELD_PREP(MT_TXOP_TRUN_EN, 0x3f) | @@ -223,16 +212,17 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, .tx_complete_skb = mt76x02u_tx_complete_skb, .tx_status_data = mt76x02_tx_status_data, .rx_skb = mt76x02_queue_rx_skb, + .sta_ps = mt76x02_sta_ps, .sta_add = mt76x02_sta_add, .sta_remove = mt76x02_sta_remove, }; struct usb_device *usb_dev = interface_to_usbdev(usb_intf); struct mt76x02_dev *dev; struct mt76_dev *mdev; - u32 asic_rev, mac_rev; + u32 mac_rev; int ret; - mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), &mt76x0u_ops, + mdev = mt76_alloc_device(&usb_dev->dev, sizeof(*dev), &mt76x0u_ops, &drv_ops); if (!mdev) return -ENOMEM; @@ -262,10 +252,14 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, goto err; } - asic_rev = mt76_rr(dev, MT_ASIC_VERSION); + mdev->rev = mt76_rr(dev, MT_ASIC_VERSION); mac_rev = mt76_rr(dev, MT_MAC_CSR0); dev_info(mdev->dev, "ASIC revision: %08x MAC revision: %08x\n", - asic_rev, mac_rev); + mdev->rev, mac_rev); + if (!is_mt76x0(dev)) { + ret = -ENODEV; + goto err; + } /* Note: vendor driver skips this check for MT76X0U */ if (!(mt76_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL)) @@ -307,8 +301,7 @@ static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf, { struct mt76x02_dev *dev = usb_get_intfdata(usb_intf); - mt76u_stop_queues(&dev->mt76); - mt76x0u_mac_stop(dev); + mt76u_stop_rx(&dev->mt76); clear_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state); mt76x0_chip_onoff(dev, false, false); @@ -318,16 +311,12 @@ static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf, static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf) { struct mt76x02_dev *dev = usb_get_intfdata(usb_intf); - struct mt76_usb *usb = &dev->mt76.usb; int ret; - ret = mt76u_submit_rx_buffers(&dev->mt76); + ret = mt76u_resume_rx(&dev->mt76); if (ret < 0) goto err; - tasklet_enable(&usb->rx_tasklet); - tasklet_enable(&usb->tx_tasklet); - ret = mt76x0u_init_hardware(dev); if (ret) goto err; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 6915cce5def9..687bd14b2d77 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -51,6 +51,7 @@ struct mt76x02_calibration { u16 false_cca; s8 avg_rssi_all; s8 agc_gain_adjust; + s8 agc_lowest_gain; s8 low_gain; s8 temp_vco; @@ -67,6 +68,13 @@ struct mt76x02_calibration { s8 tssi_dc; }; +struct mt76x02_beacon_ops { + unsigned int nslots; + unsigned int slot_size; + void (*pre_tbtt_enable) (struct mt76x02_dev *, bool); + void (*beacon_enable) (struct mt76x02_dev *, bool); +}; + struct mt76x02_dev { struct mt76_dev mt76; /* must be first */ @@ -78,23 +86,25 @@ struct mt76x02_dev { u8 txdone_seq; DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status); + spinlock_t txstatus_fifo_lock; struct sk_buff *rx_head; - struct tasklet_struct tx_tasklet; - struct tasklet_struct pre_tbtt_tasklet; + struct napi_struct tx_napi; struct delayed_work cal_work; - struct delayed_work mac_work; struct delayed_work wdt_work; + struct hrtimer pre_tbtt_timer; + struct work_struct pre_tbtt_work; + + const struct mt76x02_beacon_ops *beacon_ops; + u32 aggr_stats[32]; struct sk_buff *beacons[8]; - u8 beacon_mask; u8 beacon_data_mask; u8 tbtt_count; - u16 beacon_int; u32 tx_hang_reset; u8 tx_hang_check; @@ -114,8 +124,11 @@ struct mt76x02_dev { struct mt76x02_dfs_pattern_detector dfs_pd; /* edcca monitor */ + unsigned long ed_trigger_timeout; bool ed_tx_blocked; bool ed_monitor; + u8 ed_monitor_enabled; + u8 ed_monitor_learning; u8 ed_trigger; u8 ed_silent; ktime_t ed_time; @@ -159,7 +172,6 @@ void mt76x02_set_tx_ackto(struct mt76x02_dev *dev); void mt76x02_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class); int mt76x02_set_rts_threshold(struct ieee80211_hw *hw, u32 val); -int mt76x02_insert_hdr_pad(struct sk_buff *skb); void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len); bool mt76x02_tx_status_data(struct mt76_dev *mdev, u8 *update); void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, @@ -169,9 +181,9 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance); void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb); int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi, - struct sk_buff *skb, struct mt76_queue *q, - struct mt76_wcid *wcid, struct ieee80211_sta *sta, - u32 *tx_info); + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info); void mt76x02_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac); void mt76x02_sw_scan_complete(struct ieee80211_hw *hw, @@ -181,13 +193,30 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, u32 changed); -extern const u16 mt76x02_beacon_offsets[16]; +struct beacon_bc_data { + struct mt76x02_dev *dev; + struct sk_buff_head q; + struct sk_buff *tail[8]; +}; void mt76x02_init_beacon_config(struct mt76x02_dev *dev); -void mt76x02_set_irq_mask(struct mt76x02_dev *dev, u32 clear, u32 set); +void mt76x02e_init_beacon_config(struct mt76x02_dev *dev); +void mt76x02_resync_beacon_timer(struct mt76x02_dev *dev); +void mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif); +void mt76x02_enqueue_buffered_bc(struct mt76x02_dev *dev, + struct beacon_bc_data *data, + int max_nframes); + void mt76x02_mac_start(struct mt76x02_dev *dev); void mt76x02_init_debugfs(struct mt76x02_dev *dev); +static inline bool is_mt76x0(struct mt76x02_dev *dev) +{ + return mt76_chip(&dev->mt76) == 0x7610 || + mt76_chip(&dev->mt76) == 0x7630 || + mt76_chip(&dev->mt76) == 0x7650; +} + static inline bool is_mt76x2(struct mt76x02_dev *dev) { return mt76_chip(&dev->mt76) == 0x7612 || @@ -197,12 +226,12 @@ static inline bool is_mt76x2(struct mt76x02_dev *dev) static inline void mt76x02_irq_enable(struct mt76x02_dev *dev, u32 mask) { - mt76x02_set_irq_mask(dev, 0, mask); + mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, 0, mask); } static inline void mt76x02_irq_disable(struct mt76x02_dev *dev, u32 mask) { - mt76x02_set_irq_mask(dev, mask, 0); + mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0); } static inline bool diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c new file mode 100644 index 000000000000..e196b9c0a686 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> + * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> + * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "mt76x02.h" + +static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev) +{ + u32 regs[4] = {}; + u16 val; + int i; + + for (i = 0; i < dev->beacon_ops->nslots; i++) { + val = i * dev->beacon_ops->slot_size; + regs[i / 4] |= (val / 64) << (8 * (i % 4)); + } + + for (i = 0; i < 4; i++) + mt76_wr(dev, MT_BCN_OFFSET(i), regs[i]); +} + +static int +mt76x02_write_beacon(struct mt76x02_dev *dev, int offset, struct sk_buff *skb) +{ + int beacon_len = dev->beacon_ops->slot_size; + struct mt76x02_txwi txwi; + + if (WARN_ON_ONCE(beacon_len < skb->len + sizeof(struct mt76x02_txwi))) + return -ENOSPC; + + mt76x02_mac_write_txwi(dev, &txwi, skb, NULL, NULL, skb->len); + + mt76_wr_copy(dev, offset, &txwi, sizeof(txwi)); + offset += sizeof(txwi); + + mt76_wr_copy(dev, offset, skb->data, skb->len); + return 0; +} + +static int +__mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 bcn_idx, + struct sk_buff *skb) +{ + int beacon_len = dev->beacon_ops->slot_size; + int beacon_addr = MT_BEACON_BASE + (beacon_len * bcn_idx); + int ret = 0; + int i; + + /* Prevent corrupt transmissions during update */ + mt76_set(dev, MT_BCN_BYPASS_MASK, BIT(bcn_idx)); + + if (skb) { + ret = mt76x02_write_beacon(dev, beacon_addr, skb); + if (!ret) + dev->beacon_data_mask |= BIT(bcn_idx); + } else { + dev->beacon_data_mask &= ~BIT(bcn_idx); + for (i = 0; i < beacon_len; i += 4) + mt76_wr(dev, beacon_addr + i, 0); + } + + mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xff00 | ~dev->beacon_data_mask); + + return ret; +} + +int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, + struct sk_buff *skb) +{ + bool force_update = false; + int bcn_idx = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(dev->beacons); i++) { + if (vif_idx == i) { + force_update = !!dev->beacons[i] ^ !!skb; + + if (dev->beacons[i]) + dev_kfree_skb(dev->beacons[i]); + + dev->beacons[i] = skb; + __mt76x02_mac_set_beacon(dev, bcn_idx, skb); + } else if (force_update && dev->beacons[i]) { + __mt76x02_mac_set_beacon(dev, bcn_idx, + dev->beacons[i]); + } + + bcn_idx += !!dev->beacons[i]; + } + + for (i = bcn_idx; i < ARRAY_SIZE(dev->beacons); i++) { + if (!(dev->beacon_data_mask & BIT(i))) + break; + + __mt76x02_mac_set_beacon(dev, i, NULL); + } + + mt76_rmw_field(dev, MT_MAC_BSSID_DW1, MT_MAC_BSSID_DW1_MBEACON_N, + bcn_idx - 1); + return 0; +} +EXPORT_SYMBOL_GPL(mt76x02_mac_set_beacon); + +static void +__mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx, + bool val, struct sk_buff *skb) +{ + u8 old_mask = dev->mt76.beacon_mask; + bool en; + u32 reg; + + if (val) { + dev->mt76.beacon_mask |= BIT(vif_idx); + if (skb) + mt76x02_mac_set_beacon(dev, vif_idx, skb); + } else { + dev->mt76.beacon_mask &= ~BIT(vif_idx); + mt76x02_mac_set_beacon(dev, vif_idx, NULL); + } + + if (!!old_mask == !!dev->mt76.beacon_mask) + return; + + en = dev->mt76.beacon_mask; + + reg = MT_BEACON_TIME_CFG_BEACON_TX | + MT_BEACON_TIME_CFG_TBTT_EN | + MT_BEACON_TIME_CFG_TIMER_EN; + mt76_rmw(dev, MT_BEACON_TIME_CFG, reg, reg * en); + + dev->beacon_ops->beacon_enable(dev, en); +} + +void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, + struct ieee80211_vif *vif, bool val) +{ + u8 vif_idx = ((struct mt76x02_vif *)vif->drv_priv)->idx; + struct sk_buff *skb = NULL; + + dev->beacon_ops->pre_tbtt_enable(dev, false); + + if (mt76_is_usb(dev)) + skb = ieee80211_beacon_get(mt76_hw(dev), vif); + + if (!dev->mt76.beacon_mask) + dev->tbtt_count = 0; + + __mt76x02_mac_set_beacon_enable(dev, vif_idx, val, skb); + + dev->beacon_ops->pre_tbtt_enable(dev, true); +} + +void +mt76x02_resync_beacon_timer(struct mt76x02_dev *dev) +{ + u32 timer_val = dev->mt76.beacon_int << 4; + + dev->tbtt_count++; + + /* + * Beacon timer drifts by 1us every tick, the timer is configured + * in 1/16 TU (64us) units. + */ + if (dev->tbtt_count < 63) + return; + + /* + * The updated beacon interval takes effect after two TBTT, because + * at this point the original interval has already been loaded into + * the next TBTT_TIMER value + */ + if (dev->tbtt_count == 63) + timer_val -= 1; + + mt76_rmw_field(dev, MT_BEACON_TIME_CFG, + MT_BEACON_TIME_CFG_INTVAL, timer_val); + + if (dev->tbtt_count >= 64) { + dev->tbtt_count = 0; + return; + } +} +EXPORT_SYMBOL_GPL(mt76x02_resync_beacon_timer); + +void +mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct mt76x02_dev *dev = (struct mt76x02_dev *)priv; + struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; + struct sk_buff *skb = NULL; + + if (!(dev->mt76.beacon_mask & BIT(mvif->idx))) + return; + + skb = ieee80211_beacon_get(mt76_hw(dev), vif); + if (!skb) + return; + + mt76x02_mac_set_beacon(dev, mvif->idx, skb); +} +EXPORT_SYMBOL_GPL(mt76x02_update_beacon_iter); + +static void +mt76x02_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct beacon_bc_data *data = priv; + struct mt76x02_dev *dev = data->dev; + struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; + struct ieee80211_tx_info *info; + struct sk_buff *skb; + + if (!(dev->mt76.beacon_mask & BIT(mvif->idx))) + return; + + skb = ieee80211_get_buffered_bc(mt76_hw(dev), vif); + if (!skb) + return; + + info = IEEE80211_SKB_CB(skb); + info->control.vif = vif; + info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; + mt76_skb_set_moredata(skb, true); + __skb_queue_tail(&data->q, skb); + data->tail[mvif->idx] = skb; +} + +void +mt76x02_enqueue_buffered_bc(struct mt76x02_dev *dev, struct beacon_bc_data *data, + int max_nframes) +{ + int i, nframes; + + data->dev = dev; + __skb_queue_head_init(&data->q); + + do { + nframes = skb_queue_len(&data->q); + ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), + IEEE80211_IFACE_ITER_RESUME_ALL, + mt76x02_add_buffered_bc, data); + } while (nframes != skb_queue_len(&data->q) && + skb_queue_len(&data->q) < max_nframes); + + if (!skb_queue_len(&data->q)) + return; + + for (i = 0; i < ARRAY_SIZE(data->tail); i++) { + if (!data->tail[i]) + continue; + mt76_skb_set_moredata(data->tail[i], false); + } +} +EXPORT_SYMBOL_GPL(mt76x02_enqueue_buffered_bc); + +void mt76x02_init_beacon_config(struct mt76x02_dev *dev) +{ + int i; + + mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN | + MT_BEACON_TIME_CFG_TBTT_EN | + MT_BEACON_TIME_CFG_BEACON_TX)); + mt76_set(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_SYNC_MODE); + mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff); + + for (i = 0; i < 8; i++) + mt76x02_mac_set_beacon(dev, i, NULL); + + mt76x02_set_beacon_offsets(dev); +} +EXPORT_SYMBOL_GPL(mt76x02_init_beacon_config); + + diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c index 7580c5c986ff..b1d6fd4861e3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c @@ -116,6 +116,32 @@ static int read_agc(struct seq_file *file, void *data) return 0; } +static int +mt76_edcca_set(void *data, u64 val) +{ + struct mt76x02_dev *dev = data; + enum nl80211_dfs_regions region = dev->dfs_pd.region; + + dev->ed_monitor_enabled = !!val; + dev->ed_monitor = dev->ed_monitor_enabled && + region == NL80211_DFS_ETSI; + mt76x02_edcca_init(dev, true); + + return 0; +} + +static int +mt76_edcca_get(void *data, u64 *val) +{ + struct mt76x02_dev *dev = data; + + *val = dev->ed_monitor_enabled; + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_edcca, mt76_edcca_get, mt76_edcca_set, + "%lld\n"); + void mt76x02_init_debugfs(struct mt76x02_dev *dev) { struct dentry *dir; @@ -127,6 +153,7 @@ void mt76x02_init_debugfs(struct mt76x02_dev *dev) debugfs_create_u8("temperature", 0400, dir, &dev->cal.temp); debugfs_create_bool("tpc", 0600, dir, &dev->enable_tpc); + debugfs_create_file("edcca", 0400, dir, dev, &fops_edcca); debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat); debugfs_create_file("dfs_stats", 0400, dir, dev, &fops_dfs_stat); debugfs_create_devm_seqfile(dev->mt76.dev, "txpower", dir, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index e4649103efd4..17d12d212d1b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c @@ -885,7 +885,8 @@ mt76x02_dfs_set_domain(struct mt76x02_dev *dev, if (dfs_pd->region != region) { tasklet_disable(&dfs_pd->dfs_tasklet); - dev->ed_monitor = region == NL80211_DFS_ETSI; + dev->ed_monitor = dev->ed_monitor_enabled && + region == NL80211_DFS_ETSI; mt76x02_edcca_init(dev, true); dfs_pd->region = region; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 91ff6598eccf..56510a1a843a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -67,12 +67,39 @@ int mt76x02_mac_shared_key_setup(struct mt76x02_dev *dev, u8 vif_idx, } EXPORT_SYMBOL_GPL(mt76x02_mac_shared_key_setup); +void mt76x02_mac_wcid_sync_pn(struct mt76x02_dev *dev, u8 idx, + struct ieee80211_key_conf *key) +{ + enum mt76x02_cipher_type cipher; + u8 key_data[32]; + u32 iv, eiv; + u64 pn; + + cipher = mt76x02_mac_get_key_info(key, key_data); + iv = mt76_rr(dev, MT_WCID_IV(idx)); + eiv = mt76_rr(dev, MT_WCID_IV(idx) + 4); + + pn = (u64)eiv << 16; + if (cipher == MT_CIPHER_TKIP) { + pn |= (iv >> 16) & 0xff; + pn |= (iv & 0xff) << 8; + } else if (cipher >= MT_CIPHER_AES_CCMP) { + pn |= iv & 0xffff; + } else { + return; + } + + atomic64_set(&key->tx_pn, pn); +} + + int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx, struct ieee80211_key_conf *key) { enum mt76x02_cipher_type cipher; u8 key_data[32]; u8 iv_data[8]; + u64 pn; cipher = mt76x02_mac_get_key_info(key, key_data); if (cipher == MT_CIPHER_NONE && key) @@ -85,9 +112,22 @@ int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx, if (key) { mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PAIRWISE, !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); + + pn = atomic64_read(&key->tx_pn); + iv_data[3] = key->keyidx << 6; - if (cipher >= MT_CIPHER_TKIP) + if (cipher >= MT_CIPHER_TKIP) { iv_data[3] |= 0x20; + put_unaligned_le32(pn >> 16, &iv_data[4]); + } + + if (cipher == MT_CIPHER_TKIP) { + iv_data[0] = (pn >> 8) & 0xff; + iv_data[1] = (iv_data[0] | 0x20) & 0x7f; + iv_data[2] = pn & 0xff; + } else if (cipher >= MT_CIPHER_AES_CCMP) { + put_unaligned_le16((pn & 0xffff), &iv_data[0]); + } } mt76_wr_copy(dev, MT_WCID_IV(idx), iv_data, sizeof(iv_data)); @@ -178,10 +218,17 @@ mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev, void mt76x02_mac_wcid_set_rate(struct mt76x02_dev *dev, struct mt76_wcid *wcid, const struct ieee80211_tx_rate *rate) { - spin_lock_bh(&dev->mt76.lock); - wcid->tx_rate = mt76x02_mac_tx_rate_val(dev, rate, &wcid->tx_rate_nss); - wcid->tx_rate_set = true; - spin_unlock_bh(&dev->mt76.lock); + s8 max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, rate); + __le16 rateval; + u32 tx_info; + s8 nss; + + rateval = mt76x02_mac_tx_rate_val(dev, rate, &nss); + tx_info = FIELD_PREP(MT_WCID_TX_INFO_RATE, rateval) | + FIELD_PREP(MT_WCID_TX_INFO_NSS, nss) | + FIELD_PREP(MT_WCID_TX_INFO_TXPWR_ADJ, max_txpwr_adj) | + MT_WCID_TX_INFO_SET; + wcid->tx_info = tx_info; } void mt76x02_mac_set_short_preamble(struct mt76x02_dev *dev, bool enable) @@ -283,6 +330,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *rate = &info->control.rates[0]; struct ieee80211_key_conf *key = info->control.hw_key; + u32 wcid_tx_info; u16 rate_ht_mask = FIELD_PREP(MT_RXWI_RATE_PHY, BIT(1) | BIT(2)); u16 txwi_flags = 0; u8 nss; @@ -317,16 +365,16 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, txwi->eiv = *((__le32 *)&ccmp_pn[4]); } - spin_lock_bh(&dev->mt76.lock); if (wcid && (rate->idx < 0 || !rate->count)) { - txwi->rate = wcid->tx_rate; - max_txpwr_adj = wcid->max_txpwr_adj; - nss = wcid->tx_rate_nss; + wcid_tx_info = wcid->tx_info; + txwi->rate = FIELD_GET(MT_WCID_TX_INFO_RATE, wcid_tx_info); + max_txpwr_adj = FIELD_GET(MT_WCID_TX_INFO_TXPWR_ADJ, + wcid_tx_info); + nss = FIELD_GET(MT_WCID_TX_INFO_NSS, wcid_tx_info); } else { txwi->rate = mt76x02_mac_tx_rate_val(dev, rate, &nss); max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, rate); } - spin_unlock_bh(&dev->mt76.lock); txpwr_adj = mt76x02_tx_get_txpwr_adj(dev, dev->mt76.txpower_conf, max_txpwr_adj); @@ -426,7 +474,6 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, return; rcu_read_lock(); - mt76_tx_status_lock(mdev, &list); if (stat->wcid < ARRAY_SIZE(dev->mt76.wcid)) wcid = rcu_dereference(dev->mt76.wcid[stat->wcid]); @@ -439,6 +486,8 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, drv_priv); } + mt76_tx_status_lock(mdev, &list); + if (wcid) { if (stat->pktid >= MT_PACKET_ID_FIRST) status.skb = mt76_tx_status_skb_get(mdev, wcid, @@ -458,7 +507,9 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, if (*update == 0 && stat_val == stat_cache && stat->wcid == msta->status.wcid && msta->n_frames < 32) { msta->n_frames++; - goto out; + mt76_tx_status_unlock(mdev, &list); + rcu_read_unlock(); + return; } mt76x02_mac_fill_tx_status(dev, status.info, &msta->status, @@ -474,11 +525,10 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, if (status.skb) mt76_tx_status_skb_done(mdev, status.skb, &list); - else - ieee80211_tx_status_ext(mt76_hw(dev), &status); - -out: mt76_tx_status_unlock(mdev, &list); + + if (!status.skb) + ieee80211_tx_status_ext(mt76_hw(dev), &status); rcu_read_unlock(); } @@ -689,7 +739,6 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq) { struct mt76x02_tx_status stat = {}; - unsigned long flags; u8 update = 1; bool ret; @@ -699,9 +748,11 @@ void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq) trace_mac_txstat_poll(dev); while (!irq || !kfifo_is_full(&dev->txstatus_fifo)) { - spin_lock_irqsave(&dev->mt76.mmio.irq_lock, flags); + if (!spin_trylock(&dev->txstatus_fifo_lock)) + break; + ret = mt76x02_mac_load_tx_status(dev, &stat); - spin_unlock_irqrestore(&dev->mt76.mmio.irq_lock, flags); + spin_unlock(&dev->txstatus_fifo_lock); if (!ret) break; @@ -715,11 +766,12 @@ void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq) } } -void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, - struct mt76_queue_entry *e, bool flush) +void mt76x02_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, + struct mt76_queue_entry *e) { struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); struct mt76x02_txwi *txwi; + u8 *txwi_ptr; if (!e->txwi) { dev_kfree_skb_any(e->skb); @@ -728,7 +780,8 @@ void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, mt76x02_mac_poll_tx_status(dev, false); - txwi = (struct mt76x02_txwi *) &e->txwi->txwi; + txwi_ptr = mt76_get_txwi_ptr(mdev, e->txwi); + txwi = (struct mt76x02_txwi *)txwi_ptr; trace_mac_txdone_add(dev, txwi->wcid, txwi->pktid); mt76_tx_complete_skb(mdev, e->skb); @@ -920,6 +973,7 @@ void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable) } } mt76x02_edcca_tx_enable(dev, true); + dev->ed_monitor_learning = true; /* clear previous CCA timer value */ mt76_rr(dev, MT_ED_CCA_TIMER); @@ -929,6 +983,10 @@ EXPORT_SYMBOL_GPL(mt76x02_edcca_init); #define MT_EDCCA_TH 92 #define MT_EDCCA_BLOCK_TH 2 +#define MT_EDCCA_LEARN_TH 50 +#define MT_EDCCA_LEARN_CCA 180 +#define MT_EDCCA_LEARN_TIMEOUT (20 * HZ) + static void mt76x02_edcca_check(struct mt76x02_dev *dev) { ktime_t cur_time; @@ -951,18 +1009,30 @@ static void mt76x02_edcca_check(struct mt76x02_dev *dev) dev->ed_trigger = 0; } - if (dev->ed_trigger > MT_EDCCA_BLOCK_TH && - !dev->ed_tx_blocked) + if (dev->cal.agc_lowest_gain && + dev->cal.false_cca > MT_EDCCA_LEARN_CCA && + dev->ed_trigger > MT_EDCCA_LEARN_TH) { + dev->ed_monitor_learning = false; + dev->ed_trigger_timeout = jiffies + 20 * HZ; + } else if (!dev->ed_monitor_learning && + time_is_after_jiffies(dev->ed_trigger_timeout)) { + dev->ed_monitor_learning = true; + mt76x02_edcca_tx_enable(dev, true); + } + + if (dev->ed_monitor_learning) + return; + + if (dev->ed_trigger > MT_EDCCA_BLOCK_TH && !dev->ed_tx_blocked) mt76x02_edcca_tx_enable(dev, false); - else if (dev->ed_silent > MT_EDCCA_BLOCK_TH && - dev->ed_tx_blocked) + else if (dev->ed_silent > MT_EDCCA_BLOCK_TH && dev->ed_tx_blocked) mt76x02_edcca_tx_enable(dev, true); } void mt76x02_mac_work(struct work_struct *work) { struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev, - mac_work.work); + mt76.mac_work.work); int i, idx; mutex_lock(&dev->mt76.mutex); @@ -975,7 +1045,7 @@ void mt76x02_mac_work(struct work_struct *work) dev->aggr_stats[idx++] += val >> 16; } - if (!dev->beacon_mask) + if (!dev->mt76.beacon_mask) mt76x02_check_mac_err(dev); if (dev->ed_monitor) @@ -985,7 +1055,7 @@ void mt76x02_mac_work(struct work_struct *work) mt76_tx_status_check(&dev->mt76, NULL, false); - ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, MT_MAC_WORK_INTERVAL); } @@ -996,141 +1066,3 @@ void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr) mt76_rmw_field(dev, MT_MAC_APC_BSSID_H(idx), MT_MAC_APC_BSSID_H_ADDR, get_unaligned_le16(addr + 4)); } - -static int -mt76x02_write_beacon(struct mt76x02_dev *dev, int offset, struct sk_buff *skb) -{ - int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0]; - struct mt76x02_txwi txwi; - - if (WARN_ON_ONCE(beacon_len < skb->len + sizeof(struct mt76x02_txwi))) - return -ENOSPC; - - mt76x02_mac_write_txwi(dev, &txwi, skb, NULL, NULL, skb->len); - - mt76_wr_copy(dev, offset, &txwi, sizeof(txwi)); - offset += sizeof(txwi); - - mt76_wr_copy(dev, offset, skb->data, skb->len); - return 0; -} - -static int -__mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 bcn_idx, - struct sk_buff *skb) -{ - int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0]; - int beacon_addr = mt76x02_beacon_offsets[bcn_idx]; - int ret = 0; - int i; - - /* Prevent corrupt transmissions during update */ - mt76_set(dev, MT_BCN_BYPASS_MASK, BIT(bcn_idx)); - - if (skb) { - ret = mt76x02_write_beacon(dev, beacon_addr, skb); - if (!ret) - dev->beacon_data_mask |= BIT(bcn_idx); - } else { - dev->beacon_data_mask &= ~BIT(bcn_idx); - for (i = 0; i < beacon_len; i += 4) - mt76_wr(dev, beacon_addr + i, 0); - } - - mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xff00 | ~dev->beacon_data_mask); - - return ret; -} - -int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, - struct sk_buff *skb) -{ - bool force_update = false; - int bcn_idx = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(dev->beacons); i++) { - if (vif_idx == i) { - force_update = !!dev->beacons[i] ^ !!skb; - - if (dev->beacons[i]) - dev_kfree_skb(dev->beacons[i]); - - dev->beacons[i] = skb; - __mt76x02_mac_set_beacon(dev, bcn_idx, skb); - } else if (force_update && dev->beacons[i]) { - __mt76x02_mac_set_beacon(dev, bcn_idx, - dev->beacons[i]); - } - - bcn_idx += !!dev->beacons[i]; - } - - for (i = bcn_idx; i < ARRAY_SIZE(dev->beacons); i++) { - if (!(dev->beacon_data_mask & BIT(i))) - break; - - __mt76x02_mac_set_beacon(dev, i, NULL); - } - - mt76_rmw_field(dev, MT_MAC_BSSID_DW1, MT_MAC_BSSID_DW1_MBEACON_N, - bcn_idx - 1); - return 0; -} - -static void -__mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx, - bool val, struct sk_buff *skb) -{ - u8 old_mask = dev->beacon_mask; - bool en; - u32 reg; - - if (val) { - dev->beacon_mask |= BIT(vif_idx); - if (skb) - mt76x02_mac_set_beacon(dev, vif_idx, skb); - } else { - dev->beacon_mask &= ~BIT(vif_idx); - mt76x02_mac_set_beacon(dev, vif_idx, NULL); - } - - if (!!old_mask == !!dev->beacon_mask) - return; - - en = dev->beacon_mask; - - reg = MT_BEACON_TIME_CFG_BEACON_TX | - MT_BEACON_TIME_CFG_TBTT_EN | - MT_BEACON_TIME_CFG_TIMER_EN; - mt76_rmw(dev, MT_BEACON_TIME_CFG, reg, reg * en); - - if (mt76_is_usb(dev)) - return; - - mt76_rmw_field(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_PRE_TBTT_EN, en); - if (en) - mt76x02_irq_enable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT); - else - mt76x02_irq_disable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT); -} - -void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, - struct ieee80211_vif *vif, bool val) -{ - u8 vif_idx = ((struct mt76x02_vif *)vif->drv_priv)->idx; - struct sk_buff *skb = NULL; - - if (mt76_is_mmio(dev)) - tasklet_disable(&dev->pre_tbtt_tasklet); - else if (val) - skb = ieee80211_beacon_get(mt76_hw(dev), vif); - - if (!dev->beacon_mask) - dev->tbtt_count = 0; - - __mt76x02_mac_set_beacon_enable(dev, vif_idx, val, skb); - - if (mt76_is_mmio(dev)) - tasklet_enable(&dev->pre_tbtt_tasklet); -} diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index 6b1f25d2f64c..e4a9e0d0924b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -177,6 +177,8 @@ int mt76x02_mac_shared_key_setup(struct mt76x02_dev *dev, u8 vif_idx, u8 key_idx, struct ieee80211_key_conf *key); int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx, struct ieee80211_key_conf *key); +void mt76x02_mac_wcid_sync_pn(struct mt76x02_dev *dev, u8 idx, + struct ieee80211_key_conf *key); void mt76x02_mac_wcid_setup(struct mt76x02_dev *dev, u8 idx, u8 vif_idx, u8 *mac); void mt76x02_mac_wcid_set_drop(struct mt76x02_dev *dev, u8 idx, bool drop); @@ -196,8 +198,8 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta, int len); void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq); -void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, - struct mt76_queue_entry *e, bool flush); +void mt76x02_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, + struct mt76_queue_entry *e); void mt76x02_update_channel(struct mt76_dev *mdev); void mt76x02_mac_work(struct work_struct *work); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 1229f19f2b02..7b7163bc3b62 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -19,98 +19,21 @@ #include <linux/irq.h> #include "mt76x02.h" +#include "mt76x02_mcu.h" #include "mt76x02_trace.h" -struct beacon_bc_data { - struct mt76x02_dev *dev; - struct sk_buff_head q; - struct sk_buff *tail[8]; -}; - -static void -mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) -{ - struct mt76x02_dev *dev = (struct mt76x02_dev *)priv; - struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; - struct sk_buff *skb = NULL; - - if (!(dev->beacon_mask & BIT(mvif->idx))) - return; - - skb = ieee80211_beacon_get(mt76_hw(dev), vif); - if (!skb) - return; - - mt76x02_mac_set_beacon(dev, mvif->idx, skb); -} - -static void -mt76x02_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif) -{ - struct beacon_bc_data *data = priv; - struct mt76x02_dev *dev = data->dev; - struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; - struct ieee80211_tx_info *info; - struct sk_buff *skb; - - if (!(dev->beacon_mask & BIT(mvif->idx))) - return; - - skb = ieee80211_get_buffered_bc(mt76_hw(dev), vif); - if (!skb) - return; - - info = IEEE80211_SKB_CB(skb); - info->control.vif = vif; - info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; - mt76_skb_set_moredata(skb, true); - __skb_queue_tail(&data->q, skb); - data->tail[mvif->idx] = skb; -} - -static void -mt76x02_resync_beacon_timer(struct mt76x02_dev *dev) -{ - u32 timer_val = dev->beacon_int << 4; - - dev->tbtt_count++; - - /* - * Beacon timer drifts by 1us every tick, the timer is configured - * in 1/16 TU (64us) units. - */ - if (dev->tbtt_count < 63) - return; - - /* - * The updated beacon interval takes effect after two TBTT, because - * at this point the original interval has already been loaded into - * the next TBTT_TIMER value - */ - if (dev->tbtt_count == 63) - timer_val -= 1; - - mt76_rmw_field(dev, MT_BEACON_TIME_CFG, - MT_BEACON_TIME_CFG_INTVAL, timer_val); - - if (dev->tbtt_count >= 64) { - dev->tbtt_count = 0; - return; - } -} - static void mt76x02_pre_tbtt_tasklet(unsigned long arg) { struct mt76x02_dev *dev = (struct mt76x02_dev *)arg; - struct mt76_queue *q = &dev->mt76.q_tx[MT_TXQ_PSD]; + struct mt76_queue *q = dev->mt76.q_tx[MT_TXQ_PSD].q; struct beacon_bc_data data = {}; struct sk_buff *skb; - int i, nframes; + int i; - mt76x02_resync_beacon_timer(dev); + if (mt76_hw(dev)->conf.flags & IEEE80211_CONF_OFFCHANNEL) + return; - data.dev = dev; - __skb_queue_head_init(&data.q); + mt76x02_resync_beacon_timer(dev); ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), IEEE80211_IFACE_ITER_RESUME_ALL, @@ -121,13 +44,7 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg) if (dev->mt76.csa_complete) return; - do { - nframes = skb_queue_len(&data.q); - ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), - IEEE80211_IFACE_ITER_RESUME_ALL, - mt76x02_add_buffered_bc, &data); - } while (nframes != skb_queue_len(&data.q) && - skb_queue_len(&data.q) < 8); + mt76x02_enqueue_buffered_bc(dev, &data, 8); if (!skb_queue_len(&data.q)) return; @@ -145,25 +62,67 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg) struct ieee80211_vif *vif = info->control.vif; struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; - mt76_dma_tx_queue_skb(&dev->mt76, q, skb, &mvif->group_wcid, - NULL); + mt76_tx_queue_skb(dev, MT_TXQ_PSD, skb, &mvif->group_wcid, + NULL); } spin_unlock_bh(&q->lock); } +static void mt76x02e_pre_tbtt_enable(struct mt76x02_dev *dev, bool en) +{ + if (en) + tasklet_enable(&dev->mt76.pre_tbtt_tasklet); + else + tasklet_disable(&dev->mt76.pre_tbtt_tasklet); +} + +static void mt76x02e_beacon_enable(struct mt76x02_dev *dev, bool en) +{ + mt76_rmw_field(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_PRE_TBTT_EN, en); + if (en) + mt76x02_irq_enable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT); + else + mt76x02_irq_disable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT); +} + +void mt76x02e_init_beacon_config(struct mt76x02_dev *dev) +{ + static const struct mt76x02_beacon_ops beacon_ops = { + .nslots = 8, + .slot_size = 1024, + .pre_tbtt_enable = mt76x02e_pre_tbtt_enable, + .beacon_enable = mt76x02e_beacon_enable, + }; + + dev->beacon_ops = &beacon_ops; + + /* Fire a pre-TBTT interrupt 8 ms before TBTT */ + mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT, 8 << 4); + mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_GP_TIMER, + MT_DFS_GP_INTERVAL); + mt76_wr(dev, MT_INT_TIMER_EN, 0); + + mt76x02_init_beacon_config(dev); +} +EXPORT_SYMBOL_GPL(mt76x02e_init_beacon_config); + static int -mt76x02_init_tx_queue(struct mt76x02_dev *dev, struct mt76_queue *q, +mt76x02_init_tx_queue(struct mt76x02_dev *dev, struct mt76_sw_queue *q, int idx, int n_desc) { - int ret; + struct mt76_queue *hwq; + int err; - q->regs = dev->mt76.mmio.regs + MT_TX_RING_BASE + idx * MT_RING_SIZE; - q->ndesc = n_desc; - q->hw_idx = idx; + hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); + if (!hwq) + return -ENOMEM; - ret = mt76_queue_alloc(dev, q); - if (ret) - return ret; + err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE); + if (err < 0) + return err; + + INIT_LIST_HEAD(&q->swq); + q->q = hwq; mt76x02_irq_enable(dev, MT_INT_TX_DONE(idx)); @@ -174,15 +133,12 @@ static int mt76x02_init_rx_queue(struct mt76x02_dev *dev, struct mt76_queue *q, int idx, int n_desc, int bufsize) { - int ret; - - q->regs = dev->mt76.mmio.regs + MT_RX_RING_BASE + idx * MT_RING_SIZE; - q->ndesc = n_desc; - q->buf_size = bufsize; + int err; - ret = mt76_queue_alloc(dev, q); - if (ret) - return ret; + err = mt76_queue_alloc(dev, q, idx, n_desc, bufsize, + MT_RX_RING_BASE); + if (err < 0) + return err; mt76x02_irq_enable(dev, MT_INT_RX_DONE(idx)); @@ -201,15 +157,32 @@ static void mt76x02_process_tx_status_fifo(struct mt76x02_dev *dev) static void mt76x02_tx_tasklet(unsigned long data) { struct mt76x02_dev *dev = (struct mt76x02_dev *)data; - int i; + mt76x02_mac_poll_tx_status(dev, false); mt76x02_process_tx_status_fifo(dev); + mt76_txq_schedule_all(&dev->mt76); +} + +static int mt76x02_poll_tx(struct napi_struct *napi, int budget) +{ + struct mt76x02_dev *dev = container_of(napi, struct mt76x02_dev, tx_napi); + int i; + + mt76x02_mac_poll_tx_status(dev, false); + for (i = MT_TXQ_MCU; i >= 0; i--) mt76_queue_tx_cleanup(dev, i, false); - mt76x02_mac_poll_tx_status(dev, false); - mt76x02_irq_enable(dev, MT_INT_TX_DONE_ALL); + if (napi_complete_done(napi, 0)) + mt76x02_irq_enable(dev, MT_INT_TX_DONE_ALL); + + for (i = MT_TXQ_MCU; i >= 0; i--) + mt76_queue_tx_cleanup(dev, i, false); + + tasklet_schedule(&dev->mt76.tx_tasklet); + + return 0; } int mt76x02_dma_init(struct mt76x02_dev *dev) @@ -219,7 +192,6 @@ int mt76x02_dma_init(struct mt76x02_dev *dev) struct mt76_queue *q; void *status_fifo; - BUILD_BUG_ON(sizeof(t->txwi) < sizeof(struct mt76x02_txwi)); BUILD_BUG_ON(sizeof(struct mt76x02_rxwi) > MT_RX_HEADROOM); fifo_size = roundup_pow_of_two(32 * sizeof(struct mt76x02_tx_status)); @@ -227,10 +199,12 @@ int mt76x02_dma_init(struct mt76x02_dev *dev) if (!status_fifo) return -ENOMEM; - tasklet_init(&dev->tx_tasklet, mt76x02_tx_tasklet, (unsigned long) dev); - tasklet_init(&dev->pre_tbtt_tasklet, mt76x02_pre_tbtt_tasklet, + tasklet_init(&dev->mt76.tx_tasklet, mt76x02_tx_tasklet, + (unsigned long) dev); + tasklet_init(&dev->mt76.pre_tbtt_tasklet, mt76x02_pre_tbtt_tasklet, (unsigned long)dev); + spin_lock_init(&dev->txstatus_fifo_lock); kfifo_init(&dev->txstatus_fifo, status_fifo, fifo_size); mt76_dma_attach(&dev->mt76); @@ -267,7 +241,15 @@ int mt76x02_dma_init(struct mt76x02_dev *dev) if (ret) return ret; - return mt76_init_queues(dev); + ret = mt76_init_queues(dev); + if (ret) + return ret; + + netif_tx_napi_add(&dev->mt76.napi_dev, &dev->tx_napi, mt76x02_poll_tx, + NAPI_POLL_WEIGHT); + napi_enable(&dev->tx_napi); + + return 0; } EXPORT_SYMBOL_GPL(mt76x02_dma_init); @@ -295,11 +277,6 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance) intr &= dev->mt76.mmio.irqmask; - if (intr & MT_INT_TX_DONE_ALL) { - mt76x02_irq_disable(dev, MT_INT_TX_DONE_ALL); - tasklet_schedule(&dev->tx_tasklet); - } - if (intr & MT_INT_RX_DONE(0)) { mt76x02_irq_disable(dev, MT_INT_RX_DONE(0)); napi_schedule(&dev->mt76.napi[0]); @@ -311,19 +288,22 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance) } if (intr & MT_INT_PRE_TBTT) - tasklet_schedule(&dev->pre_tbtt_tasklet); + tasklet_schedule(&dev->mt76.pre_tbtt_tasklet); /* send buffered multicast frames now */ if (intr & MT_INT_TBTT) { if (dev->mt76.csa_complete) mt76_csa_finish(&dev->mt76); else - mt76_queue_kick(dev, &dev->mt76.q_tx[MT_TXQ_PSD]); + mt76_queue_kick(dev, dev->mt76.q_tx[MT_TXQ_PSD].q); } - if (intr & MT_INT_TX_STAT) { + if (intr & MT_INT_TX_STAT) mt76x02_mac_poll_tx_status(dev, true); - tasklet_schedule(&dev->tx_tasklet); + + if (intr & (MT_INT_TX_STAT | MT_INT_TX_DONE_ALL)) { + mt76x02_irq_disable(dev, MT_INT_TX_DONE_ALL); + napi_schedule(&dev->tx_napi); } if (intr & MT_INT_GPTIMER) { @@ -335,18 +315,6 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance) } EXPORT_SYMBOL_GPL(mt76x02_irq_handler); -void mt76x02_set_irq_mask(struct mt76x02_dev *dev, u32 clear, u32 set) -{ - unsigned long flags; - - spin_lock_irqsave(&dev->mt76.mmio.irq_lock, flags); - dev->mt76.mmio.irqmask &= ~clear; - dev->mt76.mmio.irqmask |= set; - mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask); - spin_unlock_irqrestore(&dev->mt76.mmio.irq_lock, flags); -} -EXPORT_SYMBOL_GPL(mt76x02_set_irq_mask); - static void mt76x02_dma_enable(struct mt76x02_dev *dev) { u32 val; @@ -365,7 +333,8 @@ static void mt76x02_dma_enable(struct mt76x02_dev *dev) void mt76x02_dma_cleanup(struct mt76x02_dev *dev) { - tasklet_kill(&dev->tx_tasklet); + tasklet_kill(&dev->mt76.tx_tasklet); + netif_napi_del(&dev->tx_napi); mt76_dma_cleanup(&dev->mt76); } EXPORT_SYMBOL_GPL(mt76x02_dma_cleanup); @@ -402,13 +371,13 @@ static bool mt76x02_tx_hang(struct mt76x02_dev *dev) int i; for (i = 0; i < 4; i++) { - q = &dev->mt76.q_tx[i]; + q = dev->mt76.q_tx[i].q; if (!q->queued) continue; prev_dma_idx = dev->mt76.tx_dma_idx[i]; - dma_idx = ioread32(&q->regs->dma_idx); + dma_idx = readl(&q->regs->dma_idx); dev->mt76.tx_dma_idx[i] = dma_idx; if (prev_dma_idx == dma_idx) @@ -418,23 +387,84 @@ static bool mt76x02_tx_hang(struct mt76x02_dev *dev) return i < 4; } +static void mt76x02_key_sync(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, void *data) +{ + struct mt76x02_dev *dev = hw->priv; + struct mt76_wcid *wcid; + + if (!sta) + return; + + wcid = (struct mt76_wcid *) sta->drv_priv; + + if (wcid->hw_key_idx != key->keyidx || wcid->sw_iv) + return; + + mt76x02_mac_wcid_sync_pn(dev, wcid->idx, key); +} + +static void mt76x02_reset_state(struct mt76x02_dev *dev) +{ + int i; + + lockdep_assert_held(&dev->mt76.mutex); + + clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + + rcu_read_lock(); + ieee80211_iter_keys_rcu(dev->mt76.hw, NULL, mt76x02_key_sync, NULL); + rcu_read_unlock(); + + for (i = 0; i < ARRAY_SIZE(dev->mt76.wcid); i++) { + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; + struct mt76x02_sta *msta; + struct mt76_wcid *wcid; + void *priv; + + wcid = rcu_dereference_protected(dev->mt76.wcid[i], + lockdep_is_held(&dev->mt76.mutex)); + if (!wcid) + continue; + + priv = msta = container_of(wcid, struct mt76x02_sta, wcid); + sta = container_of(priv, struct ieee80211_sta, drv_priv); + + priv = msta->vif; + vif = container_of(priv, struct ieee80211_vif, drv_priv); + + __mt76_sta_remove(&dev->mt76, vif, sta); + memset(msta, 0, sizeof(*msta)); + } + + dev->vif_mask = 0; + dev->mt76.beacon_mask = 0; +} + static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) { u32 mask = dev->mt76.mmio.irqmask; + bool restart = dev->mt76.mcu_ops->mcu_restart; int i; ieee80211_stop_queues(dev->mt76.hw); set_bit(MT76_RESET, &dev->mt76.state); - tasklet_disable(&dev->pre_tbtt_tasklet); - tasklet_disable(&dev->tx_tasklet); + tasklet_disable(&dev->mt76.pre_tbtt_tasklet); + tasklet_disable(&dev->mt76.tx_tasklet); + napi_disable(&dev->tx_napi); for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++) napi_disable(&dev->mt76.napi[i]); mutex_lock(&dev->mt76.mutex); - if (dev->beacon_mask) + if (restart) + mt76x02_reset_state(dev); + + if (dev->mt76.beacon_mask) mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_BEACON_TX | MT_BEACON_TIME_CFG_TBTT_EN); @@ -452,20 +482,21 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) /* let fw reset DMA */ mt76_set(dev, 0x734, 0x3); + if (restart) + mt76_mcu_restart(dev); + for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++) mt76_queue_tx_cleanup(dev, i, true); for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) mt76_queue_rx_reset(dev, i); - mt76_wr(dev, MT_MAC_SYS_CTRL, - MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX); - mt76_set(dev, MT_WPDMA_GLO_CFG, - MT_WPDMA_GLO_CFG_TX_DMA_EN | MT_WPDMA_GLO_CFG_RX_DMA_EN); + mt76x02_mac_start(dev); + if (dev->ed_monitor) mt76_set(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); - if (dev->beacon_mask) + if (dev->mt76.beacon_mask && !restart) mt76_set(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_BEACON_TX | MT_BEACON_TIME_CFG_TBTT_EN); @@ -476,19 +507,24 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) clear_bit(MT76_RESET, &dev->mt76.state); - tasklet_enable(&dev->tx_tasklet); - tasklet_schedule(&dev->tx_tasklet); + tasklet_enable(&dev->mt76.tx_tasklet); + napi_enable(&dev->tx_napi); + napi_schedule(&dev->tx_napi); - tasklet_enable(&dev->pre_tbtt_tasklet); + tasklet_enable(&dev->mt76.pre_tbtt_tasklet); for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++) { napi_enable(&dev->mt76.napi[i]); napi_schedule(&dev->mt76.napi[i]); } - ieee80211_wake_queues(dev->mt76.hw); - - mt76_txq_schedule_all(&dev->mt76); + if (restart) { + mt76x02_mcu_function_select(dev, Q_SELECT, 1); + ieee80211_restart_hw(dev->mt76.hw); + } else { + ieee80211_wake_queues(dev->mt76.hw); + mt76_txq_schedule_all(&dev->mt76); + } } static void mt76x02_check_tx_hang(struct mt76x02_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c index a020c757ba5c..a54b63a96eae 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c @@ -194,6 +194,8 @@ bool mt76x02_phy_adjust_vga_gain(struct mt76x02_dev *dev) ret = true; } + dev->cal.agc_lowest_gain = dev->cal.agc_gain_adjust >= limit; + return ret; } EXPORT_SYMBOL_GPL(mt76x02_phy_adjust_vga_gain); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h index 7401cb94fb72..2ce05b543dff 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h @@ -356,7 +356,10 @@ #define MT_BEACON_TIME_CFG_TSF_COMP GENMASK(31, 24) #define MT_TBTT_SYNC_CFG 0x1118 -#define MT_TBTT_TIMER_CFG 0x1124 +#define MT_TSF_TIMER_DW0 0x111c +#define MT_TSF_TIMER_DW1 0x1120 +#define MT_TBTT_TIMER 0x1124 +#define MT_TBTT_TIMER_VAL GENMASK(16, 0) #define MT_INT_TIMER_CFG 0x1128 #define MT_INT_TIMER_CFG_PRE_TBTT GENMASK(15, 0) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c index 94f47248c59f..cf7abd9b7d2e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c @@ -147,36 +147,33 @@ bool mt76x02_tx_status_data(struct mt76_dev *mdev, u8 *update) EXPORT_SYMBOL_GPL(mt76x02_tx_status_data); int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, - struct sk_buff *skb, struct mt76_queue *q, - struct mt76_wcid *wcid, struct ieee80211_sta *sta, - u32 *tx_info) + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info) { struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; struct mt76x02_txwi *txwi = txwi_ptr; - int qsel = MT_QSEL_EDCA; - int pid; - int ret; + int hdrlen, len, pid, qsel = MT_QSEL_EDCA; - if (q == &dev->mt76.q_tx[MT_TXQ_PSD] && wcid && wcid->idx < 128) + if (qid == MT_TXQ_PSD && wcid && wcid->idx < 128) mt76x02_mac_wcid_set_drop(dev, wcid->idx, false); - mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, skb->len); + hdrlen = ieee80211_hdrlen(hdr->frame_control); + len = tx_info->skb->len - (hdrlen & 2); + mt76x02_mac_write_txwi(dev, txwi, tx_info->skb, wcid, sta, len); - pid = mt76_tx_status_skb_add(mdev, wcid, skb); + pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); txwi->pktid = pid; - ret = mt76x02_insert_hdr_pad(skb); - if (ret < 0) - return ret; - if (pid >= MT_PACKET_ID_FIRST) qsel = MT_QSEL_MGMT; - *tx_info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) | - MT_TXD_INFO_80211; + tx_info->info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) | + MT_TXD_INFO_80211; if (!wcid || wcid->hw_key_idx == 0xff || wcid->sw_iv) - *tx_info |= MT_TXD_INFO_WIV; + tx_info->info |= MT_TXD_INFO_WIV; return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h b/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h index 0126e51d77ed..7b53f9e57f29 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h @@ -26,9 +26,11 @@ int mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, const void *data, int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags); int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, - struct sk_buff *skb, struct mt76_queue *q, - struct mt76_wcid *wcid, struct ieee80211_sta *sta, - u32 *tx_info); -void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, - struct mt76_queue_entry *e, bool flush); + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info); +void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, + struct mt76_queue_entry *e); +void mt76x02u_init_beacon_config(struct mt76x02_dev *dev); +void mt76x02u_exit_beacon_config(struct mt76x02_dev *dev); #endif /* __MT76x02_USB_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 43f07461c8d3..6b89f7eab26c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -26,8 +26,8 @@ static void mt76x02u_remove_dma_hdr(struct sk_buff *skb) mt76x02_remove_hdr_pad(skb, 2); } -void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, - struct mt76_queue_entry *e, bool flush) +void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, + struct mt76_queue_entry *e) { mt76x02u_remove_dma_hdr(e->skb); mt76_tx_complete_skb(mdev, e->skb); @@ -72,26 +72,26 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags) } int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, - struct sk_buff *skb, struct mt76_queue *q, - struct mt76_wcid *wcid, struct ieee80211_sta *sta, - u32 *tx_info) + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info) { struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); + int pid, len = tx_info->skb->len, ep = q2ep(mdev->q_tx[qid].q->hw_idx); struct mt76x02_txwi *txwi; enum mt76_qsel qsel; - int len = skb->len; u32 flags; - int pid; - mt76x02_insert_hdr_pad(skb); + mt76_insert_hdr_pad(tx_info->skb); - txwi = skb_push(skb, sizeof(struct mt76x02_txwi)); - mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, len); + txwi = (struct mt76x02_txwi *)(tx_info->skb->data - sizeof(*txwi)); + mt76x02_mac_write_txwi(dev, txwi, tx_info->skb, wcid, sta, len); + skb_push(tx_info->skb, sizeof(*txwi)); - pid = mt76_tx_status_skb_add(mdev, wcid, skb); + pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); txwi->pktid = pid; - if (pid >= MT_PACKET_ID_FIRST || q2ep(q->hw_idx) == MT_EP_OUT_HCCA) + if (pid >= MT_PACKET_ID_FIRST || ep == MT_EP_OUT_HCCA) qsel = MT_QSEL_MGMT; else qsel = MT_QSEL_EDCA; @@ -101,6 +101,167 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, if (!wcid || wcid->hw_key_idx == 0xff || wcid->sw_iv) flags |= MT_TXD_INFO_WIV; - return mt76x02u_skb_dma_info(skb, WLAN_PORT, flags); + return mt76x02u_skb_dma_info(tx_info->skb, WLAN_PORT, flags); } EXPORT_SYMBOL_GPL(mt76x02u_tx_prepare_skb); + +/* Trigger pre-TBTT event 8 ms before TBTT */ +#define PRE_TBTT_USEC 8000 + +/* Beacon SRAM memory is limited to 8kB. We need to send PS buffered frames + * (which can be 1500 bytes big) via beacon memory. That make limit of number + * of slots to 5. TODO: dynamically calculate offsets in beacon SRAM. + */ +#define N_BCN_SLOTS 5 + +static void mt76x02u_start_pre_tbtt_timer(struct mt76x02_dev *dev) +{ + u64 time; + u32 tbtt; + + /* Get remaining TBTT in usec */ + tbtt = mt76_get_field(dev, MT_TBTT_TIMER, MT_TBTT_TIMER_VAL); + tbtt *= 32; + + if (tbtt <= PRE_TBTT_USEC) { + queue_work(system_highpri_wq, &dev->pre_tbtt_work); + return; + } + + time = (tbtt - PRE_TBTT_USEC) * 1000ull; + hrtimer_start(&dev->pre_tbtt_timer, time, HRTIMER_MODE_REL); +} + +static void mt76x02u_restart_pre_tbtt_timer(struct mt76x02_dev *dev) +{ + u32 tbtt, dw0, dw1; + u64 tsf, time; + + /* Get remaining TBTT in usec */ + tbtt = mt76_get_field(dev, MT_TBTT_TIMER, MT_TBTT_TIMER_VAL); + tbtt *= 32; + + dw0 = mt76_rr(dev, MT_TSF_TIMER_DW0); + dw1 = mt76_rr(dev, MT_TSF_TIMER_DW1); + tsf = (u64)dw0 << 32 | dw1; + dev_dbg(dev->mt76.dev, "TSF: %llu us TBTT %u us\n", tsf, tbtt); + + /* Convert beacon interval in TU (1024 usec) to nsec */ + time = ((1000000000ull * dev->mt76.beacon_int) >> 10); + + /* Adjust time to trigger hrtimer 8ms before TBTT */ + if (tbtt < PRE_TBTT_USEC) + time -= (PRE_TBTT_USEC - tbtt) * 1000ull; + else + time += (tbtt - PRE_TBTT_USEC) * 1000ull; + + hrtimer_start(&dev->pre_tbtt_timer, time, HRTIMER_MODE_REL); +} + +static void mt76x02u_stop_pre_tbtt_timer(struct mt76x02_dev *dev) +{ + do { + hrtimer_cancel(&dev->pre_tbtt_timer); + cancel_work_sync(&dev->pre_tbtt_work); + /* Timer can be rearmed by work. */ + } while (hrtimer_active(&dev->pre_tbtt_timer)); +} + +static void mt76x02u_pre_tbtt_work(struct work_struct *work) +{ + struct mt76x02_dev *dev = + container_of(work, struct mt76x02_dev, pre_tbtt_work); + struct beacon_bc_data data = {}; + struct sk_buff *skb; + int i, nbeacons; + + if (!dev->mt76.beacon_mask) + return; + + if (mt76_hw(dev)->conf.flags & IEEE80211_CONF_OFFCHANNEL) + return; + + mt76x02_resync_beacon_timer(dev); + + ieee80211_iterate_active_interfaces(mt76_hw(dev), + IEEE80211_IFACE_ITER_RESUME_ALL, + mt76x02_update_beacon_iter, dev); + + nbeacons = hweight8(dev->mt76.beacon_mask); + mt76x02_enqueue_buffered_bc(dev, &data, N_BCN_SLOTS - nbeacons); + + for (i = nbeacons; i < N_BCN_SLOTS; i++) { + skb = __skb_dequeue(&data.q); + mt76x02_mac_set_beacon(dev, i, skb); + } + + mt76x02u_restart_pre_tbtt_timer(dev); +} + +static enum hrtimer_restart mt76x02u_pre_tbtt_interrupt(struct hrtimer *timer) +{ + struct mt76x02_dev *dev = + container_of(timer, struct mt76x02_dev, pre_tbtt_timer); + + queue_work(system_highpri_wq, &dev->pre_tbtt_work); + + return HRTIMER_NORESTART; +} + +static void mt76x02u_pre_tbtt_enable(struct mt76x02_dev *dev, bool en) +{ + if (en && dev->mt76.beacon_mask && + !hrtimer_active(&dev->pre_tbtt_timer)) + mt76x02u_start_pre_tbtt_timer(dev); + if (!en) + mt76x02u_stop_pre_tbtt_timer(dev); +} + +static void mt76x02u_beacon_enable(struct mt76x02_dev *dev, bool en) +{ + int i; + + if (WARN_ON_ONCE(!dev->mt76.beacon_int)) + return; + + if (en) { + mt76x02u_start_pre_tbtt_timer(dev); + } else { + /* Timer is already stopped, only clean up + * PS buffered frames if any. + */ + for (i = 0; i < N_BCN_SLOTS; i++) + mt76x02_mac_set_beacon(dev, i, NULL); + } +} + +void mt76x02u_init_beacon_config(struct mt76x02_dev *dev) +{ + static const struct mt76x02_beacon_ops beacon_ops = { + .nslots = N_BCN_SLOTS, + .slot_size = (8192 / N_BCN_SLOTS) & ~63, + .pre_tbtt_enable = mt76x02u_pre_tbtt_enable, + .beacon_enable = mt76x02u_beacon_enable, + }; + dev->beacon_ops = &beacon_ops; + + hrtimer_init(&dev->pre_tbtt_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + dev->pre_tbtt_timer.function = mt76x02u_pre_tbtt_interrupt; + INIT_WORK(&dev->pre_tbtt_work, mt76x02u_pre_tbtt_work); + + mt76x02_init_beacon_config(dev); +} +EXPORT_SYMBOL_GPL(mt76x02u_init_beacon_config); + +void mt76x02u_exit_beacon_config(struct mt76x02_dev *dev) +{ + if (!test_bit(MT76_REMOVED, &dev->mt76.state)) + mt76_clear(dev, MT_BEACON_TIME_CFG, + MT_BEACON_TIME_CFG_TIMER_EN | + MT_BEACON_TIME_CFG_SYNC_MODE | + MT_BEACON_TIME_CFG_TBTT_EN | + MT_BEACON_TIME_CFG_BEACON_TX); + + mt76x02u_stop_pre_tbtt_timer(dev); +} +EXPORT_SYMBOL_GPL(mt76x02u_exit_beacon_config); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index a48c261b0c63..ad5323447ed4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -132,7 +132,7 @@ void mt76x02_init_device(struct mt76x02_dev *dev) struct ieee80211_hw *hw = mt76_hw(dev); struct wiphy *wiphy = hw->wiphy; - INIT_DELAYED_WORK(&dev->mac_work, mt76x02_mac_work); + INIT_DELAYED_WORK(&dev->mt76.mac_work, mt76x02_mac_work); hw->queues = 4; hw->max_rates = 1; @@ -142,6 +142,7 @@ void mt76x02_init_device(struct mt76x02_dev *dev) wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | #ifdef CONFIG_MAC80211_MESH BIT(NL80211_IFTYPE_MESH_POINT) | #endif @@ -158,7 +159,6 @@ void mt76x02_init_device(struct mt76x02_dev *dev) wiphy->reg_notifier = mt76x02_regd_notifier; wiphy->iface_combinations = mt76x02_if_comb; wiphy->n_iface_combinations = ARRAY_SIZE(mt76x02_if_comb); - wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; /* init led callbacks */ @@ -237,6 +237,8 @@ int mt76x02_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; int idx = 0; + memset(msta, 0, sizeof(*msta)); + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, ARRAY_SIZE(dev->mt76.wcid)); if (idx < 0) return -ENOSPC; @@ -274,6 +276,8 @@ mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; struct mt76_txq *mtxq; + memset(mvif, 0, sizeof(*mvif)); + mvif->idx = idx; mvif->group_wcid.idx = MT_VIF_WCID(idx); mvif->group_wcid.hw_key_idx = -1; @@ -289,6 +293,12 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) struct mt76x02_dev *dev = hw->priv; unsigned int idx = 0; + /* Allow to change address in HW if we create first interface. */ + if (!dev->vif_mask && + (((vif->addr[0] ^ dev->mt76.macaddr[0]) & ~GENMASK(4, 1)) || + memcmp(vif->addr + 1, dev->mt76.macaddr + 1, ETH_ALEN - 1))) + mt76x02_mac_setaddr(dev, vif->addr); + if (vif->addr[0] & BIT(1)) idx = 1 + (((dev->mt76.macaddr[0] ^ vif->addr[0]) >> 2) & 7); @@ -311,10 +321,6 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) if (dev->vif_mask & BIT(idx)) return -EBUSY; - /* Allow to change address in HW if we create first interface. */ - if (!dev->vif_mask && !ether_addr_equal(dev->mt76.macaddr, vif->addr)) - mt76x02_mac_setaddr(dev, vif->addr); - dev->vif_mask |= BIT(idx); mt76x02_vif_init(dev, vif, idx); @@ -372,7 +378,7 @@ int mt76x02_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ieee80211_send_bar(vif, sta->addr, tid, mtxq->agg_ssn); break; case IEEE80211_AMPDU_TX_START: - mtxq->agg_ssn = *ssn << 4; + mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(*ssn); ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; case IEEE80211_AMPDU_TX_STOP_CONT: @@ -418,6 +424,16 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) return -EOPNOTSUPP; + /* + * In USB AP mode, broadcast/multicast frames are setup in beacon + * data registers and sent via HW beacons engine, they require to + * be already encrypted. + */ + if (mt76_is_usb(dev) && + vif->type == NL80211_IFTYPE_AP && + !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + return -EOPNOTSUPP; + msta = sta ? (struct mt76x02_sta *) sta->drv_priv : NULL; wcid = msta ? &msta->wcid : &mvif->group_wcid; @@ -459,7 +475,7 @@ int mt76x02_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u8 cw_min = 5, cw_max = 10, qid; u32 val; - qid = dev->mt76.q_tx[queue].hw_idx; + qid = dev->mt76.q_tx[queue].q->hw_idx; if (params->cw_min) cw_min = fls(params->cw_min); @@ -556,26 +572,9 @@ void mt76x02_sta_rate_tbl_update(struct ieee80211_hw *hw, rate.idx = rates->rate[0].idx; rate.flags = rates->rate[0].flags; mt76x02_mac_wcid_set_rate(dev, &msta->wcid, &rate); - msta->wcid.max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, &rate); } EXPORT_SYMBOL_GPL(mt76x02_sta_rate_tbl_update); -int mt76x02_insert_hdr_pad(struct sk_buff *skb) -{ - int len = ieee80211_get_hdrlen_from_skb(skb); - - if (len % 4 == 0) - return 0; - - skb_push(skb, 2); - memmove(skb->data, skb->data + 2, len); - - skb->data[len] = 0; - skb->data[len + 1] = 0; - return 2; -} -EXPORT_SYMBOL_GPL(mt76x02_insert_hdr_pad); - void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len) { int hdrlen; @@ -594,8 +593,6 @@ void mt76x02_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct mt76x02_dev *dev = hw->priv; - if (mt76_is_mmio(dev)) - tasklet_disable(&dev->pre_tbtt_tasklet); set_bit(MT76_SCANNING, &dev->mt76.state); } EXPORT_SYMBOL_GPL(mt76x02_sw_scan); @@ -606,9 +603,6 @@ void mt76x02_sw_scan_complete(struct ieee80211_hw *hw, struct mt76x02_dev *dev = hw->priv; clear_bit(MT76_SCANNING, &dev->mt76.state); - if (mt76_is_mmio(dev)) - tasklet_enable(&dev->pre_tbtt_tasklet); - if (dev->cal.gain_init_done) { /* Restore AGC gain and resume calibration after scanning. */ dev->cal.low_gain = -1; @@ -625,72 +619,11 @@ void mt76x02_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, int idx = msta->wcid.idx; mt76_stop_tx_queues(&dev->mt76, sta, true); - mt76x02_mac_wcid_set_drop(dev, idx, ps); + if (mt76_is_mmio(dev)) + mt76x02_mac_wcid_set_drop(dev, idx, ps); } EXPORT_SYMBOL_GPL(mt76x02_sta_ps); -const u16 mt76x02_beacon_offsets[16] = { - /* 1024 byte per beacon */ - 0xc000, - 0xc400, - 0xc800, - 0xcc00, - 0xd000, - 0xd400, - 0xd800, - 0xdc00, - /* BSS idx 8-15 not used for beacons */ - 0xc000, - 0xc000, - 0xc000, - 0xc000, - 0xc000, - 0xc000, - 0xc000, - 0xc000, -}; - -static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev) -{ - u16 val, base = MT_BEACON_BASE; - u32 regs[4] = {}; - int i; - - for (i = 0; i < 16; i++) { - val = mt76x02_beacon_offsets[i] - base; - regs[i / 4] |= (val / 64) << (8 * (i % 4)); - } - - for (i = 0; i < 4; i++) - mt76_wr(dev, MT_BCN_OFFSET(i), regs[i]); -} - -void mt76x02_init_beacon_config(struct mt76x02_dev *dev) -{ - int i; - - if (mt76_is_mmio(dev)) { - /* Fire a pre-TBTT interrupt 8 ms before TBTT */ - mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT, - 8 << 4); - mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_GP_TIMER, - MT_DFS_GP_INTERVAL); - mt76_wr(dev, MT_INT_TIMER_EN, 0); - } - - mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN | - MT_BEACON_TIME_CFG_TBTT_EN | - MT_BEACON_TIME_CFG_BEACON_TX)); - mt76_set(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_SYNC_MODE); - mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff); - - for (i = 0; i < 8; i++) - mt76x02_mac_set_beacon(dev, i, NULL); - - mt76x02_set_beacon_offsets(dev); -} -EXPORT_SYMBOL_GPL(mt76x02_init_beacon_config); - void mt76x02_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, @@ -712,7 +645,7 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw, mt76_rmw_field(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_INTVAL, info->beacon_int << 4); - dev->beacon_int = info->beacon_int; + dev->mt76.beacon_int = info->beacon_int; } if (changed & BSS_CHANGED_BEACON_ENABLED) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c index f8534362e2c8..c6078e90ca43 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c @@ -106,7 +106,7 @@ void mt76_write_mac_initvals(struct mt76x02_dev *dev) { MT_TX_SW_CFG1, 0x00010000 }, { MT_TX_SW_CFG2, 0x00000000 }, { MT_TXOP_CTRL_CFG, 0x0400583f }, - { MT_TX_RTS_CFG, 0x00100020 }, + { MT_TX_RTS_CFG, 0x00ffff20 }, { MT_TX_TIMEOUT_CFG, 0x000a2290 }, { MT_TX_RETRY_CFG, 0x47f01f0f }, { MT_EXP_ACK_TIME, 0x002c00dc }, @@ -165,27 +165,21 @@ void mt76x2_init_txpower(struct mt76x02_dev *dev, struct ieee80211_channel *chan; struct mt76x2_tx_power_info txp; struct mt76_rate_power t = {}; - int target_power; int i; for (i = 0; i < sband->n_channels; i++) { chan = &sband->channels[i]; mt76x2_get_power_info(dev, &txp, chan); - - target_power = max_t(int, (txp.chain[0].target_power + - txp.chain[0].delta), - (txp.chain[1].target_power + - txp.chain[1].delta)); - mt76x2_get_rate_power(dev, &t, chan); chan->max_power = mt76x02_get_max_rate_power(&t) + - target_power; - chan->max_power /= 2; + txp.target_power; + chan->max_power = DIV_ROUND_UP(chan->max_power, 2); /* convert to combined output power on 2x2 devices */ chan->max_power += 3; + chan->orig_mpwr = chan->max_power; } } EXPORT_SYMBOL_GPL(mt76x2_init_txpower); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h index 6c619f1c65c9..d7abe3d73bad 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h @@ -71,6 +71,7 @@ int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level, void mt76x2_cleanup(struct mt76x02_dev *dev); +int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard); void mt76x2_reset_wlan(struct mt76x02_dev *dev, bool enable); void mt76x2_init_txpower(struct mt76x02_dev *dev, struct ieee80211_supported_band *sband); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c index 6274655e1f7e..e84d5c5911ea 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c @@ -32,6 +32,7 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct mt76_driver_ops drv_ops = { .txwi_size = sizeof(struct mt76x02_txwi), + .tx_aligned4_skbs = true, .update_survey = mt76x02_update_channel, .tx_prepare_skb = mt76x02_tx_prepare_skb, .tx_complete_skb = mt76x02_tx_complete_skb, @@ -106,7 +107,7 @@ mt76pci_remove(struct pci_dev *pdev) mt76_unregister_device(mdev); mt76x2_cleanup(dev); - ieee80211_free_hw(mdev->hw); + mt76_free_device(mdev); } MODULE_DEVICE_TABLE(pci, mt76pci_device_table); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index 984d9c4c2e1a..71aea2832644 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -77,7 +77,7 @@ mt76x2_fixup_xtal(struct mt76x02_dev *dev) } } -static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard) +int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard) { const u8 *macaddr = dev->mt76.macaddr; u32 val; @@ -120,7 +120,7 @@ static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard) mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN); mt76x02_mac_setaddr(dev, macaddr); - mt76x02_init_beacon_config(dev); + mt76x02e_init_beacon_config(dev); if (!hard) return 0; @@ -291,7 +291,7 @@ static int mt76x2_init_hardware(struct mt76x02_dev *dev) void mt76x2_stop_hardware(struct mt76x02_dev *dev) { cancel_delayed_work_sync(&dev->cal_work); - cancel_delayed_work_sync(&dev->mac_work); + cancel_delayed_work_sync(&dev->mt76.mac_work); cancel_delayed_work_sync(&dev->wdt_work); mt76x02_mcu_set_radio_state(dev, false); mt76x2_mac_stop(dev, false); @@ -300,7 +300,7 @@ void mt76x2_stop_hardware(struct mt76x02_dev *dev) void mt76x2_cleanup(struct mt76x02_dev *dev) { tasklet_disable(&dev->dfs_pd.dfs_tasklet); - tasklet_disable(&dev->pre_tbtt_tasklet); + tasklet_disable(&dev->mt76.pre_tbtt_tasklet); mt76x2_stop_hardware(dev); mt76x02_dma_cleanup(dev); mt76x02_mcu_cleanup(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index 878ce92405ed..e416eee6a306 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -22,26 +22,21 @@ mt76x2_start(struct ieee80211_hw *hw) struct mt76x02_dev *dev = hw->priv; int ret; - mutex_lock(&dev->mt76.mutex); - ret = mt76x2_mac_start(dev); if (ret) - goto out; + return ret; ret = mt76x2_phy_start(dev); if (ret) - goto out; + return ret; - ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, MT_MAC_WORK_INTERVAL); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work, MT_WATCHDOG_TIME); set_bit(MT76_STATE_RUNNING, &dev->mt76.state); - -out: - mutex_unlock(&dev->mt76.mutex); - return ret; + return 0; } static void @@ -49,10 +44,8 @@ mt76x2_stop(struct ieee80211_hw *hw) { struct mt76x02_dev *dev = hw->priv; - mutex_lock(&dev->mt76.mutex); clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); mt76x2_stop_hardware(dev); - mutex_unlock(&dev->mt76.mutex); } static int @@ -66,7 +59,7 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) mt76_set_channel(&dev->mt76); - tasklet_disable(&dev->pre_tbtt_tasklet); + tasklet_disable(&dev->mt76.pre_tbtt_tasklet); tasklet_disable(&dev->dfs_pd.dfs_tasklet); mt76x2_mac_stop(dev, true); @@ -80,7 +73,7 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) mt76x2_mac_resume(dev); tasklet_enable(&dev->dfs_pd.dfs_tasklet); - tasklet_enable(&dev->pre_tbtt_tasklet); + tasklet_enable(&dev->mt76.pre_tbtt_tasklet); clear_bit(MT76_RESET, &dev->mt76.state); @@ -135,12 +128,6 @@ mt76x2_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { } -static int -mt76x2_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) -{ - return 0; -} - static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) { @@ -197,7 +184,7 @@ const struct ieee80211_ops mt76x2_ops = { .release_buffered_frames = mt76_release_buffered_frames, .set_coverage_class = mt76x02_set_coverage_class, .get_survey = mt76_get_survey, - .set_tim = mt76x2_set_tim, + .set_tim = mt76_set_tim, .set_antenna = mt76x2_set_antenna, .get_antenna = mt76x2_get_antenna, .set_rts_threshold = mt76x02_set_rts_threshold, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c index 03e24ae7f66c..605dc66ae83b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c @@ -165,9 +165,30 @@ error: return -ENOENT; } +static int +mt76pci_mcu_restart(struct mt76_dev *mdev) +{ + struct mt76x02_dev *dev; + int ret; + + dev = container_of(mdev, struct mt76x02_dev, mt76); + + mt76x02_mcu_cleanup(dev); + mt76x2_mac_reset(dev, true); + + ret = mt76pci_load_firmware(dev); + if (ret) + return ret; + + mt76_wr(dev, MT_WPDMA_RST_IDX, ~0); + + return 0; +} + int mt76x2_mcu_init(struct mt76x02_dev *dev) { static const struct mt76_mcu_ops mt76x2_mcu_ops = { + .mcu_restart = mt76pci_mcu_restart, .mcu_send_msg = mt76x02_mcu_msg_send, }; int ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c index 1848e8ab2e21..cdedf95ca4f5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c @@ -161,12 +161,12 @@ void mt76x2_phy_set_txpower(struct mt76x02_dev *dev) delta = txp.delta_bw80; mt76x2_get_rate_power(dev, &t, chan); - mt76x02_add_rate_power_offset(&t, txp.chain[0].target_power); + mt76x02_add_rate_power_offset(&t, txp.target_power + delta); mt76x02_limit_rate_power(&t, dev->mt76.txpower_conf); dev->mt76.txpower_cur = mt76x02_get_max_rate_power(&t); base_power = mt76x2_get_min_rate_power(&t); - delta += base_power - txp.chain[0].target_power; + delta = base_power - txp.target_power; txp_0 = txp.chain[0].target_power + txp.chain[0].delta + delta; txp_1 = txp.chain[1].target_power + txp.chain[1].delta + delta; @@ -182,7 +182,7 @@ void mt76x2_phy_set_txpower(struct mt76x02_dev *dev) } mt76x02_add_rate_power_offset(&t, -base_power); - dev->target_power = txp.chain[0].target_power; + dev->target_power = txp.target_power; dev->target_power_delta[0] = txp_0 - txp.chain[0].target_power; dev->target_power_delta[1] = txp_1 - txp.chain[0].target_power; dev->mt76.rate_power = t; @@ -260,10 +260,15 @@ mt76x2_phy_set_gain_val(struct mt76x02_dev *dev) gain_val[0] = dev->cal.agc_gain_cur[0] - dev->cal.agc_gain_adjust; gain_val[1] = dev->cal.agc_gain_cur[1] - dev->cal.agc_gain_adjust; - if (dev->mt76.chandef.width >= NL80211_CHAN_WIDTH_40) + val = 0x1836 << 16; + if (!mt76x2_has_ext_lna(dev) && + dev->mt76.chandef.width >= NL80211_CHAN_WIDTH_40) val = 0x1e42 << 16; - else - val = 0x1836 << 16; + + if (mt76x2_has_ext_lna(dev) && + dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ && + dev->mt76.chandef.width < NL80211_CHAN_WIDTH_40) + val = 0x0f36 << 16; val |= 0xf8; @@ -280,6 +285,7 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) { u8 *gain = dev->cal.agc_gain_init; u8 low_gain_delta, gain_delta; + u32 agc_35, agc_37; bool gain_change; int low_gain; u32 val; @@ -318,6 +324,16 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) else low_gain_delta = 14; + agc_37 = 0x2121262c; + if (dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ) + agc_35 = 0x11111516; + else if (low_gain == 2) + agc_35 = agc_37 = 0x08080808; + else if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_80) + agc_35 = 0x10101014; + else + agc_35 = 0x11111116; + if (low_gain == 2) { mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a990); mt76_wr(dev, MT_BBP(AGC, 35), 0x08080808); @@ -326,15 +342,13 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) dev->cal.agc_gain_adjust = 0; } else { mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a991); - if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_80) - mt76_wr(dev, MT_BBP(AGC, 35), 0x10101014); - else - mt76_wr(dev, MT_BBP(AGC, 35), 0x11111116); - mt76_wr(dev, MT_BBP(AGC, 37), 0x2121262C); gain_delta = 0; dev->cal.agc_gain_adjust = low_gain_delta; } + mt76_wr(dev, MT_BBP(AGC, 35), agc_35); + mt76_wr(dev, MT_BBP(AGC, 37), agc_37); + dev->cal.agc_gain_cur[0] = gain[0] - gain_delta; dev->cal.agc_gain_cur[1] = gain[1] - gain_delta; mt76x2_phy_set_gain_val(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index ddb6b2c48e01..7a994a783510 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c @@ -21,11 +21,10 @@ #include "mt76x2u.h" static const struct usb_device_id mt76x2u_device_table[] = { - { USB_DEVICE(0x0e8d, 0x7612) }, /* Alfa AWUS036ACM */ { USB_DEVICE(0x0b05, 0x1833) }, /* Asus USB-AC54 */ { USB_DEVICE(0x0b05, 0x17eb) }, /* Asus USB-AC55 */ { USB_DEVICE(0x0b05, 0x180b) }, /* Asus USB-N53 B1 */ - { USB_DEVICE(0x0e8d, 0x7612) }, /* Aukey USB-AC1200 */ + { USB_DEVICE(0x0e8d, 0x7612) }, /* Aukey USBAC1200 - Alfa AWUS036ACM */ { USB_DEVICE(0x057c, 0x8503) }, /* Avm FRITZ!WLAN AC860 */ { USB_DEVICE(0x7392, 0xb711) }, /* Edimax EW 7722 UAC */ { USB_DEVICE(0x0846, 0x9053) }, /* Netgear A6210 */ @@ -41,6 +40,7 @@ static int mt76x2u_probe(struct usb_interface *intf, .tx_complete_skb = mt76x02u_tx_complete_skb, .tx_status_data = mt76x02_tx_status_data, .rx_skb = mt76x02_queue_rx_skb, + .sta_ps = mt76x02_sta_ps, .sta_add = mt76x02_sta_add, .sta_remove = mt76x02_sta_remove, }; @@ -49,7 +49,7 @@ static int mt76x2u_probe(struct usb_interface *intf, struct mt76_dev *mdev; int err; - mdev = mt76_alloc_device(&intf->dev, sizeof(*dev), &mt76x2u_ops, + mdev = mt76_alloc_device(&udev->dev, sizeof(*dev), &mt76x2u_ops, &drv_ops); if (!mdev) return -ENOMEM; @@ -59,6 +59,8 @@ static int mt76x2u_probe(struct usb_interface *intf, udev = usb_get_dev(udev); usb_reset_device(udev); + usb_set_intfdata(intf, dev); + mt76x02u_init_mcu(mdev); err = mt76u_init(mdev, intf); if (err < 0) @@ -66,6 +68,10 @@ static int mt76x2u_probe(struct usb_interface *intf, mdev->rev = mt76_rr(dev, MT_ASIC_VERSION); dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev); + if (!is_mt76x2(dev)) { + err = -ENODEV; + goto err; + } err = mt76x2u_register_device(dev); if (err < 0) @@ -101,8 +107,7 @@ static int __maybe_unused mt76x2u_suspend(struct usb_interface *intf, { struct mt76x02_dev *dev = usb_get_intfdata(intf); - mt76u_stop_queues(&dev->mt76); - mt76x2u_stop_hw(dev); + mt76u_stop_rx(&dev->mt76); return 0; } @@ -110,16 +115,12 @@ static int __maybe_unused mt76x2u_suspend(struct usb_interface *intf, static int __maybe_unused mt76x2u_resume(struct usb_interface *intf) { struct mt76x02_dev *dev = usb_get_intfdata(intf); - struct mt76_usb *usb = &dev->mt76.usb; int err; - err = mt76u_submit_rx_buffers(&dev->mt76); + err = mt76u_resume_rx(&dev->mt76); if (err < 0) goto err; - tasklet_enable(&usb->rx_tasklet); - tasklet_enable(&usb->tx_tasklet); - err = mt76x2u_init_hardware(dev); if (err < 0) goto err; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index 1da90e58d942..f2c57d5b87f9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -183,7 +183,7 @@ int mt76x2u_init_hardware(struct mt76x02_dev *dev) mt76x02_mac_shared_key_setup(dev, i, k, NULL); } - mt76x02_init_beacon_config(dev); + mt76x02u_init_beacon_config(dev); mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e); mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x583f); @@ -244,9 +244,8 @@ fail: void mt76x2u_stop_hw(struct mt76x02_dev *dev) { - mt76u_stop_stat_wk(&dev->mt76); cancel_delayed_work_sync(&dev->cal_work); - cancel_delayed_work_sync(&dev->mac_work); + cancel_delayed_work_sync(&dev->mt76.mac_work); mt76x2u_mac_stop(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c index 5e84b4535cb1..3b82345756ea 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c @@ -93,7 +93,6 @@ int mt76x2u_mac_reset(struct mt76x02_dev *dev) mt76_wr(dev, MT_TX_LINK_CFG, 0x1020); mt76_wr(dev, MT_AUTO_RSP_CFG, 0x13); mt76_wr(dev, MT_MAX_LEN_CFG, 0x2f00); - mt76_wr(dev, MT_TX_RTS_CFG, 0x92b20); mt76_wr(dev, MT_WMM_AIFSN, 0x2273); mt76_wr(dev, MT_WMM_CWMIN, 0x2344); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 2ac78e4dc41a..97bcf6494ec1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -21,29 +21,24 @@ static int mt76x2u_start(struct ieee80211_hw *hw) struct mt76x02_dev *dev = hw->priv; int ret; - mutex_lock(&dev->mt76.mutex); - ret = mt76x2u_mac_start(dev); if (ret) - goto out; + return ret; - ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, MT_MAC_WORK_INTERVAL); set_bit(MT76_STATE_RUNNING, &dev->mt76.state); -out: - mutex_unlock(&dev->mt76.mutex); - return ret; + return 0; } static void mt76x2u_stop(struct ieee80211_hw *hw) { struct mt76x02_dev *dev = hw->priv; - mutex_lock(&dev->mt76.mutex); clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + mt76u_stop_tx(&dev->mt76); mt76x2u_stop_hw(dev); - mutex_unlock(&dev->mt76.mutex); } static int @@ -57,6 +52,8 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, mt76_set_channel(&dev->mt76); + dev->beacon_ops->pre_tbtt_enable(dev, false); + mt76x2_mac_stop(dev, false); err = mt76x2u_phy_set_channel(dev, chandef); @@ -64,6 +61,8 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, mt76x2_mac_resume(dev); mt76x02_edcca_init(dev, true); + dev->beacon_ops->pre_tbtt_enable(dev, true); + clear_bit(MT76_RESET, &dev->mt76.state); mt76_txq_schedule_all(&dev->mt76); @@ -125,4 +124,6 @@ const struct ieee80211_ops mt76x2u_ops = { .sw_scan_complete = mt76x02_sw_scan_complete, .sta_rate_tbl_update = mt76x02_sta_rate_tbl_update, .get_txpower = mt76_get_txpower, + .set_tim = mt76_set_tim, + .release_buffered_frames = mt76_release_buffered_frames, }; diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 5a349fe3e576..5397827668b9 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -21,15 +21,17 @@ mt76_alloc_txwi(struct mt76_dev *dev) { struct mt76_txwi_cache *t; dma_addr_t addr; + u8 *txwi; int size; - size = (sizeof(*t) + L1_CACHE_BYTES - 1) & ~(L1_CACHE_BYTES - 1); - t = devm_kzalloc(dev->dev, size, GFP_ATOMIC); - if (!t) + size = L1_CACHE_ALIGN(dev->drv->txwi_size + sizeof(*t)); + txwi = devm_kzalloc(dev->dev, size, GFP_ATOMIC); + if (!txwi) return NULL; - addr = dma_map_single(dev->dev, &t->txwi, sizeof(t->txwi), + addr = dma_map_single(dev->dev, txwi, dev->drv->txwi_size, DMA_TO_DEVICE); + t = (struct mt76_txwi_cache *)(txwi + dev->drv->txwi_size); t->dma_addr = addr; return t; @@ -72,13 +74,14 @@ mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t) list_add(&t->list, &dev->txwi_cache); spin_unlock_bh(&dev->lock); } +EXPORT_SYMBOL_GPL(mt76_put_txwi); void mt76_tx_free(struct mt76_dev *dev) { struct mt76_txwi_cache *t; while ((t = __mt76_get_txwi(dev)) != NULL) - dma_unmap_single(dev->dev, t->dma_addr, sizeof(t->txwi), + dma_unmap_single(dev->dev, t->dma_addr, dev->drv->txwi_size, DMA_TO_DEVICE); } @@ -266,7 +269,7 @@ mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, skb_set_queue_mapping(skb, qid); } - if (!wcid->tx_rate_set) + if (!(wcid->tx_info & MT_WCID_TX_INFO_SET)) ieee80211_get_tx_rates(info->control.vif, sta, skb, info->control.rates, 1); @@ -283,14 +286,17 @@ mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, mt76_check_agg_ssn(mtxq, skb); } - q = &dev->q_tx[qid]; + q = dev->q_tx[qid].q; spin_lock_bh(&q->lock); - dev->queue_ops->tx_queue_skb(dev, q, skb, wcid, sta); + dev->queue_ops->tx_queue_skb(dev, qid, skb, wcid, sta); dev->queue_ops->kick(dev, q); - if (q->queued > q->ndesc - 8) + if (q->queued > q->ndesc - 8 && !q->stopped) { ieee80211_stop_queue(dev->hw, skb_get_queue_mapping(skb)); + q->stopped = true; + } + spin_unlock_bh(&q->lock); } EXPORT_SYMBOL_GPL(mt76_tx); @@ -324,7 +330,6 @@ mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta, { struct mt76_wcid *wcid = (struct mt76_wcid *) sta->drv_priv; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct mt76_queue *hwq = &dev->q_tx[MT_TXQ_PSD]; info->control.flags |= IEEE80211_TX_CTRL_PS_RESPONSE; if (last) @@ -332,7 +337,7 @@ mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta, IEEE80211_TX_CTL_REQ_TX_STATUS; mt76_skb_set_moredata(skb, !last); - dev->queue_ops->tx_queue_skb(dev, hwq, skb, wcid, sta); + dev->queue_ops->tx_queue_skb(dev, MT_TXQ_PSD, skb, wcid, sta); } void @@ -343,7 +348,7 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta, { struct mt76_dev *dev = hw->priv; struct sk_buff *last_skb = NULL; - struct mt76_queue *hwq = &dev->q_tx[MT_TXQ_PSD]; + struct mt76_queue *hwq = dev->q_tx[MT_TXQ_PSD].q; int i; spin_lock_bh(&hwq->lock); @@ -374,18 +379,23 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta, if (last_skb) { mt76_queue_ps_skb(dev, sta, last_skb, true); dev->queue_ops->kick(dev, hwq); + } else { + ieee80211_sta_eosp(sta); } + spin_unlock_bh(&hwq->lock); } EXPORT_SYMBOL_GPL(mt76_release_buffered_frames); static int -mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_queue *hwq, +mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_sw_queue *sq, struct mt76_txq *mtxq, bool *empty) { struct ieee80211_txq *txq = mtxq_to_txq(mtxq); - struct ieee80211_tx_info *info; + enum mt76_txq_id qid = mt76_txq_get_qid(txq); struct mt76_wcid *wcid = mtxq->wcid; + struct mt76_queue *hwq = sq->q; + struct ieee80211_tx_info *info; struct sk_buff *skb; int n_frames = 1, limit; struct ieee80211_tx_rate tx_rate; @@ -405,7 +415,7 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_queue *hwq, } info = IEEE80211_SKB_CB(skb); - if (!wcid->tx_rate_set) + if (!(wcid->tx_info & MT_WCID_TX_INFO_SET)) ieee80211_get_tx_rates(txq->vif, txq->sta, skb, info->control.rates, 1); tx_rate = info->control.rates[0]; @@ -417,7 +427,7 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_queue *hwq, if (ampdu) mt76_check_agg_ssn(mtxq, skb); - idx = dev->queue_ops->tx_queue_skb(dev, hwq, skb, wcid, txq->sta); + idx = dev->queue_ops->tx_queue_skb(dev, qid, skb, wcid, txq->sta); if (idx < 0) return idx; @@ -452,7 +462,7 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_queue *hwq, if (cur_ampdu) mt76_check_agg_ssn(mtxq, skb); - idx = dev->queue_ops->tx_queue_skb(dev, hwq, skb, wcid, + idx = dev->queue_ops->tx_queue_skb(dev, qid, skb, wcid, txq->sta); if (idx < 0) return idx; @@ -461,8 +471,9 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_queue *hwq, } while (n_frames < limit); if (!probe) { - hwq->swq_queued++; + hwq->entry[idx].qid = sq - dev->q_tx; hwq->entry[idx].schedule = true; + sq->swq_queued++; } dev->queue_ops->kick(dev, hwq); @@ -471,22 +482,37 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_queue *hwq, } static int -mt76_txq_schedule_list(struct mt76_dev *dev, struct mt76_queue *hwq) +mt76_txq_schedule_list(struct mt76_dev *dev, enum mt76_txq_id qid) { - struct mt76_txq *mtxq, *mtxq_last; - int len = 0; + struct mt76_sw_queue *sq = &dev->q_tx[qid]; + struct mt76_queue *hwq = sq->q; + struct ieee80211_txq *txq; + struct mt76_txq *mtxq; + struct mt76_wcid *wcid; + int ret = 0; -restart: - mtxq_last = list_last_entry(&hwq->swq, struct mt76_txq, list); - while (!list_empty(&hwq->swq)) { + spin_lock_bh(&hwq->lock); + while (1) { bool empty = false; - int cur; + + if (sq->swq_queued >= 4) + break; if (test_bit(MT76_OFFCHANNEL, &dev->state) || - test_bit(MT76_RESET, &dev->state)) - return -EBUSY; + test_bit(MT76_RESET, &dev->state)) { + ret = -EBUSY; + break; + } + + txq = ieee80211_next_txq(dev->hw, qid); + if (!txq) + break; + + mtxq = (struct mt76_txq *)txq->drv_priv; + wcid = mtxq->wcid; + if (wcid && test_bit(MT_WCID_FLAG_PS, &wcid->flags)) + continue; - mtxq = list_first_entry(&hwq->swq, struct mt76_txq, list); if (mtxq->send_bar && mtxq->aggr) { struct ieee80211_txq *txq = mtxq_to_txq(mtxq); struct ieee80211_sta *sta = txq->sta; @@ -498,38 +524,37 @@ restart: spin_unlock_bh(&hwq->lock); ieee80211_send_bar(vif, sta->addr, tid, agg_ssn); spin_lock_bh(&hwq->lock); - goto restart; } - list_del_init(&mtxq->list); - - cur = mt76_txq_send_burst(dev, hwq, mtxq, &empty); - if (!empty) - list_add_tail(&mtxq->list, &hwq->swq); - - if (cur < 0) - return cur; - - len += cur; - - if (mtxq == mtxq_last) - break; + ret += mt76_txq_send_burst(dev, sq, mtxq, &empty); + if (skb_queue_empty(&mtxq->retry_q)) + empty = true; + ieee80211_return_txq(dev->hw, txq, !empty); } + spin_unlock_bh(&hwq->lock); - return len; + return ret; } -void mt76_txq_schedule(struct mt76_dev *dev, struct mt76_queue *hwq) +void mt76_txq_schedule(struct mt76_dev *dev, enum mt76_txq_id qid) { + struct mt76_sw_queue *sq = &dev->q_tx[qid]; int len; + if (qid >= 4) + return; + + if (sq->swq_queued >= 4) + return; + rcu_read_lock(); - do { - if (hwq->swq_queued >= 4 || list_empty(&hwq->swq)) - break; - len = mt76_txq_schedule_list(dev, hwq); + do { + ieee80211_txq_schedule_start(dev->hw, qid); + len = mt76_txq_schedule_list(dev, qid); + ieee80211_txq_schedule_end(dev->hw, qid); } while (len > 0); + rcu_read_unlock(); } EXPORT_SYMBOL_GPL(mt76_txq_schedule); @@ -538,13 +563,8 @@ void mt76_txq_schedule_all(struct mt76_dev *dev) { int i; - for (i = 0; i <= MT_TXQ_BK; i++) { - struct mt76_queue *q = &dev->q_tx[i]; - - spin_lock_bh(&q->lock); - mt76_txq_schedule(dev, q); - spin_unlock_bh(&q->lock); - } + for (i = 0; i <= MT_TXQ_BK; i++) + mt76_txq_schedule(dev, i); } EXPORT_SYMBOL_GPL(mt76_txq_schedule_all); @@ -555,18 +575,18 @@ void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta, for (i = 0; i < ARRAY_SIZE(sta->txq); i++) { struct ieee80211_txq *txq = sta->txq[i]; + struct mt76_queue *hwq; struct mt76_txq *mtxq; if (!txq) continue; mtxq = (struct mt76_txq *)txq->drv_priv; + hwq = mtxq->swq->q; - spin_lock_bh(&mtxq->hwq->lock); + spin_lock_bh(&hwq->lock); mtxq->send_bar = mtxq->aggr && send_bar; - if (!list_empty(&mtxq->list)) - list_del_init(&mtxq->list); - spin_unlock_bh(&mtxq->hwq->lock); + spin_unlock_bh(&hwq->lock); } } EXPORT_SYMBOL_GPL(mt76_stop_tx_queues); @@ -574,33 +594,23 @@ EXPORT_SYMBOL_GPL(mt76_stop_tx_queues); void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq) { struct mt76_dev *dev = hw->priv; - struct mt76_txq *mtxq = (struct mt76_txq *) txq->drv_priv; - struct mt76_queue *hwq = mtxq->hwq; - spin_lock_bh(&hwq->lock); - if (list_empty(&mtxq->list)) - list_add_tail(&mtxq->list, &hwq->swq); - mt76_txq_schedule(dev, hwq); - spin_unlock_bh(&hwq->lock); + if (!test_bit(MT76_STATE_RUNNING, &dev->state)) + return; + + tasklet_schedule(&dev->tx_tasklet); } EXPORT_SYMBOL_GPL(mt76_wake_tx_queue); void mt76_txq_remove(struct mt76_dev *dev, struct ieee80211_txq *txq) { struct mt76_txq *mtxq; - struct mt76_queue *hwq; struct sk_buff *skb; if (!txq) return; mtxq = (struct mt76_txq *) txq->drv_priv; - hwq = mtxq->hwq; - - spin_lock_bh(&hwq->lock); - if (!list_empty(&mtxq->list)) - list_del_init(&mtxq->list); - spin_unlock_bh(&hwq->lock); while ((skb = skb_dequeue(&mtxq->retry_q)) != NULL) ieee80211_free_txskb(dev->hw, skb); @@ -611,10 +621,9 @@ void mt76_txq_init(struct mt76_dev *dev, struct ieee80211_txq *txq) { struct mt76_txq *mtxq = (struct mt76_txq *) txq->drv_priv; - INIT_LIST_HEAD(&mtxq->list); skb_queue_head_init(&mtxq->retry_q); - mtxq->hwq = &dev->q_tx[mt76_txq_get_qid(txq)]; + mtxq->swq = &dev->q_tx[mt76_txq_get_qid(txq)]; } EXPORT_SYMBOL_GPL(mt76_txq_init); diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index ae6ada370597..bbaa1365bbda 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -31,8 +31,7 @@ static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type, u16 val, u16 offset, void *buf, size_t len) { - struct usb_interface *intf = to_usb_interface(dev->dev); - struct usb_device *udev = interface_to_usbdev(intf); + struct usb_device *udev = to_usb_device(dev->dev); unsigned int pipe; int i, ret; @@ -247,8 +246,7 @@ mt76u_rd_rp(struct mt76_dev *dev, u32 base, static bool mt76u_check_sg(struct mt76_dev *dev) { - struct usb_interface *intf = to_usb_interface(dev->dev); - struct usb_device *udev = interface_to_usbdev(intf); + struct usb_device *udev = to_usb_device(dev->dev); return (!disable_usb_sg && udev->bus->sg_tablesize > 0 && (udev->bus->no_sg_constraint || @@ -285,28 +283,24 @@ mt76u_set_endpoints(struct usb_interface *intf, } static int -mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf, - int nsgs, int len, int sglen) +mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue *q, struct urb *urb, + int nsgs, gfp_t gfp) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; - struct urb *urb = buf->urb; int i; - spin_lock_bh(&q->rx_page_lock); for (i = 0; i < nsgs; i++) { struct page *page; void *data; int offset; - data = page_frag_alloc(&q->rx_page, len, GFP_ATOMIC); + data = page_frag_alloc(&q->rx_page, q->buf_size, gfp); if (!data) break; page = virt_to_head_page(data); offset = data - page_address(page); - sg_set_page(&urb->sg[i], page, sglen, offset); + sg_set_page(&urb->sg[i], page, q->buf_size, offset); } - spin_unlock_bh(&q->rx_page_lock); if (i < nsgs) { int j; @@ -317,72 +311,78 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf, } urb->num_sgs = max_t(int, i, urb->num_sgs); - buf->len = urb->num_sgs * sglen, + urb->transfer_buffer_length = urb->num_sgs * q->buf_size, sg_init_marker(urb->sg, urb->num_sgs); return i ? : -ENOMEM; } static int -mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q, - struct mt76u_buf *buf, int nsgs, gfp_t gfp) +mt76u_refill_rx(struct mt76_dev *dev, struct urb *urb, int nsgs, gfp_t gfp) { + struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + if (dev->usb.sg_en) { - return mt76u_fill_rx_sg(dev, buf, nsgs, q->buf_size, - SKB_WITH_OVERHEAD(q->buf_size)); + return mt76u_fill_rx_sg(dev, q, urb, nsgs, gfp); } else { - buf->buf = page_frag_alloc(&q->rx_page, q->buf_size, gfp); - return buf->buf ? 0 : -ENOMEM; + urb->transfer_buffer_length = q->buf_size; + urb->transfer_buffer = page_frag_alloc(&q->rx_page, + q->buf_size, gfp); + return urb->transfer_buffer ? 0 : -ENOMEM; } } static int -mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf) +mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + unsigned int size = sizeof(struct urb); - buf->len = SKB_WITH_OVERHEAD(q->buf_size); - buf->dev = dev; + if (dev->usb.sg_en) + size += MT_SG_MAX_SIZE * sizeof(struct scatterlist); - buf->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!buf->urb) + e->urb = kzalloc(size, GFP_KERNEL); + if (!e->urb) return -ENOMEM; - if (dev->usb.sg_en) { - buf->urb->sg = devm_kcalloc(dev->dev, MT_SG_MAX_SIZE, - sizeof(*buf->urb->sg), - GFP_KERNEL); - if (!buf->urb->sg) - return -ENOMEM; + usb_init_urb(e->urb); - sg_init_table(buf->urb->sg, MT_SG_MAX_SIZE); - } + if (dev->usb.sg_en) + e->urb->sg = (struct scatterlist *)(e->urb + 1); + + return 0; +} + +static int +mt76u_rx_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e) +{ + int err; + + err = mt76u_urb_alloc(dev, e); + if (err) + return err; - return mt76u_refill_rx(dev, q, buf, MT_SG_MAX_SIZE, GFP_KERNEL); + return mt76u_refill_rx(dev, e->urb, MT_SG_MAX_SIZE, GFP_KERNEL); } -static void mt76u_buf_free(struct mt76u_buf *buf) +static void mt76u_urb_free(struct urb *urb) { - struct urb *urb = buf->urb; int i; for (i = 0; i < urb->num_sgs; i++) skb_free_frag(sg_virt(&urb->sg[i])); - if (buf->buf) - skb_free_frag(buf->buf); + if (urb->transfer_buffer) + skb_free_frag(urb->transfer_buffer); - usb_free_urb(buf->urb); + usb_free_urb(urb); } static void mt76u_fill_bulk_urb(struct mt76_dev *dev, int dir, int index, - struct mt76u_buf *buf, usb_complete_t complete_fn, + struct urb *urb, usb_complete_t complete_fn, void *context) { - struct usb_interface *intf = to_usb_interface(dev->dev); - struct usb_device *udev = interface_to_usbdev(intf); - u8 *data = buf->urb->num_sgs ? NULL : buf->buf; + struct usb_device *udev = to_usb_device(dev->dev); unsigned int pipe; if (dir == USB_DIR_IN) @@ -390,37 +390,28 @@ mt76u_fill_bulk_urb(struct mt76_dev *dev, int dir, int index, else pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[index]); - usb_fill_bulk_urb(buf->urb, udev, pipe, data, buf->len, - complete_fn, context); -} - -static int -mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, - struct mt76u_buf *buf, gfp_t gfp, - usb_complete_t complete_fn, void *context) -{ - mt76u_fill_bulk_urb(dev, dir, index, buf, complete_fn, - context); - trace_submit_urb(dev, buf->urb); - - return usb_submit_urb(buf->urb, gfp); + urb->dev = udev; + urb->pipe = pipe; + urb->complete = complete_fn; + urb->context = context; } -static inline struct mt76u_buf -*mt76u_get_next_rx_entry(struct mt76_queue *q) +static inline struct urb * +mt76u_get_next_rx_entry(struct mt76_dev *dev) { - struct mt76u_buf *buf = NULL; + struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + struct urb *urb = NULL; unsigned long flags; spin_lock_irqsave(&q->lock, flags); if (q->queued > 0) { - buf = &q->entry[q->head].ubuf; + urb = q->entry[q->head].urb; q->head = (q->head + 1) % q->ndesc; q->queued--; } spin_unlock_irqrestore(&q->lock, flags); - return buf; + return urb; } static int mt76u_get_rx_entry_len(u8 *data, u32 data_len) @@ -439,12 +430,12 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len) } static int -mt76u_process_rx_entry(struct mt76_dev *dev, struct mt76u_buf *buf) +mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) { struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; - struct urb *urb = buf->urb; - u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : buf->buf; - int data_len, len, nsgs = 1; + u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : urb->transfer_buffer; + int data_len = urb->num_sgs ? urb->sg[0].length : urb->actual_length; + int len, nsgs = 1; struct sk_buff *skb; if (!test_bit(MT76_STATE_INITIALIZED, &dev->state)) @@ -454,10 +445,11 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct mt76u_buf *buf) if (len < 0) return 0; - data_len = urb->num_sgs ? urb->sg[0].length : buf->len; data_len = min_t(int, len, data_len - MT_DMA_HDR_LEN); - if (MT_DMA_HDR_LEN + data_len > SKB_WITH_OVERHEAD(q->buf_size)) + if (MT_DMA_HDR_LEN + data_len > SKB_WITH_OVERHEAD(q->buf_size)) { + dev_err_ratelimited(dev->dev, "rx data too big %d\n", data_len); return 0; + } skb = build_skb(data, q->buf_size); if (!skb) @@ -503,7 +495,7 @@ static void mt76u_complete_rx(struct urb *urb) } spin_lock_irqsave(&q->lock, flags); - if (WARN_ONCE(q->entry[q->tail].ubuf.urb != urb, "rx urb mismatch")) + if (WARN_ONCE(q->entry[q->tail].urb != urb, "rx urb mismatch")) goto out; q->tail = (q->tail + 1) % q->ndesc; @@ -513,37 +505,43 @@ out: spin_unlock_irqrestore(&q->lock, flags); } +static int +mt76u_submit_rx_buf(struct mt76_dev *dev, struct urb *urb) +{ + mt76u_fill_bulk_urb(dev, USB_DIR_IN, MT_EP_IN_PKT_RX, urb, + mt76u_complete_rx, dev); + trace_submit_urb(dev, urb); + + return usb_submit_urb(urb, GFP_ATOMIC); +} + static void mt76u_rx_tasklet(unsigned long data) { struct mt76_dev *dev = (struct mt76_dev *)data; - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; - struct mt76u_buf *buf; + struct urb *urb; int err, count; rcu_read_lock(); while (true) { - buf = mt76u_get_next_rx_entry(q); - if (!buf) + urb = mt76u_get_next_rx_entry(dev); + if (!urb) break; - count = mt76u_process_rx_entry(dev, buf); + count = mt76u_process_rx_entry(dev, urb); if (count > 0) { - err = mt76u_refill_rx(dev, q, buf, count, - GFP_ATOMIC); + err = mt76u_refill_rx(dev, urb, count, GFP_ATOMIC); if (err < 0) break; } - mt76u_submit_buf(dev, USB_DIR_IN, MT_EP_IN_PKT_RX, - buf, GFP_ATOMIC, - mt76u_complete_rx, dev); + mt76u_submit_rx_buf(dev, urb); } mt76_rx_poll_complete(dev, MT_RXQ_MAIN, NULL); rcu_read_unlock(); } -int mt76u_submit_rx_buffers(struct mt76_dev *dev) +static int mt76u_submit_rx_buffers(struct mt76_dev *dev) { struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; unsigned long flags; @@ -551,9 +549,7 @@ int mt76u_submit_rx_buffers(struct mt76_dev *dev) spin_lock_irqsave(&q->lock, flags); for (i = 0; i < q->ndesc; i++) { - err = mt76u_submit_buf(dev, USB_DIR_IN, MT_EP_IN_PKT_RX, - &q->entry[i].ubuf, GFP_ATOMIC, - mt76u_complete_rx, dev); + err = mt76u_submit_rx_buf(dev, q->entry[i].urb); if (err < 0) break; } @@ -563,7 +559,6 @@ int mt76u_submit_rx_buffers(struct mt76_dev *dev) return err; } -EXPORT_SYMBOL_GPL(mt76u_submit_rx_buffers); static int mt76u_alloc_rx(struct mt76_dev *dev) { @@ -575,7 +570,6 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) if (!usb->mcu.data) return -ENOMEM; - spin_lock_init(&q->rx_page_lock); spin_lock_init(&q->lock); q->entry = devm_kcalloc(dev->dev, MT_NUM_RX_ENTRIES, sizeof(*q->entry), @@ -586,7 +580,7 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE; q->ndesc = MT_NUM_RX_ENTRIES; for (i = 0; i < q->ndesc; i++) { - err = mt76u_buf_alloc(dev, &q->entry[i].ubuf); + err = mt76u_rx_urb_alloc(dev, &q->entry[i]); if (err < 0) return err; } @@ -601,66 +595,88 @@ static void mt76u_free_rx(struct mt76_dev *dev) int i; for (i = 0; i < q->ndesc; i++) - mt76u_buf_free(&q->entry[i].ubuf); + mt76u_urb_free(q->entry[i].urb); - spin_lock_bh(&q->rx_page_lock); if (!q->rx_page.va) - goto out; + return; page = virt_to_page(q->rx_page.va); __page_frag_cache_drain(page, q->rx_page.pagecnt_bias); memset(&q->rx_page, 0, sizeof(q->rx_page)); -out: - spin_unlock_bh(&q->rx_page_lock); } -static void mt76u_stop_rx(struct mt76_dev *dev) +void mt76u_stop_rx(struct mt76_dev *dev) +{ + struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + int i; + + for (i = 0; i < q->ndesc; i++) + usb_poison_urb(q->entry[i].urb); + + tasklet_kill(&dev->usb.rx_tasklet); +} +EXPORT_SYMBOL_GPL(mt76u_stop_rx); + +int mt76u_resume_rx(struct mt76_dev *dev) { struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; int i; for (i = 0; i < q->ndesc; i++) - usb_kill_urb(q->entry[i].ubuf.urb); + usb_unpoison_urb(q->entry[i].urb); + + return mt76u_submit_rx_buffers(dev); } +EXPORT_SYMBOL_GPL(mt76u_resume_rx); static void mt76u_tx_tasklet(unsigned long data) { struct mt76_dev *dev = (struct mt76_dev *)data; struct mt76_queue_entry entry; - struct mt76u_buf *buf; + struct mt76_sw_queue *sq; struct mt76_queue *q; bool wake; int i; for (i = 0; i < IEEE80211_NUM_ACS; i++) { - q = &dev->q_tx[i]; + u32 n_dequeued = 0, n_sw_dequeued = 0; - spin_lock_bh(&q->lock); - while (true) { - buf = &q->entry[q->head].ubuf; - if (!buf->done || !q->queued) + sq = &dev->q_tx[i]; + q = sq->q; + + while (q->queued > n_dequeued) { + if (!q->entry[q->head].done) break; if (q->entry[q->head].schedule) { q->entry[q->head].schedule = false; - q->swq_queued--; + n_sw_dequeued++; } entry = q->entry[q->head]; + q->entry[q->head].done = false; q->head = (q->head + 1) % q->ndesc; - q->queued--; + n_dequeued++; - spin_unlock_bh(&q->lock); - dev->drv->tx_complete_skb(dev, q, &entry, false); - spin_lock_bh(&q->lock); + dev->drv->tx_complete_skb(dev, i, &entry); } - mt76_txq_schedule(dev, q); - wake = i < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8; + + spin_lock_bh(&q->lock); + + sq->swq_queued -= n_sw_dequeued; + q->queued -= n_dequeued; + + wake = q->stopped && q->queued < q->ndesc - 8; + if (wake) + q->stopped = false; + if (!q->queued) wake_up(&dev->tx_wait); spin_unlock_bh(&q->lock); + mt76_txq_schedule(dev, i); + if (!test_and_set_bit(MT76_READING_STATS, &dev->state)) ieee80211_queue_delayed_work(dev->hw, &dev->usb.stat_work, @@ -699,34 +715,43 @@ static void mt76u_tx_status_data(struct work_struct *work) static void mt76u_complete_tx(struct urb *urb) { - struct mt76u_buf *buf = urb->context; - struct mt76_dev *dev = buf->dev; + struct mt76_dev *dev = dev_get_drvdata(&urb->dev->dev); + struct mt76_queue_entry *e = urb->context; if (mt76u_urb_error(urb)) dev_err(dev->dev, "tx urb failed: %d\n", urb->status); - buf->done = true; + e->done = true; - tasklet_schedule(&dev->usb.tx_tasklet); + tasklet_schedule(&dev->tx_tasklet); } static int -mt76u_tx_build_sg(struct mt76_dev *dev, struct sk_buff *skb, - struct urb *urb) +mt76u_tx_setup_buffers(struct mt76_dev *dev, struct sk_buff *skb, + struct urb *urb) { - if (!dev->usb.sg_en) - return 0; + urb->transfer_buffer_length = skb->len; - sg_init_table(urb->sg, MT_SG_MAX_SIZE); - urb->num_sgs = skb_to_sgvec(skb, urb->sg, 0, skb->len); - return urb->num_sgs; + if (!dev->usb.sg_en) { + urb->transfer_buffer = skb->data; + return 0; + } else { + sg_init_table(urb->sg, MT_SG_MAX_SIZE); + urb->num_sgs = skb_to_sgvec(skb, urb->sg, 0, skb->len); + if (urb->num_sgs == 0) + return -ENOMEM; + return urb->num_sgs; + } } static int -mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, +mt76u_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta) { - struct mt76u_buf *buf; + struct mt76_queue *q = dev->q_tx[qid].q; + struct mt76_tx_info tx_info = { + .skb = skb, + }; u16 idx = q->tail; int err; @@ -734,24 +759,20 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, return -ENOSPC; skb->prev = skb->next = NULL; - err = dev->drv->tx_prepare_skb(dev, NULL, skb, q, wcid, sta, NULL); + err = dev->drv->tx_prepare_skb(dev, NULL, qid, wcid, sta, &tx_info); if (err < 0) return err; - buf = &q->entry[idx].ubuf; - buf->buf = skb->data; - buf->len = skb->len; - buf->done = false; - - err = mt76u_tx_build_sg(dev, skb, buf->urb); + err = mt76u_tx_setup_buffers(dev, tx_info.skb, q->entry[idx].urb); if (err < 0) return err; mt76u_fill_bulk_urb(dev, USB_DIR_OUT, q2ep(q->hw_idx), - buf, mt76u_complete_tx, buf); + q->entry[idx].urb, mt76u_complete_tx, + &q->entry[idx]); q->tail = (q->tail + 1) % q->ndesc; - q->entry[idx].skb = skb; + q->entry[idx].skb = tx_info.skb; q->queued++; return idx; @@ -759,14 +780,14 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, static void mt76u_tx_kick(struct mt76_dev *dev, struct mt76_queue *q) { - struct mt76u_buf *buf; + struct urb *urb; int err; while (q->first != q->tail) { - buf = &q->entry[q->first].ubuf; + urb = q->entry[q->first].urb; - trace_submit_urb(dev, buf->urb); - err = usb_submit_urb(buf->urb, GFP_ATOMIC); + trace_submit_urb(dev, urb); + err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { if (err == -ENODEV) set_bit(MT76_REMOVED, &dev->state); @@ -781,15 +802,24 @@ static void mt76u_tx_kick(struct mt76_dev *dev, struct mt76_queue *q) static int mt76u_alloc_tx(struct mt76_dev *dev) { - struct mt76u_buf *buf; struct mt76_queue *q; - int i, j; + int i, j, err; + + for (i = 0; i <= MT_TXQ_PSD; i++) { + INIT_LIST_HEAD(&dev->q_tx[i].swq); + + if (i >= IEEE80211_NUM_ACS) { + dev->q_tx[i].q = dev->q_tx[0].q; + continue; + } + + q = devm_kzalloc(dev->dev, sizeof(*q), GFP_KERNEL); + if (!q) + return -ENOMEM; - for (i = 0; i < IEEE80211_NUM_ACS; i++) { - q = &dev->q_tx[i]; spin_lock_init(&q->lock); - INIT_LIST_HEAD(&q->swq); q->hw_idx = mt76_ac_to_hwq(i); + dev->q_tx[i].q = q; q->entry = devm_kcalloc(dev->dev, MT_NUM_TX_ENTRIES, sizeof(*q->entry), @@ -799,22 +829,9 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) q->ndesc = MT_NUM_TX_ENTRIES; for (j = 0; j < q->ndesc; j++) { - buf = &q->entry[j].ubuf; - buf->dev = dev; - - buf->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!buf->urb) - return -ENOMEM; - - if (dev->usb.sg_en) { - size_t size = MT_SG_MAX_SIZE * - sizeof(struct scatterlist); - - buf->urb->sg = devm_kzalloc(dev->dev, size, - GFP_KERNEL); - if (!buf->urb->sg) - return -ENOMEM; - } + err = mt76u_urb_alloc(dev, &q->entry[j]); + if (err < 0) + return err; } } return 0; @@ -826,44 +843,60 @@ static void mt76u_free_tx(struct mt76_dev *dev) int i, j; for (i = 0; i < IEEE80211_NUM_ACS; i++) { - q = &dev->q_tx[i]; + q = dev->q_tx[i].q; for (j = 0; j < q->ndesc; j++) - usb_free_urb(q->entry[j].ubuf.urb); + usb_free_urb(q->entry[j].urb); } } -static void mt76u_stop_tx(struct mt76_dev *dev) +void mt76u_stop_tx(struct mt76_dev *dev) { + struct mt76_queue_entry entry; struct mt76_queue *q; - int i, j; + int i, j, ret; - for (i = 0; i < IEEE80211_NUM_ACS; i++) { - q = &dev->q_tx[i]; - for (j = 0; j < q->ndesc; j++) - usb_kill_urb(q->entry[j].ubuf.urb); - } -} + ret = wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(dev), HZ/5); + if (!ret) { + dev_err(dev->dev, "timed out waiting for pending tx\n"); -void mt76u_stop_queues(struct mt76_dev *dev) -{ - tasklet_disable(&dev->usb.rx_tasklet); - tasklet_disable(&dev->usb.tx_tasklet); + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + q = dev->q_tx[i].q; + for (j = 0; j < q->ndesc; j++) + usb_kill_urb(q->entry[j].urb); + } - mt76u_stop_rx(dev); - mt76u_stop_tx(dev); -} -EXPORT_SYMBOL_GPL(mt76u_stop_queues); + tasklet_kill(&dev->tx_tasklet); + + /* On device removal we maight queue skb's, but mt76u_tx_kick() + * will fail to submit urb, cleanup those skb's manually. + */ + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + q = dev->q_tx[i].q; + + /* Assure we are in sync with killed tasklet. */ + spin_lock_bh(&q->lock); + while (q->queued) { + entry = q->entry[q->head]; + q->head = (q->head + 1) % q->ndesc; + q->queued--; + + dev->drv->tx_complete_skb(dev, i, &entry); + } + spin_unlock_bh(&q->lock); + } + } -void mt76u_stop_stat_wk(struct mt76_dev *dev) -{ cancel_delayed_work_sync(&dev->usb.stat_work); clear_bit(MT76_READING_STATS, &dev->state); + + mt76_tx_status_check(dev, NULL, true); } -EXPORT_SYMBOL_GPL(mt76u_stop_stat_wk); +EXPORT_SYMBOL_GPL(mt76u_stop_tx); void mt76u_queues_deinit(struct mt76_dev *dev) { - mt76u_stop_queues(dev); + mt76u_stop_rx(dev); + mt76u_stop_tx(dev); mt76u_free_rx(dev); mt76u_free_tx(dev); @@ -902,7 +935,7 @@ int mt76u_init(struct mt76_dev *dev, struct mt76_usb *usb = &dev->usb; tasklet_init(&usb->rx_tasklet, mt76u_rx_tasklet, (unsigned long)dev); - tasklet_init(&usb->tx_tasklet, mt76u_tx_tasklet, (unsigned long)dev); + tasklet_init(&dev->tx_tasklet, mt76u_tx_tasklet, (unsigned long)dev); INIT_DELAYED_WORK(&usb->stat_work, mt76u_tx_status_data); skb_queue_head_init(&dev->rx_skb[MT_RXQ_MAIN]); diff --git a/drivers/net/wireless/mediatek/mt7601u/usb.c b/drivers/net/wireless/mediatek/mt7601u/usb.c index d8b7863f7926..6ae7f14dc9bf 100644 --- a/drivers/net/wireless/mediatek/mt7601u/usb.c +++ b/drivers/net/wireless/mediatek/mt7601u/usb.c @@ -303,6 +303,10 @@ static int mt7601u_probe(struct usb_interface *usb_intf, mac_rev = mt7601u_rr(dev, MT_MAC_CSR0); dev_info(dev->dev, "ASIC revision: %08x MAC revision: %08x\n", asic_rev, mac_rev); + if ((asic_rev >> 16) != 0x7601) { + ret = -ENODEV; + goto err; + } /* Note: vendor driver skips this check for MT7601U */ if (!(mt7601u_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL)) diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h b/drivers/net/wireless/quantenna/qtnfmac/bus.h index 14b569b6d1b5..7cea08f71838 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/bus.h +++ b/drivers/net/wireless/quantenna/qtnfmac/bus.h @@ -13,12 +13,11 @@ #define QTNF_MAX_MAC 3 enum qtnf_fw_state { - QTNF_FW_STATE_RESET, - QTNF_FW_STATE_FW_DNLD_DONE, + QTNF_FW_STATE_DETACHED, QTNF_FW_STATE_BOOT_DONE, QTNF_FW_STATE_ACTIVE, - QTNF_FW_STATE_DETACHED, - QTNF_FW_STATE_EP_DEAD, + QTNF_FW_STATE_RUNNING, + QTNF_FW_STATE_DEAD, }; struct qtnf_bus; @@ -50,6 +49,7 @@ struct qtnf_bus { struct napi_struct mux_napi; struct net_device mux_dev; struct workqueue_struct *workqueue; + struct workqueue_struct *hprio_workqueue; struct work_struct fw_work; struct work_struct event_work; struct mutex bus_lock; /* lock during command/event processing */ @@ -58,6 +58,23 @@ struct qtnf_bus { char bus_priv[0] __aligned(sizeof(void *)); }; +static inline bool qtnf_fw_is_up(struct qtnf_bus *bus) +{ + enum qtnf_fw_state state = bus->fw_state; + + return ((state == QTNF_FW_STATE_ACTIVE) || + (state == QTNF_FW_STATE_RUNNING)); +} + +static inline bool qtnf_fw_is_attached(struct qtnf_bus *bus) +{ + enum qtnf_fw_state state = bus->fw_state; + + return ((state == QTNF_FW_STATE_ACTIVE) || + (state == QTNF_FW_STATE_RUNNING) || + (state == QTNF_FW_STATE_DEAD)); +} + static inline void *get_bus_priv(struct qtnf_bus *bus) { if (WARN(!bus, "qtnfmac: invalid bus pointer")) diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index dcb0991432f4..d90016125dfc 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -144,6 +144,7 @@ int qtnf_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) { struct net_device *netdev = wdev->netdev; struct qtnf_vif *vif; + struct sk_buff *skb; if (WARN_ON(!netdev)) return -EFAULT; @@ -157,6 +158,11 @@ int qtnf_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) if (netif_carrier_ok(netdev)) netif_carrier_off(netdev); + while ((skb = skb_dequeue(&vif->high_pri_tx_queue))) + dev_kfree_skb_any(skb); + + cancel_work_sync(&vif->high_pri_tx_work); + if (netdev->reg_state == NETREG_REGISTERED) unregister_netdevice(netdev); @@ -424,13 +430,13 @@ qtnf_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, *cookie = short_cookie; if (params->offchan) - flags |= QLINK_MGMT_FRAME_TX_FLAG_OFFCHAN; + flags |= QLINK_FRAME_TX_FLAG_OFFCHAN; if (params->no_cck) - flags |= QLINK_MGMT_FRAME_TX_FLAG_NO_CCK; + flags |= QLINK_FRAME_TX_FLAG_NO_CCK; if (params->dont_wait_for_ack) - flags |= QLINK_MGMT_FRAME_TX_FLAG_ACK_NOWAIT; + flags |= QLINK_FRAME_TX_FLAG_ACK_NOWAIT; /* If channel is not specified, pass "freq = 0" to tell device * firmware to use current channel. @@ -445,9 +451,8 @@ qtnf_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, le16_to_cpu(mgmt_frame->frame_control), mgmt_frame->da, params->len, short_cookie, flags); - return qtnf_cmd_send_mgmt_frame(vif, short_cookie, flags, - freq, - params->buf, params->len); + return qtnf_cmd_send_frame(vif, short_cookie, flags, + freq, params->buf, params->len); } static int @@ -993,53 +998,31 @@ static struct cfg80211_ops qtn_cfg80211_ops = { #endif }; -static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in, +static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *req) { - struct qtnf_wmac *mac = wiphy_priv(wiphy_in); - struct qtnf_bus *bus = mac->bus; - struct wiphy *wiphy; - unsigned int mac_idx; + struct qtnf_wmac *mac = wiphy_priv(wiphy); enum nl80211_band band; int ret; pr_debug("MAC%u: initiator=%d alpha=%c%c\n", mac->macid, req->initiator, req->alpha2[0], req->alpha2[1]); - ret = qtnf_cmd_reg_notify(bus, req); + ret = qtnf_cmd_reg_notify(mac, req, qtnf_mac_slave_radar_get(wiphy)); if (ret) { - if (ret == -EOPNOTSUPP) { - pr_warn("reg update not supported\n"); - } else if (ret == -EALREADY) { - pr_info("regulatory domain is already set to %c%c", - req->alpha2[0], req->alpha2[1]); - } else { - pr_err("failed to update reg domain to %c%c\n", - req->alpha2[0], req->alpha2[1]); - } - + pr_err("MAC%u: failed to update region to %c%c: %d\n", + mac->macid, req->alpha2[0], req->alpha2[1], ret); return; } - for (mac_idx = 0; mac_idx < QTNF_MAX_MAC; ++mac_idx) { - if (!(bus->hw_info.mac_bitmap & (1 << mac_idx))) + for (band = 0; band < NUM_NL80211_BANDS; ++band) { + if (!wiphy->bands[band]) continue; - mac = bus->mac[mac_idx]; - if (!mac) - continue; - - wiphy = priv_to_wiphy(mac); - - for (band = 0; band < NUM_NL80211_BANDS; ++band) { - if (!wiphy->bands[band]) - continue; - - ret = qtnf_cmd_band_info_get(mac, wiphy->bands[band]); - if (ret) - pr_err("failed to get chan info for mac %u band %u\n", - mac_idx, band); - } + ret = qtnf_cmd_band_info_get(mac, wiphy->bands[band]); + if (ret) + pr_err("MAC%u: failed to update band %u\n", + mac->macid, band); } } @@ -1095,6 +1078,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) struct wiphy *wiphy = priv_to_wiphy(mac); struct qtnf_mac_info *macinfo = &mac->macinfo; int ret; + bool regdomain_is_known; if (!wiphy) { pr_err("invalid wiphy pointer\n"); @@ -1127,7 +1111,8 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | WIPHY_FLAG_AP_UAPSD | WIPHY_FLAG_HAS_CHANNEL_SWITCH | - WIPHY_FLAG_4ADDR_STATION; + WIPHY_FLAG_4ADDR_STATION | + WIPHY_FLAG_NETNS_OK; wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; if (hw_info->hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD) @@ -1166,11 +1151,19 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) wiphy->wowlan = macinfo->wowlan; #endif + regdomain_is_known = isalpha(mac->rd->alpha2[0]) && + isalpha(mac->rd->alpha2[1]); + if (hw_info->hw_capab & QLINK_HW_CAPAB_REG_UPDATE) { - wiphy->regulatory_flags |= REGULATORY_STRICT_REG | - REGULATORY_CUSTOM_REG; wiphy->reg_notifier = qtnf_cfg80211_reg_notifier; - wiphy_apply_custom_regulatory(wiphy, hw_info->rd); + + if (mac->rd->alpha2[0] == '9' && mac->rd->alpha2[1] == '9') { + wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | + REGULATORY_STRICT_REG; + wiphy_apply_custom_regulatory(wiphy, mac->rd); + } else if (regdomain_is_known) { + wiphy->regulatory_flags |= REGULATORY_STRICT_REG; + } } else { wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED; } @@ -1193,10 +1186,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) goto out; if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) - ret = regulatory_set_wiphy_regd(wiphy, hw_info->rd); - else if (isalpha(hw_info->rd->alpha2[0]) && - isalpha(hw_info->rd->alpha2[1])) - ret = regulatory_hint(wiphy, hw_info->rd->alpha2); + ret = regulatory_set_wiphy_regd(wiphy, mac->rd); + else if (regdomain_is_known) + ret = regulatory_hint(wiphy, mac->rd->alpha2); out: return ret; diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 85a2a58f4c16..459f6b81d2eb 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -11,6 +11,13 @@ #include "bus.h" #include "commands.h" +#define QTNF_SCAN_TIME_AUTO 0 + +/* Let device itself to select best values for current conditions */ +#define QTNF_SCAN_DWELL_ACTIVE_DEFAULT QTNF_SCAN_TIME_AUTO +#define QTNF_SCAN_DWELL_PASSIVE_DEFAULT QTNF_SCAN_TIME_AUTO +#define QTNF_SCAN_SAMPLE_DURATION_DEFAULT QTNF_SCAN_TIME_AUTO + static int qtnf_cmd_check_reply_header(const struct qlink_resp *resp, u16 cmd_id, u8 mac_id, u8 vif_id, size_t resp_size) @@ -89,8 +96,7 @@ static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus, pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id, cmd_id); - if (bus->fw_state != QTNF_FW_STATE_ACTIVE && - cmd_id != QLINK_CMD_FW_INIT) { + if (!qtnf_fw_is_up(bus) && cmd_id != QLINK_CMD_FW_INIT) { pr_warn("VIF%u.%u: drop cmd 0x%.4X in fw state %d\n", mac_id, vif_id, cmd_id, bus->fw_state); dev_kfree_skb(cmd_skb); @@ -177,14 +183,6 @@ static void qtnf_cmd_tlv_ie_set_add(struct sk_buff *cmd_skb, u8 frame_type, memcpy(tlv->ie_data, buf, len); } -static inline size_t qtnf_cmd_acl_data_size(const struct cfg80211_acl_data *acl) -{ - size_t size = sizeof(struct qlink_acl_data) + - acl->n_acl_entries * sizeof(struct qlink_mac_address); - - return size; -} - static bool qtnf_cmd_start_ap_can_fit(const struct qtnf_vif *vif, const struct cfg80211_ap_settings *s) { @@ -203,7 +201,7 @@ static bool qtnf_cmd_start_ap_can_fit(const struct qtnf_vif *vif, if (s->acl) len += sizeof(struct qlink_tlv_hdr) + - qtnf_cmd_acl_data_size(s->acl); + struct_size(s->acl, mac_addrs, s->acl->n_acl_entries); if (len > (sizeof(struct qlink_cmd) + QTNF_MAX_CMD_BUF_SIZE)) { pr_err("VIF%u.%u: can not fit AP settings: %u\n", @@ -310,7 +308,8 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif, } if (s->acl) { - size_t acl_size = qtnf_cmd_acl_data_size(s->acl); + size_t acl_size = struct_size(s->acl, mac_addrs, + s->acl->n_acl_entries); struct qlink_tlv_hdr *tlv = skb_put(cmd_skb, sizeof(*tlv) + acl_size); @@ -382,11 +381,11 @@ out: return ret; } -int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags, - u16 freq, const u8 *buf, size_t len) +int qtnf_cmd_send_frame(struct qtnf_vif *vif, u32 cookie, u16 flags, + u16 freq, const u8 *buf, size_t len) { struct sk_buff *cmd_skb; - struct qlink_cmd_mgmt_frame_tx *cmd; + struct qlink_cmd_frame_tx *cmd; int ret; if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) { @@ -396,14 +395,14 @@ int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags, } cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, - QLINK_CMD_SEND_MGMT_FRAME, + QLINK_CMD_SEND_FRAME, sizeof(*cmd)); if (!cmd_skb) return -ENOMEM; qtnf_bus_lock(vif->mac->bus); - cmd = (struct qlink_cmd_mgmt_frame_tx *)cmd_skb->data; + cmd = (struct qlink_cmd_frame_tx *)cmd_skb->data; cmd->cookie = cpu_to_le32(cookie); cmd->freq = cpu_to_le16(freq); cmd->flags = cpu_to_le16(flags); @@ -786,8 +785,25 @@ int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif, int use4addr, u8 *mac_addr) { - return qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr, - QLINK_CMD_CHANGE_INTF); + int ret; + + ret = qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr, + QLINK_CMD_CHANGE_INTF); + + /* Regulatory settings may be different for different interface types */ + if (ret == 0 && vif->wdev.iftype != iftype) { + enum nl80211_band band; + struct wiphy *wiphy = priv_to_wiphy(vif->mac); + + for (band = 0; band < NUM_NL80211_BANDS; ++band) { + if (!wiphy->bands[band]) + continue; + + qtnf_cmd_band_info_get(vif->mac, wiphy->bands[band]); + } + } + + return ret; } int qtnf_cmd_send_del_intf(struct qtnf_vif *vif) @@ -831,55 +847,6 @@ out: return ret; } -static u32 qtnf_cmd_resp_reg_rule_flags_parse(u32 qflags) -{ - u32 flags = 0; - - if (qflags & QLINK_RRF_NO_OFDM) - flags |= NL80211_RRF_NO_OFDM; - - if (qflags & QLINK_RRF_NO_CCK) - flags |= NL80211_RRF_NO_CCK; - - if (qflags & QLINK_RRF_NO_INDOOR) - flags |= NL80211_RRF_NO_INDOOR; - - if (qflags & QLINK_RRF_NO_OUTDOOR) - flags |= NL80211_RRF_NO_OUTDOOR; - - if (qflags & QLINK_RRF_DFS) - flags |= NL80211_RRF_DFS; - - if (qflags & QLINK_RRF_PTP_ONLY) - flags |= NL80211_RRF_PTP_ONLY; - - if (qflags & QLINK_RRF_PTMP_ONLY) - flags |= NL80211_RRF_PTMP_ONLY; - - if (qflags & QLINK_RRF_NO_IR) - flags |= NL80211_RRF_NO_IR; - - if (qflags & QLINK_RRF_AUTO_BW) - flags |= NL80211_RRF_AUTO_BW; - - if (qflags & QLINK_RRF_IR_CONCURRENT) - flags |= NL80211_RRF_IR_CONCURRENT; - - if (qflags & QLINK_RRF_NO_HT40MINUS) - flags |= NL80211_RRF_NO_HT40MINUS; - - if (qflags & QLINK_RRF_NO_HT40PLUS) - flags |= NL80211_RRF_NO_HT40PLUS; - - if (qflags & QLINK_RRF_NO_80MHZ) - flags |= NL80211_RRF_NO_80MHZ; - - if (qflags & QLINK_RRF_NO_160MHZ) - flags |= NL80211_RRF_NO_160MHZ; - - return flags; -} - static int qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, const struct qlink_resp_get_hw_info *resp, @@ -887,7 +854,6 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, { struct qtnf_hw_info *hwinfo = &bus->hw_info; const struct qlink_tlv_hdr *tlv; - const struct qlink_tlv_reg_rule *tlv_rule; const char *bld_name = NULL; const char *bld_rev = NULL; const char *bld_type = NULL; @@ -898,19 +864,8 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, const char *calibration_ver = NULL; const char *uboot_ver = NULL; u32 hw_ver = 0; - struct ieee80211_reg_rule *rule; u16 tlv_type; u16 tlv_value_len; - unsigned int rule_idx = 0; - - if (WARN_ON(resp->n_reg_rules > NL80211_MAX_SUPP_REG_RULES)) - return -E2BIG; - - hwinfo->rd = kzalloc(struct_size(hwinfo->rd, reg_rules, - resp->n_reg_rules), GFP_KERNEL); - - if (!hwinfo->rd) - return -ENOMEM; hwinfo->num_mac = resp->num_mac; hwinfo->mac_bitmap = resp->mac_bitmap; @@ -919,30 +874,11 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, hwinfo->total_tx_chain = resp->total_tx_chain; hwinfo->total_rx_chain = resp->total_rx_chain; hwinfo->hw_capab = le32_to_cpu(resp->hw_capab); - hwinfo->rd->n_reg_rules = resp->n_reg_rules; - hwinfo->rd->alpha2[0] = resp->alpha2[0]; - hwinfo->rd->alpha2[1] = resp->alpha2[1]; bld_tmstamp = le32_to_cpu(resp->bld_tmstamp); plat_id = le32_to_cpu(resp->plat_id); hw_ver = le32_to_cpu(resp->hw_ver); - switch (resp->dfs_region) { - case QLINK_DFS_FCC: - hwinfo->rd->dfs_region = NL80211_DFS_FCC; - break; - case QLINK_DFS_ETSI: - hwinfo->rd->dfs_region = NL80211_DFS_ETSI; - break; - case QLINK_DFS_JP: - hwinfo->rd->dfs_region = NL80211_DFS_JP; - break; - case QLINK_DFS_UNSET: - default: - hwinfo->rd->dfs_region = NL80211_DFS_UNSET; - break; - } - tlv = (const struct qlink_tlv_hdr *)resp->info; while (info_len >= sizeof(*tlv)) { @@ -956,37 +892,6 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, } switch (tlv_type) { - case QTN_TLV_ID_REG_RULE: - if (rule_idx >= resp->n_reg_rules) { - pr_warn("unexpected number of rules: %u\n", - resp->n_reg_rules); - return -EINVAL; - } - - if (tlv_value_len != sizeof(*tlv_rule) - sizeof(*tlv)) { - pr_warn("malformed TLV 0x%.2X; LEN: %u\n", - tlv_type, tlv_value_len); - return -EINVAL; - } - - tlv_rule = (const struct qlink_tlv_reg_rule *)tlv; - rule = &hwinfo->rd->reg_rules[rule_idx++]; - - rule->freq_range.start_freq_khz = - le32_to_cpu(tlv_rule->start_freq_khz); - rule->freq_range.end_freq_khz = - le32_to_cpu(tlv_rule->end_freq_khz); - rule->freq_range.max_bandwidth_khz = - le32_to_cpu(tlv_rule->max_bandwidth_khz); - rule->power_rule.max_antenna_gain = - le32_to_cpu(tlv_rule->max_antenna_gain); - rule->power_rule.max_eirp = - le32_to_cpu(tlv_rule->max_eirp); - rule->dfs_cac_ms = - le32_to_cpu(tlv_rule->dfs_cac_ms); - rule->flags = qtnf_cmd_resp_reg_rule_flags_parse( - le32_to_cpu(tlv_rule->flags)); - break; case QTN_TLV_ID_BUILD_NAME: bld_name = (const void *)tlv->val; break; @@ -1019,17 +924,8 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } - if (rule_idx != resp->n_reg_rules) { - pr_warn("unexpected number of rules: expected %u got %u\n", - resp->n_reg_rules, rule_idx); - kfree(hwinfo->rd); - hwinfo->rd = NULL; - return -EINVAL; - } - - pr_info("fw_version=%d, MACs map %#x, alpha2=\"%c%c\", chains Tx=%u Rx=%u, capab=0x%x\n", + pr_info("fw_version=%d, MACs map %#x, chains Tx=%u Rx=%u, capab=0x%x\n", hwinfo->fw_ver, hwinfo->mac_bitmap, - hwinfo->rd->alpha2[0], hwinfo->rd->alpha2[1], hwinfo->total_tx_chain, hwinfo->total_rx_chain, hwinfo->hw_capab); @@ -1042,7 +938,7 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, "\nHardware ID: %s" \ "\nCalibration version: %s" \ "\nU-Boot version: %s" \ - "\nHardware version: 0x%08x", + "\nHardware version: 0x%08x\n", bld_name, bld_rev, bld_type, bld_label, (unsigned long)bld_tmstamp, (unsigned long)plat_id, @@ -1085,9 +981,12 @@ qtnf_parse_wowlan_info(struct qtnf_wmac *mac, } } -static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, - const u8 *tlv_buf, size_t tlv_buf_size) +static int +qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, + const struct qlink_resp_get_mac_info *resp, + size_t tlv_buf_size) { + const u8 *tlv_buf = resp->var_info; struct ieee80211_iface_combination *comb = NULL; size_t n_comb = 0; struct ieee80211_iface_limit *limits; @@ -1105,6 +1004,38 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, u8 ext_capa_len = 0; u8 ext_capa_mask_len = 0; int i = 0; + struct ieee80211_reg_rule *rule; + unsigned int rule_idx = 0; + const struct qlink_tlv_reg_rule *tlv_rule; + + if (WARN_ON(resp->n_reg_rules > NL80211_MAX_SUPP_REG_RULES)) + return -E2BIG; + + mac->rd = kzalloc(sizeof(*mac->rd) + + sizeof(struct ieee80211_reg_rule) * + resp->n_reg_rules, GFP_KERNEL); + if (!mac->rd) + return -ENOMEM; + + mac->rd->n_reg_rules = resp->n_reg_rules; + mac->rd->alpha2[0] = resp->alpha2[0]; + mac->rd->alpha2[1] = resp->alpha2[1]; + + switch (resp->dfs_region) { + case QLINK_DFS_FCC: + mac->rd->dfs_region = NL80211_DFS_FCC; + break; + case QLINK_DFS_ETSI: + mac->rd->dfs_region = NL80211_DFS_ETSI; + break; + case QLINK_DFS_JP: + mac->rd->dfs_region = NL80211_DFS_JP; + break; + case QLINK_DFS_UNSET: + default: + mac->rd->dfs_region = NL80211_DFS_UNSET; + break; + } tlv = (const struct qlink_tlv_hdr *)tlv_buf; while (tlv_buf_size >= sizeof(struct qlink_tlv_hdr)) { @@ -1225,6 +1156,23 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, mac->macinfo.wowlan = NULL; qtnf_parse_wowlan_info(mac, wowlan); break; + case QTN_TLV_ID_REG_RULE: + if (rule_idx >= resp->n_reg_rules) { + pr_warn("unexpected number of rules: %u\n", + resp->n_reg_rules); + return -EINVAL; + } + + if (tlv_value_len != sizeof(*tlv_rule) - sizeof(*tlv)) { + pr_warn("malformed TLV 0x%.2X; LEN: %u\n", + tlv_type, tlv_value_len); + return -EINVAL; + } + + tlv_rule = (const struct qlink_tlv_reg_rule *)tlv; + rule = &mac->rd->reg_rules[rule_idx++]; + qlink_utils_regrule_q2nl(rule, tlv_rule); + break; default: pr_warn("MAC%u: unknown TLV type %u\n", mac->macid, tlv_type); @@ -1253,6 +1201,12 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, return -EINVAL; } + if (rule_idx != resp->n_reg_rules) { + pr_warn("unexpected number of rules: expected %u got %u\n", + resp->n_reg_rules, rule_idx); + return -EINVAL; + } + if (ext_capa_len > 0) { ext_capa = kmemdup(ext_capa, ext_capa_len, GFP_KERNEL); if (!ext_capa) @@ -1663,7 +1617,7 @@ int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac) resp = (const struct qlink_resp_get_mac_info *)resp_skb->data; qtnf_cmd_resp_proc_mac_info(mac, resp); - ret = qtnf_parse_variable_mac_info(mac, resp->var_info, var_data_len); + ret = qtnf_parse_variable_mac_info(mac, resp, var_data_len); out: qtnf_bus_unlock(mac->bus); @@ -1709,21 +1663,7 @@ int qtnf_cmd_band_info_get(struct qtnf_wmac *mac, struct qlink_resp_band_info_get *resp; size_t info_len = 0; int ret = 0; - u8 qband; - - switch (band->band) { - case NL80211_BAND_2GHZ: - qband = QLINK_BAND_2GHZ; - break; - case NL80211_BAND_5GHZ: - qband = QLINK_BAND_5GHZ; - break; - case NL80211_BAND_60GHZ: - qband = QLINK_BAND_60GHZ; - break; - default: - return -EINVAL; - } + u8 qband = qlink_utils_band_cfg2q(band->band); cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0, QLINK_CMD_BAND_INFO_GET, @@ -2107,22 +2047,23 @@ out: static void qtnf_cmd_channel_tlv_add(struct sk_buff *cmd_skb, const struct ieee80211_channel *sc) { - struct qlink_tlv_channel *qchan; - u32 flags = 0; - - qchan = skb_put_zero(cmd_skb, sizeof(*qchan)); - qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL); - qchan->hdr.len = cpu_to_le16(sizeof(*qchan) - sizeof(qchan->hdr)); - qchan->chan.center_freq = cpu_to_le16(sc->center_freq); - qchan->chan.hw_value = cpu_to_le16(sc->hw_value); - - if (sc->flags & IEEE80211_CHAN_NO_IR) - flags |= QLINK_CHAN_NO_IR; - - if (sc->flags & IEEE80211_CHAN_RADAR) - flags |= QLINK_CHAN_RADAR; - - qchan->chan.flags = cpu_to_le32(flags); + struct qlink_tlv_channel *tlv; + struct qlink_channel *qch; + + tlv = skb_put_zero(cmd_skb, sizeof(*tlv)); + qch = &tlv->chan; + tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL); + tlv->hdr.len = cpu_to_le16(sizeof(*qch)); + + qch->center_freq = cpu_to_le16(sc->center_freq); + qch->hw_value = cpu_to_le16(sc->hw_value); + qch->band = qlink_utils_band_cfg2q(sc->band); + qch->max_power = sc->max_power; + qch->max_reg_power = sc->max_reg_power; + qch->max_antenna_gain = sc->max_antenna_gain; + qch->beacon_found = sc->beacon_found; + qch->dfs_state = qlink_utils_dfs_state_cfg2q(sc->dfs_state); + qch->flags = cpu_to_le32(qlink_utils_chflags_cfg2q(sc->flags)); } static void qtnf_cmd_randmac_tlv_add(struct sk_buff *cmd_skb, @@ -2141,6 +2082,35 @@ static void qtnf_cmd_randmac_tlv_add(struct sk_buff *cmd_skb, memcpy(randmac->mac_addr_mask, mac_addr_mask, ETH_ALEN); } +static void qtnf_cmd_scan_set_dwell(struct qtnf_wmac *mac, + struct sk_buff *cmd_skb) +{ + struct cfg80211_scan_request *scan_req = mac->scan_req; + u16 dwell_active = QTNF_SCAN_DWELL_ACTIVE_DEFAULT; + u16 dwell_passive = QTNF_SCAN_DWELL_PASSIVE_DEFAULT; + u16 duration = QTNF_SCAN_SAMPLE_DURATION_DEFAULT; + + if (scan_req->duration) { + dwell_active = scan_req->duration; + dwell_passive = scan_req->duration; + } + + pr_debug("MAC%u: %s scan dwell active=%u, passive=%u, duration=%u\n", + mac->macid, + scan_req->duration_mandatory ? "mandatory" : "max", + dwell_active, dwell_passive, duration); + + qtnf_cmd_skb_put_tlv_u16(cmd_skb, + QTN_TLV_ID_SCAN_DWELL_ACTIVE, + dwell_active); + qtnf_cmd_skb_put_tlv_u16(cmd_skb, + QTN_TLV_ID_SCAN_DWELL_PASSIVE, + dwell_passive); + qtnf_cmd_skb_put_tlv_u16(cmd_skb, + QTN_TLV_ID_SCAN_SAMPLE_DURATION, + duration); +} + int qtnf_cmd_send_scan(struct qtnf_wmac *mac) { struct sk_buff *cmd_skb; @@ -2192,6 +2162,8 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac) } } + qtnf_cmd_scan_set_dwell(mac, cmd_skb); + if (scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { pr_debug("MAC%u: scan with random addr=%pM, mask=%pM\n", mac->macid, @@ -2207,15 +2179,6 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac) qtnf_cmd_skb_put_tlv_tag(cmd_skb, QTN_TLV_ID_SCAN_FLUSH); } - if (scan_req->duration) { - pr_debug("MAC%u: %s scan duration %u\n", mac->macid, - scan_req->duration_mandatory ? "mandatory" : "max", - scan_req->duration); - - qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_SCAN_DWELL, - scan_req->duration); - } - ret = qtnf_cmd_send(mac->bus, cmd_skb); if (ret) goto out; @@ -2404,13 +2367,18 @@ out: return ret; } -int qtnf_cmd_reg_notify(struct qtnf_bus *bus, struct regulatory_request *req) +int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req, + bool slave_radar) { + struct wiphy *wiphy = priv_to_wiphy(mac); + struct qtnf_bus *bus = mac->bus; struct sk_buff *cmd_skb; int ret; struct qlink_cmd_reg_notify *cmd; + enum nl80211_band band; + const struct ieee80211_supported_band *cfg_band; - cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD, + cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD, QLINK_CMD_REG_NOTIFY, sizeof(*cmd)); if (!cmd_skb) @@ -2447,12 +2415,41 @@ int qtnf_cmd_reg_notify(struct qtnf_bus *bus, struct regulatory_request *req) break; } + switch (req->dfs_region) { + case NL80211_DFS_FCC: + cmd->dfs_region = QLINK_DFS_FCC; + break; + case NL80211_DFS_ETSI: + cmd->dfs_region = QLINK_DFS_ETSI; + break; + case NL80211_DFS_JP: + cmd->dfs_region = QLINK_DFS_JP; + break; + default: + cmd->dfs_region = QLINK_DFS_UNSET; + break; + } + + cmd->slave_radar = slave_radar; + cmd->num_channels = 0; + + for (band = 0; band < NUM_NL80211_BANDS; band++) { + unsigned int i; + + cfg_band = wiphy->bands[band]; + if (!cfg_band) + continue; + + cmd->num_channels += cfg_band->n_channels; + + for (i = 0; i < cfg_band->n_channels; ++i) { + qtnf_cmd_channel_tlv_add(cmd_skb, + &cfg_band->channels[i]); + } + } + qtnf_bus_lock(bus); ret = qtnf_cmd_send(bus, cmd_skb); - if (ret) - goto out; - -out: qtnf_bus_unlock(bus); return ret; @@ -2592,7 +2589,7 @@ int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif, struct qtnf_bus *bus = vif->mac->bus; struct sk_buff *cmd_skb; struct qlink_tlv_hdr *tlv; - size_t acl_size = qtnf_cmd_acl_data_size(params); + size_t acl_size = struct_size(params, mac_addrs, params->n_acl_entries); int ret; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h index 64f0b9dc8a14..88d7a3cd90d2 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.h +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h @@ -27,8 +27,8 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif, const struct cfg80211_ap_settings *s); int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif); int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg); -int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags, - u16 freq, const u8 *buf, size_t len); +int qtnf_cmd_send_frame(struct qtnf_vif *vif, u32 cookie, u16 flags, + u16 freq, const u8 *buf, size_t len); int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type, const u8 *buf, size_t len); int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac, @@ -57,7 +57,8 @@ int qtnf_cmd_send_disconnect(struct qtnf_vif *vif, u16 reason_code); int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, bool up); -int qtnf_cmd_reg_notify(struct qtnf_bus *bus, struct regulatory_request *req); +int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req, + bool slave_radar); int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel, struct qtnf_chan_stats *stats); int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif, diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c index ee1b75fda1dd..8d699cc03d26 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.c +++ b/drivers/net/wireless/quantenna/qtnfmac/core.c @@ -16,6 +16,12 @@ #define QTNF_DMP_MAX_LEN 48 #define QTNF_PRIMARY_VIF_IDX 0 +static bool slave_radar = true; +module_param(slave_radar, bool, 0644); +MODULE_PARM_DESC(slave_radar, "set 0 to disable radar detection in slave mode"); + +static struct dentry *qtnf_debugfs_dir; + struct qtnf_frame_meta_info { u8 magic_s; u8 ifidx; @@ -368,6 +374,23 @@ static void qtnf_mac_scan_timeout(struct work_struct *work) qtnf_mac_scan_finish(mac, true); } +static void qtnf_vif_send_data_high_pri(struct work_struct *work) +{ + struct qtnf_vif *vif = + container_of(work, struct qtnf_vif, high_pri_tx_work); + struct sk_buff *skb; + + if (!vif->netdev || + vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) + return; + + while ((skb = skb_dequeue(&vif->high_pri_tx_queue))) { + qtnf_cmd_send_frame(vif, 0, QLINK_FRAME_TX_FLAG_8023, + 0, skb->data, skb->len); + dev_kfree_skb_any(skb); + } +} + static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus, unsigned int macid) { @@ -395,7 +418,8 @@ static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus, vif->mac = mac; vif->vifid = i; qtnf_sta_list_init(&vif->sta_list); - + INIT_WORK(&vif->high_pri_tx_work, qtnf_vif_send_data_high_pri); + skb_queue_head_init(&vif->high_pri_tx_queue); vif->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); if (!vif->stats64) pr_warn("VIF%u.%u: per cpu stats allocation failed\n", @@ -408,6 +432,11 @@ static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus, return mac; } +bool qtnf_mac_slave_radar_get(struct wiphy *wiphy) +{ + return slave_radar; +} + static const struct ethtool_ops qtnf_ethtool_ops = { .get_drvinfo = cfg80211_get_drvinfo, }; @@ -499,6 +528,8 @@ static void qtnf_core_mac_detach(struct qtnf_bus *bus, unsigned int macid) qtnf_mac_iface_comb_free(mac); qtnf_mac_ext_caps_free(mac); kfree(mac->macinfo.wowlan); + kfree(mac->rd); + mac->rd = NULL; wiphy_free(wiphy); bus->mac[macid] = NULL; } @@ -587,8 +618,6 @@ int qtnf_core_attach(struct qtnf_bus *bus) int ret; qtnf_trans_init(bus); - - bus->fw_state = QTNF_FW_STATE_BOOT_DONE; qtnf_bus_data_rx_start(bus); bus->workqueue = alloc_ordered_workqueue("QTNF_BUS", 0); @@ -598,6 +627,13 @@ int qtnf_core_attach(struct qtnf_bus *bus) goto error; } + bus->hprio_workqueue = alloc_workqueue("QTNF_HPRI", WQ_HIGHPRI, 0); + if (!bus->hprio_workqueue) { + pr_err("failed to alloc high prio workqueue\n"); + ret = -ENOMEM; + goto error; + } + INIT_WORK(&bus->event_work, qtnf_event_work_handler); ret = qtnf_cmd_send_init_fw(bus); @@ -607,7 +643,6 @@ int qtnf_core_attach(struct qtnf_bus *bus) } bus->fw_state = QTNF_FW_STATE_ACTIVE; - ret = qtnf_cmd_get_hw_info(bus); if (ret) { pr_err("failed to get HW info: %d\n", ret); @@ -637,11 +672,11 @@ int qtnf_core_attach(struct qtnf_bus *bus) } } + bus->fw_state = QTNF_FW_STATE_RUNNING; return 0; error: qtnf_core_detach(bus); - return ret; } EXPORT_SYMBOL_GPL(qtnf_core_attach); @@ -655,7 +690,7 @@ void qtnf_core_detach(struct qtnf_bus *bus) for (macid = 0; macid < QTNF_MAX_MAC; macid++) qtnf_core_mac_detach(bus, macid); - if (bus->fw_state == QTNF_FW_STATE_ACTIVE) + if (qtnf_fw_is_up(bus)) qtnf_cmd_send_deinit_fw(bus); bus->fw_state = QTNF_FW_STATE_DETACHED; @@ -663,10 +698,14 @@ void qtnf_core_detach(struct qtnf_bus *bus) if (bus->workqueue) { flush_workqueue(bus->workqueue); destroy_workqueue(bus->workqueue); + bus->workqueue = NULL; } - kfree(bus->hw_info.rd); - bus->hw_info.rd = NULL; + if (bus->hprio_workqueue) { + flush_workqueue(bus->hprio_workqueue); + destroy_workqueue(bus->hprio_workqueue); + bus->hprio_workqueue = NULL; + } qtnf_trans_free(bus); } @@ -684,6 +723,9 @@ struct net_device *qtnf_classify_skb(struct qtnf_bus *bus, struct sk_buff *skb) struct qtnf_wmac *mac; struct qtnf_vif *vif; + if (unlikely(bus->fw_state != QTNF_FW_STATE_RUNNING)) + return NULL; + meta = (struct qtnf_frame_meta_info *) (skb_tail_pointer(skb) - sizeof(*meta)); @@ -799,6 +841,39 @@ void qtnf_update_tx_stats(struct net_device *ndev, const struct sk_buff *skb) } EXPORT_SYMBOL_GPL(qtnf_update_tx_stats); +void qtnf_packet_send_hi_pri(struct sk_buff *skb) +{ + struct qtnf_vif *vif = qtnf_netdev_get_priv(skb->dev); + + skb_queue_tail(&vif->high_pri_tx_queue, skb); + queue_work(vif->mac->bus->hprio_workqueue, &vif->high_pri_tx_work); +} +EXPORT_SYMBOL_GPL(qtnf_packet_send_hi_pri); + +struct dentry *qtnf_get_debugfs_dir(void) +{ + return qtnf_debugfs_dir; +} +EXPORT_SYMBOL_GPL(qtnf_get_debugfs_dir); + +static int __init qtnf_core_register(void) +{ + qtnf_debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL); + + if (IS_ERR(qtnf_debugfs_dir)) + qtnf_debugfs_dir = NULL; + + return 0; +} + +static void __exit qtnf_core_exit(void) +{ + debugfs_remove(qtnf_debugfs_dir); +} + +module_init(qtnf_core_register); +module_exit(qtnf_core_exit); + MODULE_AUTHOR("Quantenna Communications"); MODULE_DESCRIPTION("Quantenna 802.11 wireless LAN FullMAC driver."); MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h index a31cff46e964..322858df600c 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.h +++ b/drivers/net/wireless/quantenna/qtnfmac/core.h @@ -63,6 +63,8 @@ struct qtnf_vif { struct qtnf_wmac *mac; struct work_struct reset_work; + struct work_struct high_pri_tx_work; + struct sk_buff_head high_pri_tx_queue; struct qtnf_sta_list sta_list; unsigned long cons_tx_timeout_cnt; int generation; @@ -112,6 +114,7 @@ struct qtnf_wmac { struct cfg80211_scan_request *scan_req; struct mutex mac_lock; /* lock during wmac speicific ops */ struct delayed_work scan_timeout; + struct ieee80211_regdomain *rd; }; struct qtnf_hw_info { @@ -120,7 +123,6 @@ struct qtnf_hw_info { u8 mac_bitmap; u32 fw_ver; u32 hw_capab; - struct ieee80211_regdomain *rd; u8 total_tx_chain; u8 total_rx_chain; char fw_version[ETHTOOL_FWVERS_LEN]; @@ -132,6 +134,7 @@ struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac *mac); struct qtnf_vif *qtnf_mac_get_base_vif(struct qtnf_wmac *mac); void qtnf_mac_iface_comb_free(struct qtnf_wmac *mac); void qtnf_mac_ext_caps_free(struct qtnf_wmac *mac); +bool qtnf_mac_slave_radar_get(struct wiphy *wiphy); struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus); int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *priv, const char *name, unsigned char name_assign_type); @@ -149,6 +152,8 @@ void qtnf_virtual_intf_cleanup(struct net_device *ndev); void qtnf_netdev_updown(struct net_device *ndev, bool up); void qtnf_scan_done(struct qtnf_wmac *mac, bool aborted); +void qtnf_packet_send_hi_pri(struct sk_buff *skb); +struct dentry *qtnf_get_debugfs_dir(void); static inline struct qtnf_vif *qtnf_netdev_get_priv(struct net_device *dev) { diff --git a/drivers/net/wireless/quantenna/qtnfmac/debug.c b/drivers/net/wireless/quantenna/qtnfmac/debug.c index 598ece753a4b..2d3574c1f10e 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/debug.c +++ b/drivers/net/wireless/quantenna/qtnfmac/debug.c @@ -5,7 +5,9 @@ void qtnf_debugfs_init(struct qtnf_bus *bus, const char *name) { - bus->dbg_dir = debugfs_create_dir(name, NULL); + struct dentry *parent = qtnf_get_debugfs_dir(); + + bus->dbg_dir = debugfs_create_dir(name, parent); } void qtnf_debugfs_remove(struct qtnf_bus *bus) diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c index 6c1b886339ac..b57c8c18a8d0 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/event.c +++ b/drivers/net/wireless/quantenna/qtnfmac/event.c @@ -493,14 +493,20 @@ qtnf_event_handle_freq_change(struct qtnf_wmac *mac, for (i = 0; i < QTNF_MAX_INTF; i++) { vif = &mac->iflist[i]; + if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) continue; - if (vif->netdev) { - mutex_lock(&vif->wdev.mtx); - cfg80211_ch_switch_notify(vif->netdev, &chandef); - mutex_unlock(&vif->wdev.mtx); - } + if (vif->wdev.iftype == NL80211_IFTYPE_STATION && + !vif->wdev.current_bss) + continue; + + if (!vif->netdev) + continue; + + mutex_lock(&vif->wdev.mtx); + cfg80211_ch_switch_notify(vif->netdev, &chandef); + mutex_unlock(&vif->wdev.mtx); } return 0; diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c index c3a32effa6f0..e4e9344b6982 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c @@ -56,7 +56,7 @@ int qtnf_pcie_control_tx(struct qtnf_bus *bus, struct sk_buff *skb) if (ret == -ETIMEDOUT) { pr_err("EP firmware is dead\n"); - bus->fw_state = QTNF_FW_STATE_EP_DEAD; + bus->fw_state = QTNF_FW_STATE_DEAD; } return ret; @@ -128,32 +128,22 @@ static int qtnf_dbg_shm_stats(struct seq_file *s, void *data) return 0; } -void qtnf_pcie_fw_boot_done(struct qtnf_bus *bus, bool boot_success) +int qtnf_pcie_fw_boot_done(struct qtnf_bus *bus) { - struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); - struct pci_dev *pdev = priv->pdev; int ret; - if (boot_success) { - bus->fw_state = QTNF_FW_STATE_FW_DNLD_DONE; - - ret = qtnf_core_attach(bus); - if (ret) { - pr_err("failed to attach core\n"); - boot_success = false; - } - } - - if (boot_success) { + bus->fw_state = QTNF_FW_STATE_BOOT_DONE; + ret = qtnf_core_attach(bus); + if (ret) { + pr_err("failed to attach core\n"); + } else { qtnf_debugfs_init(bus, DRV_NAME); qtnf_debugfs_add_entry(bus, "mps", qtnf_dbg_mps_show); qtnf_debugfs_add_entry(bus, "msi_enabled", qtnf_dbg_msi_show); qtnf_debugfs_add_entry(bus, "shm_stats", qtnf_dbg_shm_stats); - } else { - bus->fw_state = QTNF_FW_STATE_DETACHED; } - put_device(&pdev->dev); + return ret; } static void qtnf_tune_pcie_mps(struct pci_dev *pdev) @@ -344,7 +334,7 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) pcie_priv = get_bus_priv(bus); pci_set_drvdata(pdev, bus); bus->dev = &pdev->dev; - bus->fw_state = QTNF_FW_STATE_RESET; + bus->fw_state = QTNF_FW_STATE_DETACHED; pcie_priv->pdev = pdev; pcie_priv->tx_stopped = 0; pcie_priv->rx_bd_num = rx_bd_size_param; @@ -364,6 +354,7 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) pcie_priv->pcie_irq_count = 0; pcie_priv->tx_reclaim_done = 0; pcie_priv->tx_reclaim_req = 0; + pcie_priv->tx_eapol = 0; pcie_priv->workqueue = create_singlethread_workqueue("QTNF_PCIE"); if (!pcie_priv->workqueue) { @@ -419,8 +410,7 @@ static void qtnf_pcie_remove(struct pci_dev *dev) cancel_work_sync(&bus->fw_work); - if (bus->fw_state == QTNF_FW_STATE_ACTIVE || - bus->fw_state == QTNF_FW_STATE_EP_DEAD) + if (qtnf_fw_is_attached(bus)) qtnf_core_detach(bus); netif_napi_del(&bus->mux_napi); diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h index bbc074e1f34d..5e8b9cb68419 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h @@ -62,6 +62,7 @@ struct qtnf_pcie_bus_priv { u32 tx_done_count; u32 tx_reclaim_done; u32 tx_reclaim_req; + u32 tx_eapol; u8 msi_enabled; u8 tx_stopped; @@ -70,7 +71,7 @@ struct qtnf_pcie_bus_priv { int qtnf_pcie_control_tx(struct qtnf_bus *bus, struct sk_buff *skb); int qtnf_pcie_alloc_skb_array(struct qtnf_pcie_bus_priv *priv); -void qtnf_pcie_fw_boot_done(struct qtnf_bus *bus, bool boot_success); +int qtnf_pcie_fw_boot_done(struct qtnf_bus *bus); void qtnf_pcie_init_shm_ipc(struct qtnf_pcie_bus_priv *priv, struct qtnf_shm_ipc_region __iomem *ipc_tx_reg, struct qtnf_shm_ipc_region __iomem *ipc_rx_reg, diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c index 1f5facbb8905..3aa3714d4dfd 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c @@ -980,12 +980,11 @@ static void qtnf_pearl_fw_work_handler(struct work_struct *work) { struct qtnf_bus *bus = container_of(work, struct qtnf_bus, fw_work); struct qtnf_pcie_pearl_state *ps = (void *)get_bus_priv(bus); + u32 state = QTN_RC_FW_LOADRDY | QTN_RC_FW_QLINK; + const char *fwname = QTN_PCI_PEARL_FW_NAME; struct pci_dev *pdev = ps->base.pdev; const struct firmware *fw; int ret; - u32 state = QTN_RC_FW_LOADRDY | QTN_RC_FW_QLINK; - const char *fwname = QTN_PCI_PEARL_FW_NAME; - bool fw_boot_success = false; if (ps->base.flashboot) { state |= QTN_RC_FW_FLASHBOOT; @@ -1031,23 +1030,23 @@ static void qtnf_pearl_fw_work_handler(struct work_struct *work) goto fw_load_exit; } - pr_info("firmware is up and running\n"); - if (qtnf_poll_state(&ps->bda->bda_ep_state, QTN_EP_FW_QLINK_DONE, QTN_FW_QLINK_TIMEOUT_MS)) { pr_err("firmware runtime failure\n"); goto fw_load_exit; } - fw_boot_success = true; + pr_info("firmware is up and running\n"); -fw_load_exit: - qtnf_pcie_fw_boot_done(bus, fw_boot_success); + ret = qtnf_pcie_fw_boot_done(bus); + if (ret) + goto fw_load_exit; - if (fw_boot_success) { - qtnf_debugfs_add_entry(bus, "hdp_stats", qtnf_dbg_hdp_stats); - qtnf_debugfs_add_entry(bus, "irq_stats", qtnf_dbg_irq_stats); - } + qtnf_debugfs_add_entry(bus, "hdp_stats", qtnf_dbg_hdp_stats); + qtnf_debugfs_add_entry(bus, "irq_stats", qtnf_dbg_irq_stats); + +fw_load_exit: + put_device(&pdev->dev); } static void qtnf_pearl_reclaim_tasklet_fn(unsigned long data) diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c index cbcda57105f3..9a4380ed7f1b 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c @@ -498,6 +498,13 @@ static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb) int len; int i; + if (unlikely(skb->protocol == htons(ETH_P_PAE))) { + qtnf_packet_send_hi_pri(skb); + qtnf_update_tx_stats(skb->dev, skb); + priv->tx_eapol++; + return NETDEV_TX_OK; + } + spin_lock_irqsave(&priv->tx_lock, flags); if (!qtnf_tx_queue_ready(ts)) { @@ -761,6 +768,7 @@ static int qtnf_dbg_pkt_stats(struct seq_file *s, void *data) seq_printf(s, "tx_done_count(%u)\n", priv->tx_done_count); seq_printf(s, "tx_reclaim_done(%u)\n", priv->tx_reclaim_done); seq_printf(s, "tx_reclaim_req(%u)\n", priv->tx_reclaim_req); + seq_printf(s, "tx_eapol(%u)\n", priv->tx_eapol); seq_printf(s, "tx_bd_r_index(%u)\n", priv->tx_bd_r_index); seq_printf(s, "tx_done_index(%u)\n", tx_done_index); @@ -1023,8 +1031,9 @@ static void qtnf_topaz_fw_work_handler(struct work_struct *work) { struct qtnf_bus *bus = container_of(work, struct qtnf_bus, fw_work); struct qtnf_pcie_topaz_state *ts = (void *)get_bus_priv(bus); - int ret; int bootloader_needed = readl(&ts->bda->bda_flags) & QTN_BDA_XMIT_UBOOT; + struct pci_dev *pdev = ts->base.pdev; + int ret; qtnf_set_state(&ts->bda->bda_bootstate, QTN_BDA_FW_TARGET_BOOT); @@ -1073,19 +1082,23 @@ static void qtnf_topaz_fw_work_handler(struct work_struct *work) } } + ret = qtnf_post_init_ep(ts); + if (ret) { + pr_err("FW runtime failure\n"); + goto fw_load_exit; + } + pr_info("firmware is up and running\n"); - ret = qtnf_post_init_ep(ts); + ret = qtnf_pcie_fw_boot_done(bus); if (ret) - pr_err("FW runtime failure\n"); + goto fw_load_exit; -fw_load_exit: - qtnf_pcie_fw_boot_done(bus, ret ? false : true); + qtnf_debugfs_add_entry(bus, "pkt_stats", qtnf_dbg_pkt_stats); + qtnf_debugfs_add_entry(bus, "irq_stats", qtnf_dbg_irq_stats); - if (ret == 0) { - qtnf_debugfs_add_entry(bus, "pkt_stats", qtnf_dbg_pkt_stats); - qtnf_debugfs_add_entry(bus, "irq_stats", qtnf_dbg_irq_stats); - } +fw_load_exit: + put_device(&pdev->dev); } static void qtnf_reclaim_tasklet_fn(unsigned long data) diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index 7798edcf7980..8a3c6344fa8e 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -6,7 +6,7 @@ #include <linux/ieee80211.h> -#define QLINK_PROTO_VER 13 +#define QLINK_PROTO_VER 15 #define QLINK_MACID_RSVD 0xFF #define QLINK_VIFID_RSVD 0xFF @@ -206,6 +206,8 @@ struct qlink_sta_info_state { * execution status (one of &enum qlink_cmd_result). Reply message * may also contain data payload specific to the command type. * + * @QLINK_CMD_SEND_FRAME: send specified frame over the air; firmware will + * encapsulate 802.3 packet into 802.11 frame automatically. * @QLINK_CMD_BAND_INFO_GET: for the specified MAC and specified band, get * the band's description including number of operational channels and * info on each channel, HT/VHT capabilities, supported rates etc. @@ -220,7 +222,7 @@ enum qlink_cmd_type { QLINK_CMD_FW_INIT = 0x0001, QLINK_CMD_FW_DEINIT = 0x0002, QLINK_CMD_REGISTER_MGMT = 0x0003, - QLINK_CMD_SEND_MGMT_FRAME = 0x0004, + QLINK_CMD_SEND_FRAME = 0x0004, QLINK_CMD_MGMT_SET_APPIE = 0x0005, QLINK_CMD_PHY_PARAMS_GET = 0x0011, QLINK_CMD_PHY_PARAMS_SET = 0x0012, @@ -321,22 +323,26 @@ struct qlink_cmd_mgmt_frame_register { u8 do_register; } __packed; -enum qlink_mgmt_frame_tx_flags { - QLINK_MGMT_FRAME_TX_FLAG_NONE = 0, - QLINK_MGMT_FRAME_TX_FLAG_OFFCHAN = BIT(0), - QLINK_MGMT_FRAME_TX_FLAG_NO_CCK = BIT(1), - QLINK_MGMT_FRAME_TX_FLAG_ACK_NOWAIT = BIT(2), +/** + * @QLINK_FRAME_TX_FLAG_8023: frame has a 802.3 header; if not set, frame + * is a 802.11 encapsulated. + */ +enum qlink_frame_tx_flags { + QLINK_FRAME_TX_FLAG_OFFCHAN = BIT(0), + QLINK_FRAME_TX_FLAG_NO_CCK = BIT(1), + QLINK_FRAME_TX_FLAG_ACK_NOWAIT = BIT(2), + QLINK_FRAME_TX_FLAG_8023 = BIT(3), }; /** - * struct qlink_cmd_mgmt_frame_tx - data for QLINK_CMD_SEND_MGMT_FRAME command + * struct qlink_cmd_frame_tx - data for QLINK_CMD_SEND_FRAME command * * @cookie: opaque request identifier. * @freq: Frequency to use for frame transmission. - * @flags: Transmission flags, one of &enum qlink_mgmt_frame_tx_flags. + * @flags: Transmission flags, one of &enum qlink_frame_tx_flags. * @frame_data: frame to transmit. */ -struct qlink_cmd_mgmt_frame_tx { +struct qlink_cmd_frame_tx { struct qlink_cmd chdr; __le32 cookie; __le16 freq; @@ -580,12 +586,22 @@ enum qlink_user_reg_hint_type { * @initiator: which entity sent the request, one of &enum qlink_reg_initiator. * @user_reg_hint_type: type of hint for QLINK_REGDOM_SET_BY_USER request, one * of &enum qlink_user_reg_hint_type. + * @num_channels: number of &struct qlink_tlv_channel in a variable portion of a + * payload. + * @slave_radar: whether slave device should enable radar detection. + * @dfs_region: one of &enum qlink_dfs_regions. + * @info: variable portion of regulatory notifier callback. */ struct qlink_cmd_reg_notify { struct qlink_cmd chdr; u8 alpha2[2]; u8 initiator; u8 user_reg_hint_type; + u8 num_channels; + u8 dfs_region; + u8 slave_radar; + u8 rsvd[1]; + u8 info[0]; } __packed; /** @@ -765,6 +781,18 @@ struct qlink_resp { } __packed; /** + * enum qlink_dfs_regions - regulatory DFS regions + * + * Corresponds to &enum nl80211_dfs_regions. + */ +enum qlink_dfs_regions { + QLINK_DFS_UNSET = 0, + QLINK_DFS_FCC = 1, + QLINK_DFS_ETSI = 2, + QLINK_DFS_JP = 3, +}; + +/** * struct qlink_resp_get_mac_info - response for QLINK_CMD_MAC_INFO command * * Data describing specific physical device providing wireless MAC @@ -779,6 +807,10 @@ struct qlink_resp { * @bands_cap: wireless bands WMAC can operate in, bitmap of &enum qlink_band. * @max_ap_assoc_sta: Maximum number of associations supported by WMAC. * @radar_detect_widths: bitmask of channels BW for which WMAC can detect radar. + * @alpha2: country code ID firmware is configured to. + * @n_reg_rules: number of regulatory rules TLVs in variable portion of the + * message. + * @dfs_region: regulatory DFS region, one of &enum qlink_dfs_regions. * @var_info: variable-length WMAC info data. */ struct qlink_resp_get_mac_info { @@ -792,23 +824,14 @@ struct qlink_resp_get_mac_info { __le16 radar_detect_widths; __le32 max_acl_mac_addrs; u8 bands_cap; + u8 alpha2[2]; + u8 n_reg_rules; + u8 dfs_region; u8 rsvd[1]; u8 var_info[0]; } __packed; /** - * enum qlink_dfs_regions - regulatory DFS regions - * - * Corresponds to &enum nl80211_dfs_regions. - */ -enum qlink_dfs_regions { - QLINK_DFS_UNSET = 0, - QLINK_DFS_FCC = 1, - QLINK_DFS_ETSI = 2, - QLINK_DFS_JP = 3, -}; - -/** * struct qlink_resp_get_hw_info - response for QLINK_CMD_GET_HW_INFO command * * Description of wireless hardware capabilities and features. @@ -820,11 +843,7 @@ enum qlink_dfs_regions { * @mac_bitmap: Bitmap of MAC IDs that are active and can be used in firmware. * @total_tx_chains: total number of transmit chains used by device. * @total_rx_chains: total number of receive chains. - * @alpha2: country code ID firmware is configured to. - * @n_reg_rules: number of regulatory rules TLVs in variable portion of the - * message. - * @dfs_region: regulatory DFS region, one of @enum qlink_dfs_region. - * @info: variable-length HW info, can contain QTN_TLV_ID_REG_RULE. + * @info: variable-length HW info. */ struct qlink_resp_get_hw_info { struct qlink_resp rhdr; @@ -838,9 +857,6 @@ struct qlink_resp_get_hw_info { u8 mac_bitmap; u8 total_tx_chain; u8 total_rx_chain; - u8 alpha2[2]; - u8 n_reg_rules; - u8 dfs_region; u8 info[0]; } __packed; @@ -1148,6 +1164,13 @@ struct qlink_event_external_auth { * carried by QTN_TLV_ID_STA_STATS_MAP. * @QTN_TLV_ID_MAX_SCAN_SSIDS: maximum number of SSIDs the device can scan * for in any given scan. + * @QTN_TLV_ID_SCAN_DWELL_ACTIVE: time spent on a single channel for an active + * scan. + * @QTN_TLV_ID_SCAN_DWELL_PASSIVE: time spent on a single channel for a passive + * scan. + * @QTN_TLV_ID_SCAN_SAMPLE_DURATION: total duration of sampling a single channel + * during a scan including off-channel dwell time and operating channel + * time. */ enum qlink_tlv_id { QTN_TLV_ID_FRAG_THRESH = 0x0201, @@ -1180,7 +1203,9 @@ enum qlink_tlv_id { QTN_TLV_ID_WOWLAN_CAPAB = 0x0410, QTN_TLV_ID_WOWLAN_PATTERN = 0x0411, QTN_TLV_ID_SCAN_FLUSH = 0x0412, - QTN_TLV_ID_SCAN_DWELL = 0x0413, + QTN_TLV_ID_SCAN_DWELL_ACTIVE = 0x0413, + QTN_TLV_ID_SCAN_DWELL_PASSIVE = 0x0416, + QTN_TLV_ID_SCAN_SAMPLE_DURATION = 0x0417, }; struct qlink_tlv_hdr { diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c index 72bfd17cb687..1a972bce7b8b 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c @@ -182,3 +182,120 @@ void qlink_acl_data_cfg2q(const struct cfg80211_acl_data *acl, memcpy(qacl->mac_addrs, acl->mac_addrs, acl->n_acl_entries * sizeof(*qacl->mac_addrs)); } + +enum qlink_band qlink_utils_band_cfg2q(enum nl80211_band band) +{ + switch (band) { + case NL80211_BAND_2GHZ: + return QLINK_BAND_2GHZ; + case NL80211_BAND_5GHZ: + return QLINK_BAND_5GHZ; + case NL80211_BAND_60GHZ: + return QLINK_BAND_60GHZ; + default: + return -EINVAL; + } +} + +enum qlink_dfs_state qlink_utils_dfs_state_cfg2q(enum nl80211_dfs_state state) +{ + switch (state) { + case NL80211_DFS_USABLE: + return QLINK_DFS_USABLE; + case NL80211_DFS_AVAILABLE: + return QLINK_DFS_AVAILABLE; + case NL80211_DFS_UNAVAILABLE: + default: + return QLINK_DFS_UNAVAILABLE; + } +} + +u32 qlink_utils_chflags_cfg2q(u32 cfgflags) +{ + u32 flags = 0; + + if (cfgflags & IEEE80211_CHAN_DISABLED) + flags |= QLINK_CHAN_DISABLED; + + if (cfgflags & IEEE80211_CHAN_NO_IR) + flags |= QLINK_CHAN_NO_IR; + + if (cfgflags & IEEE80211_CHAN_RADAR) + flags |= QLINK_CHAN_RADAR; + + if (cfgflags & IEEE80211_CHAN_NO_HT40PLUS) + flags |= QLINK_CHAN_NO_HT40PLUS; + + if (cfgflags & IEEE80211_CHAN_NO_HT40MINUS) + flags |= QLINK_CHAN_NO_HT40MINUS; + + if (cfgflags & IEEE80211_CHAN_NO_80MHZ) + flags |= QLINK_CHAN_NO_80MHZ; + + if (cfgflags & IEEE80211_CHAN_NO_160MHZ) + flags |= QLINK_CHAN_NO_160MHZ; + + return flags; +} + +static u32 qtnf_reg_rule_flags_parse(u32 qflags) +{ + u32 flags = 0; + + if (qflags & QLINK_RRF_NO_OFDM) + flags |= NL80211_RRF_NO_OFDM; + + if (qflags & QLINK_RRF_NO_CCK) + flags |= NL80211_RRF_NO_CCK; + + if (qflags & QLINK_RRF_NO_INDOOR) + flags |= NL80211_RRF_NO_INDOOR; + + if (qflags & QLINK_RRF_NO_OUTDOOR) + flags |= NL80211_RRF_NO_OUTDOOR; + + if (qflags & QLINK_RRF_DFS) + flags |= NL80211_RRF_DFS; + + if (qflags & QLINK_RRF_PTP_ONLY) + flags |= NL80211_RRF_PTP_ONLY; + + if (qflags & QLINK_RRF_PTMP_ONLY) + flags |= NL80211_RRF_PTMP_ONLY; + + if (qflags & QLINK_RRF_NO_IR) + flags |= NL80211_RRF_NO_IR; + + if (qflags & QLINK_RRF_AUTO_BW) + flags |= NL80211_RRF_AUTO_BW; + + if (qflags & QLINK_RRF_IR_CONCURRENT) + flags |= NL80211_RRF_IR_CONCURRENT; + + if (qflags & QLINK_RRF_NO_HT40MINUS) + flags |= NL80211_RRF_NO_HT40MINUS; + + if (qflags & QLINK_RRF_NO_HT40PLUS) + flags |= NL80211_RRF_NO_HT40PLUS; + + if (qflags & QLINK_RRF_NO_80MHZ) + flags |= NL80211_RRF_NO_80MHZ; + + if (qflags & QLINK_RRF_NO_160MHZ) + flags |= NL80211_RRF_NO_160MHZ; + + return flags; +} + +void qlink_utils_regrule_q2nl(struct ieee80211_reg_rule *rule, + const struct qlink_tlv_reg_rule *tlv) +{ + rule->freq_range.start_freq_khz = le32_to_cpu(tlv->start_freq_khz); + rule->freq_range.end_freq_khz = le32_to_cpu(tlv->end_freq_khz); + rule->freq_range.max_bandwidth_khz = + le32_to_cpu(tlv->max_bandwidth_khz); + rule->power_rule.max_antenna_gain = le32_to_cpu(tlv->max_antenna_gain); + rule->power_rule.max_eirp = le32_to_cpu(tlv->max_eirp); + rule->dfs_cac_ms = le32_to_cpu(tlv->dfs_cac_ms); + rule->flags = qtnf_reg_rule_flags_parse(le32_to_cpu(tlv->flags)); +} diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h index 781ea7fe79f2..f873beed2ae7 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h @@ -79,5 +79,10 @@ bool qtnf_utils_is_bit_set(const u8 *arr, unsigned int bit, unsigned int arr_max_len); void qlink_acl_data_cfg2q(const struct cfg80211_acl_data *acl, struct qlink_acl_data *qacl); +enum qlink_band qlink_utils_band_cfg2q(enum nl80211_band band); +enum qlink_dfs_state qlink_utils_dfs_state_cfg2q(enum nl80211_dfs_state state); +u32 qlink_utils_chflags_cfg2q(u32 cfgflags); +void qlink_utils_regrule_q2nl(struct ieee80211_reg_rule *rule, + const struct qlink_tlv_reg_rule *tlv_rule); #endif /* _QTN_FMAC_QLINK_UTIL_H_ */ diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800.h b/drivers/net/wireless/ralink/rt2x00/rt2800.h index b05ed2f3025a..06c38bafd2ca 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h @@ -48,7 +48,8 @@ * RF2853 2.4G/5G 3T3R * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390) * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) - * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) + * RF3053 2.4G/5G 3T3R(RT3563/RT3573/RT3593) + * RF3853 2.4G/5G 3T3R(RT3883/RT3662) * RF5592 2.4G/5G 2T2R * RF3070 2.4G 1T1R * RF5360 2.4G 1T1R @@ -72,6 +73,7 @@ #define RF5592 0x000f #define RF3070 0x3070 #define RF3290 0x3290 +#define RF3853 0x3853 #define RF5350 0x5350 #define RF5360 0x5360 #define RF5362 0x5362 @@ -1726,6 +1728,20 @@ #define TX_PWR_CFG_9B_STBC_MCS7 FIELD32(0x000000ff) /* + * TX_TXBF_CFG: + */ +#define TX_TXBF_CFG_0 0x138c +#define TX_TXBF_CFG_1 0x13a4 +#define TX_TXBF_CFG_2 0x13a8 +#define TX_TXBF_CFG_3 0x13ac + +/* + * TX_FBK_CFG_3S: + */ +#define TX_FBK_CFG_3S_0 0x13c4 +#define TX_FBK_CFG_3S_1 0x13c8 + +/* * RX_FILTER_CFG: RX configuration register. */ #define RX_FILTER_CFG 0x1400 @@ -2296,6 +2312,7 @@ struct mac_iveiv_entry { /* * RFCSR 2: */ +#define RFCSR2_RESCAL_BP FIELD8(0x40) #define RFCSR2_RESCAL_EN FIELD8(0x80) #define RFCSR2_RX2_EN_MT7620 FIELD8(0x02) #define RFCSR2_TX2_EN_MT7620 FIELD8(0x20) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index a03b5284a050..c8f2bf1243fd 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -381,7 +381,8 @@ static unsigned int rt2800_eeprom_word_index(struct rt2x00_dev *rt2x00dev, wiphy_name(rt2x00dev->hw->wiphy), word)) return 0; - if (rt2x00_rt(rt2x00dev, RT3593)) + if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) map = rt2800_eeprom_map_ext; else map = rt2800_eeprom_map; @@ -590,6 +591,7 @@ void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev, { switch (rt2x00dev->chip.rt) { case RT3593: + case RT3883: *txwi_size = TXWI_DESC_SIZE_4WORDS; *rxwi_size = RXWI_DESC_SIZE_5WORDS; break; @@ -1100,7 +1102,7 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi, } EXPORT_SYMBOL_GPL(rt2800_txdone_entry); -void rt2800_txdone(struct rt2x00_dev *rt2x00dev) +void rt2800_txdone(struct rt2x00_dev *rt2x00dev, unsigned int quota) { struct data_queue *queue; struct queue_entry *entry; @@ -1108,7 +1110,7 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev) u8 qid; bool match; - while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) { + while (quota-- > 0 && kfifo_get(&rt2x00dev->txstatus_fifo, ®)) { /* * TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus qid is * guaranteed to be one of the TX QIDs . @@ -1164,15 +1166,6 @@ bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev) struct data_queue *queue; struct queue_entry *entry; - if (!test_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags)) { - unsigned long tout = msecs_to_jiffies(1000); - - if (time_before(jiffies, rt2x00dev->last_nostatus_check + tout)) - return false; - } - - rt2x00dev->last_nostatus_check = jiffies; - tx_queue_for_each(rt2x00dev, queue) { entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); if (rt2800_entry_txstatus_timeout(rt2x00dev, entry)) @@ -1183,6 +1176,23 @@ bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev) } EXPORT_SYMBOL_GPL(rt2800_txstatus_timeout); +/* + * test if there is an entry in any TX queue for which DMA is done + * but the TX status has not been returned yet + */ +bool rt2800_txstatus_pending(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + + tx_queue_for_each(rt2x00dev, queue) { + if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) != + rt2x00queue_get_entry(queue, Q_INDEX_DONE)) + return true; + } + return false; +} +EXPORT_SYMBOL_GPL(rt2800_txstatus_pending); + void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; @@ -2172,7 +2182,8 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) rt2800_bbp_write(rt2x00dev, 3, r3); rt2800_bbp_write(rt2x00dev, 1, r1); - if (rt2x00_rt(rt2x00dev, RT3593)) { + if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) { if (ant->rx_chain_num == 1) rt2800_bbp_write(rt2x00dev, 86, 0x00); else @@ -2194,7 +2205,8 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev, eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_LNA); lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); } else if (libconf->rf.channel <= 128) { - if (rt2x00_rt(rt2x00dev, RT3593)) { + if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) { eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2); lna_gain = rt2x00_get_field16(eeprom, EEPROM_EXT_LNA2_A1); @@ -2204,7 +2216,8 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev, EEPROM_RSSI_BG2_LNA_A1); } } else { - if (rt2x00_rt(rt2x00dev, RT3593)) { + if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) { eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2); lna_gain = rt2x00_get_field16(eeprom, EEPROM_EXT_LNA2_A2); @@ -2872,6 +2885,211 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev, } } +static void rt2800_config_channel_rf3853(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) +{ + u8 rfcsr; + u8 bbp; + u8 pwr1, pwr2, pwr3; + + const bool txbf_enabled = false; /* TODO */ + + /* TODO: add band selection */ + + if (rf->channel <= 14) + rt2800_rfcsr_write(rt2x00dev, 6, 0x40); + else if (rf->channel < 132) + rt2800_rfcsr_write(rt2x00dev, 6, 0x80); + else + rt2800_rfcsr_write(rt2x00dev, 6, 0x40); + + rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); + rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3); + + if (rf->channel <= 14) + rt2800_rfcsr_write(rt2x00dev, 11, 0x46); + else + rt2800_rfcsr_write(rt2x00dev, 11, 0x48); + + if (rf->channel <= 14) + rt2800_rfcsr_write(rt2x00dev, 12, 0x1a); + else + rt2800_rfcsr_write(rt2x00dev, 12, 0x52); + + rt2800_rfcsr_write(rt2x00dev, 13, 0x12); + + rfcsr = rt2800_rfcsr_read(rt2x00dev, 1); + rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); + rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); + + switch (rt2x00dev->default_ant.tx_chain_num) { + case 3: + rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); + /* fallthrough */ + case 2: + rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); + /* fallthrough */ + case 1: + rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); + break; + } + + switch (rt2x00dev->default_ant.rx_chain_num) { + case 3: + rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); + /* fallthrough */ + case 2: + rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); + /* fallthrough */ + case 1: + rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); + break; + } + rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + + rt2800_freq_cal_mode1(rt2x00dev); + + rfcsr = rt2800_rfcsr_read(rt2x00dev, 30); + if (!conf_is_ht40(conf)) + rfcsr &= ~(0x06); + else + rfcsr |= 0x06; + rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); + + if (rf->channel <= 14) + rt2800_rfcsr_write(rt2x00dev, 31, 0xa0); + else + rt2800_rfcsr_write(rt2x00dev, 31, 0x80); + + if (conf_is_ht40(conf)) + rt2800_rfcsr_write(rt2x00dev, 32, 0x80); + else + rt2800_rfcsr_write(rt2x00dev, 32, 0xd8); + + if (rf->channel <= 14) + rt2800_rfcsr_write(rt2x00dev, 34, 0x3c); + else + rt2800_rfcsr_write(rt2x00dev, 34, 0x20); + + /* loopback RF_BS */ + rfcsr = rt2800_rfcsr_read(rt2x00dev, 36); + if (rf->channel <= 14) + rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 1); + else + rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 0); + rt2800_rfcsr_write(rt2x00dev, 36, rfcsr); + + if (rf->channel <= 14) + rfcsr = 0x23; + else if (rf->channel < 100) + rfcsr = 0x36; + else if (rf->channel < 132) + rfcsr = 0x32; + else + rfcsr = 0x30; + + if (txbf_enabled) + rfcsr |= 0x40; + + rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); + + if (rf->channel <= 14) + rt2800_rfcsr_write(rt2x00dev, 44, 0x93); + else + rt2800_rfcsr_write(rt2x00dev, 44, 0x9b); + + if (rf->channel <= 14) + rfcsr = 0xbb; + else if (rf->channel < 100) + rfcsr = 0xeb; + else if (rf->channel < 132) + rfcsr = 0xb3; + else + rfcsr = 0x9b; + rt2800_rfcsr_write(rt2x00dev, 45, rfcsr); + + if (rf->channel <= 14) + rfcsr = 0x8e; + else + rfcsr = 0x8a; + + if (txbf_enabled) + rfcsr |= 0x20; + + rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); + + rt2800_rfcsr_write(rt2x00dev, 50, 0x86); + + rfcsr = rt2800_rfcsr_read(rt2x00dev, 51); + if (rf->channel <= 14) + rt2800_rfcsr_write(rt2x00dev, 51, 0x75); + else + rt2800_rfcsr_write(rt2x00dev, 51, 0x51); + + rfcsr = rt2800_rfcsr_read(rt2x00dev, 52); + if (rf->channel <= 14) + rt2800_rfcsr_write(rt2x00dev, 52, 0x45); + else + rt2800_rfcsr_write(rt2x00dev, 52, 0x05); + + if (rf->channel <= 14) { + pwr1 = info->default_power1 & 0x1f; + pwr2 = info->default_power2 & 0x1f; + pwr3 = info->default_power3 & 0x1f; + } else { + pwr1 = 0x48 | ((info->default_power1 & 0x18) << 1) | + (info->default_power1 & 0x7); + pwr2 = 0x48 | ((info->default_power2 & 0x18) << 1) | + (info->default_power2 & 0x7); + pwr3 = 0x48 | ((info->default_power3 & 0x18) << 1) | + (info->default_power3 & 0x7); + } + + rt2800_rfcsr_write(rt2x00dev, 53, pwr1); + rt2800_rfcsr_write(rt2x00dev, 54, pwr2); + rt2800_rfcsr_write(rt2x00dev, 55, pwr3); + + rt2x00_dbg(rt2x00dev, "Channel:%d, pwr1:%02x, pwr2:%02x, pwr3:%02x\n", + rf->channel, pwr1, pwr2, pwr3); + + bbp = (info->default_power1 >> 5) | + ((info->default_power2 & 0xe0) >> 1); + rt2800_bbp_write(rt2x00dev, 109, bbp); + + bbp = rt2800_bbp_read(rt2x00dev, 110); + bbp &= 0x0f; + bbp |= (info->default_power3 & 0xe0) >> 1; + rt2800_bbp_write(rt2x00dev, 110, bbp); + + rfcsr = rt2800_rfcsr_read(rt2x00dev, 57); + if (rf->channel <= 14) + rt2800_rfcsr_write(rt2x00dev, 57, 0x6e); + else + rt2800_rfcsr_write(rt2x00dev, 57, 0x3e); + + /* Enable RF tuning */ + rfcsr = rt2800_rfcsr_read(rt2x00dev, 3); + rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); + rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); + + udelay(2000); + + bbp = rt2800_bbp_read(rt2x00dev, 49); + /* clear update flag */ + rt2800_bbp_write(rt2x00dev, 49, bbp & 0xfe); + rt2800_bbp_write(rt2x00dev, 49, bbp); + + /* TODO: add calibration for TxBF */ +} + #define POWER_BOUND 0x27 #define POWER_BOUND_5G 0x2b @@ -3675,19 +3893,51 @@ static char rt2800_txpower_to_dev(struct rt2x00_dev *rt2x00dev, unsigned int channel, char txpower) { - if (rt2x00_rt(rt2x00dev, RT3593)) + if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) txpower = rt2x00_get_field8(txpower, EEPROM_TXPOWER_ALC); if (channel <= 14) return clamp_t(char, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER); - if (rt2x00_rt(rt2x00dev, RT3593)) + if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) return clamp_t(char, txpower, MIN_A_TXPOWER_3593, MAX_A_TXPOWER_3593); else return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER); } +static void rt3883_bbp_adjust(struct rt2x00_dev *rt2x00dev, + struct rf_channel *rf) +{ + u8 bbp; + + bbp = (rf->channel > 14) ? 0x48 : 0x38; + rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, bbp); + + rt2800_bbp_write(rt2x00dev, 69, 0x12); + + if (rf->channel <= 14) { + rt2800_bbp_write(rt2x00dev, 70, 0x0a); + } else { + /* Disable CCK packet detection */ + rt2800_bbp_write(rt2x00dev, 70, 0x00); + } + + rt2800_bbp_write(rt2x00dev, 73, 0x10); + + if (rf->channel > 14) { + rt2800_bbp_write(rt2x00dev, 62, 0x1d); + rt2800_bbp_write(rt2x00dev, 63, 0x1d); + rt2800_bbp_write(rt2x00dev, 64, 0x1d); + } else { + rt2800_bbp_write(rt2x00dev, 62, 0x2d); + rt2800_bbp_write(rt2x00dev, 63, 0x2d); + rt2800_bbp_write(rt2x00dev, 64, 0x2d); + } +} + static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, struct rf_channel *rf, @@ -3706,6 +3956,12 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2800_txpower_to_dev(rt2x00dev, rf->channel, info->default_power3); + switch (rt2x00dev->chip.rt) { + case RT3883: + rt3883_bbp_adjust(rt2x00dev, rf); + break; + } + switch (rt2x00dev->chip.rf) { case RF2020: case RF3020: @@ -3726,6 +3982,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, case RF3322: rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info); break; + case RF3853: + rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info); + break; case RF3070: case RF5350: case RF5360: @@ -3807,6 +4066,15 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); rt2800_bbp_write(rt2x00dev, 77, 0x98); + } else if (rt2x00_rt(rt2x00dev, RT3883)) { + rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); + + if (rt2x00dev->default_ant.rx_chain_num > 1) + rt2800_bbp_write(rt2x00dev, 86, 0x46); + else + rt2800_bbp_write(rt2x00dev, 86, 0); } else { rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); @@ -3820,6 +4088,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, !rt2x00_rt(rt2x00dev, RT6352)) { if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { rt2800_bbp_write(rt2x00dev, 82, 0x62); + rt2800_bbp_write(rt2x00dev, 82, 0x62); rt2800_bbp_write(rt2x00dev, 75, 0x46); } else { if (rt2x00_rt(rt2x00dev, RT3593)) @@ -3828,19 +4097,22 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2800_bbp_write(rt2x00dev, 82, 0x84); rt2800_bbp_write(rt2x00dev, 75, 0x50); } - if (rt2x00_rt(rt2x00dev, RT3593)) + if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) rt2800_bbp_write(rt2x00dev, 83, 0x8a); } } else { if (rt2x00_rt(rt2x00dev, RT3572)) rt2800_bbp_write(rt2x00dev, 82, 0x94); - else if (rt2x00_rt(rt2x00dev, RT3593)) + else if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) rt2800_bbp_write(rt2x00dev, 82, 0x82); else if (!rt2x00_rt(rt2x00dev, RT6352)) rt2800_bbp_write(rt2x00dev, 82, 0xf2); - if (rt2x00_rt(rt2x00dev, RT3593)) + if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) rt2800_bbp_write(rt2x00dev, 83, 0x9a); if (rt2x00_has_cap_external_lna_a(rt2x00dev)) @@ -3976,6 +4248,23 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, usleep_range(1000, 1500); } + if (rt2x00_rt(rt2x00dev, RT3883)) { + if (!conf_is_ht40(conf)) + rt2800_bbp_write(rt2x00dev, 105, 0x34); + else + rt2800_bbp_write(rt2x00dev, 105, 0x04); + + /* AGC init */ + if (rf->channel <= 14) + reg = 0x2e + rt2x00dev->lna_gain; + else + reg = 0x20 + ((rt2x00dev->lna_gain * 5) / 3); + + rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); + + usleep_range(1000, 1500); + } + if (rt2x00_rt(rt2x00dev, RT5592) || rt2x00_rt(rt2x00dev, RT6352)) { reg = 0x10; if (!conf_is_ht40(conf)) { @@ -4235,6 +4524,9 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, if (rt2x00_rt(rt2x00dev, RT3593)) return min_t(u8, txpower, 0xc); + if (rt2x00_rt(rt2x00dev, RT3883)) + return min_t(u8, txpower, 0xf); + if (rt2x00_has_cap_power_limit(rt2x00dev)) { /* * Check if eirp txpower exceed txpower_limit. @@ -4996,7 +5288,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, struct ieee80211_channel *chan, int power_level) { - if (rt2x00_rt(rt2x00dev, RT3593)) + if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) rt2800_config_txpower_rt3593(rt2x00dev, chan, power_level); else if (rt2x00_rt(rt2x00dev, RT6352)) rt2800_config_txpower_rt6352(rt2x00dev, chan, power_level); @@ -5043,6 +5336,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev) case RF3053: case RF3070: case RF3290: + case RF3853: case RF5350: case RF5360: case RF5362: @@ -5243,7 +5537,8 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) else vgc = 0x2e + rt2x00dev->lna_gain; } else { /* 5GHZ band */ - if (rt2x00_rt(rt2x00dev, RT3593)) + if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3; else if (rt2x00_rt(rt2x00dev, RT5592)) vgc = 0x24 + (2 * rt2x00dev->lna_gain); @@ -5263,7 +5558,8 @@ static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev, { if (qual->vgc_level != vgc_level) { if (rt2x00_rt(rt2x00dev, RT3572) || - rt2x00_rt(rt2x00dev, RT3593)) { + rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) { rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, vgc_level); } else if (rt2x00_rt(rt2x00dev, RT5592)) { @@ -5310,6 +5606,11 @@ void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, } break; + case RT3883: + if (qual->rssi > -65) + vgc += 0x10; + break; + case RT5592: if (qual->rssi > -65) vgc += 0x20; @@ -5462,6 +5763,12 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); } + } else if (rt2x00_rt(rt2x00dev, RT3883)) { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402); + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); + rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00040000); + rt2800_register_write(rt2x00dev, TX_TXBF_CFG_0, 0x8000fc21); + rt2800_register_write(rt2x00dev, TX_TXBF_CFG_3, 0x00009c40); } else if (rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392) || rt2x00_rt(rt2x00dev, RT6352)) { @@ -5675,6 +5982,11 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002; rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg); + if (rt2x00_rt(rt2x00dev, RT3883)) { + rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_0, 0x12111008); + rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_1, 0x16151413); + } + reg = rt2800_register_read(rt2x00dev, TX_RTS_CFG); rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 7); rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, @@ -6291,6 +6603,47 @@ static void rt2800_init_bbp_3593(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 103, 0xc0); } +static void rt2800_init_bbp_3883(struct rt2x00_dev *rt2x00dev) +{ + rt2800_init_bbp_early(rt2x00dev); + + rt2800_bbp_write(rt2x00dev, 4, 0x50); + rt2800_bbp_write(rt2x00dev, 47, 0x48); + + rt2800_bbp_write(rt2x00dev, 86, 0x46); + rt2800_bbp_write(rt2x00dev, 88, 0x90); + + rt2800_bbp_write(rt2x00dev, 92, 0x02); + + rt2800_bbp_write(rt2x00dev, 103, 0xc0); + rt2800_bbp_write(rt2x00dev, 104, 0x92); + rt2800_bbp_write(rt2x00dev, 105, 0x34); + rt2800_bbp_write(rt2x00dev, 106, 0x12); + rt2800_bbp_write(rt2x00dev, 120, 0x50); + rt2800_bbp_write(rt2x00dev, 137, 0x0f); + rt2800_bbp_write(rt2x00dev, 163, 0x9d); + + /* Set ITxBF timeout to 0x9C40=1000msec */ + rt2800_bbp_write(rt2x00dev, 179, 0x02); + rt2800_bbp_write(rt2x00dev, 180, 0x00); + rt2800_bbp_write(rt2x00dev, 182, 0x40); + rt2800_bbp_write(rt2x00dev, 180, 0x01); + rt2800_bbp_write(rt2x00dev, 182, 0x9c); + + rt2800_bbp_write(rt2x00dev, 179, 0x00); + + /* Reprogram the inband interface to put right values in RXWI */ + rt2800_bbp_write(rt2x00dev, 142, 0x04); + rt2800_bbp_write(rt2x00dev, 143, 0x3b); + rt2800_bbp_write(rt2x00dev, 142, 0x06); + rt2800_bbp_write(rt2x00dev, 143, 0xa0); + rt2800_bbp_write(rt2x00dev, 142, 0x07); + rt2800_bbp_write(rt2x00dev, 143, 0xa1); + rt2800_bbp_write(rt2x00dev, 142, 0x08); + rt2800_bbp_write(rt2x00dev, 143, 0xa2); + rt2800_bbp_write(rt2x00dev, 148, 0xc8); +} + static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) { int ant, div_mode; @@ -6735,6 +7088,9 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) case RT3593: rt2800_init_bbp_3593(rt2x00dev); return; + case RT3883: + rt2800_init_bbp_3883(rt2x00dev); + return; case RT5390: case RT5392: rt2800_init_bbp_53xx(rt2x00dev); @@ -7606,6 +7962,144 @@ static void rt2800_init_rfcsr_5350(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 63, 0x00); } +static void rt2800_init_rfcsr_3883(struct rt2x00_dev *rt2x00dev) +{ + u8 rfcsr; + + /* TODO: get the actual ECO value from the SoC */ + const unsigned int eco = 5; + + rt2800_rf_init_calibration(rt2x00dev, 2); + + rt2800_rfcsr_write(rt2x00dev, 0, 0xe0); + rt2800_rfcsr_write(rt2x00dev, 1, 0x03); + rt2800_rfcsr_write(rt2x00dev, 2, 0x50); + rt2800_rfcsr_write(rt2x00dev, 3, 0x20); + rt2800_rfcsr_write(rt2x00dev, 4, 0x00); + rt2800_rfcsr_write(rt2x00dev, 5, 0x00); + rt2800_rfcsr_write(rt2x00dev, 6, 0x40); + rt2800_rfcsr_write(rt2x00dev, 7, 0x00); + rt2800_rfcsr_write(rt2x00dev, 8, 0x5b); + rt2800_rfcsr_write(rt2x00dev, 9, 0x08); + rt2800_rfcsr_write(rt2x00dev, 10, 0xd3); + rt2800_rfcsr_write(rt2x00dev, 11, 0x48); + rt2800_rfcsr_write(rt2x00dev, 12, 0x1a); + rt2800_rfcsr_write(rt2x00dev, 13, 0x12); + rt2800_rfcsr_write(rt2x00dev, 14, 0x00); + rt2800_rfcsr_write(rt2x00dev, 15, 0x00); + rt2800_rfcsr_write(rt2x00dev, 16, 0x00); + + /* RFCSR 17 will be initialized later based on the + * frequency offset stored in the EEPROM + */ + + rt2800_rfcsr_write(rt2x00dev, 18, 0x40); + rt2800_rfcsr_write(rt2x00dev, 19, 0x00); + rt2800_rfcsr_write(rt2x00dev, 20, 0x00); + rt2800_rfcsr_write(rt2x00dev, 21, 0x00); + rt2800_rfcsr_write(rt2x00dev, 22, 0x20); + rt2800_rfcsr_write(rt2x00dev, 23, 0xc0); + rt2800_rfcsr_write(rt2x00dev, 24, 0x00); + rt2800_rfcsr_write(rt2x00dev, 25, 0x00); + rt2800_rfcsr_write(rt2x00dev, 26, 0x00); + rt2800_rfcsr_write(rt2x00dev, 27, 0x00); + rt2800_rfcsr_write(rt2x00dev, 28, 0x00); + rt2800_rfcsr_write(rt2x00dev, 29, 0x00); + rt2800_rfcsr_write(rt2x00dev, 30, 0x10); + rt2800_rfcsr_write(rt2x00dev, 31, 0x80); + rt2800_rfcsr_write(rt2x00dev, 32, 0x80); + rt2800_rfcsr_write(rt2x00dev, 33, 0x00); + rt2800_rfcsr_write(rt2x00dev, 34, 0x20); + rt2800_rfcsr_write(rt2x00dev, 35, 0x00); + rt2800_rfcsr_write(rt2x00dev, 36, 0x00); + rt2800_rfcsr_write(rt2x00dev, 37, 0x00); + rt2800_rfcsr_write(rt2x00dev, 38, 0x86); + rt2800_rfcsr_write(rt2x00dev, 39, 0x23); + rt2800_rfcsr_write(rt2x00dev, 40, 0x00); + rt2800_rfcsr_write(rt2x00dev, 41, 0x00); + rt2800_rfcsr_write(rt2x00dev, 42, 0x00); + rt2800_rfcsr_write(rt2x00dev, 43, 0x00); + rt2800_rfcsr_write(rt2x00dev, 44, 0x93); + rt2800_rfcsr_write(rt2x00dev, 45, 0xbb); + rt2800_rfcsr_write(rt2x00dev, 46, 0x60); + rt2800_rfcsr_write(rt2x00dev, 47, 0x00); + rt2800_rfcsr_write(rt2x00dev, 48, 0x00); + rt2800_rfcsr_write(rt2x00dev, 49, 0x8e); + rt2800_rfcsr_write(rt2x00dev, 50, 0x86); + rt2800_rfcsr_write(rt2x00dev, 51, 0x51); + rt2800_rfcsr_write(rt2x00dev, 52, 0x05); + rt2800_rfcsr_write(rt2x00dev, 53, 0x76); + rt2800_rfcsr_write(rt2x00dev, 54, 0x76); + rt2800_rfcsr_write(rt2x00dev, 55, 0x76); + rt2800_rfcsr_write(rt2x00dev, 56, 0xdb); + rt2800_rfcsr_write(rt2x00dev, 57, 0x3e); + rt2800_rfcsr_write(rt2x00dev, 58, 0x00); + rt2800_rfcsr_write(rt2x00dev, 59, 0x00); + rt2800_rfcsr_write(rt2x00dev, 60, 0x00); + rt2800_rfcsr_write(rt2x00dev, 61, 0x00); + rt2800_rfcsr_write(rt2x00dev, 62, 0x00); + rt2800_rfcsr_write(rt2x00dev, 63, 0x00); + + /* TODO: rx filter calibration? */ + + rt2800_bbp_write(rt2x00dev, 137, 0x0f); + + rt2800_bbp_write(rt2x00dev, 163, 0x9d); + + rt2800_bbp_write(rt2x00dev, 105, 0x05); + + rt2800_bbp_write(rt2x00dev, 179, 0x02); + rt2800_bbp_write(rt2x00dev, 180, 0x00); + rt2800_bbp_write(rt2x00dev, 182, 0x40); + rt2800_bbp_write(rt2x00dev, 180, 0x01); + rt2800_bbp_write(rt2x00dev, 182, 0x9c); + + rt2800_bbp_write(rt2x00dev, 179, 0x00); + + rt2800_bbp_write(rt2x00dev, 142, 0x04); + rt2800_bbp_write(rt2x00dev, 143, 0x3b); + rt2800_bbp_write(rt2x00dev, 142, 0x06); + rt2800_bbp_write(rt2x00dev, 143, 0xa0); + rt2800_bbp_write(rt2x00dev, 142, 0x07); + rt2800_bbp_write(rt2x00dev, 143, 0xa1); + rt2800_bbp_write(rt2x00dev, 142, 0x08); + rt2800_bbp_write(rt2x00dev, 143, 0xa2); + rt2800_bbp_write(rt2x00dev, 148, 0xc8); + + if (eco == 5) { + rt2800_rfcsr_write(rt2x00dev, 32, 0xd8); + rt2800_rfcsr_write(rt2x00dev, 33, 0x32); + } + + rfcsr = rt2800_rfcsr_read(rt2x00dev, 2); + rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_BP, 0); + rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1); + rt2800_rfcsr_write(rt2x00dev, 2, rfcsr); + msleep(1); + rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 0); + rt2800_rfcsr_write(rt2x00dev, 2, rfcsr); + + rfcsr = rt2800_rfcsr_read(rt2x00dev, 1); + rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); + rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + + rfcsr = rt2800_rfcsr_read(rt2x00dev, 6); + rfcsr |= 0xc0; + rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); + + rfcsr = rt2800_rfcsr_read(rt2x00dev, 22); + rfcsr |= 0x20; + rt2800_rfcsr_write(rt2x00dev, 22, rfcsr); + + rfcsr = rt2800_rfcsr_read(rt2x00dev, 46); + rfcsr |= 0x20; + rt2800_rfcsr_write(rt2x00dev, 46, rfcsr); + + rfcsr = rt2800_rfcsr_read(rt2x00dev, 20); + rfcsr &= ~0xee; + rt2800_rfcsr_write(rt2x00dev, 20, rfcsr); +} + static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) { rt2800_rf_init_calibration(rt2x00dev, 2); @@ -8448,6 +8942,9 @@ static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) case RT3390: rt2800_init_rfcsr_3390(rt2x00dev); break; + case RT3883: + rt2800_init_rfcsr_3883(rt2x00dev); + break; case RT3572: rt2800_init_rfcsr_3572(rt2x00dev); break; @@ -8653,7 +9150,8 @@ static u8 rt2800_get_txmixer_gain_24g(struct rt2x00_dev *rt2x00dev) { u16 word; - if (rt2x00_rt(rt2x00dev, RT3593)) + if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) return 0; word = rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG); @@ -8667,7 +9165,8 @@ static u8 rt2800_get_txmixer_gain_5g(struct rt2x00_dev *rt2x00dev) { u16 word; - if (rt2x00_rt(rt2x00dev, RT3593)) + if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) return 0; word = rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A); @@ -8773,7 +9272,8 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) word = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2); if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10) rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0); - if (!rt2x00_rt(rt2x00dev, RT3593)) { + if (!rt2x00_rt(rt2x00dev, RT3593) && + !rt2x00_rt(rt2x00dev, RT3883)) { if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 || rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff) rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1, @@ -8793,7 +9293,8 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) word = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2); if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10) rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0); - if (!rt2x00_rt(rt2x00dev, RT3593)) { + if (!rt2x00_rt(rt2x00dev, RT3593) && + !rt2x00_rt(rt2x00dev, RT3883)) { if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 || rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff) rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2, @@ -8801,7 +9302,8 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) } rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); - if (rt2x00_rt(rt2x00dev, RT3593)) { + if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) { word = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2); if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0x00 || rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff) @@ -8840,6 +9342,8 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) rf = rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID); else if (rt2x00_rt(rt2x00dev, RT3352)) rf = RF3322; + else if (rt2x00_rt(rt2x00dev, RT3883)) + rf = RF3853; else if (rt2x00_rt(rt2x00dev, RT5350)) rf = RF5350; else @@ -8860,6 +9364,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) case RF3290: case RF3320: case RF3322: + case RF3853: case RF5350: case RF5360: case RF5362: @@ -9146,6 +9651,66 @@ static const struct rf_channel rf_vals_3x_xtal20[] = { {14, 0xF0, 2, 0x18}, }; +static const struct rf_channel rf_vals_3853[] = { + {1, 241, 6, 2}, + {2, 241, 6, 7}, + {3, 242, 6, 2}, + {4, 242, 6, 7}, + {5, 243, 6, 2}, + {6, 243, 6, 7}, + {7, 244, 6, 2}, + {8, 244, 6, 7}, + {9, 245, 6, 2}, + {10, 245, 6, 7}, + {11, 246, 6, 2}, + {12, 246, 6, 7}, + {13, 247, 6, 2}, + {14, 248, 6, 4}, + + {36, 0x56, 8, 4}, + {38, 0x56, 8, 6}, + {40, 0x56, 8, 8}, + {44, 0x57, 8, 0}, + {46, 0x57, 8, 2}, + {48, 0x57, 8, 4}, + {52, 0x57, 8, 8}, + {54, 0x57, 8, 10}, + {56, 0x58, 8, 0}, + {60, 0x58, 8, 4}, + {62, 0x58, 8, 6}, + {64, 0x58, 8, 8}, + + {100, 0x5b, 8, 8}, + {102, 0x5b, 8, 10}, + {104, 0x5c, 8, 0}, + {108, 0x5c, 8, 4}, + {110, 0x5c, 8, 6}, + {112, 0x5c, 8, 8}, + {114, 0x5c, 8, 10}, + {116, 0x5d, 8, 0}, + {118, 0x5d, 8, 2}, + {120, 0x5d, 8, 4}, + {124, 0x5d, 8, 8}, + {126, 0x5d, 8, 10}, + {128, 0x5e, 8, 0}, + {132, 0x5e, 8, 4}, + {134, 0x5e, 8, 6}, + {136, 0x5e, 8, 8}, + {140, 0x5f, 8, 0}, + + {149, 0x5f, 8, 9}, + {151, 0x5f, 8, 11}, + {153, 0x60, 8, 1}, + {157, 0x60, 8, 5}, + {159, 0x60, 8, 7}, + {161, 0x60, 8, 9}, + {165, 0x61, 8, 1}, + {167, 0x61, 8, 3}, + {169, 0x61, 8, 5}, + {171, 0x61, 8, 7}, + {173, 0x61, 8, 9}, +}; + static const struct rf_channel rf_vals_5592_xtal20[] = { /* Channel, N, K, mod, R */ {1, 482, 4, 10, 3}, @@ -9409,6 +9974,11 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->channels = rf_vals_3x; break; + case RF3853: + spec->num_channels = ARRAY_SIZE(rf_vals_3853); + spec->channels = rf_vals_3853; + break; + case RF5592: reg = rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX); if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) { @@ -9528,6 +10098,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) case RF3053: case RF3070: case RF3290: + case RF3853: case RF5350: case RF5360: case RF5362: @@ -9570,6 +10141,7 @@ static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev) case RT3390: case RT3572: case RT3593: + case RT3883: case RT5350: case RT5390: case RT5392: diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h index 0dff2c7b3010..759eab2b70c3 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h @@ -195,9 +195,10 @@ void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *tx void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi, bool match); -void rt2800_txdone(struct rt2x00_dev *rt2x00dev); +void rt2800_txdone(struct rt2x00_dev *rt2x00dev, unsigned int quota); void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev); bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev); +bool rt2800_txstatus_pending(struct rt2x00_dev *rt2x00dev); void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); void rt2800_clear_beacon(struct queue_entry *entry); diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c index ddb88cfeace2..ecc4c9332ec7 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c @@ -255,26 +255,12 @@ void rt2800mmio_autowake_tasklet(unsigned long data) } EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet); -static void rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev) -{ - bool timeout = false; - - while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) || - (timeout = rt2800_txstatus_timeout(rt2x00dev))) { - - rt2800_txdone(rt2x00dev); - - if (timeout) - rt2800_txdone_nostatus(rt2x00dev); - } -} - -static bool rt2800mmio_fetch_txstatus(struct rt2x00_dev *rt2x00dev) +static void rt2800mmio_fetch_txstatus(struct rt2x00_dev *rt2x00dev) { u32 status; - bool more = false; + unsigned long flags; - /* FIXEME: rewrite this comment + /* * The TX_FIFO_STATUS interrupt needs special care. We should * read TX_STA_FIFO but we should do it immediately as otherwise * the register can overflow and we would lose status reports. @@ -285,34 +271,32 @@ static bool rt2800mmio_fetch_txstatus(struct rt2x00_dev *rt2x00dev) * because we can schedule the tasklet multiple times (when the * interrupt fires again during tx status processing). * - * txstatus tasklet is called with INT_SOURCE_CSR_TX_FIFO_STATUS - * disabled so have only one producer and one consumer - we don't - * need to lock the kfifo. + * We also read statuses from tx status timeout timer, use + * lock to prevent concurent writes to fifo. */ + + spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); + while (!kfifo_is_full(&rt2x00dev->txstatus_fifo)) { status = rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO); if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) break; kfifo_put(&rt2x00dev->txstatus_fifo, status); - more = true; } - return more; + spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); } void rt2800mmio_txstatus_tasklet(unsigned long data) { struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; - do { - rt2800mmio_txdone(rt2x00dev); + rt2800_txdone(rt2x00dev, 16); - } while (rt2800mmio_fetch_txstatus(rt2x00dev)); + if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) + tasklet_schedule(&rt2x00dev->txstatus_tasklet); - if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - rt2800mmio_enable_interrupt(rt2x00dev, - INT_SOURCE_CSR_TX_FIFO_STATUS); } EXPORT_SYMBOL_GPL(rt2800mmio_txstatus_tasklet); @@ -339,8 +323,10 @@ irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance) mask = ~reg; if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) { + rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1); rt2800mmio_fetch_txstatus(rt2x00dev); - tasklet_schedule(&rt2x00dev->txstatus_tasklet); + if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) + tasklet_schedule(&rt2x00dev->txstatus_tasklet); } if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT)) @@ -440,6 +426,9 @@ void rt2800mmio_start_queue(struct data_queue *queue) } EXPORT_SYMBOL_GPL(rt2800mmio_start_queue); +/* 200 ms */ +#define TXSTATUS_TIMEOUT 200000000 + void rt2800mmio_kick_queue(struct data_queue *queue) { struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; @@ -454,6 +443,8 @@ void rt2800mmio_kick_queue(struct data_queue *queue) entry = rt2x00queue_get_entry(queue, Q_INDEX); rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), entry->entry_idx); + hrtimer_start(&rt2x00dev->txstatus_timer, + TXSTATUS_TIMEOUT, HRTIMER_MODE_REL); break; case QID_MGMT: entry = rt2x00queue_get_entry(queue, Q_INDEX); @@ -498,11 +489,8 @@ void rt2800mmio_flush_queue(struct data_queue *queue, bool drop) * For TX queues schedule completion tasklet to catch * tx status timeouts, othewise just wait. */ - if (tx_queue) { - tasklet_disable(&rt2x00dev->txstatus_tasklet); - rt2800mmio_txdone(rt2x00dev); - tasklet_enable(&rt2x00dev->txstatus_tasklet); - } + if (tx_queue) + queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); /* * Wait for a little while to give the driver @@ -640,6 +628,10 @@ void rt2800mmio_clear_entry(struct queue_entry *entry) word = rt2x00_desc_read(entry_priv->desc, 1); rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1); rt2x00_desc_write(entry_priv->desc, 1, word); + + /* If last entry stop txstatus timer */ + if (entry->queue->length == 1) + hrtimer_cancel(&rt2x00dev->txstatus_timer); } } EXPORT_SYMBOL_GPL(rt2800mmio_clear_entry); @@ -772,6 +764,70 @@ int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev) } EXPORT_SYMBOL_GPL(rt2800mmio_enable_radio); +static void rt2800mmio_work_txdone(struct work_struct *work) +{ + struct rt2x00_dev *rt2x00dev = + container_of(work, struct rt2x00_dev, txdone_work); + + if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) + return; + + while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) || + rt2800_txstatus_timeout(rt2x00dev)) { + + tasklet_disable(&rt2x00dev->txstatus_tasklet); + rt2800_txdone(rt2x00dev, UINT_MAX); + rt2800_txdone_nostatus(rt2x00dev); + tasklet_enable(&rt2x00dev->txstatus_tasklet); + } + + if (rt2800_txstatus_pending(rt2x00dev)) + hrtimer_start(&rt2x00dev->txstatus_timer, + TXSTATUS_TIMEOUT, HRTIMER_MODE_REL); +} + +static enum hrtimer_restart rt2800mmio_tx_sta_fifo_timeout(struct hrtimer *timer) +{ + struct rt2x00_dev *rt2x00dev = + container_of(timer, struct rt2x00_dev, txstatus_timer); + + if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) + goto out; + + if (!rt2800_txstatus_pending(rt2x00dev)) + goto out; + + rt2800mmio_fetch_txstatus(rt2x00dev); + if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) + tasklet_schedule(&rt2x00dev->txstatus_tasklet); + else + queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); +out: + return HRTIMER_NORESTART; +} + +int rt2800mmio_probe_hw(struct rt2x00_dev *rt2x00dev) +{ + int retval; + + retval = rt2800_probe_hw(rt2x00dev); + if (retval) + return retval; + + /* + * Set txstatus timer function. + */ + rt2x00dev->txstatus_timer.function = rt2800mmio_tx_sta_fifo_timeout; + + /* + * Overwrite TX done handler + */ + INIT_WORK(&rt2x00dev->txdone_work, rt2800mmio_work_txdone); + + return 0; +} +EXPORT_SYMBOL_GPL(rt2800mmio_probe_hw); + MODULE_AUTHOR(DRV_PROJECT); MODULE_VERSION(DRV_VERSION); MODULE_DESCRIPTION("rt2800 MMIO library"); diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h index 3a513273f414..ca58e6c3a4e5 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h @@ -153,6 +153,7 @@ void rt2800mmio_stop_queue(struct data_queue *queue); void rt2800mmio_queue_init(struct data_queue *queue); /* Initialization functions */ +int rt2800mmio_probe_hw(struct rt2x00_dev *rt2x00dev); bool rt2800mmio_get_entry_state(struct queue_entry *entry); void rt2800mmio_clear_entry(struct queue_entry *entry); int rt2800mmio_init_queues(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c index 0291441ac548..43e1b1ee96bf 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c @@ -346,7 +346,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .tbtt_tasklet = rt2800mmio_tbtt_tasklet, .rxdone_tasklet = rt2800mmio_rxdone_tasklet, .autowake_tasklet = rt2800mmio_autowake_tasklet, - .probe_hw = rt2800_probe_hw, + .probe_hw = rt2800mmio_probe_hw, .get_firmware_name = rt2800pci_get_firmware_name, .check_firmware = rt2800_check_firmware, .load_firmware = rt2800_load_firmware, diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c index a502816214ab..4e9e38771a56 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c @@ -51,9 +51,16 @@ static bool rt2800soc_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev) static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev) { + u32 reg; + rt2800_disable_radio(rt2x00dev); rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0); - rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0); + + reg = 0; + if (rt2x00_rt(rt2x00dev, RT3883)) + rt2x00_set_field32(®, TX_PIN_CFG_RFTR_EN, 1); + + rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, reg); } static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev, @@ -185,7 +192,7 @@ static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = { .tbtt_tasklet = rt2800mmio_tbtt_tasklet, .rxdone_tasklet = rt2800mmio_rxdone_tasklet, .autowake_tasklet = rt2800mmio_autowake_tasklet, - .probe_hw = rt2800_probe_hw, + .probe_hw = rt2800mmio_probe_hw, .get_firmware_name = rt2800soc_get_firmware_name, .check_firmware = rt2800soc_check_firmware, .load_firmware = rt2800soc_load_firmware, @@ -203,7 +210,7 @@ static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = { .start_queue = rt2800mmio_start_queue, .kick_queue = rt2800mmio_kick_queue, .stop_queue = rt2800mmio_stop_queue, - .flush_queue = rt2x00mmio_flush_queue, + .flush_queue = rt2800mmio_flush_queue, .write_tx_desc = rt2800mmio_write_tx_desc, .write_tx_data = rt2800_write_tx_data, .write_beacon = rt2800_write_beacon, diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c index 19eabf16147b..b5f75df9b563 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c @@ -100,22 +100,6 @@ static void rt2800usb_stop_queue(struct data_queue *queue) } } -/* - * test if there is an entry in any TX queue for which DMA is done - * but the TX status has not been returned yet - */ -static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue; - - tx_queue_for_each(rt2x00dev, queue) { - if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) != - rt2x00queue_get_entry(queue, Q_INDEX_DONE)) - return true; - } - return false; -} - #define TXSTATUS_READ_INTERVAL 1000000 static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, @@ -145,7 +129,7 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, if (rt2800_txstatus_timeout(rt2x00dev)) queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); - if (rt2800usb_txstatus_pending(rt2x00dev)) { + if (rt2800_txstatus_pending(rt2x00dev)) { /* Read register after 1 ms */ hrtimer_start(&rt2x00dev->txstatus_timer, TXSTATUS_READ_INTERVAL, @@ -160,7 +144,7 @@ stop_reading: * clear_bit someone could do rt2x00usb_interrupt_txdone, so recheck * here again if status reading is needed. */ - if (rt2800usb_txstatus_pending(rt2x00dev) && + if (rt2800_txstatus_pending(rt2x00dev) && !test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags)) return true; else @@ -480,7 +464,7 @@ static void rt2800usb_work_txdone(struct work_struct *work) while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) || rt2800_txstatus_timeout(rt2x00dev)) { - rt2800_txdone(rt2x00dev); + rt2800_txdone(rt2x00dev, UINT_MAX); rt2800_txdone_nostatus(rt2x00dev); @@ -489,7 +473,7 @@ static void rt2800usb_work_txdone(struct work_struct *work) * if the medium is busy, thus the TX_STA_FIFO entry is * also delayed -> use a timer to retrieve it. */ - if (rt2800usb_txstatus_pending(rt2x00dev)) + if (rt2800_txstatus_pending(rt2x00dev)) rt2800usb_async_read_tx_status(rt2x00dev); } } @@ -562,13 +546,13 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, * stripped it from the frame. Signal this to mac80211. */ rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; - + if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) { rxdesc->flags |= RX_FLAG_DECRYPTED; } else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) { /* * In order to check the Michael Mic, the packet must have - * been decrypted. Mac80211 doesnt check the MMIC failure + * been decrypted. Mac80211 doesnt check the MMIC failure * flag to initiate MMIC countermeasures if the decoded flag * has not been set. */ diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h index 4b1744e9fb78..9c6ef0ca932b 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h @@ -69,10 +69,10 @@ printk(KERN_ERR KBUILD_MODNAME ": %s: Error - " fmt, \ __func__, ##__VA_ARGS__) #define rt2x00_err(dev, fmt, ...) \ - wiphy_err((dev)->hw->wiphy, "%s: Error - " fmt, \ + wiphy_err_ratelimited((dev)->hw->wiphy, "%s: Error - " fmt, \ __func__, ##__VA_ARGS__) #define rt2x00_warn(dev, fmt, ...) \ - wiphy_warn((dev)->hw->wiphy, "%s: Warning - " fmt, \ + wiphy_warn_ratelimited((dev)->hw->wiphy, "%s: Warning - " fmt, \ __func__, ##__VA_ARGS__) #define rt2x00_info(dev, fmt, ...) \ wiphy_info((dev)->hw->wiphy, "%s: Info - " fmt, \ @@ -673,7 +673,6 @@ enum rt2x00_state_flags { CONFIG_CHANNEL_HT40, CONFIG_POWERSAVING, CONFIG_HT_DISABLED, - CONFIG_QOS_DISABLED, CONFIG_MONITORING, /* @@ -981,8 +980,6 @@ struct rt2x00_dev { */ DECLARE_KFIFO_PTR(txstatus_fifo, u32); - unsigned long last_nostatus_check; - /* * Timer to ensure tx status reports are read (rt2800usb). */ @@ -1017,6 +1014,7 @@ struct rt2x00_dev { unsigned int extra_tx_headroom; struct usb_anchor *anchor; + unsigned int num_proto_errs; /* Clock for System On Chip devices. */ struct clk *clk; diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c index 357c0941aaad..1b08b01db27b 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c @@ -1007,7 +1007,7 @@ void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr const char *mac_addr; mac_addr = of_get_mac_address(rt2x00dev->dev->of_node); - if (mac_addr) + if (!IS_ERR(mac_addr)) ether_addr_copy(eeprom_mac_addr, mac_addr); if (!is_valid_ether_addr(eeprom_mac_addr)) { @@ -1391,6 +1391,8 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) mutex_init(&rt2x00dev->conf_mutex); INIT_LIST_HEAD(&rt2x00dev->bar_list); spin_lock_init(&rt2x00dev->bar_list_lock); + hrtimer_init(&rt2x00dev->txstatus_timer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); @@ -1515,6 +1517,8 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) cancel_delayed_work_sync(&rt2x00dev->autowakeup_work); cancel_work_sync(&rt2x00dev->sleep_work); + hrtimer_cancel(&rt2x00dev->txstatus_timer); + /* * Kill the tx status tasklet. */ diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c index 2825560e2424..e8462f25d252 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c @@ -642,19 +642,9 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, rt2x00dev->intf_associated--; rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); - - clear_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags); } /* - * Check for access point which do not support 802.11e . We have to - * generate data frames sequence number in S/W for such AP, because - * of H/W bug. - */ - if (changes & BSS_CHANGED_QOS && !bss_conf->qos) - set_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags); - - /* * When the erp information has changed, we should perform * additional configuration steps. For all other changes we are done. */ diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h index 184a4148b2f8..03e6cdb0b5a4 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h @@ -80,8 +80,6 @@ int rt2x00mmio_regbusy_read(struct rt2x00_dev *rt2x00dev, * * @desc: Pointer to device descriptor * @desc_dma: DMA pointer to &desc. - * @data: Pointer to device's entry memory. - * @data_dma: DMA pointer to &data. */ struct queue_entry_priv_mmio { __le32 *desc; diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c index 92ddc19e7bf7..03b206440208 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c @@ -201,15 +201,18 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, if (!rt2x00_has_cap_flag(rt2x00dev, REQUIRE_SW_SEQNO)) { /* * rt2800 has a H/W (or F/W) bug, device incorrectly increase - * seqno on retransmited data (non-QOS) frames. To workaround - * the problem let's generate seqno in software if QOS is - * disabled. + * seqno on retransmitted data (non-QOS) and management frames. + * To workaround the problem let's generate seqno in software. + * Except for beacons which are transmitted periodically by H/W + * hence hardware has to assign seqno for them. */ - if (test_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags)) - __clear_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); - else + if (ieee80211_is_beacon(hdr->frame_control)) { + __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); /* H/W will generate sequence number */ return; + } + + __clear_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); } /* @@ -671,7 +674,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, spin_lock(&queue->tx_lock); if (unlikely(rt2x00queue_full(queue))) { - rt2x00_err(queue->rt2x00dev, "Dropping frame due to full tx queue %d\n", + rt2x00_dbg(queue->rt2x00dev, "Dropping frame due to full tx queue %d\n", queue->qid); ret = -ENOBUFS; goto out; @@ -1039,7 +1042,6 @@ void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev) */ tx_queue_for_each(rt2x00dev, queue) rt2x00queue_start_queue(queue); - rt2x00dev->last_nostatus_check = jiffies; rt2x00queue_start_queue(rt2x00dev->rx); } diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h index a15bae29917b..20113f861b9e 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h @@ -361,7 +361,6 @@ enum queue_entry_flags { ENTRY_DATA_PENDING, ENTRY_DATA_IO_FAILED, ENTRY_DATA_STATUS_PENDING, - ENTRY_DATA_STATUS_SET, }; /** @@ -387,8 +386,6 @@ struct queue_entry { unsigned int entry_idx; - u32 status; - void *priv_data; }; diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c index 086aad22743d..9cdd7f2c92b5 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c @@ -31,6 +31,22 @@ #include "rt2x00.h" #include "rt2x00usb.h" +static bool rt2x00usb_check_usb_error(struct rt2x00_dev *rt2x00dev, int status) +{ + if (status == -ENODEV || status == -ENOENT) + return true; + + if (status == -EPROTO || status == -ETIMEDOUT) + rt2x00dev->num_proto_errs++; + else + rt2x00dev->num_proto_errs = 0; + + if (rt2x00dev->num_proto_errs > 3) + return true; + + return false; +} + /* * Interfacing with the HW. */ @@ -57,7 +73,7 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, if (status >= 0) return 0; - if (status == -ENODEV || status == -ENOENT) { + if (rt2x00usb_check_usb_error(rt2x00dev, status)) { /* Device has disappeared. */ clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); break; @@ -321,7 +337,7 @@ static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void *data) status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC); if (status) { - if (status == -ENODEV || status == -ENOENT) + if (rt2x00usb_check_usb_error(rt2x00dev, status)) clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); rt2x00lib_dmadone(entry); @@ -410,7 +426,7 @@ static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void *data) status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC); if (status) { - if (status == -ENODEV || status == -ENOENT) + if (rt2x00usb_check_usb_error(rt2x00dev, status)) clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); rt2x00lib_dmadone(entry); diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 44a943d18b84..ee4d8106bba5 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -2795,6 +2795,8 @@ static int __init init_ray_cs(void) rc = pcmcia_register_driver(&ray_driver); pr_debug("raylink init_module register_pcmcia_driver returns 0x%x\n", rc); + if (rc) + return rc; #ifdef CONFIG_PROC_FS proc_mkdir("driver/ray_cs", NULL); @@ -2818,11 +2820,7 @@ static void __exit exit_ray_cs(void) pr_debug("ray_cs: cleanup_module\n"); #ifdef CONFIG_PROC_FS - remove_proc_entry("driver/ray_cs/ray_cs", NULL); - remove_proc_entry("driver/ray_cs/essid", NULL); - remove_proc_entry("driver/ray_cs/net_type", NULL); - remove_proc_entry("driver/ray_cs/translate", NULL); - remove_proc_entry("driver/ray_cs", NULL); + remove_proc_subtree("driver/ray_cs", NULL); #endif pcmcia_unregister_driver(&ray_driver); diff --git a/drivers/net/wireless/realtek/Kconfig b/drivers/net/wireless/realtek/Kconfig index 3db988e689d7..9189fd672578 100644 --- a/drivers/net/wireless/realtek/Kconfig +++ b/drivers/net/wireless/realtek/Kconfig @@ -14,5 +14,6 @@ if WLAN_VENDOR_REALTEK source "drivers/net/wireless/realtek/rtl818x/Kconfig" source "drivers/net/wireless/realtek/rtlwifi/Kconfig" source "drivers/net/wireless/realtek/rtl8xxxu/Kconfig" +source "drivers/net/wireless/realtek/rtw88/Kconfig" endif # WLAN_VENDOR_REALTEK diff --git a/drivers/net/wireless/realtek/Makefile b/drivers/net/wireless/realtek/Makefile index 9c78deb5eea9..118af9963d61 100644 --- a/drivers/net/wireless/realtek/Makefile +++ b/drivers/net/wireless/realtek/Makefile @@ -6,4 +6,5 @@ obj-$(CONFIG_RTL8180) += rtl818x/ obj-$(CONFIG_RTL8187) += rtl818x/ obj-$(CONFIG_RTLWIFI) += rtlwifi/ obj-$(CONFIG_RTL8XXXU) += rtl8xxxu/ +obj-$(CONFIG_RTW88) += rtw88/ diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 217d2a7a43c7..ac746c322554 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -448,6 +448,11 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) /* <2> work queue */ rtlpriv->works.hw = hw; rtlpriv->works.rtl_wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name); + if (unlikely(!rtlpriv->works.rtl_wq)) { + pr_err("Failed to allocate work queue\n"); + return; + } + INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq, (void *)rtl_watchdog_wq_callback); INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq, diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index 48ca52102cef..4055e0ab75ba 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -499,16 +499,16 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); - spin_lock_bh(&rtlpriv->locks.waitq_lock); + spin_lock(&rtlpriv->locks.waitq_lock); if (!skb_queue_empty(&mac->skb_waitq[tid]) && (ring->entries - skb_queue_len(&ring->queue) > rtlhal->max_earlymode_num)) { skb = skb_dequeue(&mac->skb_waitq[tid]); } else { - spin_unlock_bh(&rtlpriv->locks.waitq_lock); + spin_unlock(&rtlpriv->locks.waitq_lock); break; } - spin_unlock_bh(&rtlpriv->locks.waitq_lock); + spin_unlock(&rtlpriv->locks.waitq_lock); /* Some macaddr can't do early mode. like * multicast/broadcast/no_qos data diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c index 203e7b574e84..e2e0bfbc24fe 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c @@ -600,6 +600,8 @@ void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) u1rsvdpageloc, 3); skb = dev_alloc_skb(totalpacketlen); + if (!skb) + return; skb_put_data(skb, &reserved_page_packet, totalpacketlen); rtstatus = rtl_cmd_send_packet(hw, skb); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c index 106011a24827..483dc8bdc555 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c @@ -372,8 +372,9 @@ bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct rx_fwinfo_88e *p_drvinfo; struct ieee80211_hdr *hdr; - + u8 wake_match; u32 phystatus = GET_RX_DESC_PHYST(pdesc); + status->packet_report_type = (u8)GET_RX_STATUS_DESC_RPT_SEL(pdesc); if (status->packet_report_type == TX_REPORT2) status->length = (u16)GET_RX_RPT2_DESC_PKT_LEN(pdesc); @@ -399,18 +400,18 @@ bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, status->is_cck = RTL8188_RX_HAL_IS_CCK_RATE(status->rate); status->macid = GET_RX_DESC_MACID(pdesc); - if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) - status->wake_match = BIT(2); + if (GET_RX_STATUS_DESC_PATTERN_MATCH(pdesc)) + wake_match = BIT(2); else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) - status->wake_match = BIT(1); + wake_match = BIT(1); else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc)) - status->wake_match = BIT(0); + wake_match = BIT(0); else - status->wake_match = 0; - if (status->wake_match) + wake_match = 0; + if (wake_match) RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, "GGGGGGGGGGGGGet Wakeup Packet!! WakeMatch=%d\n", - status->wake_match); + wake_match); rx_status->freq = hw->conf.chandef.chan->center_freq; rx_status->band = hw->conf.chandef.chan->band; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c index 18c76990a089..86b1b88cc4ed 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c @@ -623,6 +623,8 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, u1rsvdpageloc, 3); skb = dev_alloc_skb(totalpacketlen); + if (!skb) + return; skb_put_data(skb, &reserved_page_packet, totalpacketlen); if (cmd_send_packet) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c index f3a336e0ea98..d259794a308b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c @@ -42,12 +42,9 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); u32 tx_agc[2] = { 0, 0 }, tmpval = 0; - bool turbo_scanoff = false; u8 idx1, idx2; u8 *ptr; - if ((rtlefuse->eeprom_regulatory != 0) || (rtlefuse->external_pa)) - turbo_scanoff = true; if (mac->act_scanning) { tx_agc[RF90_PATH_A] = 0x3f3f3f3f; tx_agc[RF90_PATH_B] = 0x3f3f3f3f; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c index 7c5b54b71a92..67305ce915ec 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c @@ -744,6 +744,8 @@ void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) u1rsvdpageloc, 3); skb = dev_alloc_skb(totalpacketlen); + if (!skb) + return; skb_put_data(skb, &reserved_page_packet, totalpacketlen); rtstatus = rtl_cmd_send_packet(hw, skb); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c index 09cf8180e4ff..d297cfc0fd2b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c @@ -331,6 +331,7 @@ bool rtl92ee_rx_query_desc(struct ieee80211_hw *hw, struct rx_fwinfo *p_drvinfo; struct ieee80211_hdr *hdr; u32 phystatus = GET_RX_DESC_PHYST(pdesc); + u8 wake_match; if (GET_RX_STATUS_DESC_RPT_SEL(pdesc) == 0) status->packet_report_type = NORMAL_RX; @@ -350,18 +351,18 @@ bool rtl92ee_rx_query_desc(struct ieee80211_hw *hw, status->is_cck = RTL92EE_RX_HAL_IS_CCK_RATE(status->rate); status->macid = GET_RX_DESC_MACID(pdesc); - if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) - status->wake_match = BIT(2); + if (GET_RX_STATUS_DESC_PATTERN_MATCH(pdesc)) + wake_match = BIT(2); else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) - status->wake_match = BIT(1); + wake_match = BIT(1); else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc)) - status->wake_match = BIT(0); + wake_match = BIT(0); else - status->wake_match = 0; - if (status->wake_match) + wake_match = 0; + if (wake_match) RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, "GGGGGGGGGGGGGet Wakeup Packet!! WakeMatch=%d\n", - status->wake_match); + wake_match); rx_status->freq = hw->conf.chandef.chan->center_freq; rx_status->band = hw->conf.chandef.chan->band; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c index 514891ea2c64..d8260c7afe09 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c @@ -663,7 +663,7 @@ void rtl8723e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) } -void rtl8723e_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) +static void rtl8723e_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c index be451a6f7dbe..33481232fad0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c @@ -448,6 +448,8 @@ void rtl8723e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) u1rsvdpageloc, 3); skb = dev_alloc_skb(totalpacketlen); + if (!skb) + return; skb_put_data(skb, &reserved_page_packet, totalpacketlen); rtstatus = rtl_cmd_send_packet(hw, skb); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c index 6bab162e1bb8..655460f61bbc 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c @@ -1675,6 +1675,7 @@ static void _rtl8723e_read_adapter_info(struct ieee80211_hw *hw, rtlhal->oem_id = RT_CID_819X_LENOVO; break; } + break; case 0x1025: rtlhal->oem_id = RT_CID_819X_ACER; break; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c index 4d7fa27f55ca..aa56058af56e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c @@ -562,6 +562,8 @@ void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, u1rsvdpageloc, sizeof(u1rsvdpageloc)); skb = dev_alloc_skb(totalpacketlen); + if (!skb) + return; skb_put_data(skb, &reserved_page_packet, totalpacketlen); rtstatus = rtl_cmd_send_packet(hw, skb); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c index 9ada9a06c6ea..d87ba03fe78f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c @@ -300,7 +300,7 @@ bool rtl8723be_rx_query_desc(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct rx_fwinfo_8723be *p_drvinfo; struct ieee80211_hdr *hdr; - + u8 wake_match; u32 phystatus = GET_RX_DESC_PHYST(pdesc); status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); @@ -329,18 +329,18 @@ bool rtl8723be_rx_query_desc(struct ieee80211_hw *hw, status->packet_report_type = NORMAL_RX; - if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) - status->wake_match = BIT(2); + if (GET_RX_STATUS_DESC_PATTERN_MATCH(pdesc)) + wake_match = BIT(2); else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) - status->wake_match = BIT(1); + wake_match = BIT(1); else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc)) - status->wake_match = BIT(0); + wake_match = BIT(0); else - status->wake_match = 0; - if (status->wake_match) + wake_match = 0; + if (wake_match) RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, "GGGGGGGGGGGGGet Wakeup Packet!! WakeMatch=%d\n", - status->wake_match); + wake_match); rx_status->freq = hw->conf.chandef.chan->center_freq; rx_status->band = hw->conf.chandef.chan->band; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c index dc0eb692088f..fe32d397d287 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c @@ -1623,6 +1623,8 @@ out: &reserved_page_packet_8812[0], totalpacketlen); skb = dev_alloc_skb(totalpacketlen); + if (!skb) + return; skb_put_data(skb, &reserved_page_packet_8812, totalpacketlen); rtstatus = rtl_cmd_send_packet(hw, skb); @@ -1759,6 +1761,8 @@ out: &reserved_page_packet_8821[0], totalpacketlen); skb = dev_alloc_skb(totalpacketlen); + if (!skb) + return; skb_put_data(skb, &reserved_page_packet_8821, totalpacketlen); rtstatus = rtl_cmd_send_packet(hw, skb); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c index db5e628b17ed..7b6faf38e09c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c @@ -436,7 +436,7 @@ bool rtl8821ae_rx_query_desc(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct rx_fwinfo_8821ae *p_drvinfo; struct ieee80211_hdr *hdr; - + u8 wake_match; u32 phystatus = GET_RX_DESC_PHYST(pdesc); status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); @@ -473,18 +473,18 @@ bool rtl8821ae_rx_query_desc(struct ieee80211_hw *hw, status->packet_report_type = NORMAL_RX; if (GET_RX_STATUS_DESC_PATTERN_MATCH(pdesc)) - status->wake_match = BIT(2); + wake_match = BIT(2); else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) - status->wake_match = BIT(1); + wake_match = BIT(1); else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc)) - status->wake_match = BIT(0); + wake_match = BIT(0); else - status->wake_match = 0; + wake_match = 0; - if (status->wake_match) + if (wake_match) RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, "GGGGGGGGGGGGGet Wakeup Packet!! WakeMatch=%d\n", - status->wake_match); + wake_match); rx_status->freq = hw->conf.chandef.chan->center_freq; rx_status->band = hw->conf.chandef.chan->band; diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index e32e9ffa3192..518aaa875361 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -2138,7 +2138,6 @@ struct rtl_stats { u8 packet_report_type; u32 macid; - u8 wake_match; u32 bt_rx_rssi_percentage; u32 macid_valid_entry[2]; }; diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig new file mode 100644 index 000000000000..55b1bf3dd9b6 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/Kconfig @@ -0,0 +1,54 @@ +menuconfig RTW88 + tristate "Realtek 802.11ac wireless chips support" + depends on MAC80211 + help + This module adds support for mac80211-based wireless drivers that + enables Realtek IEEE 802.11ac wireless chipsets. + + If you choose to build a module, it'll be called rtw88. + +if RTW88 + +config RTW88_CORE + tristate + +config RTW88_PCI + tristate + +config RTW88_8822BE + bool "Realtek 8822BE PCI wireless network adapter" + depends on PCI + select RTW88_CORE + select RTW88_PCI + help + Select this option will enable support for 8822BE chipset + + 802.11ac PCIe wireless network adapter + +config RTW88_8822CE + bool "Realtek 8822CE PCI wireless network adapter" + depends on PCI + select RTW88_CORE + select RTW88_PCI + help + Select this option will enable support for 8822CE chipset + + 802.11ac PCIe wireless network adapter + +config RTW88_DEBUG + bool "Realtek rtw88 debug support" + depends on RTW88_CORE + help + Enable debug support + + If unsure, say Y to simplify debug problems + +config RTW88_DEBUGFS + bool "Realtek rtw88 debugfs support" + depends on RTW88_CORE + help + Enable debug support + + If unsure, say Y to simplify debug problems + +endif diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile new file mode 100644 index 000000000000..e0bfefd154af --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/Makefile @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + +obj-$(CONFIG_RTW88_CORE) += rtw88.o +rtw88-y += main.o \ + mac80211.o \ + util.o \ + debug.o \ + tx.o \ + rx.o \ + mac.o \ + phy.o \ + efuse.o \ + fw.o \ + ps.o \ + sec.o \ + regd.o + +rtw88-$(CONFIG_RTW88_8822BE) += rtw8822b.o rtw8822b_table.o +rtw88-$(CONFIG_RTW88_8822CE) += rtw8822c.o rtw8822c_table.o + +obj-$(CONFIG_RTW88_PCI) += rtwpci.o +rtwpci-objs := pci.o diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c new file mode 100644 index 000000000000..f0ae26018f97 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/debug.c @@ -0,0 +1,637 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include "main.h" +#include "sec.h" +#include "fw.h" +#include "debug.h" + +#ifdef CONFIG_RTW88_DEBUGFS + +struct rtw_debugfs_priv { + struct rtw_dev *rtwdev; + int (*cb_read)(struct seq_file *m, void *v); + ssize_t (*cb_write)(struct file *filp, const char __user *buffer, + size_t count, loff_t *loff); + union { + u32 cb_data; + u8 *buf; + struct { + u32 page_offset; + u32 page_num; + } rsvd_page; + struct { + u8 rf_path; + u32 rf_addr; + u32 rf_mask; + }; + struct { + u32 addr; + u32 len; + } read_reg; + }; +}; + +static int rtw_debugfs_single_show(struct seq_file *m, void *v) +{ + struct rtw_debugfs_priv *debugfs_priv = m->private; + + return debugfs_priv->cb_read(m, v); +} + +static ssize_t rtw_debugfs_common_write(struct file *filp, + const char __user *buffer, + size_t count, loff_t *loff) +{ + struct rtw_debugfs_priv *debugfs_priv = filp->private_data; + + return debugfs_priv->cb_write(filp, buffer, count, loff); +} + +static ssize_t rtw_debugfs_single_write(struct file *filp, + const char __user *buffer, + size_t count, loff_t *loff) +{ + struct seq_file *seqpriv = (struct seq_file *)filp->private_data; + struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; + + return debugfs_priv->cb_write(filp, buffer, count, loff); +} + +static int rtw_debugfs_single_open_rw(struct inode *inode, struct file *filp) +{ + return single_open(filp, rtw_debugfs_single_show, inode->i_private); +} + +static int rtw_debugfs_close(struct inode *inode, struct file *filp) +{ + return 0; +} + +static const struct file_operations file_ops_single_r = { + .owner = THIS_MODULE, + .open = rtw_debugfs_single_open_rw, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static const struct file_operations file_ops_single_rw = { + .owner = THIS_MODULE, + .open = rtw_debugfs_single_open_rw, + .release = single_release, + .read = seq_read, + .llseek = seq_lseek, + .write = rtw_debugfs_single_write, +}; + +static const struct file_operations file_ops_common_write = { + .owner = THIS_MODULE, + .write = rtw_debugfs_common_write, + .open = simple_open, + .release = rtw_debugfs_close, +}; + +static int rtw_debugfs_get_read_reg(struct seq_file *m, void *v) +{ + struct rtw_debugfs_priv *debugfs_priv = m->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + u32 val, len, addr; + + len = debugfs_priv->read_reg.len; + addr = debugfs_priv->read_reg.addr; + switch (len) { + case 1: + val = rtw_read8(rtwdev, addr); + seq_printf(m, "reg 0x%03x: 0x%02x\n", addr, val); + break; + case 2: + val = rtw_read16(rtwdev, addr); + seq_printf(m, "reg 0x%03x: 0x%04x\n", addr, val); + break; + case 4: + val = rtw_read32(rtwdev, addr); + seq_printf(m, "reg 0x%03x: 0x%08x\n", addr, val); + break; + } + return 0; +} + +static int rtw_debugfs_get_rf_read(struct seq_file *m, void *v) +{ + struct rtw_debugfs_priv *debugfs_priv = m->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + u32 val, addr, mask; + u8 path; + + path = debugfs_priv->rf_path; + addr = debugfs_priv->rf_addr; + mask = debugfs_priv->rf_mask; + + val = rtw_read_rf(rtwdev, path, addr, mask); + + seq_printf(m, "rf_read path:%d addr:0x%08x mask:0x%08x val=0x%08x\n", + path, addr, mask, val); + + return 0; +} + +static int rtw_debugfs_copy_from_user(char tmp[], int size, + const char __user *buffer, size_t count, + int num) +{ + int tmp_len; + + if (count < num) + return -EFAULT; + + tmp_len = (count > size - 1 ? size - 1 : count); + + if (!buffer || copy_from_user(tmp, buffer, tmp_len)) + return count; + + tmp[tmp_len] = '\0'; + + return 0; +} + +static ssize_t rtw_debugfs_set_read_reg(struct file *filp, + const char __user *buffer, + size_t count, loff_t *loff) +{ + struct seq_file *seqpriv = (struct seq_file *)filp->private_data; + struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + char tmp[32 + 1]; + u32 addr, len; + int num; + + rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2); + + num = sscanf(tmp, "%x %x", &addr, &len); + + if (num != 2) + return count; + + if (len != 1 && len != 2 && len != 4) { + rtw_warn(rtwdev, "read reg setting wrong len\n"); + return -EINVAL; + } + debugfs_priv->read_reg.addr = addr; + debugfs_priv->read_reg.len = len; + + return count; +} + +static int rtw_debugfs_get_dump_cam(struct seq_file *m, void *v) +{ + struct rtw_debugfs_priv *debugfs_priv = m->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + u32 val, command; + u32 hw_key_idx = debugfs_priv->cb_data << RTW_SEC_CAM_ENTRY_SHIFT; + u32 read_cmd = RTW_SEC_CMD_POLLING; + int i; + + seq_printf(m, "cam entry%d\n", debugfs_priv->cb_data); + seq_puts(m, "0x0 0x1 0x2 0x3 "); + seq_puts(m, "0x4 0x5\n"); + mutex_lock(&rtwdev->mutex); + for (i = 0; i <= 5; i++) { + command = read_cmd | (hw_key_idx + i); + rtw_write32(rtwdev, RTW_SEC_CMD_REG, command); + val = rtw_read32(rtwdev, RTW_SEC_READ_REG); + seq_printf(m, "%8.8x", val); + if (i < 2) + seq_puts(m, " "); + } + seq_puts(m, "\n"); + mutex_unlock(&rtwdev->mutex); + return 0; +} + +static int rtw_debugfs_get_rsvd_page(struct seq_file *m, void *v) +{ + struct rtw_debugfs_priv *debugfs_priv = m->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + u8 page_size = rtwdev->chip->page_size; + u32 buf_size = debugfs_priv->rsvd_page.page_num * page_size; + u32 offset = debugfs_priv->rsvd_page.page_offset * page_size; + u8 *buf; + int i; + int ret; + + buf = vzalloc(buf_size); + if (!buf) + return -ENOMEM; + + ret = rtw_dump_drv_rsvd_page(rtwdev, offset, buf_size, (u32 *)buf); + if (ret) { + rtw_err(rtwdev, "failed to dump rsvd page\n"); + vfree(buf); + return ret; + } + + for (i = 0 ; i < buf_size ; i += 8) { + if (i % page_size == 0) + seq_printf(m, "PAGE %d\n", (i + offset) / page_size); + seq_printf(m, "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", + *(buf + i), *(buf + i + 1), + *(buf + i + 2), *(buf + i + 3), + *(buf + i + 4), *(buf + i + 5), + *(buf + i + 6), *(buf + i + 7)); + } + vfree(buf); + + return 0; +} + +static ssize_t rtw_debugfs_set_rsvd_page(struct file *filp, + const char __user *buffer, + size_t count, loff_t *loff) +{ + struct seq_file *seqpriv = (struct seq_file *)filp->private_data; + struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + char tmp[32 + 1]; + u32 offset, page_num; + int num; + + rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2); + + num = sscanf(tmp, "%d %d", &offset, &page_num); + + if (num != 2) { + rtw_warn(rtwdev, "invalid arguments\n"); + return num; + } + + debugfs_priv->rsvd_page.page_offset = offset; + debugfs_priv->rsvd_page.page_num = page_num; + + return count; +} + +static ssize_t rtw_debugfs_set_single_input(struct file *filp, + const char __user *buffer, + size_t count, loff_t *loff) +{ + struct seq_file *seqpriv = (struct seq_file *)filp->private_data; + struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + char tmp[32 + 1]; + u32 input; + int num; + + rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); + + num = kstrtoint(tmp, 0, &input); + + if (num) { + rtw_warn(rtwdev, "kstrtoint failed\n"); + return num; + } + + debugfs_priv->cb_data = input; + + return count; +} + +static ssize_t rtw_debugfs_set_write_reg(struct file *filp, + const char __user *buffer, + size_t count, loff_t *loff) +{ + struct rtw_debugfs_priv *debugfs_priv = filp->private_data; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + char tmp[32 + 1]; + u32 addr, val, len; + int num; + + rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); + + /* write BB/MAC register */ + num = sscanf(tmp, "%x %x %x", &addr, &val, &len); + + if (num != 3) + return count; + + switch (len) { + case 1: + rtw_dbg(rtwdev, RTW_DBG_DEBUGFS, + "reg write8 0x%03x: 0x%08x\n", addr, val); + rtw_write8(rtwdev, addr, (u8)val); + break; + case 2: + rtw_dbg(rtwdev, RTW_DBG_DEBUGFS, + "reg write16 0x%03x: 0x%08x\n", addr, val); + rtw_write16(rtwdev, addr, (u16)val); + break; + case 4: + rtw_dbg(rtwdev, RTW_DBG_DEBUGFS, + "reg write32 0x%03x: 0x%08x\n", addr, val); + rtw_write32(rtwdev, addr, (u32)val); + break; + default: + rtw_dbg(rtwdev, RTW_DBG_DEBUGFS, + "error write length = %d\n", len); + break; + } + + return count; +} + +static ssize_t rtw_debugfs_set_rf_write(struct file *filp, + const char __user *buffer, + size_t count, loff_t *loff) +{ + struct rtw_debugfs_priv *debugfs_priv = filp->private_data; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + char tmp[32 + 1]; + u32 path, addr, mask, val; + int num; + + rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 4); + + num = sscanf(tmp, "%x %x %x %x", &path, &addr, &mask, &val); + + if (num != 4) { + rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n"); + return count; + } + + rtw_write_rf(rtwdev, path, addr, mask, val); + rtw_dbg(rtwdev, RTW_DBG_DEBUGFS, + "write_rf path:%d addr:0x%08x mask:0x%08x, val:0x%08x\n", + path, addr, mask, val); + + return count; +} + +static ssize_t rtw_debugfs_set_rf_read(struct file *filp, + const char __user *buffer, + size_t count, loff_t *loff) +{ + struct seq_file *seqpriv = (struct seq_file *)filp->private_data; + struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + char tmp[32 + 1]; + u32 path, addr, mask; + int num; + + rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); + + num = sscanf(tmp, "%x %x %x", &path, &addr, &mask); + + if (num != 3) { + rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n"); + return count; + } + + debugfs_priv->rf_path = path; + debugfs_priv->rf_addr = addr; + debugfs_priv->rf_mask = mask; + + return count; +} + +static int rtw_debug_get_mac_page(struct seq_file *m, void *v) +{ + struct rtw_debugfs_priv *debugfs_priv = m->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + u32 val; + u32 page = debugfs_priv->cb_data; + int i, n; + int max = 0xff; + + val = rtw_read32(rtwdev, debugfs_priv->cb_data); + for (n = 0; n <= max; ) { + seq_printf(m, "\n%8.8x ", n + page); + for (i = 0; i < 4 && n <= max; i++, n += 4) + seq_printf(m, "%8.8x ", + rtw_read32(rtwdev, (page | n))); + } + seq_puts(m, "\n"); + return 0; +} + +static int rtw_debug_get_bb_page(struct seq_file *m, void *v) +{ + struct rtw_debugfs_priv *debugfs_priv = m->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + u32 val; + u32 page = debugfs_priv->cb_data; + int i, n; + int max = 0xff; + + val = rtw_read32(rtwdev, debugfs_priv->cb_data); + for (n = 0; n <= max; ) { + seq_printf(m, "\n%8.8x ", n + page); + for (i = 0; i < 4 && n <= max; i++, n += 4) + seq_printf(m, "%8.8x ", + rtw_read32(rtwdev, (page | n))); + } + seq_puts(m, "\n"); + return 0; +} + +static int rtw_debug_get_rf_dump(struct seq_file *m, void *v) +{ + struct rtw_debugfs_priv *debugfs_priv = m->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + u32 addr, offset, data; + u8 path; + + for (path = 0; path < rtwdev->hal.rf_path_num; path++) { + seq_printf(m, "RF path:%d\n", path); + for (addr = 0; addr < 0x100; addr += 4) { + seq_printf(m, "%8.8x ", addr); + for (offset = 0; offset < 4; offset++) { + data = rtw_read_rf(rtwdev, path, addr + offset, + 0xffffffff); + seq_printf(m, "%8.8x ", data); + } + seq_puts(m, "\n"); + } + seq_puts(m, "\n"); + } + + return 0; +} + +#define rtw_debug_impl_mac(page, addr) \ +static struct rtw_debugfs_priv rtw_debug_priv_mac_ ##page = { \ + .cb_read = rtw_debug_get_mac_page, \ + .cb_data = addr, \ +} + +rtw_debug_impl_mac(0, 0x0000); +rtw_debug_impl_mac(1, 0x0100); +rtw_debug_impl_mac(2, 0x0200); +rtw_debug_impl_mac(3, 0x0300); +rtw_debug_impl_mac(4, 0x0400); +rtw_debug_impl_mac(5, 0x0500); +rtw_debug_impl_mac(6, 0x0600); +rtw_debug_impl_mac(7, 0x0700); +rtw_debug_impl_mac(10, 0x1000); +rtw_debug_impl_mac(11, 0x1100); +rtw_debug_impl_mac(12, 0x1200); +rtw_debug_impl_mac(13, 0x1300); +rtw_debug_impl_mac(14, 0x1400); +rtw_debug_impl_mac(15, 0x1500); +rtw_debug_impl_mac(16, 0x1600); +rtw_debug_impl_mac(17, 0x1700); + +#define rtw_debug_impl_bb(page, addr) \ +static struct rtw_debugfs_priv rtw_debug_priv_bb_ ##page = { \ + .cb_read = rtw_debug_get_bb_page, \ + .cb_data = addr, \ +} + +rtw_debug_impl_bb(8, 0x0800); +rtw_debug_impl_bb(9, 0x0900); +rtw_debug_impl_bb(a, 0x0a00); +rtw_debug_impl_bb(b, 0x0b00); +rtw_debug_impl_bb(c, 0x0c00); +rtw_debug_impl_bb(d, 0x0d00); +rtw_debug_impl_bb(e, 0x0e00); +rtw_debug_impl_bb(f, 0x0f00); +rtw_debug_impl_bb(18, 0x1800); +rtw_debug_impl_bb(19, 0x1900); +rtw_debug_impl_bb(1a, 0x1a00); +rtw_debug_impl_bb(1b, 0x1b00); +rtw_debug_impl_bb(1c, 0x1c00); +rtw_debug_impl_bb(1d, 0x1d00); +rtw_debug_impl_bb(1e, 0x1e00); +rtw_debug_impl_bb(1f, 0x1f00); +rtw_debug_impl_bb(2c, 0x2c00); +rtw_debug_impl_bb(2d, 0x2d00); +rtw_debug_impl_bb(40, 0x4000); +rtw_debug_impl_bb(41, 0x4100); + +static struct rtw_debugfs_priv rtw_debug_priv_rf_dump = { + .cb_read = rtw_debug_get_rf_dump, +}; + +static struct rtw_debugfs_priv rtw_debug_priv_write_reg = { + .cb_write = rtw_debugfs_set_write_reg, +}; + +static struct rtw_debugfs_priv rtw_debug_priv_rf_write = { + .cb_write = rtw_debugfs_set_rf_write, +}; + +static struct rtw_debugfs_priv rtw_debug_priv_rf_read = { + .cb_write = rtw_debugfs_set_rf_read, + .cb_read = rtw_debugfs_get_rf_read, +}; + +static struct rtw_debugfs_priv rtw_debug_priv_read_reg = { + .cb_write = rtw_debugfs_set_read_reg, + .cb_read = rtw_debugfs_get_read_reg, +}; + +static struct rtw_debugfs_priv rtw_debug_priv_dump_cam = { + .cb_write = rtw_debugfs_set_single_input, + .cb_read = rtw_debugfs_get_dump_cam, +}; + +static struct rtw_debugfs_priv rtw_debug_priv_rsvd_page = { + .cb_write = rtw_debugfs_set_rsvd_page, + .cb_read = rtw_debugfs_get_rsvd_page, +}; + +#define rtw_debugfs_add_core(name, mode, fopname, parent) \ + do { \ + rtw_debug_priv_ ##name.rtwdev = rtwdev; \ + if (!debugfs_create_file(#name, mode, \ + parent, &rtw_debug_priv_ ##name,\ + &file_ops_ ##fopname)) \ + pr_debug("Unable to initialize debugfs:%s\n", \ + #name); \ + } while (0) + +#define rtw_debugfs_add_w(name) \ + rtw_debugfs_add_core(name, S_IFREG | 0222, common_write, debugfs_topdir) +#define rtw_debugfs_add_rw(name) \ + rtw_debugfs_add_core(name, S_IFREG | 0666, single_rw, debugfs_topdir) +#define rtw_debugfs_add_r(name) \ + rtw_debugfs_add_core(name, S_IFREG | 0444, single_r, debugfs_topdir) + +void rtw_debugfs_init(struct rtw_dev *rtwdev) +{ + struct dentry *debugfs_topdir = rtwdev->debugfs; + + debugfs_topdir = debugfs_create_dir("rtw88", + rtwdev->hw->wiphy->debugfsdir); + rtw_debugfs_add_w(write_reg); + rtw_debugfs_add_rw(read_reg); + rtw_debugfs_add_w(rf_write); + rtw_debugfs_add_rw(rf_read); + rtw_debugfs_add_rw(dump_cam); + rtw_debugfs_add_rw(rsvd_page); + rtw_debugfs_add_r(mac_0); + rtw_debugfs_add_r(mac_1); + rtw_debugfs_add_r(mac_2); + rtw_debugfs_add_r(mac_3); + rtw_debugfs_add_r(mac_4); + rtw_debugfs_add_r(mac_5); + rtw_debugfs_add_r(mac_6); + rtw_debugfs_add_r(mac_7); + rtw_debugfs_add_r(bb_8); + rtw_debugfs_add_r(bb_9); + rtw_debugfs_add_r(bb_a); + rtw_debugfs_add_r(bb_b); + rtw_debugfs_add_r(bb_c); + rtw_debugfs_add_r(bb_d); + rtw_debugfs_add_r(bb_e); + rtw_debugfs_add_r(bb_f); + rtw_debugfs_add_r(mac_10); + rtw_debugfs_add_r(mac_11); + rtw_debugfs_add_r(mac_12); + rtw_debugfs_add_r(mac_13); + rtw_debugfs_add_r(mac_14); + rtw_debugfs_add_r(mac_15); + rtw_debugfs_add_r(mac_16); + rtw_debugfs_add_r(mac_17); + rtw_debugfs_add_r(bb_18); + rtw_debugfs_add_r(bb_19); + rtw_debugfs_add_r(bb_1a); + rtw_debugfs_add_r(bb_1b); + rtw_debugfs_add_r(bb_1c); + rtw_debugfs_add_r(bb_1d); + rtw_debugfs_add_r(bb_1e); + rtw_debugfs_add_r(bb_1f); + if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C) { + rtw_debugfs_add_r(bb_2c); + rtw_debugfs_add_r(bb_2d); + rtw_debugfs_add_r(bb_40); + rtw_debugfs_add_r(bb_41); + } + rtw_debugfs_add_r(rf_dump); +} + +#endif /* CONFIG_RTW88_DEBUGFS */ + +#ifdef CONFIG_RTW88_DEBUG + +void __rtw_dbg(struct rtw_dev *rtwdev, enum rtw_debug_mask mask, + const char *fmt, ...) +{ + struct va_format vaf = { + .fmt = fmt, + }; + va_list args; + + va_start(args, fmt); + vaf.va = &args; + + if (rtw_debug_mask & mask) + dev_printk(KERN_DEBUG, rtwdev->dev, "%pV", &vaf); + + va_end(args); +} +EXPORT_SYMBOL(__rtw_dbg); + +#endif /* CONFIG_RTW88_DEBUG */ diff --git a/drivers/net/wireless/realtek/rtw88/debug.h b/drivers/net/wireless/realtek/rtw88/debug.h new file mode 100644 index 000000000000..45851cbbd2ab --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/debug.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW_DEBUG_H +#define __RTW_DEBUG_H + +enum rtw_debug_mask { + RTW_DBG_PCI = 0x00000001, + RTW_DBG_TX = 0x00000002, + RTW_DBG_RX = 0x00000004, + RTW_DBG_PHY = 0x00000008, + RTW_DBG_FW = 0x00000010, + RTW_DBG_EFUSE = 0x00000020, + RTW_DBG_COEX = 0x00000040, + RTW_DBG_RFK = 0x00000080, + RTW_DBG_REGD = 0x00000100, + RTW_DBG_DEBUGFS = 0x00000200, + + RTW_DBG_ALL = 0xffffffff +}; + +#ifdef CONFIG_RTW88_DEBUGFS + +void rtw_debugfs_init(struct rtw_dev *rtwdev); + +#else + +static inline void rtw_debugfs_init(struct rtw_dev *rtwdev) {} + +#endif /* CONFIG_RTW88_DEBUGFS */ + +#ifdef CONFIG_RTW88_DEBUG + +__printf(3, 4) +void __rtw_dbg(struct rtw_dev *rtwdev, enum rtw_debug_mask mask, + const char *fmt, ...); + +#define rtw_dbg(rtwdev, a...) __rtw_dbg(rtwdev, ##a) + +#else + +static inline void rtw_dbg(struct rtw_dev *rtwdev, enum rtw_debug_mask mask, + const char *fmt, ...) {} + +#endif /* CONFIG_RTW88_DEBUG */ + +#define rtw_info(rtwdev, a...) dev_info(rtwdev->dev, ##a) +#define rtw_warn(rtwdev, a...) dev_warn(rtwdev->dev, ##a) +#define rtw_err(rtwdev, a...) dev_err(rtwdev->dev, ##a) + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/efuse.c b/drivers/net/wireless/realtek/rtw88/efuse.c new file mode 100644 index 000000000000..212c8376a8c9 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/efuse.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "efuse.h" +#include "reg.h" +#include "debug.h" + +#define RTW_EFUSE_BANK_WIFI 0x0 + +static void switch_efuse_bank(struct rtw_dev *rtwdev) +{ + rtw_write32_mask(rtwdev, REG_LDO_EFUSE_CTRL, BIT_MASK_EFUSE_BANK_SEL, + RTW_EFUSE_BANK_WIFI); +} + +#define invalid_efuse_header(hdr1, hdr2) \ + ((hdr1) == 0xff || (((hdr1) & 0x1f) == 0xf && (hdr2) == 0xff)) +#define invalid_efuse_content(word_en, i) \ + (((word_en) & BIT(i)) != 0x0) +#define get_efuse_blk_idx_2_byte(hdr1, hdr2) \ + ((((hdr2) & 0xf0) >> 1) | (((hdr1) >> 5) & 0x07)) +#define get_efuse_blk_idx_1_byte(hdr1) \ + (((hdr1) & 0xf0) >> 4) +#define block_idx_to_logical_idx(blk_idx, i) \ + (((blk_idx) << 3) + ((i) << 1)) + +/* efuse header format + * + * | 7 5 4 0 | 7 4 3 0 | 15 8 7 0 | + * block[2:0] 0 1111 block[6:3] word_en[3:0] byte0 byte1 + * | header 1 (optional) | header 2 | word N | + * + * word_en: 4 bits each word. 0 -> write; 1 -> not write + * N: 1~4, depends on word_en + */ +static int rtw_dump_logical_efuse_map(struct rtw_dev *rtwdev, u8 *phy_map, + u8 *log_map) +{ + u32 physical_size = rtwdev->efuse.physical_size; + u32 protect_size = rtwdev->efuse.protect_size; + u32 logical_size = rtwdev->efuse.logical_size; + u32 phy_idx, log_idx; + u8 hdr1, hdr2; + u8 blk_idx; + u8 word_en; + int i; + + for (phy_idx = 0; phy_idx < physical_size - protect_size;) { + hdr1 = phy_map[phy_idx]; + hdr2 = phy_map[phy_idx + 1]; + if (invalid_efuse_header(hdr1, hdr2)) + break; + + if ((hdr1 & 0x1f) == 0xf) { + /* 2-byte header format */ + blk_idx = get_efuse_blk_idx_2_byte(hdr1, hdr2); + word_en = hdr2 & 0xf; + phy_idx += 2; + } else { + /* 1-byte header format */ + blk_idx = get_efuse_blk_idx_1_byte(hdr1); + word_en = hdr1 & 0xf; + phy_idx += 1; + } + + for (i = 0; i < 4; i++) { + if (invalid_efuse_content(word_en, i)) + continue; + + log_idx = block_idx_to_logical_idx(blk_idx, i); + if (phy_idx + 1 > physical_size - protect_size || + log_idx + 1 > logical_size) + return -EINVAL; + + log_map[log_idx] = phy_map[phy_idx]; + log_map[log_idx + 1] = phy_map[phy_idx + 1]; + phy_idx += 2; + } + } + return 0; +} + +static int rtw_dump_physical_efuse_map(struct rtw_dev *rtwdev, u8 *map) +{ + struct rtw_chip_info *chip = rtwdev->chip; + u32 size = rtwdev->efuse.physical_size; + u32 efuse_ctl; + u32 addr; + u32 cnt; + + switch_efuse_bank(rtwdev); + + /* disable 2.5V LDO */ + chip->ops->cfg_ldo25(rtwdev, false); + + efuse_ctl = rtw_read32(rtwdev, REG_EFUSE_CTRL); + + for (addr = 0; addr < size; addr++) { + efuse_ctl &= ~(BIT_MASK_EF_DATA | BITS_EF_ADDR); + efuse_ctl |= (addr & BIT_MASK_EF_ADDR) << BIT_SHIFT_EF_ADDR; + rtw_write32(rtwdev, REG_EFUSE_CTRL, efuse_ctl & (~BIT_EF_FLAG)); + + cnt = 1000000; + do { + udelay(1); + efuse_ctl = rtw_read32(rtwdev, REG_EFUSE_CTRL); + if (--cnt == 0) + return -EBUSY; + } while (!(efuse_ctl & BIT_EF_FLAG)); + + *(map + addr) = (u8)(efuse_ctl & BIT_MASK_EF_DATA); + } + + return 0; +} + +int rtw_parse_efuse_map(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; + u32 phy_size = efuse->physical_size; + u32 log_size = efuse->logical_size; + u8 *phy_map = NULL; + u8 *log_map = NULL; + int ret = 0; + + phy_map = kmalloc(phy_size, GFP_KERNEL); + log_map = kmalloc(log_size, GFP_KERNEL); + if (!phy_map || !log_map) { + ret = -ENOMEM; + goto out_free; + } + + ret = rtw_dump_physical_efuse_map(rtwdev, phy_map); + if (ret) { + rtw_err(rtwdev, "failed to dump efuse physical map\n"); + goto out_free; + } + + memset(log_map, 0xff, log_size); + ret = rtw_dump_logical_efuse_map(rtwdev, phy_map, log_map); + if (ret) { + rtw_err(rtwdev, "failed to dump efuse logical map\n"); + goto out_free; + } + + ret = chip->ops->read_efuse(rtwdev, log_map); + if (ret) { + rtw_err(rtwdev, "failed to read efuse map\n"); + goto out_free; + } + +out_free: + kfree(log_map); + kfree(phy_map); + + return ret; +} diff --git a/drivers/net/wireless/realtek/rtw88/efuse.h b/drivers/net/wireless/realtek/rtw88/efuse.h new file mode 100644 index 000000000000..115bbe85946a --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/efuse.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW_EFUSE_H__ +#define __RTW_EFUSE_H__ + +#define EFUSE_HW_CAP_IGNORE 0 +#define EFUSE_HW_CAP_PTCL_VHT 3 +#define EFUSE_HW_CAP_SUPP_BW80 7 +#define EFUSE_HW_CAP_SUPP_BW40 6 + +#define GET_EFUSE_HW_CAP_HCI(hw_cap) \ + le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(3, 0)) +#define GET_EFUSE_HW_CAP_BW(hw_cap) \ + le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(18, 16)) +#define GET_EFUSE_HW_CAP_NSS(hw_cap) \ + le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(20, 19)) +#define GET_EFUSE_HW_CAP_ANT_NUM(hw_cap) \ + le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(23, 21)) +#define GET_EFUSE_HW_CAP_PTCL(hw_cap) \ + le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(27, 26)) + +int rtw_parse_efuse_map(struct rtw_dev *rtwdev); + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c new file mode 100644 index 000000000000..cf4265cda224 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -0,0 +1,633 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "fw.h" +#include "tx.h" +#include "reg.h" +#include "debug.h" + +void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev, struct sk_buff *skb) +{ + struct rtw_c2h_cmd *c2h; + u8 sub_cmd_id; + + c2h = get_c2h_from_skb(skb); + sub_cmd_id = c2h->payload[0]; + + switch (sub_cmd_id) { + case C2H_CCX_RPT: + rtw_tx_report_handle(rtwdev, skb); + break; + default: + break; + } +} + +void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) +{ + struct rtw_c2h_cmd *c2h; + u32 pkt_offset; + u8 len; + + pkt_offset = *((u32 *)skb->cb); + c2h = (struct rtw_c2h_cmd *)(skb->data + pkt_offset); + len = skb->len - pkt_offset - 2; + + rtw_dbg(rtwdev, RTW_DBG_FW, "recv C2H, id=0x%02x, seq=0x%02x, len=%d\n", + c2h->id, c2h->seq, len); + + switch (c2h->id) { + case C2H_HALMAC: + rtw_fw_c2h_cmd_handle_ext(rtwdev, skb); + break; + default: + break; + } +} + +void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, u8 *h2c) +{ + u8 box; + u8 box_state; + u32 box_reg, box_ex_reg; + u32 h2c_wait; + int idx; + + rtw_dbg(rtwdev, RTW_DBG_FW, + "send H2C content %02x%02x%02x%02x %02x%02x%02x%02x\n", + h2c[3], h2c[2], h2c[1], h2c[0], + h2c[7], h2c[6], h2c[5], h2c[4]); + + spin_lock(&rtwdev->h2c.lock); + + box = rtwdev->h2c.last_box_num; + switch (box) { + case 0: + box_reg = REG_HMEBOX0; + box_ex_reg = REG_HMEBOX0_EX; + break; + case 1: + box_reg = REG_HMEBOX1; + box_ex_reg = REG_HMEBOX1_EX; + break; + case 2: + box_reg = REG_HMEBOX2; + box_ex_reg = REG_HMEBOX2_EX; + break; + case 3: + box_reg = REG_HMEBOX3; + box_ex_reg = REG_HMEBOX3_EX; + break; + default: + WARN(1, "invalid h2c mail box number\n"); + goto out; + } + + h2c_wait = 20; + do { + box_state = rtw_read8(rtwdev, REG_HMETFR); + } while ((box_state >> box) & 0x1 && --h2c_wait > 0); + + if (!h2c_wait) { + rtw_err(rtwdev, "failed to send h2c command\n"); + goto out; + } + + for (idx = 0; idx < 4; idx++) + rtw_write8(rtwdev, box_reg + idx, h2c[idx]); + for (idx = 0; idx < 4; idx++) + rtw_write8(rtwdev, box_ex_reg + idx, h2c[idx + 4]); + + if (++rtwdev->h2c.last_box_num >= 4) + rtwdev->h2c.last_box_num = 0; + +out: + spin_unlock(&rtwdev->h2c.lock); +} + +static void rtw_fw_send_h2c_packet(struct rtw_dev *rtwdev, u8 *h2c_pkt) +{ + int ret; + + spin_lock(&rtwdev->h2c.lock); + + FW_OFFLOAD_H2C_SET_SEQ_NUM(h2c_pkt, rtwdev->h2c.seq); + ret = rtw_hci_write_data_h2c(rtwdev, h2c_pkt, H2C_PKT_SIZE); + if (ret) + rtw_err(rtwdev, "failed to send h2c packet\n"); + rtwdev->h2c.seq++; + + spin_unlock(&rtwdev->h2c.lock); +} + +void +rtw_fw_send_general_info(struct rtw_dev *rtwdev) +{ + struct rtw_fifo_conf *fifo = &rtwdev->fifo; + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + u16 total_size = H2C_PKT_HDR_SIZE + 4; + + rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_GENERAL_INFO); + + SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size); + + GENERAL_INFO_SET_FW_TX_BOUNDARY(h2c_pkt, + fifo->rsvd_fw_txbuf_addr - + fifo->rsvd_boundary); + + rtw_fw_send_h2c_packet(rtwdev, h2c_pkt); +} + +void +rtw_fw_send_phydm_info(struct rtw_dev *rtwdev) +{ + struct rtw_hal *hal = &rtwdev->hal; + struct rtw_efuse *efuse = &rtwdev->efuse; + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + u16 total_size = H2C_PKT_HDR_SIZE + 8; + u8 fw_rf_type = 0; + + if (hal->rf_type == RF_1T1R) + fw_rf_type = FW_RF_1T1R; + else if (hal->rf_type == RF_2T2R) + fw_rf_type = FW_RF_2T2R; + + rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_PHYDM_INFO); + + SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size); + PHYDM_INFO_SET_REF_TYPE(h2c_pkt, efuse->rfe_option); + PHYDM_INFO_SET_RF_TYPE(h2c_pkt, fw_rf_type); + PHYDM_INFO_SET_CUT_VER(h2c_pkt, hal->cut_version); + PHYDM_INFO_SET_RX_ANT_STATUS(h2c_pkt, hal->antenna_tx); + PHYDM_INFO_SET_TX_ANT_STATUS(h2c_pkt, hal->antenna_rx); + + rtw_fw_send_h2c_packet(rtwdev, h2c_pkt); +} + +void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + u16 total_size = H2C_PKT_HDR_SIZE + 1; + + rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_IQK); + SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size); + IQK_SET_CLEAR(h2c_pkt, para->clear); + IQK_SET_SEGMENT_IQK(h2c_pkt, para->segment_iqk); + + rtw_fw_send_h2c_packet(rtwdev, h2c_pkt); +} + +void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + u8 rssi = ewma_rssi_read(&si->avg_rssi); + bool stbc_en = si->stbc_en ? true : false; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RSSI_MONITOR); + + SET_RSSI_INFO_MACID(h2c_pkt, si->mac_id); + SET_RSSI_INFO_RSSI(h2c_pkt, rssi); + SET_RSSI_INFO_STBC(h2c_pkt, stbc_en); + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + +void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + bool no_update = si->updated; + bool disable_pt = true; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RA_INFO); + + SET_RA_INFO_MACID(h2c_pkt, si->mac_id); + SET_RA_INFO_RATE_ID(h2c_pkt, si->rate_id); + SET_RA_INFO_INIT_RA_LVL(h2c_pkt, si->init_ra_lv); + SET_RA_INFO_SGI_EN(h2c_pkt, si->sgi_enable); + SET_RA_INFO_BW_MODE(h2c_pkt, si->bw_mode); + SET_RA_INFO_LDPC(h2c_pkt, si->ldpc_en); + SET_RA_INFO_NO_UPDATE(h2c_pkt, no_update); + SET_RA_INFO_VHT_EN(h2c_pkt, si->vht_enable); + SET_RA_INFO_DIS_PT(h2c_pkt, disable_pt); + SET_RA_INFO_RA_MASK0(h2c_pkt, (si->ra_mask & 0xff)); + SET_RA_INFO_RA_MASK1(h2c_pkt, (si->ra_mask & 0xff00) >> 8); + SET_RA_INFO_RA_MASK2(h2c_pkt, (si->ra_mask & 0xff0000) >> 16); + SET_RA_INFO_RA_MASK3(h2c_pkt, (si->ra_mask & 0xff000000) >> 24); + + si->init_ra_lv = 0; + si->updated = true; + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + +void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool connect) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_MEDIA_STATUS_RPT); + MEDIA_STATUS_RPT_SET_OP_MODE(h2c_pkt, connect); + MEDIA_STATUS_RPT_SET_MACID(h2c_pkt, mac_id); + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + +void rtw_fw_set_pwr_mode(struct rtw_dev *rtwdev) +{ + struct rtw_lps_conf *conf = &rtwdev->lps_conf; + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_SET_PWR_MODE); + + SET_PWR_MODE_SET_MODE(h2c_pkt, conf->mode); + SET_PWR_MODE_SET_RLBM(h2c_pkt, conf->rlbm); + SET_PWR_MODE_SET_SMART_PS(h2c_pkt, conf->smart_ps); + SET_PWR_MODE_SET_AWAKE_INTERVAL(h2c_pkt, conf->awake_interval); + SET_PWR_MODE_SET_PORT_ID(h2c_pkt, conf->port_id); + SET_PWR_MODE_SET_PWR_STATE(h2c_pkt, conf->state); + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + +static u8 rtw_get_rsvd_page_location(struct rtw_dev *rtwdev, + enum rtw_rsvd_packet_type type) +{ + struct rtw_rsvd_page *rsvd_pkt; + u8 location = 0; + + list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) { + if (type == rsvd_pkt->type) + location = rsvd_pkt->page; + } + + return location; +} + +void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + u8 location = 0; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RSVD_PAGE); + + location = rtw_get_rsvd_page_location(rtwdev, RSVD_PROBE_RESP); + *(h2c_pkt + 1) = location; + rtw_dbg(rtwdev, RTW_DBG_FW, "RSVD_PROBE_RESP loc: %d\n", location); + + location = rtw_get_rsvd_page_location(rtwdev, RSVD_PS_POLL); + *(h2c_pkt + 2) = location; + rtw_dbg(rtwdev, RTW_DBG_FW, "RSVD_PS_POLL loc: %d\n", location); + + location = rtw_get_rsvd_page_location(rtwdev, RSVD_NULL); + *(h2c_pkt + 3) = location; + rtw_dbg(rtwdev, RTW_DBG_FW, "RSVD_NULL loc: %d\n", location); + + location = rtw_get_rsvd_page_location(rtwdev, RSVD_QOS_NULL); + *(h2c_pkt + 4) = location; + rtw_dbg(rtwdev, RTW_DBG_FW, "RSVD_QOS_NULL loc: %d\n", location); + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + +static struct sk_buff * +rtw_beacon_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct sk_buff *skb_new; + + if (vif->type != NL80211_IFTYPE_AP && + vif->type != NL80211_IFTYPE_ADHOC && + !ieee80211_vif_is_mesh(vif)) { + skb_new = alloc_skb(1, GFP_KERNEL); + if (!skb_new) + return NULL; + skb_put(skb_new, 1); + } else { + skb_new = ieee80211_beacon_get(hw, vif); + } + + return skb_new; +} + +static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum rtw_rsvd_packet_type type) +{ + struct sk_buff *skb_new; + + switch (type) { + case RSVD_BEACON: + skb_new = rtw_beacon_get(hw, vif); + break; + case RSVD_PS_POLL: + skb_new = ieee80211_pspoll_get(hw, vif); + break; + case RSVD_PROBE_RESP: + skb_new = ieee80211_proberesp_get(hw, vif); + break; + case RSVD_NULL: + skb_new = ieee80211_nullfunc_get(hw, vif, false); + break; + case RSVD_QOS_NULL: + skb_new = ieee80211_nullfunc_get(hw, vif, true); + break; + default: + return NULL; + } + + if (!skb_new) + return NULL; + + return skb_new; +} + +static void rtw_fill_rsvd_page_desc(struct rtw_dev *rtwdev, struct sk_buff *skb) +{ + struct rtw_tx_pkt_info pkt_info; + struct rtw_chip_info *chip = rtwdev->chip; + u8 *pkt_desc; + + memset(&pkt_info, 0, sizeof(pkt_info)); + rtw_rsvd_page_pkt_info_update(rtwdev, &pkt_info, skb); + pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz); + memset(pkt_desc, 0, chip->tx_pkt_desc_sz); + rtw_tx_fill_tx_desc(&pkt_info, skb); +} + +static inline u8 rtw_len_to_page(unsigned int len, u8 page_size) +{ + return DIV_ROUND_UP(len, page_size); +} + +static void rtw_rsvd_page_list_to_buf(struct rtw_dev *rtwdev, u8 page_size, + u8 page_margin, u32 page, u8 *buf, + struct rtw_rsvd_page *rsvd_pkt) +{ + struct sk_buff *skb = rsvd_pkt->skb; + + if (rsvd_pkt->add_txdesc) + rtw_fill_rsvd_page_desc(rtwdev, skb); + + if (page >= 1) + memcpy(buf + page_margin + page_size * (page - 1), + skb->data, skb->len); + else + memcpy(buf, skb->data, skb->len); +} + +void rtw_add_rsvd_page(struct rtw_dev *rtwdev, enum rtw_rsvd_packet_type type, + bool txdesc) +{ + struct rtw_rsvd_page *rsvd_pkt; + + lockdep_assert_held(&rtwdev->mutex); + + list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) { + if (rsvd_pkt->type == type) + return; + } + + rsvd_pkt = kmalloc(sizeof(*rsvd_pkt), GFP_KERNEL); + if (!rsvd_pkt) + return; + + rsvd_pkt->type = type; + rsvd_pkt->add_txdesc = txdesc; + list_add_tail(&rsvd_pkt->list, &rtwdev->rsvd_page_list); +} + +void rtw_reset_rsvd_page(struct rtw_dev *rtwdev) +{ + struct rtw_rsvd_page *rsvd_pkt, *tmp; + + lockdep_assert_held(&rtwdev->mutex); + + list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, list) { + if (rsvd_pkt->type == RSVD_BEACON) + continue; + list_del(&rsvd_pkt->list); + kfree(rsvd_pkt); + } +} + +int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, + u8 *buf, u32 size) +{ + u8 bckp[2]; + u8 val; + u16 rsvd_pg_head; + int ret; + + lockdep_assert_held(&rtwdev->mutex); + + if (!size) + return -EINVAL; + + pg_addr &= BIT_MASK_BCN_HEAD_1_V1; + rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2, pg_addr | BIT_BCN_VALID_V1); + + val = rtw_read8(rtwdev, REG_CR + 1); + bckp[0] = val; + val |= BIT_ENSWBCN >> 8; + rtw_write8(rtwdev, REG_CR + 1, val); + + val = rtw_read8(rtwdev, REG_FWHW_TXQ_CTRL + 2); + bckp[1] = val; + val &= ~(BIT_EN_BCNQ_DL >> 16); + rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 2, val); + + ret = rtw_hci_write_data_rsvd_page(rtwdev, buf, size); + if (ret) { + rtw_err(rtwdev, "failed to write data to rsvd page\n"); + goto restore; + } + + if (!check_hw_ready(rtwdev, REG_FIFOPAGE_CTRL_2, BIT_BCN_VALID_V1, 1)) { + rtw_err(rtwdev, "error beacon valid\n"); + ret = -EBUSY; + } + +restore: + rsvd_pg_head = rtwdev->fifo.rsvd_boundary; + rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2, + rsvd_pg_head | BIT_BCN_VALID_V1); + rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 2, bckp[1]); + rtw_write8(rtwdev, REG_CR + 1, bckp[0]); + + return ret; +} + +static int rtw_download_drv_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size) +{ + u32 pg_size; + u32 pg_num = 0; + u16 pg_addr = 0; + + pg_size = rtwdev->chip->page_size; + pg_num = size / pg_size + ((size & (pg_size - 1)) ? 1 : 0); + if (pg_num > rtwdev->fifo.rsvd_drv_pg_num) + return -ENOMEM; + + pg_addr = rtwdev->fifo.rsvd_drv_addr; + + return rtw_fw_write_data_rsvd_page(rtwdev, pg_addr, buf, size); +} + +static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, + struct ieee80211_vif *vif, u32 *size) +{ + struct ieee80211_hw *hw = rtwdev->hw; + struct rtw_chip_info *chip = rtwdev->chip; + struct sk_buff *iter; + struct rtw_rsvd_page *rsvd_pkt; + u32 page = 0; + u8 total_page = 0; + u8 page_size, page_margin, tx_desc_sz; + u8 *buf; + + page_size = chip->page_size; + tx_desc_sz = chip->tx_pkt_desc_sz; + page_margin = page_size - tx_desc_sz; + + list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) { + iter = rtw_get_rsvd_page_skb(hw, vif, rsvd_pkt->type); + if (!iter) { + rtw_err(rtwdev, "fail to build rsvd packet\n"); + goto release_skb; + } + rsvd_pkt->skb = iter; + rsvd_pkt->page = total_page; + if (rsvd_pkt->add_txdesc) + total_page += rtw_len_to_page(iter->len + tx_desc_sz, + page_size); + else + total_page += rtw_len_to_page(iter->len, page_size); + } + + if (total_page > rtwdev->fifo.rsvd_drv_pg_num) { + rtw_err(rtwdev, "rsvd page over size: %d\n", total_page); + goto release_skb; + } + + *size = (total_page - 1) * page_size + page_margin; + buf = kzalloc(*size, GFP_KERNEL); + if (!buf) + goto release_skb; + + list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) { + rtw_rsvd_page_list_to_buf(rtwdev, page_size, page_margin, + page, buf, rsvd_pkt); + page += rtw_len_to_page(rsvd_pkt->skb->len, page_size); + } + list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) + kfree_skb(rsvd_pkt->skb); + + return buf; + +release_skb: + list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) + kfree_skb(rsvd_pkt->skb); + + return NULL; +} + +static int +rtw_download_beacon(struct rtw_dev *rtwdev, struct ieee80211_vif *vif) +{ + struct ieee80211_hw *hw = rtwdev->hw; + struct sk_buff *skb; + int ret = 0; + + skb = rtw_beacon_get(hw, vif); + if (!skb) { + rtw_err(rtwdev, "failed to get beacon skb\n"); + ret = -ENOMEM; + goto out; + } + + ret = rtw_download_drv_rsvd_page(rtwdev, skb->data, skb->len); + if (ret) + rtw_err(rtwdev, "failed to download drv rsvd page\n"); + + dev_kfree_skb(skb); + +out: + return ret; +} + +int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev, struct ieee80211_vif *vif) +{ + u8 *buf; + u32 size; + int ret; + + buf = rtw_build_rsvd_page(rtwdev, vif, &size); + if (!buf) { + rtw_err(rtwdev, "failed to build rsvd page pkt\n"); + return -ENOMEM; + } + + ret = rtw_download_drv_rsvd_page(rtwdev, buf, size); + if (ret) { + rtw_err(rtwdev, "failed to download drv rsvd page\n"); + goto free; + } + + ret = rtw_download_beacon(rtwdev, vif); + if (ret) { + rtw_err(rtwdev, "failed to download beacon\n"); + goto free; + } + +free: + kfree(buf); + + return ret; +} + +int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev, + u32 offset, u32 size, u32 *buf) +{ + struct rtw_fifo_conf *fifo = &rtwdev->fifo; + u32 residue, i; + u16 start_pg; + u16 idx = 0; + u16 ctl; + u8 rcr; + + if (size & 0x3) { + rtw_warn(rtwdev, "should be 4-byte aligned\n"); + return -EINVAL; + } + + offset += fifo->rsvd_boundary << TX_PAGE_SIZE_SHIFT; + residue = offset & (FIFO_PAGE_SIZE - 1); + start_pg = offset >> FIFO_PAGE_SIZE_SHIFT; + start_pg += RSVD_PAGE_START_ADDR; + + rcr = rtw_read8(rtwdev, REG_RCR + 2); + ctl = rtw_read16(rtwdev, REG_PKTBUF_DBG_CTRL) & 0xf000; + + /* disable rx clock gate */ + rtw_write8(rtwdev, REG_RCR, rcr | BIT(3)); + + do { + rtw_write16(rtwdev, REG_PKTBUF_DBG_CTRL, start_pg | ctl); + + for (i = FIFO_DUMP_ADDR + residue; + i < FIFO_DUMP_ADDR + FIFO_PAGE_SIZE; i += 4) { + buf[idx++] = rtw_read32(rtwdev, i); + size -= 4; + if (size == 0) + goto out; + } + + residue = 0; + start_pg++; + } while (size); + +out: + rtw_write16(rtwdev, REG_PKTBUF_DBG_CTRL, ctl); + rtw_write8(rtwdev, REG_RCR + 2, rcr); + return 0; +} diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h new file mode 100644 index 000000000000..703466393ecb --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/fw.h @@ -0,0 +1,222 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW_FW_H_ +#define __RTW_FW_H_ + +#define H2C_PKT_SIZE 32 +#define H2C_PKT_HDR_SIZE 8 + +/* FW bin information */ +#define FW_HDR_SIZE 64 +#define FW_HDR_CHKSUM_SIZE 8 +#define FW_HDR_VERSION 4 +#define FW_HDR_SUBVERSION 6 +#define FW_HDR_SUBINDEX 7 +#define FW_HDR_MONTH 16 +#define FW_HDR_DATE 17 +#define FW_HDR_HOUR 18 +#define FW_HDR_MIN 19 +#define FW_HDR_YEAR 20 +#define FW_HDR_MEM_USAGE 24 +#define FW_HDR_H2C_FMT_VER 28 +#define FW_HDR_DMEM_ADDR 32 +#define FW_HDR_DMEM_SIZE 36 +#define FW_HDR_IMEM_SIZE 48 +#define FW_HDR_EMEM_SIZE 52 +#define FW_HDR_EMEM_ADDR 56 +#define FW_HDR_IMEM_ADDR 60 + +#define FIFO_PAGE_SIZE_SHIFT 12 +#define FIFO_PAGE_SIZE 4096 +#define RSVD_PAGE_START_ADDR 0x780 +#define FIFO_DUMP_ADDR 0x8000 + +enum rtw_c2h_cmd_id { + C2H_BT_INFO = 0x09, + C2H_HW_FEATURE_REPORT = 0x19, + C2H_HW_FEATURE_DUMP = 0xfd, + C2H_HALMAC = 0xff, +}; + +enum rtw_c2h_cmd_id_ext { + C2H_CCX_RPT = 0x0f, +}; + +struct rtw_c2h_cmd { + u8 id; + u8 seq; + u8 payload[0]; +} __packed; + +enum rtw_rsvd_packet_type { + RSVD_BEACON, + RSVD_PS_POLL, + RSVD_PROBE_RESP, + RSVD_NULL, + RSVD_QOS_NULL, +}; + +enum rtw_fw_rf_type { + FW_RF_1T2R = 0, + FW_RF_2T4R = 1, + FW_RF_2T2R = 2, + FW_RF_2T3R = 3, + FW_RF_1T1R = 4, + FW_RF_2T2R_GREEN = 5, + FW_RF_3T3R = 6, + FW_RF_3T4R = 7, + FW_RF_4T4R = 8, + FW_RF_MAX_TYPE = 0xF, +}; + +struct rtw_iqk_para { + u8 clear; + u8 segment_iqk; +}; + +struct rtw_rsvd_page { + struct list_head list; + struct sk_buff *skb; + enum rtw_rsvd_packet_type type; + u8 page; + bool add_txdesc; +}; + +/* C2H */ +#define GET_CCX_REPORT_SEQNUM(c2h_payload) (c2h_payload[8] & 0xfc) +#define GET_CCX_REPORT_STATUS(c2h_payload) (c2h_payload[9] & 0xc0) + +/* PKT H2C */ +#define H2C_PKT_CMD_ID 0xFF +#define H2C_PKT_CATEGORY 0x01 + +#define H2C_PKT_GENERAL_INFO 0x0D +#define H2C_PKT_PHYDM_INFO 0x11 +#define H2C_PKT_IQK 0x0E + +#define SET_PKT_H2C_CATEGORY(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(6, 0)) +#define SET_PKT_H2C_CMD_ID(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8)) +#define SET_PKT_H2C_SUB_CMD_ID(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 16)) +#define SET_PKT_H2C_TOTAL_LEN(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 0)) + +static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) +{ + SET_PKT_H2C_CATEGORY(h2c_pkt, H2C_PKT_CATEGORY); + SET_PKT_H2C_CMD_ID(h2c_pkt, H2C_PKT_CMD_ID); + SET_PKT_H2C_SUB_CMD_ID(h2c_pkt, sub_id); +} + +#define FW_OFFLOAD_H2C_SET_SEQ_NUM(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(31, 16)) +#define GENERAL_INFO_SET_FW_TX_BOUNDARY(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(23, 16)) + +#define PHYDM_INFO_SET_REF_TYPE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(7, 0)) +#define PHYDM_INFO_SET_RF_TYPE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 8)) +#define PHYDM_INFO_SET_CUT_VER(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(23, 16)) +#define PHYDM_INFO_SET_RX_ANT_STATUS(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(27, 24)) +#define PHYDM_INFO_SET_TX_ANT_STATUS(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(31, 28)) +#define IQK_SET_CLEAR(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(0)) +#define IQK_SET_SEGMENT_IQK(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(1)) + +/* Command H2C */ +#define H2C_CMD_RSVD_PAGE 0x0 +#define H2C_CMD_MEDIA_STATUS_RPT 0x01 +#define H2C_CMD_SET_PWR_MODE 0x20 +#define H2C_CMD_RA_INFO 0x40 +#define H2C_CMD_RSSI_MONITOR 0x42 + +#define SET_H2C_CMD_ID_CLASS(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(7, 0)) + +#define MEDIA_STATUS_RPT_SET_OP_MODE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8)) +#define MEDIA_STATUS_RPT_SET_MACID(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) + +#define SET_PWR_MODE_SET_MODE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(14, 8)) +#define SET_PWR_MODE_SET_RLBM(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(19, 16)) +#define SET_PWR_MODE_SET_SMART_PS(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 20)) +#define SET_PWR_MODE_SET_AWAKE_INTERVAL(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24)) +#define SET_PWR_MODE_SET_PORT_ID(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 5)) +#define SET_PWR_MODE_SET_PWR_STATE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8)) +#define SET_RSSI_INFO_MACID(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8)) +#define SET_RSSI_INFO_RSSI(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24)) +#define SET_RSSI_INFO_STBC(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, BIT(1)) +#define SET_RA_INFO_MACID(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8)) +#define SET_RA_INFO_RATE_ID(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(20, 16)) +#define SET_RA_INFO_INIT_RA_LVL(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(22, 21)) +#define SET_RA_INFO_SGI_EN(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(23)) +#define SET_RA_INFO_BW_MODE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(25, 24)) +#define SET_RA_INFO_LDPC(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(26)) +#define SET_RA_INFO_NO_UPDATE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(27)) +#define SET_RA_INFO_VHT_EN(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(29, 28)) +#define SET_RA_INFO_DIS_PT(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(30)) +#define SET_RA_INFO_RA_MASK0(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0)) +#define SET_RA_INFO_RA_MASK1(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8)) +#define SET_RA_INFO_RA_MASK2(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(23, 16)) +#define SET_RA_INFO_RA_MASK3(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(31, 24)) + +static inline struct rtw_c2h_cmd *get_c2h_from_skb(struct sk_buff *skb) +{ + u32 pkt_offset; + + pkt_offset = *((u32 *)skb->cb); + return (struct rtw_c2h_cmd *)(skb->data + pkt_offset); +} + +void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb); +void rtw_fw_send_general_info(struct rtw_dev *rtwdev); +void rtw_fw_send_phydm_info(struct rtw_dev *rtwdev); + +void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para); +void rtw_fw_set_pwr_mode(struct rtw_dev *rtwdev); +void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); +void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); +void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool conn); +void rtw_add_rsvd_page(struct rtw_dev *rtwdev, enum rtw_rsvd_packet_type type, + bool txdesc); +int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, + u8 *buf, u32 size); +void rtw_reset_rsvd_page(struct rtw_dev *rtwdev); +int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev, + struct ieee80211_vif *vif); +void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev); +int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev, + u32 offset, u32 size, u32 *buf); +#endif diff --git a/drivers/net/wireless/realtek/rtw88/hci.h b/drivers/net/wireless/realtek/rtw88/hci.h new file mode 100644 index 000000000000..2676582a85a0 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/hci.h @@ -0,0 +1,211 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW_HCI_H__ +#define __RTW_HCI_H__ + +/* ops for PCI, USB and SDIO */ +struct rtw_hci_ops { + int (*tx)(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct sk_buff *skb); + int (*setup)(struct rtw_dev *rtwdev); + int (*start)(struct rtw_dev *rtwdev); + void (*stop)(struct rtw_dev *rtwdev); + + int (*write_data_rsvd_page)(struct rtw_dev *rtwdev, u8 *buf, u32 size); + int (*write_data_h2c)(struct rtw_dev *rtwdev, u8 *buf, u32 size); + + u8 (*read8)(struct rtw_dev *rtwdev, u32 addr); + u16 (*read16)(struct rtw_dev *rtwdev, u32 addr); + u32 (*read32)(struct rtw_dev *rtwdev, u32 addr); + void (*write8)(struct rtw_dev *rtwdev, u32 addr, u8 val); + void (*write16)(struct rtw_dev *rtwdev, u32 addr, u16 val); + void (*write32)(struct rtw_dev *rtwdev, u32 addr, u32 val); +}; + +static inline int rtw_hci_tx(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct sk_buff *skb) +{ + return rtwdev->hci.ops->tx(rtwdev, pkt_info, skb); +} + +static inline int rtw_hci_setup(struct rtw_dev *rtwdev) +{ + return rtwdev->hci.ops->setup(rtwdev); +} + +static inline int rtw_hci_start(struct rtw_dev *rtwdev) +{ + return rtwdev->hci.ops->start(rtwdev); +} + +static inline void rtw_hci_stop(struct rtw_dev *rtwdev) +{ + rtwdev->hci.ops->stop(rtwdev); +} + +static inline int +rtw_hci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size) +{ + return rtwdev->hci.ops->write_data_rsvd_page(rtwdev, buf, size); +} + +static inline int +rtw_hci_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size) +{ + return rtwdev->hci.ops->write_data_h2c(rtwdev, buf, size); +} + +static inline u8 rtw_read8(struct rtw_dev *rtwdev, u32 addr) +{ + return rtwdev->hci.ops->read8(rtwdev, addr); +} + +static inline u16 rtw_read16(struct rtw_dev *rtwdev, u32 addr) +{ + return rtwdev->hci.ops->read16(rtwdev, addr); +} + +static inline u32 rtw_read32(struct rtw_dev *rtwdev, u32 addr) +{ + return rtwdev->hci.ops->read32(rtwdev, addr); +} + +static inline void rtw_write8(struct rtw_dev *rtwdev, u32 addr, u8 val) +{ + rtwdev->hci.ops->write8(rtwdev, addr, val); +} + +static inline void rtw_write16(struct rtw_dev *rtwdev, u32 addr, u16 val) +{ + rtwdev->hci.ops->write16(rtwdev, addr, val); +} + +static inline void rtw_write32(struct rtw_dev *rtwdev, u32 addr, u32 val) +{ + rtwdev->hci.ops->write32(rtwdev, addr, val); +} + +static inline void rtw_write8_set(struct rtw_dev *rtwdev, u32 addr, u8 bit) +{ + u8 val; + + val = rtw_read8(rtwdev, addr); + rtw_write8(rtwdev, addr, val | bit); +} + +static inline void rtw_writ16_set(struct rtw_dev *rtwdev, u32 addr, u16 bit) +{ + u16 val; + + val = rtw_read16(rtwdev, addr); + rtw_write16(rtwdev, addr, val | bit); +} + +static inline void rtw_write32_set(struct rtw_dev *rtwdev, u32 addr, u32 bit) +{ + u32 val; + + val = rtw_read32(rtwdev, addr); + rtw_write32(rtwdev, addr, val | bit); +} + +static inline void rtw_write8_clr(struct rtw_dev *rtwdev, u32 addr, u8 bit) +{ + u8 val; + + val = rtw_read8(rtwdev, addr); + rtw_write8(rtwdev, addr, val & ~bit); +} + +static inline void rtw_write16_clr(struct rtw_dev *rtwdev, u32 addr, u16 bit) +{ + u16 val; + + val = rtw_read16(rtwdev, addr); + rtw_write16(rtwdev, addr, val & ~bit); +} + +static inline void rtw_write32_clr(struct rtw_dev *rtwdev, u32 addr, u32 bit) +{ + u32 val; + + val = rtw_read32(rtwdev, addr); + rtw_write32(rtwdev, addr, val & ~bit); +} + +static inline u32 +rtw_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask) +{ + unsigned long flags; + u32 val; + + spin_lock_irqsave(&rtwdev->rf_lock, flags); + val = rtwdev->chip->ops->read_rf(rtwdev, rf_path, addr, mask); + spin_unlock_irqrestore(&rtwdev->rf_lock, flags); + + return val; +} + +static inline void +rtw_write_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask, u32 data) +{ + unsigned long flags; + + spin_lock_irqsave(&rtwdev->rf_lock, flags); + rtwdev->chip->ops->write_rf(rtwdev, rf_path, addr, mask, data); + spin_unlock_irqrestore(&rtwdev->rf_lock, flags); +} + +static inline u32 +rtw_read32_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask) +{ + u32 shift = __ffs(mask); + u32 orig; + u32 ret; + + orig = rtw_read32(rtwdev, addr); + ret = (orig & mask) >> shift; + + return ret; +} + +static inline void +rtw_write32_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) +{ + u32 shift = __ffs(mask); + u32 orig; + u32 set; + + WARN(addr & 0x3, "should be 4-byte aligned, addr = 0x%08x\n", addr); + + orig = rtw_read32(rtwdev, addr); + set = (orig & ~mask) | ((data << shift) & mask); + rtw_write32(rtwdev, addr, set); +} + +static inline void +rtw_write8_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u8 data) +{ + u32 shift; + u8 orig, set; + + mask &= 0xff; + shift = __ffs(mask); + + orig = rtw_read8(rtwdev, addr); + set = (orig & ~mask) | ((data << shift) & mask); + rtw_write8(rtwdev, addr, set); +} + +static inline enum rtw_hci_type rtw_hci_type(struct rtw_dev *rtwdev) +{ + return rtwdev->hci.type; +} + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c new file mode 100644 index 000000000000..25a923bc6366 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -0,0 +1,965 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "mac.h" +#include "reg.h" +#include "fw.h" +#include "debug.h" + +void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw, + u8 primary_ch_idx) +{ + u8 txsc40 = 0, txsc20 = 0; + u32 value32; + u8 value8; + + txsc20 = primary_ch_idx; + if (txsc20 == 1 || txsc20 == 3) + txsc40 = 9; + else + txsc40 = 10; + rtw_write8(rtwdev, REG_DATA_SC, + BIT_TXSC_20M(txsc20) | BIT_TXSC_40M(txsc40)); + + value32 = rtw_read32(rtwdev, REG_WMAC_TRXPTCL_CTL); + value32 &= ~BIT_RFMOD; + switch (bw) { + case RTW_CHANNEL_WIDTH_80: + value32 |= BIT_RFMOD_80M; + break; + case RTW_CHANNEL_WIDTH_40: + value32 |= BIT_RFMOD_40M; + break; + case RTW_CHANNEL_WIDTH_20: + default: + break; + } + rtw_write32(rtwdev, REG_WMAC_TRXPTCL_CTL, value32); + + value32 = rtw_read32(rtwdev, REG_AFE_CTRL1) & ~(BIT_MAC_CLK_SEL); + value32 |= (MAC_CLK_HW_DEF_80M << BIT_SHIFT_MAC_CLK_SEL); + rtw_write32(rtwdev, REG_AFE_CTRL1, value32); + + rtw_write8(rtwdev, REG_USTIME_TSF, MAC_CLK_SPEED); + rtw_write8(rtwdev, REG_USTIME_EDCA, MAC_CLK_SPEED); + + value8 = rtw_read8(rtwdev, REG_CCK_CHECK); + value8 = value8 & ~BIT_CHECK_CCK_EN; + if (channel > 35) + value8 |= BIT_CHECK_CCK_EN; + rtw_write8(rtwdev, REG_CCK_CHECK, value8); +} + +static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev) +{ + u32 value32; + u8 value8; + + rtw_write8(rtwdev, REG_RSV_CTRL, 0); + + switch (rtw_hci_type(rtwdev)) { + case RTW_HCI_TYPE_PCIE: + rtw_write32_set(rtwdev, REG_HCI_OPT_CTRL, BIT_BT_DIG_CLK_EN); + break; + case RTW_HCI_TYPE_USB: + break; + default: + return -EINVAL; + } + + /* config PIN Mux */ + value32 = rtw_read32(rtwdev, REG_PAD_CTRL1); + value32 |= BIT_PAPE_WLBT_SEL | BIT_LNAON_WLBT_SEL; + rtw_write32(rtwdev, REG_PAD_CTRL1, value32); + + value32 = rtw_read32(rtwdev, REG_LED_CFG); + value32 &= ~(BIT_PAPE_SEL_EN | BIT_LNAON_SEL_EN); + rtw_write32(rtwdev, REG_LED_CFG, value32); + + value32 = rtw_read32(rtwdev, REG_GPIO_MUXCFG); + value32 |= BIT_WLRFE_4_5_EN; + rtw_write32(rtwdev, REG_GPIO_MUXCFG, value32); + + /* disable BB/RF */ + value8 = rtw_read8(rtwdev, REG_SYS_FUNC_EN); + value8 &= ~(BIT_FEN_BB_RSTB | BIT_FEN_BB_GLB_RST); + rtw_write8(rtwdev, REG_SYS_FUNC_EN, value8); + + value8 = rtw_read8(rtwdev, REG_RF_CTRL); + value8 &= ~(BIT_RF_SDM_RSTB | BIT_RF_RSTB | BIT_RF_EN); + rtw_write8(rtwdev, REG_RF_CTRL, value8); + + value32 = rtw_read32(rtwdev, REG_WLRF1); + value32 &= ~BIT_WLRF1_BBRF_EN; + rtw_write32(rtwdev, REG_WLRF1, value32); + + return 0; +} + +static int rtw_pwr_cmd_polling(struct rtw_dev *rtwdev, + struct rtw_pwr_seq_cmd *cmd) +{ + u8 value; + u8 flag = 0; + u32 offset; + u32 cnt = RTW_PWR_POLLING_CNT; + + if (cmd->base == RTW_PWR_ADDR_SDIO) + offset = cmd->offset | SDIO_LOCAL_OFFSET; + else + offset = cmd->offset; + + do { + cnt--; + value = rtw_read8(rtwdev, offset); + value &= cmd->mask; + if (value == (cmd->value & cmd->mask)) + return 0; + if (cnt == 0) { + if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE && + flag == 0) { + value = rtw_read8(rtwdev, REG_SYS_PW_CTRL); + value |= BIT(3); + rtw_write8(rtwdev, REG_SYS_PW_CTRL, value); + value &= ~BIT(3); + rtw_write8(rtwdev, REG_SYS_PW_CTRL, value); + cnt = RTW_PWR_POLLING_CNT; + flag = 1; + } else { + return -EBUSY; + } + } else { + udelay(50); + } + } while (1); +} + +static int rtw_sub_pwr_seq_parser(struct rtw_dev *rtwdev, u8 intf_mask, + u8 cut_mask, struct rtw_pwr_seq_cmd *cmd) +{ + struct rtw_pwr_seq_cmd *cur_cmd; + u32 offset; + u8 value; + + for (cur_cmd = cmd; cur_cmd->cmd != RTW_PWR_CMD_END; cur_cmd++) { + if (!(cur_cmd->intf_mask & intf_mask) || + !(cur_cmd->cut_mask & cut_mask)) + continue; + + switch (cur_cmd->cmd) { + case RTW_PWR_CMD_WRITE: + offset = cur_cmd->offset; + + if (cur_cmd->base == RTW_PWR_ADDR_SDIO) + offset |= SDIO_LOCAL_OFFSET; + + value = rtw_read8(rtwdev, offset); + value &= ~cur_cmd->mask; + value |= (cur_cmd->value & cur_cmd->mask); + rtw_write8(rtwdev, offset, value); + break; + case RTW_PWR_CMD_POLLING: + if (rtw_pwr_cmd_polling(rtwdev, cur_cmd)) + return -EBUSY; + break; + case RTW_PWR_CMD_DELAY: + if (cur_cmd->value == RTW_PWR_DELAY_US) + udelay(cur_cmd->offset); + else + mdelay(cur_cmd->offset); + break; + case RTW_PWR_CMD_READ: + break; + default: + return -EINVAL; + } + } + + return 0; +} + +static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, + struct rtw_pwr_seq_cmd **cmd_seq) +{ + u8 cut_mask; + u8 intf_mask; + u8 cut; + u32 idx = 0; + struct rtw_pwr_seq_cmd *cmd; + int ret; + + cut = rtwdev->hal.cut_version; + cut_mask = cut_version_to_mask(cut); + switch (rtw_hci_type(rtwdev)) { + case RTW_HCI_TYPE_PCIE: + intf_mask = BIT(2); + break; + case RTW_HCI_TYPE_USB: + intf_mask = BIT(1); + break; + default: + return -EINVAL; + } + + do { + cmd = cmd_seq[idx]; + if (!cmd) + break; + + ret = rtw_sub_pwr_seq_parser(rtwdev, intf_mask, cut_mask, cmd); + if (ret) + return -EBUSY; + + idx++; + } while (1); + + return 0; +} + +static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_pwr_seq_cmd **pwr_seq; + u8 rpwm; + bool cur_pwr; + + rpwm = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr); + + /* Check FW still exist or not */ + if (rtw_read16(rtwdev, REG_MCUFW_CTRL) == 0xC078) { + rpwm = (rpwm ^ BIT_RPWM_TOGGLE) & BIT_RPWM_TOGGLE; + rtw_write8(rtwdev, rtwdev->hci.rpwm_addr, rpwm); + } + + if (rtw_read8(rtwdev, REG_CR) == 0xea) + cur_pwr = false; + else if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB && + (rtw_read8(rtwdev, REG_SYS_STATUS1 + 1) & BIT(0))) + cur_pwr = false; + else + cur_pwr = true; + + if (pwr_on && cur_pwr) + return -EALREADY; + + pwr_seq = pwr_on ? chip->pwr_on_seq : chip->pwr_off_seq; + if (rtw_pwr_seq_parser(rtwdev, pwr_seq)) + return -EINVAL; + + return 0; +} + +static int rtw_mac_init_system_cfg(struct rtw_dev *rtwdev) +{ + u8 sys_func_en = rtwdev->chip->sys_func_en; + u8 value8; + u32 value, tmp; + + value = rtw_read32(rtwdev, REG_CPU_DMEM_CON); + value |= BIT_WL_PLATFORM_RST | BIT_DDMA_EN; + rtw_write32(rtwdev, REG_CPU_DMEM_CON, value); + + rtw_write8(rtwdev, REG_SYS_FUNC_EN + 1, sys_func_en); + value8 = (rtw_read8(rtwdev, REG_CR_EXT + 3) & 0xF0) | 0x0C; + rtw_write8(rtwdev, REG_CR_EXT + 3, value8); + + /* disable boot-from-flash for driver's DL FW */ + tmp = rtw_read32(rtwdev, REG_MCUFW_CTRL); + if (tmp & BIT_BOOT_FSPI_EN) { + rtw_write32(rtwdev, REG_MCUFW_CTRL, tmp & (~BIT_BOOT_FSPI_EN)); + value = rtw_read32(rtwdev, REG_GPIO_MUXCFG) & (~BIT_FSPI_EN); + rtw_write32(rtwdev, REG_GPIO_MUXCFG, value); + } + + return 0; +} + +int rtw_mac_power_on(struct rtw_dev *rtwdev) +{ + int ret = 0; + + ret = rtw_mac_pre_system_cfg(rtwdev); + if (ret) + goto err; + + ret = rtw_mac_power_switch(rtwdev, true); + if (ret) + goto err; + + ret = rtw_mac_init_system_cfg(rtwdev); + if (ret) + goto err; + + return 0; + +err: + rtw_err(rtwdev, "mac power on failed"); + return ret; +} + +void rtw_mac_power_off(struct rtw_dev *rtwdev) +{ + rtw_mac_power_switch(rtwdev, false); +} + +static bool check_firmware_size(const u8 *data, u32 size) +{ + u32 dmem_size; + u32 imem_size; + u32 emem_size; + u32 real_size; + + dmem_size = le32_to_cpu(*((__le32 *)(data + FW_HDR_DMEM_SIZE))); + imem_size = le32_to_cpu(*((__le32 *)(data + FW_HDR_IMEM_SIZE))); + emem_size = ((*(data + FW_HDR_MEM_USAGE)) & BIT(4)) ? + le32_to_cpu(*((__le32 *)(data + FW_HDR_EMEM_SIZE))) : 0; + + dmem_size += FW_HDR_CHKSUM_SIZE; + imem_size += FW_HDR_CHKSUM_SIZE; + emem_size += emem_size ? FW_HDR_CHKSUM_SIZE : 0; + real_size = FW_HDR_SIZE + dmem_size + imem_size + emem_size; + if (real_size != size) + return false; + + return true; +} + +static void wlan_cpu_enable(struct rtw_dev *rtwdev, bool enable) +{ + if (enable) { + /* cpu io interface enable */ + rtw_write8_set(rtwdev, REG_RSV_CTRL + 1, BIT_WLMCU_IOIF); + + /* cpu enable */ + rtw_write8_set(rtwdev, REG_SYS_FUNC_EN + 1, BIT_FEN_CPUEN); + } else { + /* cpu io interface disable */ + rtw_write8_clr(rtwdev, REG_SYS_FUNC_EN + 1, BIT_FEN_CPUEN); + + /* cpu disable */ + rtw_write8_clr(rtwdev, REG_RSV_CTRL + 1, BIT_WLMCU_IOIF); + } +} + +#define DLFW_RESTORE_REG_NUM 6 + +static void download_firmware_reg_backup(struct rtw_dev *rtwdev, + struct rtw_backup_info *bckp) +{ + u8 tmp; + u8 bckp_idx = 0; + + /* set HIQ to hi priority */ + bckp[bckp_idx].len = 1; + bckp[bckp_idx].reg = REG_TXDMA_PQ_MAP + 1; + bckp[bckp_idx].val = rtw_read8(rtwdev, REG_TXDMA_PQ_MAP + 1); + bckp_idx++; + tmp = RTW_DMA_MAPPING_HIGH << 6; + rtw_write8(rtwdev, REG_TXDMA_PQ_MAP + 1, tmp); + + /* DLFW only use HIQ, map HIQ to hi priority */ + bckp[bckp_idx].len = 1; + bckp[bckp_idx].reg = REG_CR; + bckp[bckp_idx].val = rtw_read8(rtwdev, REG_CR); + bckp_idx++; + bckp[bckp_idx].len = 4; + bckp[bckp_idx].reg = REG_H2CQ_CSR; + bckp[bckp_idx].val = BIT_H2CQ_FULL; + bckp_idx++; + tmp = BIT_HCI_TXDMA_EN | BIT_TXDMA_EN; + rtw_write8(rtwdev, REG_CR, tmp); + rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL); + + /* Config hi priority queue and public priority queue page number */ + bckp[bckp_idx].len = 2; + bckp[bckp_idx].reg = REG_FIFOPAGE_INFO_1; + bckp[bckp_idx].val = rtw_read16(rtwdev, REG_FIFOPAGE_INFO_1); + bckp_idx++; + bckp[bckp_idx].len = 4; + bckp[bckp_idx].reg = REG_RQPN_CTRL_2; + bckp[bckp_idx].val = rtw_read32(rtwdev, REG_RQPN_CTRL_2) | BIT_LD_RQPN; + bckp_idx++; + rtw_write16(rtwdev, REG_FIFOPAGE_INFO_1, 0x200); + rtw_write32(rtwdev, REG_RQPN_CTRL_2, bckp[bckp_idx - 1].val); + + /* Disable beacon related functions */ + tmp = rtw_read8(rtwdev, REG_BCN_CTRL); + bckp[bckp_idx].len = 1; + bckp[bckp_idx].reg = REG_BCN_CTRL; + bckp[bckp_idx].val = tmp; + bckp_idx++; + tmp = (u8)((tmp & (~BIT_EN_BCN_FUNCTION)) | BIT_DIS_TSF_UDT); + rtw_write8(rtwdev, REG_BCN_CTRL, tmp); + + WARN(bckp_idx != DLFW_RESTORE_REG_NUM, "wrong backup number\n"); +} + +static void download_firmware_reset_platform(struct rtw_dev *rtwdev) +{ + rtw_write8_clr(rtwdev, REG_CPU_DMEM_CON + 2, BIT_WL_PLATFORM_RST >> 16); + rtw_write8_clr(rtwdev, REG_SYS_CLK_CTRL + 1, BIT_CPU_CLK_EN >> 8); + rtw_write8_set(rtwdev, REG_CPU_DMEM_CON + 2, BIT_WL_PLATFORM_RST >> 16); + rtw_write8_set(rtwdev, REG_SYS_CLK_CTRL + 1, BIT_CPU_CLK_EN >> 8); +} + +static void download_firmware_reg_restore(struct rtw_dev *rtwdev, + struct rtw_backup_info *bckp, + u8 bckp_num) +{ + rtw_restore_reg(rtwdev, bckp, bckp_num); +} + +#define TX_DESC_SIZE 48 + +static int send_firmware_pkt_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, + const u8 *data, u32 size) +{ + u8 *buf; + int ret; + + buf = kmemdup(data, size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = rtw_fw_write_data_rsvd_page(rtwdev, pg_addr, buf, size); + kfree(buf); + return ret; +} + +static int +send_firmware_pkt(struct rtw_dev *rtwdev, u16 pg_addr, const u8 *data, u32 size) +{ + int ret; + + if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB && + !((size + TX_DESC_SIZE) & (512 - 1))) + size += 1; + + ret = send_firmware_pkt_rsvd_page(rtwdev, pg_addr, data, size); + if (ret) + rtw_err(rtwdev, "failed to download rsvd page\n"); + + return ret; +} + +static int +iddma_enable(struct rtw_dev *rtwdev, u32 src, u32 dst, u32 ctrl) +{ + rtw_write32(rtwdev, REG_DDMA_CH0SA, src); + rtw_write32(rtwdev, REG_DDMA_CH0DA, dst); + rtw_write32(rtwdev, REG_DDMA_CH0CTRL, ctrl); + + if (!check_hw_ready(rtwdev, REG_DDMA_CH0CTRL, BIT_DDMACH0_OWN, 0)) + return -EBUSY; + + return 0; +} + +static int iddma_download_firmware(struct rtw_dev *rtwdev, u32 src, u32 dst, + u32 len, u8 first) +{ + u32 ch0_ctrl = BIT_DDMACH0_CHKSUM_EN | BIT_DDMACH0_OWN; + + if (!check_hw_ready(rtwdev, REG_DDMA_CH0CTRL, BIT_DDMACH0_OWN, 0)) + return -EBUSY; + + ch0_ctrl |= len & BIT_MASK_DDMACH0_DLEN; + if (!first) + ch0_ctrl |= BIT_DDMACH0_CHKSUM_CONT; + + if (iddma_enable(rtwdev, src, dst, ch0_ctrl)) + return -EBUSY; + + return 0; +} + +static bool +check_fw_checksum(struct rtw_dev *rtwdev, u32 addr) +{ + u8 fw_ctrl; + + fw_ctrl = rtw_read8(rtwdev, REG_MCUFW_CTRL); + + if (rtw_read32(rtwdev, REG_DDMA_CH0CTRL) & BIT_DDMACH0_CHKSUM_STS) { + if (addr < OCPBASE_DMEM_88XX) { + fw_ctrl |= BIT_IMEM_DW_OK; + fw_ctrl &= ~BIT_IMEM_CHKSUM_OK; + rtw_write8(rtwdev, REG_MCUFW_CTRL, fw_ctrl); + } else { + fw_ctrl |= BIT_DMEM_DW_OK; + fw_ctrl &= ~BIT_DMEM_CHKSUM_OK; + rtw_write8(rtwdev, REG_MCUFW_CTRL, fw_ctrl); + } + + rtw_err(rtwdev, "invalid fw checksum\n"); + + return false; + } + + if (addr < OCPBASE_DMEM_88XX) { + fw_ctrl |= (BIT_IMEM_DW_OK | BIT_IMEM_CHKSUM_OK); + rtw_write8(rtwdev, REG_MCUFW_CTRL, fw_ctrl); + } else { + fw_ctrl |= (BIT_DMEM_DW_OK | BIT_DMEM_CHKSUM_OK); + rtw_write8(rtwdev, REG_MCUFW_CTRL, fw_ctrl); + } + + return true; +} + +static int +download_firmware_to_mem(struct rtw_dev *rtwdev, const u8 *data, + u32 src, u32 dst, u32 size) +{ + struct rtw_chip_info *chip = rtwdev->chip; + u32 desc_size = chip->tx_pkt_desc_sz; + u8 first_part; + u32 mem_offset; + u32 residue_size; + u32 pkt_size; + u32 max_size = 0x1000; + u32 val; + int ret; + + mem_offset = 0; + first_part = 1; + residue_size = size; + + val = rtw_read32(rtwdev, REG_DDMA_CH0CTRL); + val |= BIT_DDMACH0_RESET_CHKSUM_STS; + rtw_write32(rtwdev, REG_DDMA_CH0CTRL, val); + + while (residue_size) { + if (residue_size >= max_size) + pkt_size = max_size; + else + pkt_size = residue_size; + + ret = send_firmware_pkt(rtwdev, (u16)(src >> 7), + data + mem_offset, pkt_size); + if (ret) + return ret; + + ret = iddma_download_firmware(rtwdev, OCPBASE_TXBUF_88XX + + src + desc_size, + dst + mem_offset, pkt_size, + first_part); + if (ret) + return ret; + + first_part = 0; + mem_offset += pkt_size; + residue_size -= pkt_size; + } + + if (!check_fw_checksum(rtwdev, dst)) + return -EINVAL; + + return 0; +} + +static void update_firmware_info(struct rtw_dev *rtwdev, + struct rtw_fw_state *fw) +{ + const u8 *data = fw->firmware->data; + + fw->h2c_version = + le16_to_cpu(*((__le16 *)(data + FW_HDR_H2C_FMT_VER))); + fw->version = + le16_to_cpu(*((__le16 *)(data + FW_HDR_VERSION))); + fw->sub_version = *(data + FW_HDR_SUBVERSION); + fw->sub_index = *(data + FW_HDR_SUBINDEX); + + rtw_dbg(rtwdev, RTW_DBG_FW, "fw h2c version: %x\n", fw->h2c_version); + rtw_dbg(rtwdev, RTW_DBG_FW, "fw version: %x\n", fw->version); + rtw_dbg(rtwdev, RTW_DBG_FW, "fw sub version: %x\n", fw->sub_version); + rtw_dbg(rtwdev, RTW_DBG_FW, "fw sub index: %x\n", fw->sub_index); +} + +static int +start_download_firmware(struct rtw_dev *rtwdev, const u8 *data, u32 size) +{ + const u8 *cur_fw; + u16 val; + u32 imem_size; + u32 dmem_size; + u32 emem_size; + u32 addr; + int ret; + + dmem_size = le32_to_cpu(*((__le32 *)(data + FW_HDR_DMEM_SIZE))); + imem_size = le32_to_cpu(*((__le32 *)(data + FW_HDR_IMEM_SIZE))); + emem_size = ((*(data + FW_HDR_MEM_USAGE)) & BIT(4)) ? + le32_to_cpu(*((__le32 *)(data + FW_HDR_EMEM_SIZE))) : 0; + dmem_size += FW_HDR_CHKSUM_SIZE; + imem_size += FW_HDR_CHKSUM_SIZE; + emem_size += emem_size ? FW_HDR_CHKSUM_SIZE : 0; + + val = (u16)(rtw_read16(rtwdev, REG_MCUFW_CTRL) & 0x3800); + val |= BIT_MCUFWDL_EN; + rtw_write16(rtwdev, REG_MCUFW_CTRL, val); + + cur_fw = data + FW_HDR_SIZE; + addr = le32_to_cpu(*((__le32 *)(data + FW_HDR_DMEM_ADDR))); + addr &= ~BIT(31); + ret = download_firmware_to_mem(rtwdev, cur_fw, 0, addr, dmem_size); + if (ret) + return ret; + + cur_fw = data + FW_HDR_SIZE + dmem_size; + addr = le32_to_cpu(*((__le32 *)(data + FW_HDR_IMEM_ADDR))); + addr &= ~BIT(31); + ret = download_firmware_to_mem(rtwdev, cur_fw, 0, addr, imem_size); + if (ret) + return ret; + + if (emem_size) { + cur_fw = data + FW_HDR_SIZE + dmem_size + imem_size; + addr = le32_to_cpu(*((__le32 *)(data + FW_HDR_EMEM_ADDR))); + addr &= ~BIT(31); + ret = download_firmware_to_mem(rtwdev, cur_fw, 0, addr, + emem_size); + if (ret) + return ret; + } + + return 0; +} + +static int download_firmware_validate(struct rtw_dev *rtwdev) +{ + u32 fw_key; + + if (!check_hw_ready(rtwdev, REG_MCUFW_CTRL, FW_READY_MASK, FW_READY)) { + fw_key = rtw_read32(rtwdev, REG_FW_DBG7) & FW_KEY_MASK; + if (fw_key == ILLEGAL_KEY_GROUP) + rtw_err(rtwdev, "invalid fw key\n"); + return -EINVAL; + } + + return 0; +} + +static void download_firmware_end_flow(struct rtw_dev *rtwdev) +{ + u16 fw_ctrl; + + rtw_write32(rtwdev, REG_TXDMA_STATUS, BTI_PAGE_OVF); + + /* Check IMEM & DMEM checksum is OK or not */ + fw_ctrl = rtw_read16(rtwdev, REG_MCUFW_CTRL); + if ((fw_ctrl & BIT_CHECK_SUM_OK) != BIT_CHECK_SUM_OK) + return; + + fw_ctrl = (fw_ctrl | BIT_FW_DW_RDY) & ~BIT_MCUFWDL_EN; + rtw_write16(rtwdev, REG_MCUFW_CTRL, fw_ctrl); +} + +int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) +{ + struct rtw_backup_info bckp[DLFW_RESTORE_REG_NUM]; + const u8 *data = fw->firmware->data; + u32 size = fw->firmware->size; + u32 ltecoex_bckp; + int ret; + + if (!check_firmware_size(data, size)) + return -EINVAL; + + if (!ltecoex_read_reg(rtwdev, 0x38, <ecoex_bckp)) + return -EBUSY; + + wlan_cpu_enable(rtwdev, false); + + download_firmware_reg_backup(rtwdev, bckp); + download_firmware_reset_platform(rtwdev); + + ret = start_download_firmware(rtwdev, data, size); + if (ret) + goto dlfw_fail; + + download_firmware_reg_restore(rtwdev, bckp, DLFW_RESTORE_REG_NUM); + + download_firmware_end_flow(rtwdev); + + wlan_cpu_enable(rtwdev, true); + + if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp)) + return -EBUSY; + + ret = download_firmware_validate(rtwdev); + if (ret) + goto dlfw_fail; + + update_firmware_info(rtwdev, fw); + + /* reset desc and index */ + rtw_hci_setup(rtwdev); + + rtwdev->h2c.last_box_num = 0; + rtwdev->h2c.seq = 0; + + rtw_fw_send_general_info(rtwdev); + rtw_fw_send_phydm_info(rtwdev); + + rtw_flag_set(rtwdev, RTW_FLAG_FW_RUNNING); + + return 0; + +dlfw_fail: + /* Disable FWDL_EN */ + rtw_write8_clr(rtwdev, REG_MCUFW_CTRL, BIT_MCUFWDL_EN); + rtw_write8_set(rtwdev, REG_SYS_FUNC_EN + 1, BIT_FEN_CPUEN); + + return ret; +} + +static int txdma_queue_mapping(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_rqpn *rqpn = NULL; + u16 txdma_pq_map = 0; + + switch (rtw_hci_type(rtwdev)) { + case RTW_HCI_TYPE_PCIE: + rqpn = &chip->rqpn_table[1]; + break; + case RTW_HCI_TYPE_USB: + if (rtwdev->hci.bulkout_num == 2) + rqpn = &chip->rqpn_table[2]; + else if (rtwdev->hci.bulkout_num == 3) + rqpn = &chip->rqpn_table[3]; + else if (rtwdev->hci.bulkout_num == 4) + rqpn = &chip->rqpn_table[4]; + else + return -EINVAL; + break; + default: + return -EINVAL; + } + + txdma_pq_map |= BIT_TXDMA_HIQ_MAP(rqpn->dma_map_hi); + txdma_pq_map |= BIT_TXDMA_MGQ_MAP(rqpn->dma_map_mg); + txdma_pq_map |= BIT_TXDMA_BKQ_MAP(rqpn->dma_map_bk); + txdma_pq_map |= BIT_TXDMA_BEQ_MAP(rqpn->dma_map_be); + txdma_pq_map |= BIT_TXDMA_VIQ_MAP(rqpn->dma_map_vi); + txdma_pq_map |= BIT_TXDMA_VOQ_MAP(rqpn->dma_map_vo); + rtw_write16(rtwdev, REG_TXDMA_PQ_MAP, txdma_pq_map); + + rtw_write8(rtwdev, REG_CR, 0); + rtw_write8(rtwdev, REG_CR, MAC_TRX_ENABLE); + rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL); + + return 0; +} + +static int set_trx_fifo_info(struct rtw_dev *rtwdev) +{ + struct rtw_fifo_conf *fifo = &rtwdev->fifo; + struct rtw_chip_info *chip = rtwdev->chip; + u16 cur_pg_addr; + u8 csi_buf_pg_num = chip->csi_buf_pg_num; + + /* config rsvd page num */ + fifo->rsvd_drv_pg_num = 8; + fifo->txff_pg_num = chip->txff_size >> 7; + fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num + + RSVD_PG_H2C_EXTRAINFO_NUM + + RSVD_PG_H2C_STATICINFO_NUM + + RSVD_PG_H2CQ_NUM + + RSVD_PG_CPU_INSTRUCTION_NUM + + RSVD_PG_FW_TXBUF_NUM + + csi_buf_pg_num; + + if (fifo->rsvd_pg_num > fifo->txff_pg_num) + return -ENOMEM; + + fifo->acq_pg_num = fifo->txff_pg_num - fifo->rsvd_pg_num; + fifo->rsvd_boundary = fifo->txff_pg_num - fifo->rsvd_pg_num; + + cur_pg_addr = fifo->txff_pg_num; + cur_pg_addr -= csi_buf_pg_num; + fifo->rsvd_csibuf_addr = cur_pg_addr; + cur_pg_addr -= RSVD_PG_FW_TXBUF_NUM; + fifo->rsvd_fw_txbuf_addr = cur_pg_addr; + cur_pg_addr -= RSVD_PG_CPU_INSTRUCTION_NUM; + fifo->rsvd_cpu_instr_addr = cur_pg_addr; + cur_pg_addr -= RSVD_PG_H2CQ_NUM; + fifo->rsvd_h2cq_addr = cur_pg_addr; + cur_pg_addr -= RSVD_PG_H2C_STATICINFO_NUM; + fifo->rsvd_h2c_sta_info_addr = cur_pg_addr; + cur_pg_addr -= RSVD_PG_H2C_EXTRAINFO_NUM; + fifo->rsvd_h2c_info_addr = cur_pg_addr; + cur_pg_addr -= fifo->rsvd_drv_pg_num; + fifo->rsvd_drv_addr = cur_pg_addr; + + if (fifo->rsvd_boundary != fifo->rsvd_drv_addr) { + rtw_err(rtwdev, "wrong rsvd driver address\n"); + return -EINVAL; + } + + return 0; +} + +static int priority_queue_cfg(struct rtw_dev *rtwdev) +{ + struct rtw_fifo_conf *fifo = &rtwdev->fifo; + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_page_table *pg_tbl = NULL; + u16 pubq_num; + int ret; + + ret = set_trx_fifo_info(rtwdev); + if (ret) + return ret; + + switch (rtw_hci_type(rtwdev)) { + case RTW_HCI_TYPE_PCIE: + pg_tbl = &chip->page_table[1]; + break; + case RTW_HCI_TYPE_USB: + if (rtwdev->hci.bulkout_num == 2) + pg_tbl = &chip->page_table[2]; + else if (rtwdev->hci.bulkout_num == 3) + pg_tbl = &chip->page_table[3]; + else if (rtwdev->hci.bulkout_num == 4) + pg_tbl = &chip->page_table[4]; + else + return -EINVAL; + break; + default: + return -EINVAL; + } + + pubq_num = fifo->acq_pg_num - pg_tbl->hq_num - pg_tbl->lq_num - + pg_tbl->nq_num - pg_tbl->exq_num - pg_tbl->gapq_num; + rtw_write16(rtwdev, REG_FIFOPAGE_INFO_1, pg_tbl->hq_num); + rtw_write16(rtwdev, REG_FIFOPAGE_INFO_2, pg_tbl->lq_num); + rtw_write16(rtwdev, REG_FIFOPAGE_INFO_3, pg_tbl->nq_num); + rtw_write16(rtwdev, REG_FIFOPAGE_INFO_4, pg_tbl->exq_num); + rtw_write16(rtwdev, REG_FIFOPAGE_INFO_5, pubq_num); + rtw_write32_set(rtwdev, REG_RQPN_CTRL_2, BIT_LD_RQPN); + + rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2, fifo->rsvd_boundary); + rtw_write8_set(rtwdev, REG_FWHW_TXQ_CTRL + 2, BIT_EN_WR_FREE_TAIL >> 16); + + rtw_write16(rtwdev, REG_BCNQ_BDNY_V1, fifo->rsvd_boundary); + rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2 + 2, fifo->rsvd_boundary); + rtw_write16(rtwdev, REG_BCNQ1_BDNY_V1, fifo->rsvd_boundary); + rtw_write32(rtwdev, REG_RXFF_BNDY, chip->rxff_size - C2H_PKT_BUF - 1); + rtw_write8_set(rtwdev, REG_AUTO_LLT_V1, BIT_AUTO_INIT_LLT_V1); + + if (!check_hw_ready(rtwdev, REG_AUTO_LLT_V1, BIT_AUTO_INIT_LLT_V1, 0)) + return -EBUSY; + + rtw_write8(rtwdev, REG_CR + 3, 0); + + return 0; +} + +static int init_h2c(struct rtw_dev *rtwdev) +{ + struct rtw_fifo_conf *fifo = &rtwdev->fifo; + u8 value8; + u32 value32; + u32 h2cq_addr; + u32 h2cq_size; + u32 h2cq_free; + u32 wp, rp; + + h2cq_addr = fifo->rsvd_h2cq_addr << TX_PAGE_SIZE_SHIFT; + h2cq_size = RSVD_PG_H2CQ_NUM << TX_PAGE_SIZE_SHIFT; + + value32 = rtw_read32(rtwdev, REG_H2C_HEAD); + value32 = (value32 & 0xFFFC0000) | h2cq_addr; + rtw_write32(rtwdev, REG_H2C_HEAD, value32); + + value32 = rtw_read32(rtwdev, REG_H2C_READ_ADDR); + value32 = (value32 & 0xFFFC0000) | h2cq_addr; + rtw_write32(rtwdev, REG_H2C_READ_ADDR, value32); + + value32 = rtw_read32(rtwdev, REG_H2C_TAIL); + value32 &= 0xFFFC0000; + value32 |= (h2cq_addr + h2cq_size); + rtw_write32(rtwdev, REG_H2C_TAIL, value32); + + value8 = rtw_read8(rtwdev, REG_H2C_INFO); + value8 = (u8)((value8 & 0xFC) | 0x01); + rtw_write8(rtwdev, REG_H2C_INFO, value8); + + value8 = rtw_read8(rtwdev, REG_H2C_INFO); + value8 = (u8)((value8 & 0xFB) | 0x04); + rtw_write8(rtwdev, REG_H2C_INFO, value8); + + value8 = rtw_read8(rtwdev, REG_TXDMA_OFFSET_CHK + 1); + value8 = (u8)((value8 & 0x7f) | 0x80); + rtw_write8(rtwdev, REG_TXDMA_OFFSET_CHK + 1, value8); + + wp = rtw_read32(rtwdev, REG_H2C_PKT_WRITEADDR) & 0x3FFFF; + rp = rtw_read32(rtwdev, REG_H2C_PKT_READADDR) & 0x3FFFF; + h2cq_free = wp >= rp ? h2cq_size - (wp - rp) : rp - wp; + + if (h2cq_size != h2cq_free) { + rtw_err(rtwdev, "H2C queue mismatch\n"); + return -EINVAL; + } + + return 0; +} + +static int rtw_init_trx_cfg(struct rtw_dev *rtwdev) +{ + int ret; + + ret = txdma_queue_mapping(rtwdev); + if (ret) + return ret; + + ret = priority_queue_cfg(rtwdev); + if (ret) + return ret; + + ret = init_h2c(rtwdev); + if (ret) + return ret; + + return 0; +} + +static int rtw_drv_info_cfg(struct rtw_dev *rtwdev) +{ + u8 value8; + + rtw_write8(rtwdev, REG_RX_DRVINFO_SZ, PHY_STATUS_SIZE); + value8 = rtw_read8(rtwdev, REG_TRXFF_BNDY + 1); + value8 &= 0xF0; + /* For rxdesc len = 0 issue */ + value8 |= 0xF; + rtw_write8(rtwdev, REG_TRXFF_BNDY + 1, value8); + rtw_write32_set(rtwdev, REG_RCR, BIT_APP_PHYSTS); + rtw_write32_clr(rtwdev, REG_WMAC_OPTION_FUNCTION + 4, BIT(8) | BIT(9)); + + return 0; +} + +int rtw_mac_init(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + int ret; + + ret = rtw_init_trx_cfg(rtwdev); + if (ret) + return ret; + + ret = chip->ops->mac_init(rtwdev); + if (ret) + return ret; + + ret = rtw_drv_info_cfg(rtwdev); + if (ret) + return ret; + + return 0; +} diff --git a/drivers/net/wireless/realtek/rtw88/mac.h b/drivers/net/wireless/realtek/rtw88/mac.h new file mode 100644 index 000000000000..efe6f731f240 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/mac.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW_MAC_H__ +#define __RTW_MAC_H__ + +#define RTW_HW_PORT_NUM 5 +#define cut_version_to_mask(cut) (0x1 << ((cut) + 1)) +#define SDIO_LOCAL_OFFSET 0x10250000 +#define DDMA_POLLING_COUNT 1000 +#define C2H_PKT_BUF 256 +#define PHY_STATUS_SIZE 4 +#define ILLEGAL_KEY_GROUP 0xFAAAAA00 + +/* HW memory address */ +#define OCPBASE_TXBUF_88XX 0x18780000 +#define OCPBASE_DMEM_88XX 0x00200000 +#define OCPBASE_EMEM_88XX 0x00100000 + +#define RSVD_PG_DRV_NUM 16 +#define RSVD_PG_H2C_EXTRAINFO_NUM 24 +#define RSVD_PG_H2C_STATICINFO_NUM 8 +#define RSVD_PG_H2CQ_NUM 8 +#define RSVD_PG_CPU_INSTRUCTION_NUM 0 +#define RSVD_PG_FW_TXBUF_NUM 4 + +void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw, + u8 primary_ch_idx); +int rtw_mac_power_on(struct rtw_dev *rtwdev); +void rtw_mac_power_off(struct rtw_dev *rtwdev); +int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw); +int rtw_mac_init(struct rtw_dev *rtwdev); + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c new file mode 100644 index 000000000000..abded63f138d --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -0,0 +1,481 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "sec.h" +#include "tx.h" +#include "fw.h" +#include "mac.h" +#include "ps.h" +#include "reg.h" +#include "debug.h" + +static void rtw_ops_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_tx_pkt_info pkt_info = {0}; + + if (!rtw_flag_check(rtwdev, RTW_FLAG_RUNNING)) + goto out; + + rtw_tx_pkt_info_update(rtwdev, &pkt_info, control, skb); + if (rtw_hci_tx(rtwdev, &pkt_info, skb)) + goto out; + + return; + +out: + ieee80211_free_txskb(hw, skb); +} + +static int rtw_ops_start(struct ieee80211_hw *hw) +{ + struct rtw_dev *rtwdev = hw->priv; + int ret; + + mutex_lock(&rtwdev->mutex); + ret = rtw_core_start(rtwdev); + mutex_unlock(&rtwdev->mutex); + + return ret; +} + +static void rtw_ops_stop(struct ieee80211_hw *hw) +{ + struct rtw_dev *rtwdev = hw->priv; + + mutex_lock(&rtwdev->mutex); + rtw_core_stop(rtwdev); + mutex_unlock(&rtwdev->mutex); +} + +static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed) +{ + struct rtw_dev *rtwdev = hw->priv; + int ret = 0; + + mutex_lock(&rtwdev->mutex); + + if (changed & IEEE80211_CONF_CHANGE_IDLE) { + if (hw->conf.flags & IEEE80211_CONF_IDLE) { + rtw_enter_ips(rtwdev); + } else { + ret = rtw_leave_ips(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to leave idle state\n"); + goto out; + } + } + } + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) + rtw_set_channel(rtwdev); + +out: + mutex_unlock(&rtwdev->mutex); + return ret; +} + +static const struct rtw_vif_port rtw_vif_port[] = { + [0] = { + .mac_addr = {.addr = 0x0610}, + .bssid = {.addr = 0x0618}, + .net_type = {.addr = 0x0100, .mask = 0x30000}, + .aid = {.addr = 0x06a8, .mask = 0x7ff}, + }, + [1] = { + .mac_addr = {.addr = 0x0700}, + .bssid = {.addr = 0x0708}, + .net_type = {.addr = 0x0100, .mask = 0xc0000}, + .aid = {.addr = 0x0710, .mask = 0x7ff}, + }, + [2] = { + .mac_addr = {.addr = 0x1620}, + .bssid = {.addr = 0x1628}, + .net_type = {.addr = 0x1100, .mask = 0x3}, + .aid = {.addr = 0x1600, .mask = 0x7ff}, + }, + [3] = { + .mac_addr = {.addr = 0x1630}, + .bssid = {.addr = 0x1638}, + .net_type = {.addr = 0x1100, .mask = 0xc}, + .aid = {.addr = 0x1604, .mask = 0x7ff}, + }, + [4] = { + .mac_addr = {.addr = 0x1640}, + .bssid = {.addr = 0x1648}, + .net_type = {.addr = 0x1100, .mask = 0x30}, + .aid = {.addr = 0x1608, .mask = 0x7ff}, + }, +}; + +static int rtw_ops_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + enum rtw_net_type net_type; + u32 config = 0; + u8 port = 0; + + rtwvif->port = port; + rtwvif->vif = vif; + rtwvif->stats.tx_unicast = 0; + rtwvif->stats.rx_unicast = 0; + rtwvif->stats.tx_cnt = 0; + rtwvif->stats.rx_cnt = 0; + rtwvif->in_lps = false; + rtwvif->conf = &rtw_vif_port[port]; + + mutex_lock(&rtwdev->mutex); + + switch (vif->type) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: + net_type = RTW_NET_AP_MODE; + break; + case NL80211_IFTYPE_ADHOC: + net_type = RTW_NET_AD_HOC; + break; + case NL80211_IFTYPE_STATION: + default: + net_type = RTW_NET_NO_LINK; + break; + } + + ether_addr_copy(rtwvif->mac_addr, vif->addr); + config |= PORT_SET_MAC_ADDR; + rtwvif->net_type = net_type; + config |= PORT_SET_NET_TYPE; + rtw_vif_port_config(rtwdev, rtwvif, config); + + mutex_unlock(&rtwdev->mutex); + + rtw_info(rtwdev, "start vif %pM on port %d\n", vif->addr, rtwvif->port); + return 0; +} + +static void rtw_ops_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + u32 config = 0; + + rtw_info(rtwdev, "stop vif %pM on port %d\n", vif->addr, rtwvif->port); + + mutex_lock(&rtwdev->mutex); + + eth_zero_addr(rtwvif->mac_addr); + config |= PORT_SET_MAC_ADDR; + rtwvif->net_type = RTW_NET_NO_LINK; + config |= PORT_SET_NET_TYPE; + rtw_vif_port_config(rtwdev, rtwvif, config); + + mutex_unlock(&rtwdev->mutex); +} + +static void rtw_ops_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *new_flags, + u64 multicast) +{ + struct rtw_dev *rtwdev = hw->priv; + + *new_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_FCSFAIL | + FIF_BCN_PRBRESP_PROMISC; + + mutex_lock(&rtwdev->mutex); + + if (changed_flags & FIF_ALLMULTI) { + if (*new_flags & FIF_ALLMULTI) + rtwdev->hal.rcr |= BIT_AM | BIT_AB; + else + rtwdev->hal.rcr &= ~(BIT_AM | BIT_AB); + } + if (changed_flags & FIF_FCSFAIL) { + if (*new_flags & FIF_FCSFAIL) + rtwdev->hal.rcr |= BIT_ACRC32; + else + rtwdev->hal.rcr &= ~(BIT_ACRC32); + } + if (changed_flags & FIF_OTHER_BSS) { + if (*new_flags & FIF_OTHER_BSS) + rtwdev->hal.rcr |= BIT_AAP; + else + rtwdev->hal.rcr &= ~(BIT_AAP); + } + if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { + if (*new_flags & FIF_BCN_PRBRESP_PROMISC) + rtwdev->hal.rcr &= ~(BIT_CBSSID_BCN | BIT_CBSSID_DATA); + else + rtwdev->hal.rcr |= BIT_CBSSID_BCN; + } + + rtw_dbg(rtwdev, RTW_DBG_RX, + "config rx filter, changed=0x%08x, new=0x%08x, rcr=0x%08x\n", + changed_flags, *new_flags, rtwdev->hal.rcr); + + rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr); + + mutex_unlock(&rtwdev->mutex); +} + +static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf, + u32 changed) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + u32 config = 0; + + mutex_lock(&rtwdev->mutex); + + if (changed & BSS_CHANGED_ASSOC) { + struct rtw_chip_info *chip = rtwdev->chip; + enum rtw_net_type net_type; + + if (conf->assoc) { + net_type = RTW_NET_MGD_LINKED; + chip->ops->do_iqk(rtwdev); + + rtwvif->aid = conf->aid; + rtw_add_rsvd_page(rtwdev, RSVD_PS_POLL, true); + rtw_add_rsvd_page(rtwdev, RSVD_QOS_NULL, true); + rtw_add_rsvd_page(rtwdev, RSVD_NULL, true); + rtw_fw_download_rsvd_page(rtwdev, vif); + rtw_send_rsvd_page_h2c(rtwdev); + } else { + net_type = RTW_NET_NO_LINK; + rtwvif->aid = 0; + rtw_reset_rsvd_page(rtwdev); + } + + rtwvif->net_type = net_type; + config |= PORT_SET_NET_TYPE; + config |= PORT_SET_AID; + } + + if (changed & BSS_CHANGED_BSSID) { + ether_addr_copy(rtwvif->bssid, conf->bssid); + config |= PORT_SET_BSSID; + } + + if (changed & BSS_CHANGED_BEACON) + rtw_fw_download_rsvd_page(rtwdev, vif); + + rtw_vif_port_config(rtwdev, rtwvif, config); + + mutex_unlock(&rtwdev->mutex); +} + +static u8 rtw_acquire_macid(struct rtw_dev *rtwdev) +{ + unsigned long mac_id; + + mac_id = find_first_zero_bit(rtwdev->mac_id_map, RTW_MAX_MAC_ID_NUM); + if (mac_id < RTW_MAX_MAC_ID_NUM) + set_bit(mac_id, rtwdev->mac_id_map); + + return mac_id; +} + +static void rtw_release_macid(struct rtw_dev *rtwdev, u8 mac_id) +{ + clear_bit(mac_id, rtwdev->mac_id_map); +} + +static int rtw_ops_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; + int ret = 0; + + mutex_lock(&rtwdev->mutex); + + si->mac_id = rtw_acquire_macid(rtwdev); + if (si->mac_id >= RTW_MAX_MAC_ID_NUM) { + ret = -ENOSPC; + goto out; + } + + si->sta = sta; + si->vif = vif; + si->init_ra_lv = 1; + ewma_rssi_init(&si->avg_rssi); + + rtw_update_sta_info(rtwdev, si); + rtw_fw_media_status_report(rtwdev, si->mac_id, true); + + rtwdev->sta_cnt++; + + rtw_info(rtwdev, "sta %pM joined with macid %d\n", + sta->addr, si->mac_id); + +out: + mutex_unlock(&rtwdev->mutex); + return ret; +} + +static int rtw_ops_sta_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; + + mutex_lock(&rtwdev->mutex); + + rtw_release_macid(rtwdev, si->mac_id); + rtw_fw_media_status_report(rtwdev, si->mac_id, false); + + rtwdev->sta_cnt--; + + rtw_info(rtwdev, "sta %pM with macid %d left\n", + sta->addr, si->mac_id); + + mutex_unlock(&rtwdev->mutex); + return 0; +} + +static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_sec_desc *sec = &rtwdev->sec; + u8 hw_key_type; + u8 hw_key_idx; + int ret = 0; + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + hw_key_type = RTW_CAM_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + hw_key_type = RTW_CAM_WEP104; + break; + case WLAN_CIPHER_SUITE_TKIP: + hw_key_type = RTW_CAM_TKIP; + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + break; + case WLAN_CIPHER_SUITE_CCMP: + hw_key_type = RTW_CAM_AES; + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + case WLAN_CIPHER_SUITE_BIP_CMAC_256: + case WLAN_CIPHER_SUITE_BIP_GMAC_128: + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + /* suppress error messages */ + return -EOPNOTSUPP; + default: + return -ENOTSUPP; + } + + mutex_lock(&rtwdev->mutex); + + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { + hw_key_idx = rtw_sec_get_free_cam(sec); + } else { + /* multiple interfaces? */ + hw_key_idx = key->keyidx; + } + + if (hw_key_idx > sec->total_cam_num) { + ret = -ENOSPC; + goto out; + } + + switch (cmd) { + case SET_KEY: + /* need sw generated IV */ + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + key->hw_key_idx = hw_key_idx; + rtw_sec_write_cam(rtwdev, sec, sta, key, + hw_key_type, hw_key_idx); + break; + case DISABLE_KEY: + rtw_sec_clear_cam(rtwdev, sec, key->hw_key_idx); + break; + } + +out: + mutex_unlock(&rtwdev->mutex); + + return ret; +} + +static int rtw_ops_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_ampdu_params *params) +{ + struct ieee80211_sta *sta = params->sta; + u16 tid = params->tid; + + switch (params->action) { + case IEEE80211_AMPDU_TX_START: + ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); + break; + case IEEE80211_AMPDU_TX_STOP_CONT: + case IEEE80211_AMPDU_TX_STOP_FLUSH: + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + break; + case IEEE80211_AMPDU_TX_OPERATIONAL: + case IEEE80211_AMPDU_RX_START: + case IEEE80211_AMPDU_RX_STOP: + break; + default: + WARN_ON(1); + return -ENOTSUPP; + } + + return 0; +} + +static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + + rtw_leave_lps(rtwdev, rtwvif); + + rtw_flag_set(rtwdev, RTW_FLAG_DIG_DISABLE); + rtw_flag_set(rtwdev, RTW_FLAG_SCANNING); +} + +static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtw_dev *rtwdev = hw->priv; + + rtw_flag_clear(rtwdev, RTW_FLAG_SCANNING); + rtw_flag_clear(rtwdev, RTW_FLAG_DIG_DISABLE); +} + +const struct ieee80211_ops rtw_ops = { + .tx = rtw_ops_tx, + .start = rtw_ops_start, + .stop = rtw_ops_stop, + .config = rtw_ops_config, + .add_interface = rtw_ops_add_interface, + .remove_interface = rtw_ops_remove_interface, + .configure_filter = rtw_ops_configure_filter, + .bss_info_changed = rtw_ops_bss_info_changed, + .sta_add = rtw_ops_sta_add, + .sta_remove = rtw_ops_sta_remove, + .set_key = rtw_ops_set_key, + .ampdu_action = rtw_ops_ampdu_action, + .sw_scan_start = rtw_ops_sw_scan_start, + .sw_scan_complete = rtw_ops_sw_scan_complete, +}; +EXPORT_SYMBOL(rtw_ops); diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c new file mode 100644 index 000000000000..f447361f7573 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -0,0 +1,1211 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "regd.h" +#include "fw.h" +#include "ps.h" +#include "sec.h" +#include "mac.h" +#include "phy.h" +#include "reg.h" +#include "efuse.h" +#include "debug.h" + +static bool rtw_fw_support_lps; +unsigned int rtw_debug_mask; +EXPORT_SYMBOL(rtw_debug_mask); + +module_param_named(support_lps, rtw_fw_support_lps, bool, 0644); +module_param_named(debug_mask, rtw_debug_mask, uint, 0644); + +MODULE_PARM_DESC(support_lps, "Set Y to enable LPS support"); +MODULE_PARM_DESC(debug_mask, "Debugging mask"); + +static struct ieee80211_channel rtw_channeltable_2g[] = { + {.center_freq = 2412, .hw_value = 1,}, + {.center_freq = 2417, .hw_value = 2,}, + {.center_freq = 2422, .hw_value = 3,}, + {.center_freq = 2427, .hw_value = 4,}, + {.center_freq = 2432, .hw_value = 5,}, + {.center_freq = 2437, .hw_value = 6,}, + {.center_freq = 2442, .hw_value = 7,}, + {.center_freq = 2447, .hw_value = 8,}, + {.center_freq = 2452, .hw_value = 9,}, + {.center_freq = 2457, .hw_value = 10,}, + {.center_freq = 2462, .hw_value = 11,}, + {.center_freq = 2467, .hw_value = 12,}, + {.center_freq = 2472, .hw_value = 13,}, + {.center_freq = 2484, .hw_value = 14,}, +}; + +static struct ieee80211_channel rtw_channeltable_5g[] = { + {.center_freq = 5180, .hw_value = 36,}, + {.center_freq = 5200, .hw_value = 40,}, + {.center_freq = 5220, .hw_value = 44,}, + {.center_freq = 5240, .hw_value = 48,}, + {.center_freq = 5260, .hw_value = 52,}, + {.center_freq = 5280, .hw_value = 56,}, + {.center_freq = 5300, .hw_value = 60,}, + {.center_freq = 5320, .hw_value = 64,}, + {.center_freq = 5500, .hw_value = 100,}, + {.center_freq = 5520, .hw_value = 104,}, + {.center_freq = 5540, .hw_value = 108,}, + {.center_freq = 5560, .hw_value = 112,}, + {.center_freq = 5580, .hw_value = 116,}, + {.center_freq = 5600, .hw_value = 120,}, + {.center_freq = 5620, .hw_value = 124,}, + {.center_freq = 5640, .hw_value = 128,}, + {.center_freq = 5660, .hw_value = 132,}, + {.center_freq = 5680, .hw_value = 136,}, + {.center_freq = 5700, .hw_value = 140,}, + {.center_freq = 5745, .hw_value = 149,}, + {.center_freq = 5765, .hw_value = 153,}, + {.center_freq = 5785, .hw_value = 157,}, + {.center_freq = 5805, .hw_value = 161,}, + {.center_freq = 5825, .hw_value = 165, + .flags = IEEE80211_CHAN_NO_HT40MINUS}, +}; + +static struct ieee80211_rate rtw_ratetable[] = { + {.bitrate = 10, .hw_value = 0x00,}, + {.bitrate = 20, .hw_value = 0x01,}, + {.bitrate = 55, .hw_value = 0x02,}, + {.bitrate = 110, .hw_value = 0x03,}, + {.bitrate = 60, .hw_value = 0x04,}, + {.bitrate = 90, .hw_value = 0x05,}, + {.bitrate = 120, .hw_value = 0x06,}, + {.bitrate = 180, .hw_value = 0x07,}, + {.bitrate = 240, .hw_value = 0x08,}, + {.bitrate = 360, .hw_value = 0x09,}, + {.bitrate = 480, .hw_value = 0x0a,}, + {.bitrate = 540, .hw_value = 0x0b,}, +}; + +static struct ieee80211_supported_band rtw_band_2ghz = { + .band = NL80211_BAND_2GHZ, + + .channels = rtw_channeltable_2g, + .n_channels = ARRAY_SIZE(rtw_channeltable_2g), + + .bitrates = rtw_ratetable, + .n_bitrates = ARRAY_SIZE(rtw_ratetable), + + .ht_cap = {0}, + .vht_cap = {0}, +}; + +static struct ieee80211_supported_band rtw_band_5ghz = { + .band = NL80211_BAND_5GHZ, + + .channels = rtw_channeltable_5g, + .n_channels = ARRAY_SIZE(rtw_channeltable_5g), + + /* 5G has no CCK rates */ + .bitrates = rtw_ratetable + 4, + .n_bitrates = ARRAY_SIZE(rtw_ratetable) - 4, + + .ht_cap = {0}, + .vht_cap = {0}, +}; + +struct rtw_watch_dog_iter_data { + struct rtw_vif *rtwvif; + bool active; + u8 assoc_cnt; +}; + +static void rtw_vif_watch_dog_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct rtw_watch_dog_iter_data *iter_data = data; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + + if (vif->type == NL80211_IFTYPE_STATION) { + if (vif->bss_conf.assoc) { + iter_data->assoc_cnt++; + iter_data->rtwvif = rtwvif; + } + if (rtwvif->stats.tx_cnt > RTW_LPS_THRESHOLD || + rtwvif->stats.rx_cnt > RTW_LPS_THRESHOLD) + iter_data->active = true; + } else { + /* only STATION mode can enter lps */ + iter_data->active = true; + } + + rtwvif->stats.tx_unicast = 0; + rtwvif->stats.rx_unicast = 0; + rtwvif->stats.tx_cnt = 0; + rtwvif->stats.rx_cnt = 0; +} + +/* process TX/RX statistics periodically for hardware, + * the information helps hardware to enhance performance + */ +static void rtw_watch_dog_work(struct work_struct *work) +{ + struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, + watch_dog_work.work); + struct rtw_watch_dog_iter_data data = {}; + + if (!rtw_flag_check(rtwdev, RTW_FLAG_RUNNING)) + return; + + ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->watch_dog_work, + RTW_WATCH_DOG_DELAY_TIME); + + /* reset tx/rx statictics */ + rtwdev->stats.tx_unicast = 0; + rtwdev->stats.rx_unicast = 0; + rtwdev->stats.tx_cnt = 0; + rtwdev->stats.rx_cnt = 0; + + rtw_iterate_vifs(rtwdev, rtw_vif_watch_dog_iter, &data); + + /* fw supports only one station associated to enter lps, if there are + * more than two stations associated to the AP, then we can not enter + * lps, because fw does not handle the overlapped beacon interval + */ + if (rtw_fw_support_lps && + data.rtwvif && !data.active && data.assoc_cnt == 1) + rtw_enter_lps(rtwdev, data.rtwvif); + + if (rtw_flag_check(rtwdev, RTW_FLAG_SCANNING)) + return; + + rtw_phy_dynamic_mechanism(rtwdev); + + rtwdev->watch_dog_cnt++; +} + +static void rtw_c2h_work(struct work_struct *work) +{ + struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, c2h_work); + struct sk_buff *skb, *tmp; + + skb_queue_walk_safe(&rtwdev->c2h_queue, skb, tmp) { + skb_unlink(skb, &rtwdev->c2h_queue); + rtw_fw_c2h_cmd_handle(rtwdev, skb); + dev_kfree_skb_any(skb); + } +} + +void rtw_get_channel_params(struct cfg80211_chan_def *chandef, + struct rtw_channel_params *chan_params) +{ + struct ieee80211_channel *channel = chandef->chan; + enum nl80211_chan_width width = chandef->width; + u32 primary_freq, center_freq; + u8 center_chan; + u8 bandwidth = RTW_CHANNEL_WIDTH_20; + u8 primary_chan_idx = 0; + + center_chan = channel->hw_value; + primary_freq = channel->center_freq; + center_freq = chandef->center_freq1; + + switch (width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + bandwidth = RTW_CHANNEL_WIDTH_20; + primary_chan_idx = 0; + break; + case NL80211_CHAN_WIDTH_40: + bandwidth = RTW_CHANNEL_WIDTH_40; + if (primary_freq > center_freq) { + primary_chan_idx = 1; + center_chan -= 2; + } else { + primary_chan_idx = 2; + center_chan += 2; + } + break; + case NL80211_CHAN_WIDTH_80: + bandwidth = RTW_CHANNEL_WIDTH_80; + if (primary_freq > center_freq) { + if (primary_freq - center_freq == 10) { + primary_chan_idx = 1; + center_chan -= 2; + } else { + primary_chan_idx = 3; + center_chan -= 6; + } + } else { + if (center_freq - primary_freq == 10) { + primary_chan_idx = 2; + center_chan += 2; + } else { + primary_chan_idx = 4; + center_chan += 6; + } + } + break; + default: + center_chan = 0; + break; + } + + chan_params->center_chan = center_chan; + chan_params->bandwidth = bandwidth; + chan_params->primary_chan_idx = primary_chan_idx; +} + +void rtw_set_channel(struct rtw_dev *rtwdev) +{ + struct ieee80211_hw *hw = rtwdev->hw; + struct rtw_hal *hal = &rtwdev->hal; + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_channel_params ch_param; + u8 center_chan, bandwidth, primary_chan_idx; + + rtw_get_channel_params(&hw->conf.chandef, &ch_param); + if (WARN(ch_param.center_chan == 0, "Invalid channel\n")) + return; + + center_chan = ch_param.center_chan; + bandwidth = ch_param.bandwidth; + primary_chan_idx = ch_param.primary_chan_idx; + + hal->current_band_width = bandwidth; + hal->current_channel = center_chan; + hal->current_band_type = center_chan > 14 ? RTW_BAND_5G : RTW_BAND_2G; + chip->ops->set_channel(rtwdev, center_chan, bandwidth, primary_chan_idx); + + rtw_phy_set_tx_power_level(rtwdev, center_chan); +} + +static void rtw_vif_write_addr(struct rtw_dev *rtwdev, u32 start, u8 *addr) +{ + int i; + + for (i = 0; i < ETH_ALEN; i++) + rtw_write8(rtwdev, start + i, addr[i]); +} + +void rtw_vif_port_config(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif, + u32 config) +{ + u32 addr, mask; + + if (config & PORT_SET_MAC_ADDR) { + addr = rtwvif->conf->mac_addr.addr; + rtw_vif_write_addr(rtwdev, addr, rtwvif->mac_addr); + } + if (config & PORT_SET_BSSID) { + addr = rtwvif->conf->bssid.addr; + rtw_vif_write_addr(rtwdev, addr, rtwvif->bssid); + } + if (config & PORT_SET_NET_TYPE) { + addr = rtwvif->conf->net_type.addr; + mask = rtwvif->conf->net_type.mask; + rtw_write32_mask(rtwdev, addr, mask, rtwvif->net_type); + } + if (config & PORT_SET_AID) { + addr = rtwvif->conf->aid.addr; + mask = rtwvif->conf->aid.mask; + rtw_write32_mask(rtwdev, addr, mask, rtwvif->aid); + } +} + +static u8 hw_bw_cap_to_bitamp(u8 bw_cap) +{ + u8 bw = 0; + + switch (bw_cap) { + case EFUSE_HW_CAP_IGNORE: + case EFUSE_HW_CAP_SUPP_BW80: + bw |= BIT(RTW_CHANNEL_WIDTH_80); + /* fall through */ + case EFUSE_HW_CAP_SUPP_BW40: + bw |= BIT(RTW_CHANNEL_WIDTH_40); + /* fall through */ + default: + bw |= BIT(RTW_CHANNEL_WIDTH_20); + break; + } + + return bw; +} + +static void rtw_hw_config_rf_ant_num(struct rtw_dev *rtwdev, u8 hw_ant_num) +{ + struct rtw_hal *hal = &rtwdev->hal; + + if (hw_ant_num == EFUSE_HW_CAP_IGNORE || + hw_ant_num >= hal->rf_path_num) + return; + + switch (hw_ant_num) { + case 1: + hal->rf_type = RF_1T1R; + hal->rf_path_num = 1; + hal->antenna_tx = BB_PATH_A; + hal->antenna_rx = BB_PATH_A; + break; + default: + WARN(1, "invalid hw configuration from efuse\n"); + break; + } +} + +static u64 get_vht_ra_mask(struct ieee80211_sta *sta) +{ + u64 ra_mask = 0; + u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map); + u8 vht_mcs_cap; + int i, nss; + + /* 4SS, every two bits for MCS7/8/9 */ + for (i = 0, nss = 12; i < 4; i++, mcs_map >>= 2, nss += 10) { + vht_mcs_cap = mcs_map & 0x3; + switch (vht_mcs_cap) { + case 2: /* MCS9 */ + ra_mask |= 0x3ffULL << nss; + break; + case 1: /* MCS8 */ + ra_mask |= 0x1ffULL << nss; + break; + case 0: /* MCS7 */ + ra_mask |= 0x0ffULL << nss; + break; + default: + break; + } + } + + return ra_mask; +} + +static u8 get_rate_id(u8 wireless_set, enum rtw_bandwidth bw_mode, u8 tx_num) +{ + u8 rate_id = 0; + + switch (wireless_set) { + case WIRELESS_CCK: + rate_id = RTW_RATEID_B_20M; + break; + case WIRELESS_OFDM: + rate_id = RTW_RATEID_G; + break; + case WIRELESS_CCK | WIRELESS_OFDM: + rate_id = RTW_RATEID_BG; + break; + case WIRELESS_OFDM | WIRELESS_HT: + if (tx_num == 1) + rate_id = RTW_RATEID_GN_N1SS; + else if (tx_num == 2) + rate_id = RTW_RATEID_GN_N2SS; + else if (tx_num == 3) + rate_id = RTW_RATEID_ARFR5_N_3SS; + break; + case WIRELESS_CCK | WIRELESS_OFDM | WIRELESS_HT: + if (bw_mode == RTW_CHANNEL_WIDTH_40) { + if (tx_num == 1) + rate_id = RTW_RATEID_BGN_40M_1SS; + else if (tx_num == 2) + rate_id = RTW_RATEID_BGN_40M_2SS; + else if (tx_num == 3) + rate_id = RTW_RATEID_ARFR5_N_3SS; + else if (tx_num == 4) + rate_id = RTW_RATEID_ARFR7_N_4SS; + } else { + if (tx_num == 1) + rate_id = RTW_RATEID_BGN_20M_1SS; + else if (tx_num == 2) + rate_id = RTW_RATEID_BGN_20M_2SS; + else if (tx_num == 3) + rate_id = RTW_RATEID_ARFR5_N_3SS; + else if (tx_num == 4) + rate_id = RTW_RATEID_ARFR7_N_4SS; + } + break; + case WIRELESS_OFDM | WIRELESS_VHT: + if (tx_num == 1) + rate_id = RTW_RATEID_ARFR1_AC_1SS; + else if (tx_num == 2) + rate_id = RTW_RATEID_ARFR0_AC_2SS; + else if (tx_num == 3) + rate_id = RTW_RATEID_ARFR4_AC_3SS; + else if (tx_num == 4) + rate_id = RTW_RATEID_ARFR6_AC_4SS; + break; + case WIRELESS_CCK | WIRELESS_OFDM | WIRELESS_VHT: + if (bw_mode >= RTW_CHANNEL_WIDTH_80) { + if (tx_num == 1) + rate_id = RTW_RATEID_ARFR1_AC_1SS; + else if (tx_num == 2) + rate_id = RTW_RATEID_ARFR0_AC_2SS; + else if (tx_num == 3) + rate_id = RTW_RATEID_ARFR4_AC_3SS; + else if (tx_num == 4) + rate_id = RTW_RATEID_ARFR6_AC_4SS; + } else { + if (tx_num == 1) + rate_id = RTW_RATEID_ARFR2_AC_2G_1SS; + else if (tx_num == 2) + rate_id = RTW_RATEID_ARFR3_AC_2G_2SS; + else if (tx_num == 3) + rate_id = RTW_RATEID_ARFR4_AC_3SS; + else if (tx_num == 4) + rate_id = RTW_RATEID_ARFR6_AC_4SS; + } + break; + default: + break; + } + + return rate_id; +} + +#define RA_MASK_CCK_RATES 0x0000f +#define RA_MASK_OFDM_RATES 0x00ff0 +#define RA_MASK_HT_RATES_1SS (0xff000ULL << 0) +#define RA_MASK_HT_RATES_2SS (0xff000ULL << 8) +#define RA_MASK_HT_RATES_3SS (0xff000ULL << 16) +#define RA_MASK_HT_RATES (RA_MASK_HT_RATES_1SS | \ + RA_MASK_HT_RATES_2SS | \ + RA_MASK_HT_RATES_3SS) +#define RA_MASK_VHT_RATES_1SS (0x3ff000ULL << 0) +#define RA_MASK_VHT_RATES_2SS (0x3ff000ULL << 10) +#define RA_MASK_VHT_RATES_3SS (0x3ff000ULL << 20) +#define RA_MASK_VHT_RATES (RA_MASK_VHT_RATES_1SS | \ + RA_MASK_VHT_RATES_2SS | \ + RA_MASK_VHT_RATES_3SS) +#define RA_MASK_CCK_IN_HT 0x00005 +#define RA_MASK_CCK_IN_VHT 0x00005 +#define RA_MASK_OFDM_IN_VHT 0x00010 +#define RA_MASK_OFDM_IN_HT_2G 0x00010 +#define RA_MASK_OFDM_IN_HT_5G 0x00030 + +void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) +{ + struct ieee80211_sta *sta = si->sta; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_hal *hal = &rtwdev->hal; + u8 rssi_level; + u8 wireless_set; + u8 bw_mode; + u8 rate_id; + u8 rf_type = RF_1T1R; + u8 stbc_en = 0; + u8 ldpc_en = 0; + u8 tx_num = 1; + u64 ra_mask = 0; + bool is_vht_enable = false; + bool is_support_sgi = false; + + if (sta->vht_cap.vht_supported) { + is_vht_enable = true; + ra_mask |= get_vht_ra_mask(sta); + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) + stbc_en = VHT_STBC_EN; + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC) + ldpc_en = VHT_LDPC_EN; + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) + is_support_sgi = true; + } else if (sta->ht_cap.ht_supported) { + ra_mask |= (sta->ht_cap.mcs.rx_mask[NL80211_BAND_5GHZ] << 20) | + (sta->ht_cap.mcs.rx_mask[NL80211_BAND_2GHZ] << 12); + if (sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) + stbc_en = HT_STBC_EN; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING) + ldpc_en = HT_LDPC_EN; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20 || + sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) + is_support_sgi = true; + } + + if (hal->current_band_type == RTW_BAND_5G) { + ra_mask |= (u64)sta->supp_rates[NL80211_BAND_5GHZ] << 4; + if (sta->vht_cap.vht_supported) { + ra_mask &= RA_MASK_VHT_RATES | RA_MASK_OFDM_IN_VHT; + wireless_set = WIRELESS_OFDM | WIRELESS_VHT; + } else if (sta->ht_cap.ht_supported) { + ra_mask &= RA_MASK_HT_RATES | RA_MASK_OFDM_IN_HT_5G; + wireless_set = WIRELESS_OFDM | WIRELESS_HT; + } else { + wireless_set = WIRELESS_OFDM; + } + } else if (hal->current_band_type == RTW_BAND_2G) { + ra_mask |= sta->supp_rates[NL80211_BAND_2GHZ]; + if (sta->vht_cap.vht_supported) { + ra_mask &= RA_MASK_VHT_RATES | RA_MASK_CCK_IN_VHT | + RA_MASK_OFDM_IN_VHT; + wireless_set = WIRELESS_CCK | WIRELESS_OFDM | + WIRELESS_HT | WIRELESS_VHT; + } else if (sta->ht_cap.ht_supported) { + ra_mask &= RA_MASK_HT_RATES | RA_MASK_CCK_IN_HT | + RA_MASK_OFDM_IN_HT_2G; + wireless_set = WIRELESS_CCK | WIRELESS_OFDM | + WIRELESS_HT; + } else if (sta->supp_rates[0] <= 0xf) { + wireless_set = WIRELESS_CCK; + } else { + wireless_set = WIRELESS_CCK | WIRELESS_OFDM; + } + } else { + rtw_err(rtwdev, "Unknown band type\n"); + wireless_set = 0; + } + + if (efuse->hw_cap.nss == 1) { + ra_mask &= RA_MASK_VHT_RATES_1SS; + ra_mask &= RA_MASK_HT_RATES_1SS; + } + + switch (sta->bandwidth) { + case IEEE80211_STA_RX_BW_80: + bw_mode = RTW_CHANNEL_WIDTH_80; + break; + case IEEE80211_STA_RX_BW_40: + bw_mode = RTW_CHANNEL_WIDTH_40; + break; + default: + bw_mode = RTW_CHANNEL_WIDTH_20; + break; + } + + if (sta->vht_cap.vht_supported && ra_mask & 0xffc00000) { + tx_num = 2; + rf_type = RF_2T2R; + } else if (sta->ht_cap.ht_supported && ra_mask & 0xfff00000) { + tx_num = 2; + rf_type = RF_2T2R; + } + + rate_id = get_rate_id(wireless_set, bw_mode, tx_num); + + if (wireless_set != WIRELESS_CCK) { + rssi_level = si->rssi_level; + if (rssi_level == 0) + ra_mask &= 0xffffffffffffffffULL; + else if (rssi_level == 1) + ra_mask &= 0xfffffffffffffff0ULL; + else if (rssi_level == 2) + ra_mask &= 0xffffffffffffefe0ULL; + else if (rssi_level == 3) + ra_mask &= 0xffffffffffffcfc0ULL; + else if (rssi_level == 4) + ra_mask &= 0xffffffffffff8f80ULL; + else if (rssi_level >= 5) + ra_mask &= 0xffffffffffff0f00ULL; + } + + si->bw_mode = bw_mode; + si->stbc_en = stbc_en; + si->ldpc_en = ldpc_en; + si->rf_type = rf_type; + si->wireless_set = wireless_set; + si->sgi_enable = is_support_sgi; + si->vht_enable = is_vht_enable; + si->ra_mask = ra_mask; + si->rate_id = rate_id; + + rtw_fw_send_ra_info(rtwdev, si); +} + +static int rtw_power_on(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_fw_state *fw = &rtwdev->fw; + int ret; + + ret = rtw_hci_setup(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to setup hci\n"); + goto err; + } + + /* power on MAC before firmware downloaded */ + ret = rtw_mac_power_on(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to power on mac\n"); + goto err; + } + + wait_for_completion(&fw->completion); + if (!fw->firmware) { + ret = -EINVAL; + rtw_err(rtwdev, "failed to load firmware\n"); + goto err; + } + + ret = rtw_download_firmware(rtwdev, fw); + if (ret) { + rtw_err(rtwdev, "failed to download firmware\n"); + goto err_off; + } + + /* config mac after firmware downloaded */ + ret = rtw_mac_init(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to configure mac\n"); + goto err_off; + } + + chip->ops->phy_set_param(rtwdev); + + ret = rtw_hci_start(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to start hci\n"); + goto err_off; + } + + return 0; + +err_off: + rtw_mac_power_off(rtwdev); + +err: + return ret; +} + +int rtw_core_start(struct rtw_dev *rtwdev) +{ + int ret; + + ret = rtw_power_on(rtwdev); + if (ret) + return ret; + + rtw_sec_enable_sec_engine(rtwdev); + + /* rcr reset after powered on */ + rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr); + + ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->watch_dog_work, + RTW_WATCH_DOG_DELAY_TIME); + + rtw_flag_set(rtwdev, RTW_FLAG_RUNNING); + + return 0; +} + +static void rtw_power_off(struct rtw_dev *rtwdev) +{ + rtwdev->hci.ops->stop(rtwdev); + rtw_mac_power_off(rtwdev); +} + +void rtw_core_stop(struct rtw_dev *rtwdev) +{ + rtw_flag_clear(rtwdev, RTW_FLAG_RUNNING); + rtw_flag_clear(rtwdev, RTW_FLAG_FW_RUNNING); + + cancel_delayed_work_sync(&rtwdev->watch_dog_work); + + rtw_power_off(rtwdev); +} + +static void rtw_init_ht_cap(struct rtw_dev *rtwdev, + struct ieee80211_sta_ht_cap *ht_cap) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + + ht_cap->ht_supported = true; + ht_cap->cap = 0; + ht_cap->cap |= IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_MAX_AMSDU | + IEEE80211_HT_CAP_LDPC_CODING | + (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); + if (efuse->hw_cap.bw & BIT(RTW_CHANNEL_WIDTH_40)) + ht_cap->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_DSSSCCK40 | + IEEE80211_HT_CAP_SGI_40; + ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; + ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; + if (efuse->hw_cap.nss > 1) { + ht_cap->mcs.rx_mask[0] = 0xFF; + ht_cap->mcs.rx_mask[1] = 0xFF; + ht_cap->mcs.rx_mask[4] = 0x01; + ht_cap->mcs.rx_highest = cpu_to_le16(300); + } else { + ht_cap->mcs.rx_mask[0] = 0xFF; + ht_cap->mcs.rx_mask[1] = 0x00; + ht_cap->mcs.rx_mask[4] = 0x01; + ht_cap->mcs.rx_highest = cpu_to_le16(150); + } +} + +static void rtw_init_vht_cap(struct rtw_dev *rtwdev, + struct ieee80211_sta_vht_cap *vht_cap) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + u16 mcs_map; + __le16 highest; + + if (efuse->hw_cap.ptcl != EFUSE_HW_CAP_IGNORE && + efuse->hw_cap.ptcl != EFUSE_HW_CAP_PTCL_VHT) + return; + + vht_cap->vht_supported = true; + vht_cap->cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | + IEEE80211_VHT_CAP_RXLDPC | + IEEE80211_VHT_CAP_SHORT_GI_80 | + IEEE80211_VHT_CAP_TXSTBC | + IEEE80211_VHT_CAP_RXSTBC_1 | + IEEE80211_VHT_CAP_HTC_VHT | + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | + 0; + mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; + if (efuse->hw_cap.nss > 1) { + highest = cpu_to_le16(780); + mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << 2; + } else { + highest = cpu_to_le16(390); + mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << 2; + } + + vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); + vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); + vht_cap->vht_mcs.rx_highest = highest; + vht_cap->vht_mcs.tx_highest = highest; +} + +static void rtw_set_supported_band(struct ieee80211_hw *hw, + struct rtw_chip_info *chip) +{ + struct rtw_dev *rtwdev = hw->priv; + struct ieee80211_supported_band *sband; + + if (chip->band & RTW_BAND_2G) { + sband = kmemdup(&rtw_band_2ghz, sizeof(*sband), GFP_KERNEL); + if (!sband) + goto err_out; + if (chip->ht_supported) + rtw_init_ht_cap(rtwdev, &sband->ht_cap); + hw->wiphy->bands[NL80211_BAND_2GHZ] = sband; + } + + if (chip->band & RTW_BAND_5G) { + sband = kmemdup(&rtw_band_5ghz, sizeof(*sband), GFP_KERNEL); + if (!sband) + goto err_out; + if (chip->ht_supported) + rtw_init_ht_cap(rtwdev, &sband->ht_cap); + if (chip->vht_supported) + rtw_init_vht_cap(rtwdev, &sband->vht_cap); + hw->wiphy->bands[NL80211_BAND_5GHZ] = sband; + } + + return; + +err_out: + rtw_err(rtwdev, "failed to set supported band\n"); + kfree(sband); +} + +static void rtw_unset_supported_band(struct ieee80211_hw *hw, + struct rtw_chip_info *chip) +{ + kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]); + kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]); +} + +static void rtw_load_firmware_cb(const struct firmware *firmware, void *context) +{ + struct rtw_dev *rtwdev = context; + struct rtw_fw_state *fw = &rtwdev->fw; + + if (!firmware) + rtw_err(rtwdev, "failed to request firmware\n"); + + fw->firmware = firmware; + complete_all(&fw->completion); +} + +static int rtw_load_firmware(struct rtw_dev *rtwdev, const char *fw_name) +{ + struct rtw_fw_state *fw = &rtwdev->fw; + int ret; + + init_completion(&fw->completion); + + ret = request_firmware_nowait(THIS_MODULE, true, fw_name, rtwdev->dev, + GFP_KERNEL, rtwdev, rtw_load_firmware_cb); + if (ret) { + rtw_err(rtwdev, "async firmware request failed\n"); + return ret; + } + + return 0; +} + +static int rtw_chip_parameter_setup(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_hal *hal = &rtwdev->hal; + struct rtw_efuse *efuse = &rtwdev->efuse; + u32 wl_bt_pwr_ctrl; + int ret = 0; + + switch (rtw_hci_type(rtwdev)) { + case RTW_HCI_TYPE_PCIE: + rtwdev->hci.rpwm_addr = 0x03d9; + break; + default: + rtw_err(rtwdev, "unsupported hci type\n"); + return -EINVAL; + } + + wl_bt_pwr_ctrl = rtw_read32(rtwdev, REG_WL_BT_PWR_CTRL); + if (wl_bt_pwr_ctrl & BIT_BT_FUNC_EN) + rtwdev->efuse.btcoex = true; + hal->chip_version = rtw_read32(rtwdev, REG_SYS_CFG1); + hal->fab_version = BIT_GET_VENDOR_ID(hal->chip_version) >> 2; + hal->cut_version = BIT_GET_CHIP_VER(hal->chip_version); + hal->mp_chip = (hal->chip_version & BIT_RTL_ID) ? 0 : 1; + if (hal->chip_version & BIT_RF_TYPE_ID) { + hal->rf_type = RF_2T2R; + hal->rf_path_num = 2; + hal->antenna_tx = BB_PATH_AB; + hal->antenna_rx = BB_PATH_AB; + } else { + hal->rf_type = RF_1T1R; + hal->rf_path_num = 1; + hal->antenna_tx = BB_PATH_A; + hal->antenna_rx = BB_PATH_A; + } + + if (hal->fab_version == 2) + hal->fab_version = 1; + else if (hal->fab_version == 1) + hal->fab_version = 2; + + efuse->physical_size = chip->phy_efuse_size; + efuse->logical_size = chip->log_efuse_size; + efuse->protect_size = chip->ptct_efuse_size; + + /* default use ack */ + rtwdev->hal.rcr |= BIT_VHT_DACK; + + return ret; +} + +static int rtw_chip_efuse_enable(struct rtw_dev *rtwdev) +{ + struct rtw_fw_state *fw = &rtwdev->fw; + int ret; + + ret = rtw_hci_setup(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to setup hci\n"); + goto err; + } + + ret = rtw_mac_power_on(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to power on mac\n"); + goto err; + } + + rtw_write8(rtwdev, REG_C2HEVT, C2H_HW_FEATURE_DUMP); + + wait_for_completion(&fw->completion); + if (!fw->firmware) { + ret = -EINVAL; + rtw_err(rtwdev, "failed to load firmware\n"); + goto err; + } + + ret = rtw_download_firmware(rtwdev, fw); + if (ret) { + rtw_err(rtwdev, "failed to download firmware\n"); + goto err_off; + } + + return 0; + +err_off: + rtw_mac_power_off(rtwdev); + +err: + return ret; +} + +static int rtw_dump_hw_feature(struct rtw_dev *rtwdev) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + u8 hw_feature[HW_FEATURE_LEN]; + u8 id; + u8 bw; + int i; + + id = rtw_read8(rtwdev, REG_C2HEVT); + if (id != C2H_HW_FEATURE_REPORT) { + rtw_err(rtwdev, "failed to read hw feature report\n"); + return -EBUSY; + } + + for (i = 0; i < HW_FEATURE_LEN; i++) + hw_feature[i] = rtw_read8(rtwdev, REG_C2HEVT + 2 + i); + + rtw_write8(rtwdev, REG_C2HEVT, 0); + + bw = GET_EFUSE_HW_CAP_BW(hw_feature); + efuse->hw_cap.bw = hw_bw_cap_to_bitamp(bw); + efuse->hw_cap.hci = GET_EFUSE_HW_CAP_HCI(hw_feature); + efuse->hw_cap.nss = GET_EFUSE_HW_CAP_NSS(hw_feature); + efuse->hw_cap.ptcl = GET_EFUSE_HW_CAP_PTCL(hw_feature); + efuse->hw_cap.ant_num = GET_EFUSE_HW_CAP_ANT_NUM(hw_feature); + + rtw_hw_config_rf_ant_num(rtwdev, efuse->hw_cap.ant_num); + + if (efuse->hw_cap.nss == EFUSE_HW_CAP_IGNORE) + efuse->hw_cap.nss = rtwdev->hal.rf_path_num; + + rtw_dbg(rtwdev, RTW_DBG_EFUSE, + "hw cap: hci=0x%02x, bw=0x%02x, ptcl=0x%02x, ant_num=%d, nss=%d\n", + efuse->hw_cap.hci, efuse->hw_cap.bw, efuse->hw_cap.ptcl, + efuse->hw_cap.ant_num, efuse->hw_cap.nss); + + return 0; +} + +static void rtw_chip_efuse_disable(struct rtw_dev *rtwdev) +{ + rtw_hci_stop(rtwdev); + rtw_mac_power_off(rtwdev); +} + +static int rtw_chip_efuse_info_setup(struct rtw_dev *rtwdev) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + int ret; + + mutex_lock(&rtwdev->mutex); + + /* power on mac to read efuse */ + ret = rtw_chip_efuse_enable(rtwdev); + if (ret) + goto out; + + ret = rtw_parse_efuse_map(rtwdev); + if (ret) + goto out; + + ret = rtw_dump_hw_feature(rtwdev); + if (ret) + goto out; + + ret = rtw_check_supported_rfe(rtwdev); + if (ret) + goto out; + + if (efuse->crystal_cap == 0xff) + efuse->crystal_cap = 0; + if (efuse->pa_type_2g == 0xff) + efuse->pa_type_2g = 0; + if (efuse->pa_type_5g == 0xff) + efuse->pa_type_5g = 0; + if (efuse->lna_type_2g == 0xff) + efuse->lna_type_2g = 0; + if (efuse->lna_type_5g == 0xff) + efuse->lna_type_5g = 0; + if (efuse->channel_plan == 0xff) + efuse->channel_plan = 0x7f; + if (efuse->bt_setting & BIT(0)) + efuse->share_ant = true; + if (efuse->regd == 0xff) + efuse->regd = 0; + + efuse->ext_pa_2g = efuse->pa_type_2g & BIT(4) ? 1 : 0; + efuse->ext_lna_2g = efuse->lna_type_2g & BIT(3) ? 1 : 0; + efuse->ext_pa_5g = efuse->pa_type_5g & BIT(0) ? 1 : 0; + efuse->ext_lna_2g = efuse->lna_type_5g & BIT(3) ? 1 : 0; + + rtw_chip_efuse_disable(rtwdev); + +out: + mutex_unlock(&rtwdev->mutex); + return ret; +} + +static int rtw_chip_board_info_setup(struct rtw_dev *rtwdev) +{ + struct rtw_hal *hal = &rtwdev->hal; + const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev); + + if (!rfe_def) + return -ENODEV; + + rtw_phy_setup_phy_cond(rtwdev, 0); + + rtw_hw_init_tx_power(hal); + rtw_load_table(rtwdev, rfe_def->phy_pg_tbl); + rtw_load_table(rtwdev, rfe_def->txpwr_lmt_tbl); + rtw_phy_tx_power_by_rate_config(hal); + rtw_phy_tx_power_limit_config(hal); + + return 0; +} + +int rtw_chip_info_setup(struct rtw_dev *rtwdev) +{ + int ret; + + ret = rtw_chip_parameter_setup(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to setup chip parameters\n"); + goto err_out; + } + + ret = rtw_chip_efuse_info_setup(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to setup chip efuse info\n"); + goto err_out; + } + + ret = rtw_chip_board_info_setup(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to setup chip board info\n"); + goto err_out; + } + + return 0; + +err_out: + return ret; +} +EXPORT_SYMBOL(rtw_chip_info_setup); + +int rtw_core_init(struct rtw_dev *rtwdev) +{ + int ret; + + INIT_LIST_HEAD(&rtwdev->rsvd_page_list); + + timer_setup(&rtwdev->tx_report.purge_timer, + rtw_tx_report_purge_timer, 0); + + INIT_DELAYED_WORK(&rtwdev->watch_dog_work, rtw_watch_dog_work); + INIT_DELAYED_WORK(&rtwdev->lps_work, rtw_lps_work); + INIT_WORK(&rtwdev->c2h_work, rtw_c2h_work); + skb_queue_head_init(&rtwdev->c2h_queue); + skb_queue_head_init(&rtwdev->tx_report.queue); + + spin_lock_init(&rtwdev->dm_lock); + spin_lock_init(&rtwdev->rf_lock); + spin_lock_init(&rtwdev->h2c.lock); + spin_lock_init(&rtwdev->tx_report.q_lock); + + mutex_init(&rtwdev->mutex); + mutex_init(&rtwdev->hal.tx_power_mutex); + + rtwdev->sec.total_cam_num = 32; + rtwdev->hal.current_channel = 1; + set_bit(RTW_BC_MC_MACID, rtwdev->mac_id_map); + + mutex_lock(&rtwdev->mutex); + rtw_add_rsvd_page(rtwdev, RSVD_BEACON, false); + mutex_unlock(&rtwdev->mutex); + + /* default rx filter setting */ + rtwdev->hal.rcr = BIT_APP_FCS | BIT_APP_MIC | BIT_APP_ICV | + BIT_HTC_LOC_CTRL | BIT_APP_PHYSTS | + BIT_AB | BIT_AM | BIT_APM; + + ret = rtw_load_firmware(rtwdev, rtwdev->chip->fw_name); + if (ret) { + rtw_warn(rtwdev, "no firmware loaded\n"); + return ret; + } + + return 0; +} +EXPORT_SYMBOL(rtw_core_init); + +void rtw_core_deinit(struct rtw_dev *rtwdev) +{ + struct rtw_fw_state *fw = &rtwdev->fw; + struct rtw_rsvd_page *rsvd_pkt, *tmp; + unsigned long flags; + + if (fw->firmware) + release_firmware(fw->firmware); + + spin_lock_irqsave(&rtwdev->tx_report.q_lock, flags); + skb_queue_purge(&rtwdev->tx_report.queue); + spin_unlock_irqrestore(&rtwdev->tx_report.q_lock, flags); + + list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, list) { + list_del(&rsvd_pkt->list); + kfree(rsvd_pkt); + } + + mutex_destroy(&rtwdev->mutex); + mutex_destroy(&rtwdev->hal.tx_power_mutex); +} +EXPORT_SYMBOL(rtw_core_deinit); + +int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) +{ + int max_tx_headroom = 0; + int ret; + + /* TODO: USB & SDIO may need extra room? */ + max_tx_headroom = rtwdev->chip->tx_pkt_desc_sz; + + hw->extra_tx_headroom = max_tx_headroom; + hw->queues = IEEE80211_NUM_ACS; + hw->sta_data_size = sizeof(struct rtw_sta_info); + hw->vif_data_size = sizeof(struct rtw_vif); + + ieee80211_hw_set(hw, SIGNAL_DBM); + ieee80211_hw_set(hw, RX_INCLUDES_FCS); + ieee80211_hw_set(hw, AMPDU_AGGREGATION); + ieee80211_hw_set(hw, MFP_CAPABLE); + ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); + ieee80211_hw_set(hw, SUPPORTS_PS); + ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); + + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_MESH_POINT); + + hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | + WIPHY_FLAG_TDLS_EXTERNAL_SETUP; + + rtw_set_supported_band(hw, rtwdev->chip); + SET_IEEE80211_PERM_ADDR(hw, rtwdev->efuse.addr); + + rtw_regd_init(rtwdev, rtw_regd_notifier); + + ret = ieee80211_register_hw(hw); + if (ret) { + rtw_err(rtwdev, "failed to register hw\n"); + return ret; + } + + if (regulatory_hint(hw->wiphy, rtwdev->regd.alpha2)) + rtw_err(rtwdev, "regulatory_hint fail\n"); + + rtw_debugfs_init(rtwdev); + + return 0; +} +EXPORT_SYMBOL(rtw_register_hw); + +void rtw_unregister_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) +{ + struct rtw_chip_info *chip = rtwdev->chip; + + ieee80211_unregister_hw(hw); + rtw_unset_supported_band(hw, chip); +} +EXPORT_SYMBOL(rtw_unregister_hw); + +MODULE_AUTHOR("Realtek Corporation"); +MODULE_DESCRIPTION("Realtek 802.11ac wireless core module"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h new file mode 100644 index 000000000000..00fc77fb9b54 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -0,0 +1,1104 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTK_MAIN_H_ +#define __RTK_MAIN_H_ + +#include <net/mac80211.h> +#include <linux/vmalloc.h> +#include <linux/firmware.h> +#include <linux/average.h> +#include <linux/bitops.h> +#include <linux/bitfield.h> + +#include "util.h" + +#define RTW_MAX_MAC_ID_NUM 32 +#define RTW_MAX_SEC_CAM_NUM 32 + +#define RTW_WATCH_DOG_DELAY_TIME round_jiffies_relative(HZ * 2) + +#define RFREG_MASK 0xfffff +#define INV_RF_DATA 0xffffffff +#define TX_PAGE_SIZE_SHIFT 7 + +#define RTW_CHANNEL_WIDTH_MAX 3 +#define RTW_RF_PATH_MAX 4 +#define HW_FEATURE_LEN 13 + +extern unsigned int rtw_debug_mask; +extern const struct ieee80211_ops rtw_ops; +extern struct rtw_chip_info rtw8822b_hw_spec; +extern struct rtw_chip_info rtw8822c_hw_spec; + +#define RTW_MAX_CHANNEL_NUM_2G 14 +#define RTW_MAX_CHANNEL_NUM_5G 49 + +struct rtw_dev; + +enum rtw_hci_type { + RTW_HCI_TYPE_PCIE, + RTW_HCI_TYPE_USB, + RTW_HCI_TYPE_SDIO, + + RTW_HCI_TYPE_UNDEFINE, +}; + +struct rtw_hci { + struct rtw_hci_ops *ops; + enum rtw_hci_type type; + + u32 rpwm_addr; + + u8 bulkout_num; +}; + +enum rtw_supported_band { + RTW_BAND_2G = 1 << 0, + RTW_BAND_5G = 1 << 1, + RTW_BAND_60G = 1 << 2, + + RTW_BAND_MAX, +}; + +enum rtw_bandwidth { + RTW_CHANNEL_WIDTH_20 = 0, + RTW_CHANNEL_WIDTH_40 = 1, + RTW_CHANNEL_WIDTH_80 = 2, + RTW_CHANNEL_WIDTH_160 = 3, + RTW_CHANNEL_WIDTH_80_80 = 4, + RTW_CHANNEL_WIDTH_5 = 5, + RTW_CHANNEL_WIDTH_10 = 6, +}; + +enum rtw_net_type { + RTW_NET_NO_LINK = 0, + RTW_NET_AD_HOC = 1, + RTW_NET_MGD_LINKED = 2, + RTW_NET_AP_MODE = 3, +}; + +enum rtw_rf_type { + RF_1T1R = 0, + RF_1T2R = 1, + RF_2T2R = 2, + RF_2T3R = 3, + RF_2T4R = 4, + RF_3T3R = 5, + RF_3T4R = 6, + RF_4T4R = 7, + RF_TYPE_MAX, +}; + +enum rtw_rf_path { + RF_PATH_A = 0, + RF_PATH_B = 1, + RF_PATH_C = 2, + RF_PATH_D = 3, +}; + +enum rtw_bb_path { + BB_PATH_A = BIT(0), + BB_PATH_B = BIT(1), + BB_PATH_C = BIT(2), + BB_PATH_D = BIT(3), + + BB_PATH_AB = (BB_PATH_A | BB_PATH_B), + BB_PATH_AC = (BB_PATH_A | BB_PATH_C), + BB_PATH_AD = (BB_PATH_A | BB_PATH_D), + BB_PATH_BC = (BB_PATH_B | BB_PATH_C), + BB_PATH_BD = (BB_PATH_B | BB_PATH_D), + BB_PATH_CD = (BB_PATH_C | BB_PATH_D), + + BB_PATH_ABC = (BB_PATH_A | BB_PATH_B | BB_PATH_C), + BB_PATH_ABD = (BB_PATH_A | BB_PATH_B | BB_PATH_D), + BB_PATH_ACD = (BB_PATH_A | BB_PATH_C | BB_PATH_D), + BB_PATH_BCD = (BB_PATH_B | BB_PATH_C | BB_PATH_D), + + BB_PATH_ABCD = (BB_PATH_A | BB_PATH_B | BB_PATH_C | BB_PATH_D), +}; + +enum rtw_rate_section { + RTW_RATE_SECTION_CCK = 0, + RTW_RATE_SECTION_OFDM, + RTW_RATE_SECTION_HT_1S, + RTW_RATE_SECTION_HT_2S, + RTW_RATE_SECTION_VHT_1S, + RTW_RATE_SECTION_VHT_2S, + + /* keep last */ + RTW_RATE_SECTION_MAX, +}; + +enum rtw_wireless_set { + WIRELESS_CCK = 0x00000001, + WIRELESS_OFDM = 0x00000002, + WIRELESS_HT = 0x00000004, + WIRELESS_VHT = 0x00000008, +}; + +#define HT_STBC_EN BIT(0) +#define VHT_STBC_EN BIT(1) +#define HT_LDPC_EN BIT(0) +#define VHT_LDPC_EN BIT(1) + +enum rtw_chip_type { + RTW_CHIP_TYPE_8822B, + RTW_CHIP_TYPE_8822C, +}; + +enum rtw_tx_queue_type { + /* the order of AC queues matters */ + RTW_TX_QUEUE_BK = 0x0, + RTW_TX_QUEUE_BE = 0x1, + RTW_TX_QUEUE_VI = 0x2, + RTW_TX_QUEUE_VO = 0x3, + + RTW_TX_QUEUE_BCN = 0x4, + RTW_TX_QUEUE_MGMT = 0x5, + RTW_TX_QUEUE_HI0 = 0x6, + RTW_TX_QUEUE_H2C = 0x7, + /* keep it last */ + RTK_MAX_TX_QUEUE_NUM +}; + +enum rtw_rx_queue_type { + RTW_RX_QUEUE_MPDU = 0x0, + RTW_RX_QUEUE_C2H = 0x1, + /* keep it last */ + RTK_MAX_RX_QUEUE_NUM +}; + +enum rtw_rate_index { + RTW_RATEID_BGN_40M_2SS = 0, + RTW_RATEID_BGN_40M_1SS = 1, + RTW_RATEID_BGN_20M_2SS = 2, + RTW_RATEID_BGN_20M_1SS = 3, + RTW_RATEID_GN_N2SS = 4, + RTW_RATEID_GN_N1SS = 5, + RTW_RATEID_BG = 6, + RTW_RATEID_G = 7, + RTW_RATEID_B_20M = 8, + RTW_RATEID_ARFR0_AC_2SS = 9, + RTW_RATEID_ARFR1_AC_1SS = 10, + RTW_RATEID_ARFR2_AC_2G_1SS = 11, + RTW_RATEID_ARFR3_AC_2G_2SS = 12, + RTW_RATEID_ARFR4_AC_3SS = 13, + RTW_RATEID_ARFR5_N_3SS = 14, + RTW_RATEID_ARFR7_N_4SS = 15, + RTW_RATEID_ARFR6_AC_4SS = 16 +}; + +enum rtw_trx_desc_rate { + DESC_RATE1M = 0x00, + DESC_RATE2M = 0x01, + DESC_RATE5_5M = 0x02, + DESC_RATE11M = 0x03, + + DESC_RATE6M = 0x04, + DESC_RATE9M = 0x05, + DESC_RATE12M = 0x06, + DESC_RATE18M = 0x07, + DESC_RATE24M = 0x08, + DESC_RATE36M = 0x09, + DESC_RATE48M = 0x0a, + DESC_RATE54M = 0x0b, + + DESC_RATEMCS0 = 0x0c, + DESC_RATEMCS1 = 0x0d, + DESC_RATEMCS2 = 0x0e, + DESC_RATEMCS3 = 0x0f, + DESC_RATEMCS4 = 0x10, + DESC_RATEMCS5 = 0x11, + DESC_RATEMCS6 = 0x12, + DESC_RATEMCS7 = 0x13, + DESC_RATEMCS8 = 0x14, + DESC_RATEMCS9 = 0x15, + DESC_RATEMCS10 = 0x16, + DESC_RATEMCS11 = 0x17, + DESC_RATEMCS12 = 0x18, + DESC_RATEMCS13 = 0x19, + DESC_RATEMCS14 = 0x1a, + DESC_RATEMCS15 = 0x1b, + DESC_RATEMCS16 = 0x1c, + DESC_RATEMCS17 = 0x1d, + DESC_RATEMCS18 = 0x1e, + DESC_RATEMCS19 = 0x1f, + DESC_RATEMCS20 = 0x20, + DESC_RATEMCS21 = 0x21, + DESC_RATEMCS22 = 0x22, + DESC_RATEMCS23 = 0x23, + DESC_RATEMCS24 = 0x24, + DESC_RATEMCS25 = 0x25, + DESC_RATEMCS26 = 0x26, + DESC_RATEMCS27 = 0x27, + DESC_RATEMCS28 = 0x28, + DESC_RATEMCS29 = 0x29, + DESC_RATEMCS30 = 0x2a, + DESC_RATEMCS31 = 0x2b, + + DESC_RATEVHT1SS_MCS0 = 0x2c, + DESC_RATEVHT1SS_MCS1 = 0x2d, + DESC_RATEVHT1SS_MCS2 = 0x2e, + DESC_RATEVHT1SS_MCS3 = 0x2f, + DESC_RATEVHT1SS_MCS4 = 0x30, + DESC_RATEVHT1SS_MCS5 = 0x31, + DESC_RATEVHT1SS_MCS6 = 0x32, + DESC_RATEVHT1SS_MCS7 = 0x33, + DESC_RATEVHT1SS_MCS8 = 0x34, + DESC_RATEVHT1SS_MCS9 = 0x35, + + DESC_RATEVHT2SS_MCS0 = 0x36, + DESC_RATEVHT2SS_MCS1 = 0x37, + DESC_RATEVHT2SS_MCS2 = 0x38, + DESC_RATEVHT2SS_MCS3 = 0x39, + DESC_RATEVHT2SS_MCS4 = 0x3a, + DESC_RATEVHT2SS_MCS5 = 0x3b, + DESC_RATEVHT2SS_MCS6 = 0x3c, + DESC_RATEVHT2SS_MCS7 = 0x3d, + DESC_RATEVHT2SS_MCS8 = 0x3e, + DESC_RATEVHT2SS_MCS9 = 0x3f, + + DESC_RATEVHT3SS_MCS0 = 0x40, + DESC_RATEVHT3SS_MCS1 = 0x41, + DESC_RATEVHT3SS_MCS2 = 0x42, + DESC_RATEVHT3SS_MCS3 = 0x43, + DESC_RATEVHT3SS_MCS4 = 0x44, + DESC_RATEVHT3SS_MCS5 = 0x45, + DESC_RATEVHT3SS_MCS6 = 0x46, + DESC_RATEVHT3SS_MCS7 = 0x47, + DESC_RATEVHT3SS_MCS8 = 0x48, + DESC_RATEVHT3SS_MCS9 = 0x49, + + DESC_RATEVHT4SS_MCS0 = 0x4a, + DESC_RATEVHT4SS_MCS1 = 0x4b, + DESC_RATEVHT4SS_MCS2 = 0x4c, + DESC_RATEVHT4SS_MCS3 = 0x4d, + DESC_RATEVHT4SS_MCS4 = 0x4e, + DESC_RATEVHT4SS_MCS5 = 0x4f, + DESC_RATEVHT4SS_MCS6 = 0x50, + DESC_RATEVHT4SS_MCS7 = 0x51, + DESC_RATEVHT4SS_MCS8 = 0x52, + DESC_RATEVHT4SS_MCS9 = 0x53, + + DESC_RATE_MAX, +}; + +enum rtw_regulatory_domains { + RTW_REGD_FCC = 0, + RTW_REGD_MKK = 1, + RTW_REGD_ETSI = 2, + RTW_REGD_WW = 3, + + RTW_REGD_MAX +}; + +enum rtw_flags { + RTW_FLAG_RUNNING, + RTW_FLAG_FW_RUNNING, + RTW_FLAG_SCANNING, + RTW_FLAG_INACTIVE_PS, + RTW_FLAG_LEISURE_PS, + RTW_FLAG_DIG_DISABLE, + + NUM_OF_RTW_FLAGS, +}; + +/* the power index is represented by differences, which cck-1s & ht40-1s are + * the base values, so for 1s's differences, there are only ht20 & ofdm + */ +struct rtw_2g_1s_pwr_idx_diff { +#ifdef __LITTLE_ENDIAN + s8 ofdm:4; + s8 bw20:4; +#else + s8 bw20:4; + s8 ofdm:4; +#endif +} __packed; + +struct rtw_2g_ns_pwr_idx_diff { +#ifdef __LITTLE_ENDIAN + s8 bw20:4; + s8 bw40:4; + s8 cck:4; + s8 ofdm:4; +#else + s8 ofdm:4; + s8 cck:4; + s8 bw40:4; + s8 bw20:4; +#endif +} __packed; + +struct rtw_2g_txpwr_idx { + u8 cck_base[6]; + u8 bw40_base[5]; + struct rtw_2g_1s_pwr_idx_diff ht_1s_diff; + struct rtw_2g_ns_pwr_idx_diff ht_2s_diff; + struct rtw_2g_ns_pwr_idx_diff ht_3s_diff; + struct rtw_2g_ns_pwr_idx_diff ht_4s_diff; +}; + +struct rtw_5g_ht_1s_pwr_idx_diff { +#ifdef __LITTLE_ENDIAN + s8 ofdm:4; + s8 bw20:4; +#else + s8 bw20:4; + s8 ofdm:4; +#endif +} __packed; + +struct rtw_5g_ht_ns_pwr_idx_diff { +#ifdef __LITTLE_ENDIAN + s8 bw20:4; + s8 bw40:4; +#else + s8 bw40:4; + s8 bw20:4; +#endif +} __packed; + +struct rtw_5g_ofdm_ns_pwr_idx_diff { +#ifdef __LITTLE_ENDIAN + s8 ofdm_3s:4; + s8 ofdm_2s:4; + s8 ofdm_4s:4; + s8 res:4; +#else + s8 res:4; + s8 ofdm_4s:4; + s8 ofdm_2s:4; + s8 ofdm_3s:4; +#endif +} __packed; + +struct rtw_5g_vht_ns_pwr_idx_diff { +#ifdef __LITTLE_ENDIAN + s8 bw160:4; + s8 bw80:4; +#else + s8 bw80:4; + s8 bw160:4; +#endif +} __packed; + +struct rtw_5g_txpwr_idx { + u8 bw40_base[14]; + struct rtw_5g_ht_1s_pwr_idx_diff ht_1s_diff; + struct rtw_5g_ht_ns_pwr_idx_diff ht_2s_diff; + struct rtw_5g_ht_ns_pwr_idx_diff ht_3s_diff; + struct rtw_5g_ht_ns_pwr_idx_diff ht_4s_diff; + struct rtw_5g_ofdm_ns_pwr_idx_diff ofdm_diff; + struct rtw_5g_vht_ns_pwr_idx_diff vht_1s_diff; + struct rtw_5g_vht_ns_pwr_idx_diff vht_2s_diff; + struct rtw_5g_vht_ns_pwr_idx_diff vht_3s_diff; + struct rtw_5g_vht_ns_pwr_idx_diff vht_4s_diff; +}; + +struct rtw_txpwr_idx { + struct rtw_2g_txpwr_idx pwr_idx_2g; + struct rtw_5g_txpwr_idx pwr_idx_5g; +}; + +struct rtw_timer_list { + struct timer_list timer; + void (*function)(void *data); + void *args; +}; + +struct rtw_channel_params { + u8 center_chan; + u8 bandwidth; + u8 primary_chan_idx; +}; + +struct rtw_hw_reg { + u32 addr; + u32 mask; +}; + +struct rtw_backup_info { + u8 len; + u32 reg; + u32 val; +}; + +enum rtw_vif_port_set { + PORT_SET_MAC_ADDR = BIT(0), + PORT_SET_BSSID = BIT(1), + PORT_SET_NET_TYPE = BIT(2), + PORT_SET_AID = BIT(3), +}; + +struct rtw_vif_port { + struct rtw_hw_reg mac_addr; + struct rtw_hw_reg bssid; + struct rtw_hw_reg net_type; + struct rtw_hw_reg aid; +}; + +struct rtw_tx_pkt_info { + u32 tx_pkt_size; + u8 offset; + u8 pkt_offset; + u8 mac_id; + u8 rate_id; + u8 rate; + u8 qsel; + u8 bw; + u8 sec_type; + u8 sn; + bool ampdu_en; + u8 ampdu_factor; + u8 ampdu_density; + u16 seq; + bool stbc; + bool ldpc; + bool dis_rate_fallback; + bool bmc; + bool use_rate; + bool ls; + bool fs; + bool short_gi; + bool report; +}; + +struct rtw_rx_pkt_stat { + bool phy_status; + bool icv_err; + bool crc_err; + bool decrypted; + bool is_c2h; + + s32 signal_power; + u16 pkt_len; + u8 bw; + u8 drv_info_sz; + u8 shift; + u8 rate; + u8 mac_id; + u8 cam_id; + u8 ppdu_cnt; + u32 tsf_low; + s8 rx_power[RTW_RF_PATH_MAX]; + u8 rssi; + u8 rxsc; + struct rtw_sta_info *si; + struct ieee80211_vif *vif; +}; + +struct rtw_traffic_stats { + /* units in bytes */ + u64 tx_unicast; + u64 rx_unicast; + + /* count for packets */ + u64 tx_cnt; + u64 rx_cnt; + + /* units in Mbps */ + u32 tx_throughput; + u32 rx_throughput; +}; + +enum rtw_lps_mode { + RTW_MODE_ACTIVE = 0, + RTW_MODE_LPS = 1, + RTW_MODE_WMM_PS = 2, +}; + +enum rtw_pwr_state { + RTW_RF_OFF = 0x0, + RTW_RF_ON = 0x4, + RTW_ALL_ON = 0xc, +}; + +struct rtw_lps_conf { + /* the interface to enter lps */ + struct rtw_vif *rtwvif; + enum rtw_lps_mode mode; + enum rtw_pwr_state state; + u8 awake_interval; + u8 rlbm; + u8 smart_ps; + u8 port_id; +}; + +enum rtw_hw_key_type { + RTW_CAM_NONE = 0, + RTW_CAM_WEP40 = 1, + RTW_CAM_TKIP = 2, + RTW_CAM_AES = 4, + RTW_CAM_WEP104 = 5, +}; + +struct rtw_cam_entry { + bool valid; + bool group; + u8 addr[ETH_ALEN]; + u8 hw_key_type; + struct ieee80211_key_conf *key; +}; + +struct rtw_sec_desc { + /* search strategy */ + bool default_key_search; + + u32 total_cam_num; + struct rtw_cam_entry cam_table[RTW_MAX_SEC_CAM_NUM]; + DECLARE_BITMAP(cam_map, RTW_MAX_SEC_CAM_NUM); +}; + +struct rtw_tx_report { + /* protect the tx report queue */ + spinlock_t q_lock; + struct sk_buff_head queue; + atomic_t sn; + struct timer_list purge_timer; +}; + +#define RTW_BC_MC_MACID 1 +DECLARE_EWMA(rssi, 10, 16); + +struct rtw_sta_info { + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; + + struct ewma_rssi avg_rssi; + u8 rssi_level; + + u8 mac_id; + u8 rate_id; + enum rtw_bandwidth bw_mode; + enum rtw_rf_type rf_type; + enum rtw_wireless_set wireless_set; + u8 stbc_en:2; + u8 ldpc_en:2; + bool sgi_enable; + bool vht_enable; + bool updated; + u8 init_ra_lv; + u64 ra_mask; +}; + +struct rtw_vif { + struct ieee80211_vif *vif; + enum rtw_net_type net_type; + u16 aid; + u8 mac_addr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + u8 port; + const struct rtw_vif_port *conf; + + struct rtw_traffic_stats stats; + bool in_lps; +}; + +struct rtw_regulatory { + char alpha2[2]; + u8 chplan; + u8 txpwr_regd; +}; + +struct rtw_chip_ops { + int (*mac_init)(struct rtw_dev *rtwdev); + int (*read_efuse)(struct rtw_dev *rtwdev, u8 *map); + void (*phy_set_param)(struct rtw_dev *rtwdev); + void (*set_channel)(struct rtw_dev *rtwdev, u8 channel, + u8 bandwidth, u8 primary_chan_idx); + void (*query_rx_desc)(struct rtw_dev *rtwdev, u8 *rx_desc, + struct rtw_rx_pkt_stat *pkt_stat, + struct ieee80211_rx_status *rx_status); + u32 (*read_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask); + bool (*write_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask, u32 data); + void (*set_tx_power_index)(struct rtw_dev *rtwdev); + int (*rsvd_page_dump)(struct rtw_dev *rtwdev, u8 *buf, u32 offset, + u32 size); + void (*set_antenna)(struct rtw_dev *rtwdev, u8 antenna_tx, + u8 antenna_rx); + void (*cfg_ldo25)(struct rtw_dev *rtwdev, bool enable); + void (*false_alarm_statistics)(struct rtw_dev *rtwdev); + void (*do_iqk)(struct rtw_dev *rtwdev); +}; + +#define RTW_PWR_POLLING_CNT 20000 + +#define RTW_PWR_CMD_READ 0x00 +#define RTW_PWR_CMD_WRITE 0x01 +#define RTW_PWR_CMD_POLLING 0x02 +#define RTW_PWR_CMD_DELAY 0x03 +#define RTW_PWR_CMD_END 0x04 + +/* define the base address of each block */ +#define RTW_PWR_ADDR_MAC 0x00 +#define RTW_PWR_ADDR_USB 0x01 +#define RTW_PWR_ADDR_PCIE 0x02 +#define RTW_PWR_ADDR_SDIO 0x03 + +#define RTW_PWR_INTF_SDIO_MSK BIT(0) +#define RTW_PWR_INTF_USB_MSK BIT(1) +#define RTW_PWR_INTF_PCI_MSK BIT(2) +#define RTW_PWR_INTF_ALL_MSK (BIT(0) | BIT(1) | BIT(2) | BIT(3)) + +#define RTW_PWR_CUT_A_MSK BIT(1) +#define RTW_PWR_CUT_B_MSK BIT(2) +#define RTW_PWR_CUT_C_MSK BIT(3) +#define RTW_PWR_CUT_D_MSK BIT(4) +#define RTW_PWR_CUT_E_MSK BIT(5) +#define RTW_PWR_CUT_F_MSK BIT(6) +#define RTW_PWR_CUT_G_MSK BIT(7) +#define RTW_PWR_CUT_ALL_MSK 0xFF + +enum rtw_pwr_seq_cmd_delay_unit { + RTW_PWR_DELAY_US, + RTW_PWR_DELAY_MS, +}; + +struct rtw_pwr_seq_cmd { + u16 offset; + u8 cut_mask; + u8 intf_mask; + u8 base:4; + u8 cmd:4; + u8 mask; + u8 value; +}; + +enum rtw_chip_ver { + RTW_CHIP_VER_CUT_A = 0x00, + RTW_CHIP_VER_CUT_B = 0x01, + RTW_CHIP_VER_CUT_C = 0x02, + RTW_CHIP_VER_CUT_D = 0x03, + RTW_CHIP_VER_CUT_E = 0x04, + RTW_CHIP_VER_CUT_F = 0x05, + RTW_CHIP_VER_CUT_G = 0x06, +}; + +#define RTW_INTF_PHY_PLATFORM_ALL 0 + +enum rtw_intf_phy_cut { + RTW_INTF_PHY_CUT_A = BIT(0), + RTW_INTF_PHY_CUT_B = BIT(1), + RTW_INTF_PHY_CUT_C = BIT(2), + RTW_INTF_PHY_CUT_D = BIT(3), + RTW_INTF_PHY_CUT_E = BIT(4), + RTW_INTF_PHY_CUT_F = BIT(5), + RTW_INTF_PHY_CUT_G = BIT(6), + RTW_INTF_PHY_CUT_ALL = 0xFFFF, +}; + +enum rtw_ip_sel { + RTW_IP_SEL_PHY = 0, + RTW_IP_SEL_MAC = 1, + RTW_IP_SEL_DBI = 2, + + RTW_IP_SEL_UNDEF = 0xFFFF +}; + +enum rtw_pq_map_id { + RTW_PQ_MAP_VO = 0x0, + RTW_PQ_MAP_VI = 0x1, + RTW_PQ_MAP_BE = 0x2, + RTW_PQ_MAP_BK = 0x3, + RTW_PQ_MAP_MG = 0x4, + RTW_PQ_MAP_HI = 0x5, + RTW_PQ_MAP_NUM = 0x6, + + RTW_PQ_MAP_UNDEF, +}; + +enum rtw_dma_mapping { + RTW_DMA_MAPPING_EXTRA = 0, + RTW_DMA_MAPPING_LOW = 1, + RTW_DMA_MAPPING_NORMAL = 2, + RTW_DMA_MAPPING_HIGH = 3, + + RTW_DMA_MAPPING_UNDEF, +}; + +struct rtw_rqpn { + enum rtw_dma_mapping dma_map_vo; + enum rtw_dma_mapping dma_map_vi; + enum rtw_dma_mapping dma_map_be; + enum rtw_dma_mapping dma_map_bk; + enum rtw_dma_mapping dma_map_mg; + enum rtw_dma_mapping dma_map_hi; +}; + +struct rtw_page_table { + u16 hq_num; + u16 nq_num; + u16 lq_num; + u16 exq_num; + u16 gapq_num; +}; + +struct rtw_intf_phy_para { + u16 offset; + u16 value; + u16 ip_sel; + u16 cut_mask; + u16 platform; +}; + +struct rtw_intf_phy_para_table { + struct rtw_intf_phy_para *usb2_para; + struct rtw_intf_phy_para *usb3_para; + struct rtw_intf_phy_para *gen1_para; + struct rtw_intf_phy_para *gen2_para; + u8 n_usb2_para; + u8 n_usb3_para; + u8 n_gen1_para; + u8 n_gen2_para; +}; + +struct rtw_table { + const void *data; + const u32 size; + void (*parse)(struct rtw_dev *rtwdev, const struct rtw_table *tbl); + void (*do_cfg)(struct rtw_dev *rtwdev, const struct rtw_table *tbl, + u32 addr, u32 data); + enum rtw_rf_path rf_path; +}; + +static inline void rtw_load_table(struct rtw_dev *rtwdev, + const struct rtw_table *tbl) +{ + (*tbl->parse)(rtwdev, tbl); +} + +enum rtw_rfe_fem { + RTW_RFE_IFEM, + RTW_RFE_EFEM, + RTW_RFE_IFEM2G_EFEM5G, + RTW_RFE_NUM, +}; + +struct rtw_rfe_def { + const struct rtw_table *phy_pg_tbl; + const struct rtw_table *txpwr_lmt_tbl; +}; + +#define RTW_DEF_RFE(chip, bb_pg, pwrlmt) { \ + .phy_pg_tbl = &rtw ## chip ## _bb_pg_type ## bb_pg ## _tbl, \ + .txpwr_lmt_tbl = &rtw ## chip ## _txpwr_lmt_type ## pwrlmt ## _tbl, \ + } + +/* hardware configuration for each IC */ +struct rtw_chip_info { + struct rtw_chip_ops *ops; + u8 id; + + const char *fw_name; + u8 tx_pkt_desc_sz; + u8 tx_buf_desc_sz; + u8 rx_pkt_desc_sz; + u8 rx_buf_desc_sz; + u32 phy_efuse_size; + u32 log_efuse_size; + u32 ptct_efuse_size; + u32 txff_size; + u32 rxff_size; + u8 band; + u8 page_size; + u8 csi_buf_pg_num; + u8 dig_max; + u8 dig_min; + u8 txgi_factor; + bool is_pwr_by_rate_dec; + u8 max_power_index; + + bool ht_supported; + bool vht_supported; + + /* init values */ + u8 sys_func_en; + struct rtw_pwr_seq_cmd **pwr_on_seq; + struct rtw_pwr_seq_cmd **pwr_off_seq; + struct rtw_rqpn *rqpn_table; + struct rtw_page_table *page_table; + struct rtw_intf_phy_para_table *intf_table; + + struct rtw_hw_reg *dig; + u32 rf_base_addr[2]; + u32 rf_sipi_addr[2]; + + const struct rtw_table *mac_tbl; + const struct rtw_table *agc_tbl; + const struct rtw_table *bb_tbl; + const struct rtw_table *rf_tbl[RTW_RF_PATH_MAX]; + const struct rtw_table *rfk_init_tbl; + + const struct rtw_rfe_def *rfe_defs; + u32 rfe_defs_size; +}; + +struct rtw_dm_info { + u32 cck_fa_cnt; + u32 ofdm_fa_cnt; + u32 total_fa_cnt; + u8 min_rssi; + u8 pre_min_rssi; + u16 fa_history[4]; + u8 igi_history[4]; + u8 igi_bitmap; + bool damping; + u8 damping_cnt; + u8 damping_rssi; + + u8 cck_gi_u_bnd; + u8 cck_gi_l_bnd; +}; + +struct rtw_efuse { + u32 size; + u32 physical_size; + u32 logical_size; + u32 protect_size; + + u8 addr[ETH_ALEN]; + u8 channel_plan; + u8 country_code[2]; + u8 rfe_option; + u8 thermal_meter; + u8 crystal_cap; + u8 ant_div_cfg; + u8 ant_div_type; + u8 regd; + + u8 lna_type_2g; + u8 lna_type_5g; + u8 glna_type; + u8 alna_type; + bool ext_lna_2g; + bool ext_lna_5g; + u8 pa_type_2g; + u8 pa_type_5g; + u8 gpa_type; + u8 apa_type; + bool ext_pa_2g; + bool ext_pa_5g; + + bool btcoex; + /* bt share antenna with wifi */ + bool share_ant; + u8 bt_setting; + + struct { + u8 hci; + u8 bw; + u8 ptcl; + u8 nss; + u8 ant_num; + } hw_cap; + + struct rtw_txpwr_idx txpwr_idx_table[4]; +}; + +struct rtw_phy_cond { +#ifdef __LITTLE_ENDIAN + u32 rfe:8; + u32 intf:4; + u32 pkg:4; + u32 plat:4; + u32 intf_rsvd:4; + u32 cut:4; + u32 branch:2; + u32 neg:1; + u32 pos:1; +#else + u32 pos:1; + u32 neg:1; + u32 branch:2; + u32 cut:4; + u32 intf_rsvd:4; + u32 plat:4; + u32 pkg:4; + u32 intf:4; + u32 rfe:8; +#endif + /* for intf:4 */ + #define INTF_PCIE BIT(0) + #define INTF_USB BIT(1) + #define INTF_SDIO BIT(2) + /* for branch:2 */ + #define BRANCH_IF 0 + #define BRANCH_ELIF 1 + #define BRANCH_ELSE 2 + #define BRANCH_ENDIF 3 +}; + +struct rtw_fifo_conf { + /* tx fifo information */ + u16 rsvd_boundary; + u16 rsvd_pg_num; + u16 rsvd_drv_pg_num; + u16 txff_pg_num; + u16 acq_pg_num; + u16 rsvd_drv_addr; + u16 rsvd_h2c_info_addr; + u16 rsvd_h2c_sta_info_addr; + u16 rsvd_h2cq_addr; + u16 rsvd_cpu_instr_addr; + u16 rsvd_fw_txbuf_addr; + u16 rsvd_csibuf_addr; + enum rtw_dma_mapping pq_map[RTW_PQ_MAP_NUM]; +}; + +struct rtw_fw_state { + const struct firmware *firmware; + struct completion completion; + u16 version; + u8 sub_version; + u8 sub_index; + u16 h2c_version; +}; + +struct rtw_hal { + u32 rcr; + + u32 chip_version; + u8 fab_version; + u8 cut_version; + u8 mp_chip; + u8 oem_id; + struct rtw_phy_cond phy_cond; + + u8 ps_mode; + u8 current_channel; + u8 current_band_width; + u8 current_band_type; + u8 sec_ch_offset; + u8 rf_type; + u8 rf_path_num; + u8 antenna_tx; + u8 antenna_rx; + + /* protect tx power section */ + struct mutex tx_power_mutex; + s8 tx_pwr_by_rate_offset_2g[RTW_RF_PATH_MAX] + [DESC_RATE_MAX]; + s8 tx_pwr_by_rate_offset_5g[RTW_RF_PATH_MAX] + [DESC_RATE_MAX]; + s8 tx_pwr_by_rate_base_2g[RTW_RF_PATH_MAX] + [RTW_RATE_SECTION_MAX]; + s8 tx_pwr_by_rate_base_5g[RTW_RF_PATH_MAX] + [RTW_RATE_SECTION_MAX]; + s8 tx_pwr_limit_2g[RTW_REGD_MAX] + [RTW_CHANNEL_WIDTH_MAX] + [RTW_RATE_SECTION_MAX] + [RTW_MAX_CHANNEL_NUM_2G]; + s8 tx_pwr_limit_5g[RTW_REGD_MAX] + [RTW_CHANNEL_WIDTH_MAX] + [RTW_RATE_SECTION_MAX] + [RTW_MAX_CHANNEL_NUM_5G]; + s8 tx_pwr_tbl[RTW_RF_PATH_MAX] + [DESC_RATE_MAX]; +}; + +struct rtw_dev { + struct ieee80211_hw *hw; + struct device *dev; + + struct rtw_hci hci; + + struct rtw_chip_info *chip; + struct rtw_hal hal; + struct rtw_fifo_conf fifo; + struct rtw_fw_state fw; + struct rtw_efuse efuse; + struct rtw_sec_desc sec; + struct rtw_traffic_stats stats; + struct rtw_regulatory regd; + + struct rtw_dm_info dm_info; + + /* ensures exclusive access from mac80211 callbacks */ + struct mutex mutex; + + /* lock for dm to use */ + spinlock_t dm_lock; + + /* read/write rf register */ + spinlock_t rf_lock; + + /* watch dog every 2 sec */ + struct delayed_work watch_dog_work; + u32 watch_dog_cnt; + + struct list_head rsvd_page_list; + + /* c2h cmd queue & handler work */ + struct sk_buff_head c2h_queue; + struct work_struct c2h_work; + + struct rtw_tx_report tx_report; + + struct { + /* incicate the mail box to use with fw */ + u8 last_box_num; + /* protect to send h2c to fw */ + spinlock_t lock; + u32 seq; + } h2c; + + /* lps power state & handler work */ + struct rtw_lps_conf lps_conf; + struct delayed_work lps_work; + + struct dentry *debugfs; + + u8 sta_cnt; + + DECLARE_BITMAP(mac_id_map, RTW_MAX_MAC_ID_NUM); + DECLARE_BITMAP(flags, NUM_OF_RTW_FLAGS); + + u8 mp_mode; + + /* hci related data, must be last */ + u8 priv[0] __aligned(sizeof(void *)); +}; + +#include "hci.h" + +static inline bool rtw_flag_check(struct rtw_dev *rtwdev, enum rtw_flags flag) +{ + return test_bit(flag, rtwdev->flags); +} + +static inline void rtw_flag_clear(struct rtw_dev *rtwdev, enum rtw_flags flag) +{ + clear_bit(flag, rtwdev->flags); +} + +static inline void rtw_flag_set(struct rtw_dev *rtwdev, enum rtw_flags flag) +{ + set_bit(flag, rtwdev->flags); +} + +void rtw_get_channel_params(struct cfg80211_chan_def *chandef, + struct rtw_channel_params *ch_param); +bool check_hw_ready(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target); +bool ltecoex_read_reg(struct rtw_dev *rtwdev, u16 offset, u32 *val); +bool ltecoex_reg_write(struct rtw_dev *rtwdev, u16 offset, u32 value); +void rtw_restore_reg(struct rtw_dev *rtwdev, + struct rtw_backup_info *bckp, u32 num); +void rtw_set_channel(struct rtw_dev *rtwdev); +void rtw_vif_port_config(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif, + u32 config); +void rtw_tx_report_purge_timer(struct timer_list *t); +void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); +int rtw_core_start(struct rtw_dev *rtwdev); +void rtw_core_stop(struct rtw_dev *rtwdev); +int rtw_chip_info_setup(struct rtw_dev *rtwdev); +int rtw_core_init(struct rtw_dev *rtwdev); +void rtw_core_deinit(struct rtw_dev *rtwdev); +int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw); +void rtw_unregister_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c new file mode 100644 index 000000000000..cfe05ba7280d --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -0,0 +1,1211 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include <linux/module.h> +#include <linux/pci.h> +#include "main.h" +#include "pci.h" +#include "tx.h" +#include "rx.h" +#include "debug.h" + +static u32 rtw_pci_tx_queue_idx_addr[] = { + [RTW_TX_QUEUE_BK] = RTK_PCI_TXBD_IDX_BKQ, + [RTW_TX_QUEUE_BE] = RTK_PCI_TXBD_IDX_BEQ, + [RTW_TX_QUEUE_VI] = RTK_PCI_TXBD_IDX_VIQ, + [RTW_TX_QUEUE_VO] = RTK_PCI_TXBD_IDX_VOQ, + [RTW_TX_QUEUE_MGMT] = RTK_PCI_TXBD_IDX_MGMTQ, + [RTW_TX_QUEUE_HI0] = RTK_PCI_TXBD_IDX_HI0Q, + [RTW_TX_QUEUE_H2C] = RTK_PCI_TXBD_IDX_H2CQ, +}; + +static u8 rtw_pci_get_tx_qsel(struct sk_buff *skb, u8 queue) +{ + switch (queue) { + case RTW_TX_QUEUE_BCN: + return TX_DESC_QSEL_BEACON; + case RTW_TX_QUEUE_H2C: + return TX_DESC_QSEL_H2C; + case RTW_TX_QUEUE_MGMT: + return TX_DESC_QSEL_MGMT; + case RTW_TX_QUEUE_HI0: + return TX_DESC_QSEL_HIGH; + default: + return skb->priority; + } +}; + +static u8 rtw_pci_read8(struct rtw_dev *rtwdev, u32 addr) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + + return readb(rtwpci->mmap + addr); +} + +static u16 rtw_pci_read16(struct rtw_dev *rtwdev, u32 addr) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + + return readw(rtwpci->mmap + addr); +} + +static u32 rtw_pci_read32(struct rtw_dev *rtwdev, u32 addr) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + + return readl(rtwpci->mmap + addr); +} + +static void rtw_pci_write8(struct rtw_dev *rtwdev, u32 addr, u8 val) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + + writeb(val, rtwpci->mmap + addr); +} + +static void rtw_pci_write16(struct rtw_dev *rtwdev, u32 addr, u16 val) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + + writew(val, rtwpci->mmap + addr); +} + +static void rtw_pci_write32(struct rtw_dev *rtwdev, u32 addr, u32 val) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + + writel(val, rtwpci->mmap + addr); +} + +static inline void *rtw_pci_get_tx_desc(struct rtw_pci_tx_ring *tx_ring, u8 idx) +{ + int offset = tx_ring->r.desc_size * idx; + + return tx_ring->r.head + offset; +} + +static void rtw_pci_free_tx_ring(struct rtw_dev *rtwdev, + struct rtw_pci_tx_ring *tx_ring) +{ + struct pci_dev *pdev = to_pci_dev(rtwdev->dev); + struct rtw_pci_tx_data *tx_data; + struct sk_buff *skb, *tmp; + dma_addr_t dma; + u8 *head = tx_ring->r.head; + u32 len = tx_ring->r.len; + int ring_sz = len * tx_ring->r.desc_size; + + /* free every skb remained in tx list */ + skb_queue_walk_safe(&tx_ring->queue, skb, tmp) { + __skb_unlink(skb, &tx_ring->queue); + tx_data = rtw_pci_get_tx_data(skb); + dma = tx_data->dma; + + pci_unmap_single(pdev, dma, skb->len, PCI_DMA_TODEVICE); + dev_kfree_skb_any(skb); + } + + /* free the ring itself */ + pci_free_consistent(pdev, ring_sz, head, tx_ring->r.dma); + tx_ring->r.head = NULL; +} + +static void rtw_pci_free_rx_ring(struct rtw_dev *rtwdev, + struct rtw_pci_rx_ring *rx_ring) +{ + struct pci_dev *pdev = to_pci_dev(rtwdev->dev); + struct sk_buff *skb; + dma_addr_t dma; + u8 *head = rx_ring->r.head; + int buf_sz = RTK_PCI_RX_BUF_SIZE; + int ring_sz = rx_ring->r.desc_size * rx_ring->r.len; + int i; + + for (i = 0; i < rx_ring->r.len; i++) { + skb = rx_ring->buf[i]; + if (!skb) + continue; + + dma = *((dma_addr_t *)skb->cb); + pci_unmap_single(pdev, dma, buf_sz, PCI_DMA_FROMDEVICE); + dev_kfree_skb(skb); + rx_ring->buf[i] = NULL; + } + + pci_free_consistent(pdev, ring_sz, head, rx_ring->r.dma); +} + +static void rtw_pci_free_trx_ring(struct rtw_dev *rtwdev) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + struct rtw_pci_tx_ring *tx_ring; + struct rtw_pci_rx_ring *rx_ring; + int i; + + for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++) { + tx_ring = &rtwpci->tx_rings[i]; + rtw_pci_free_tx_ring(rtwdev, tx_ring); + } + + for (i = 0; i < RTK_MAX_RX_QUEUE_NUM; i++) { + rx_ring = &rtwpci->rx_rings[i]; + rtw_pci_free_rx_ring(rtwdev, rx_ring); + } +} + +static int rtw_pci_init_tx_ring(struct rtw_dev *rtwdev, + struct rtw_pci_tx_ring *tx_ring, + u8 desc_size, u32 len) +{ + struct pci_dev *pdev = to_pci_dev(rtwdev->dev); + int ring_sz = desc_size * len; + dma_addr_t dma; + u8 *head; + + head = pci_zalloc_consistent(pdev, ring_sz, &dma); + if (!head) { + rtw_err(rtwdev, "failed to allocate tx ring\n"); + return -ENOMEM; + } + + skb_queue_head_init(&tx_ring->queue); + tx_ring->r.head = head; + tx_ring->r.dma = dma; + tx_ring->r.len = len; + tx_ring->r.desc_size = desc_size; + tx_ring->r.wp = 0; + tx_ring->r.rp = 0; + + return 0; +} + +static int rtw_pci_reset_rx_desc(struct rtw_dev *rtwdev, struct sk_buff *skb, + struct rtw_pci_rx_ring *rx_ring, + u32 idx, u32 desc_sz) +{ + struct pci_dev *pdev = to_pci_dev(rtwdev->dev); + struct rtw_pci_rx_buffer_desc *buf_desc; + int buf_sz = RTK_PCI_RX_BUF_SIZE; + dma_addr_t dma; + + if (!skb) + return -EINVAL; + + dma = pci_map_single(pdev, skb->data, buf_sz, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(pdev, dma)) + return -EBUSY; + + *((dma_addr_t *)skb->cb) = dma; + buf_desc = (struct rtw_pci_rx_buffer_desc *)(rx_ring->r.head + + idx * desc_sz); + memset(buf_desc, 0, sizeof(*buf_desc)); + buf_desc->buf_size = cpu_to_le16(RTK_PCI_RX_BUF_SIZE); + buf_desc->dma = cpu_to_le32(dma); + + return 0; +} + +static int rtw_pci_init_rx_ring(struct rtw_dev *rtwdev, + struct rtw_pci_rx_ring *rx_ring, + u8 desc_size, u32 len) +{ + struct pci_dev *pdev = to_pci_dev(rtwdev->dev); + struct sk_buff *skb = NULL; + dma_addr_t dma; + u8 *head; + int ring_sz = desc_size * len; + int buf_sz = RTK_PCI_RX_BUF_SIZE; + int i, allocated; + int ret = 0; + + head = pci_zalloc_consistent(pdev, ring_sz, &dma); + if (!head) { + rtw_err(rtwdev, "failed to allocate rx ring\n"); + return -ENOMEM; + } + rx_ring->r.head = head; + + for (i = 0; i < len; i++) { + skb = dev_alloc_skb(buf_sz); + if (!skb) { + allocated = i; + ret = -ENOMEM; + goto err_out; + } + + memset(skb->data, 0, buf_sz); + rx_ring->buf[i] = skb; + ret = rtw_pci_reset_rx_desc(rtwdev, skb, rx_ring, i, desc_size); + if (ret) { + allocated = i; + dev_kfree_skb_any(skb); + goto err_out; + } + } + + rx_ring->r.dma = dma; + rx_ring->r.len = len; + rx_ring->r.desc_size = desc_size; + rx_ring->r.wp = 0; + rx_ring->r.rp = 0; + + return 0; + +err_out: + for (i = 0; i < allocated; i++) { + skb = rx_ring->buf[i]; + if (!skb) + continue; + dma = *((dma_addr_t *)skb->cb); + pci_unmap_single(pdev, dma, buf_sz, PCI_DMA_FROMDEVICE); + dev_kfree_skb_any(skb); + rx_ring->buf[i] = NULL; + } + pci_free_consistent(pdev, ring_sz, head, dma); + + rtw_err(rtwdev, "failed to init rx buffer\n"); + + return ret; +} + +static int rtw_pci_init_trx_ring(struct rtw_dev *rtwdev) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + struct rtw_pci_tx_ring *tx_ring; + struct rtw_pci_rx_ring *rx_ring; + struct rtw_chip_info *chip = rtwdev->chip; + int i = 0, j = 0, tx_alloced = 0, rx_alloced = 0; + int tx_desc_size, rx_desc_size; + u32 len; + int ret; + + tx_desc_size = chip->tx_buf_desc_sz; + + for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++) { + tx_ring = &rtwpci->tx_rings[i]; + len = max_num_of_tx_queue(i); + ret = rtw_pci_init_tx_ring(rtwdev, tx_ring, tx_desc_size, len); + if (ret) + goto out; + } + + rx_desc_size = chip->rx_buf_desc_sz; + + for (j = 0; j < RTK_MAX_RX_QUEUE_NUM; j++) { + rx_ring = &rtwpci->rx_rings[j]; + ret = rtw_pci_init_rx_ring(rtwdev, rx_ring, rx_desc_size, + RTK_MAX_RX_DESC_NUM); + if (ret) + goto out; + } + + return 0; + +out: + tx_alloced = i; + for (i = 0; i < tx_alloced; i++) { + tx_ring = &rtwpci->tx_rings[i]; + rtw_pci_free_tx_ring(rtwdev, tx_ring); + } + + rx_alloced = j; + for (j = 0; j < rx_alloced; j++) { + rx_ring = &rtwpci->rx_rings[j]; + rtw_pci_free_rx_ring(rtwdev, rx_ring); + } + + return ret; +} + +static void rtw_pci_deinit(struct rtw_dev *rtwdev) +{ + rtw_pci_free_trx_ring(rtwdev); +} + +static int rtw_pci_init(struct rtw_dev *rtwdev) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + int ret = 0; + + rtwpci->irq_mask[0] = IMR_HIGHDOK | + IMR_MGNTDOK | + IMR_BKDOK | + IMR_BEDOK | + IMR_VIDOK | + IMR_VODOK | + IMR_ROK | + IMR_BCNDMAINT_E | + 0; + rtwpci->irq_mask[1] = IMR_TXFOVW | + 0; + rtwpci->irq_mask[3] = IMR_H2CDOK | + 0; + spin_lock_init(&rtwpci->irq_lock); + ret = rtw_pci_init_trx_ring(rtwdev); + + return ret; +} + +static void rtw_pci_reset_buf_desc(struct rtw_dev *rtwdev) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + u32 len; + u8 tmp; + dma_addr_t dma; + + tmp = rtw_read8(rtwdev, RTK_PCI_CTRL + 3); + rtw_write8(rtwdev, RTK_PCI_CTRL + 3, tmp | 0xf7); + + dma = rtwpci->tx_rings[RTW_TX_QUEUE_BCN].r.dma; + rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_BCNQ, dma); + + len = rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.len; + dma = rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.dma; + rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.rp = 0; + rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.wp = 0; + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_H2CQ, len); + rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_H2CQ, dma); + + len = rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.len; + dma = rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.dma; + rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.rp = 0; + rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.wp = 0; + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_BKQ, len); + rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_BKQ, dma); + + len = rtwpci->tx_rings[RTW_TX_QUEUE_BE].r.len; + dma = rtwpci->tx_rings[RTW_TX_QUEUE_BE].r.dma; + rtwpci->tx_rings[RTW_TX_QUEUE_BE].r.rp = 0; + rtwpci->tx_rings[RTW_TX_QUEUE_BE].r.wp = 0; + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_BEQ, len); + rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_BEQ, dma); + + len = rtwpci->tx_rings[RTW_TX_QUEUE_VO].r.len; + dma = rtwpci->tx_rings[RTW_TX_QUEUE_VO].r.dma; + rtwpci->tx_rings[RTW_TX_QUEUE_VO].r.rp = 0; + rtwpci->tx_rings[RTW_TX_QUEUE_VO].r.wp = 0; + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_VOQ, len); + rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_VOQ, dma); + + len = rtwpci->tx_rings[RTW_TX_QUEUE_VI].r.len; + dma = rtwpci->tx_rings[RTW_TX_QUEUE_VI].r.dma; + rtwpci->tx_rings[RTW_TX_QUEUE_VI].r.rp = 0; + rtwpci->tx_rings[RTW_TX_QUEUE_VI].r.wp = 0; + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_VIQ, len); + rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_VIQ, dma); + + len = rtwpci->tx_rings[RTW_TX_QUEUE_MGMT].r.len; + dma = rtwpci->tx_rings[RTW_TX_QUEUE_MGMT].r.dma; + rtwpci->tx_rings[RTW_TX_QUEUE_MGMT].r.rp = 0; + rtwpci->tx_rings[RTW_TX_QUEUE_MGMT].r.wp = 0; + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_MGMTQ, len); + rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_MGMTQ, dma); + + len = rtwpci->tx_rings[RTW_TX_QUEUE_HI0].r.len; + dma = rtwpci->tx_rings[RTW_TX_QUEUE_HI0].r.dma; + rtwpci->tx_rings[RTW_TX_QUEUE_HI0].r.rp = 0; + rtwpci->tx_rings[RTW_TX_QUEUE_HI0].r.wp = 0; + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_HI0Q, len); + rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_HI0Q, dma); + + len = rtwpci->rx_rings[RTW_RX_QUEUE_MPDU].r.len; + dma = rtwpci->rx_rings[RTW_RX_QUEUE_MPDU].r.dma; + rtwpci->rx_rings[RTW_RX_QUEUE_MPDU].r.rp = 0; + rtwpci->rx_rings[RTW_RX_QUEUE_MPDU].r.wp = 0; + rtw_write16(rtwdev, RTK_PCI_RXBD_NUM_MPDUQ, len & 0xfff); + rtw_write32(rtwdev, RTK_PCI_RXBD_DESA_MPDUQ, dma); + + /* reset read/write point */ + rtw_write32(rtwdev, RTK_PCI_TXBD_RWPTR_CLR, 0xffffffff); + + /* rest H2C Queue index */ + rtw_write32_set(rtwdev, RTK_PCI_TXBD_H2CQ_CSR, BIT_CLR_H2CQ_HOST_IDX); + rtw_write32_set(rtwdev, RTK_PCI_TXBD_H2CQ_CSR, BIT_CLR_H2CQ_HW_IDX); +} + +static void rtw_pci_reset_trx_ring(struct rtw_dev *rtwdev) +{ + rtw_pci_reset_buf_desc(rtwdev); +} + +static void rtw_pci_enable_interrupt(struct rtw_dev *rtwdev, + struct rtw_pci *rtwpci) +{ + rtw_write32(rtwdev, RTK_PCI_HIMR0, rtwpci->irq_mask[0]); + rtw_write32(rtwdev, RTK_PCI_HIMR1, rtwpci->irq_mask[1]); + rtw_write32(rtwdev, RTK_PCI_HIMR3, rtwpci->irq_mask[3]); + rtwpci->irq_enabled = true; +} + +static void rtw_pci_disable_interrupt(struct rtw_dev *rtwdev, + struct rtw_pci *rtwpci) +{ + rtw_write32(rtwdev, RTK_PCI_HIMR0, 0); + rtw_write32(rtwdev, RTK_PCI_HIMR1, 0); + rtw_write32(rtwdev, RTK_PCI_HIMR3, 0); + rtwpci->irq_enabled = false; +} + +static int rtw_pci_setup(struct rtw_dev *rtwdev) +{ + rtw_pci_reset_trx_ring(rtwdev); + + return 0; +} + +static void rtw_pci_dma_reset(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci) +{ + /* reset dma and rx tag */ + rtw_write32_set(rtwdev, RTK_PCI_CTRL, + BIT_RST_TRXDMA_INTF | BIT_RX_TAG_EN); + rtwpci->rx_tag = 0; +} + +static int rtw_pci_start(struct rtw_dev *rtwdev) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + unsigned long flags; + + rtw_pci_dma_reset(rtwdev, rtwpci); + + spin_lock_irqsave(&rtwpci->irq_lock, flags); + rtw_pci_enable_interrupt(rtwdev, rtwpci); + spin_unlock_irqrestore(&rtwpci->irq_lock, flags); + + return 0; +} + +static void rtw_pci_stop(struct rtw_dev *rtwdev) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + unsigned long flags; + + spin_lock_irqsave(&rtwpci->irq_lock, flags); + rtw_pci_disable_interrupt(rtwdev, rtwpci); + spin_unlock_irqrestore(&rtwpci->irq_lock, flags); +} + +static u8 ac_to_hwq[] = { + [0] = RTW_TX_QUEUE_VO, + [1] = RTW_TX_QUEUE_VI, + [2] = RTW_TX_QUEUE_BE, + [3] = RTW_TX_QUEUE_BK, +}; + +static u8 rtw_hw_queue_mapping(struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + __le16 fc = hdr->frame_control; + u8 q_mapping = skb_get_queue_mapping(skb); + u8 queue; + + if (unlikely(ieee80211_is_beacon(fc))) + queue = RTW_TX_QUEUE_BCN; + else if (unlikely(ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))) + queue = RTW_TX_QUEUE_MGMT; + else + queue = ac_to_hwq[q_mapping]; + + return queue; +} + +static void rtw_pci_release_rsvd_page(struct rtw_pci *rtwpci, + struct rtw_pci_tx_ring *ring) +{ + struct sk_buff *prev = skb_dequeue(&ring->queue); + struct rtw_pci_tx_data *tx_data; + dma_addr_t dma; + + if (!prev) + return; + + tx_data = rtw_pci_get_tx_data(prev); + dma = tx_data->dma; + pci_unmap_single(rtwpci->pdev, dma, prev->len, + PCI_DMA_TODEVICE); + dev_kfree_skb_any(prev); +} + +static void rtw_pci_dma_check(struct rtw_dev *rtwdev, + struct rtw_pci_rx_ring *rx_ring, + u32 idx) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_pci_rx_buffer_desc *buf_desc; + u32 desc_sz = chip->rx_buf_desc_sz; + u16 total_pkt_size; + + buf_desc = (struct rtw_pci_rx_buffer_desc *)(rx_ring->r.head + + idx * desc_sz); + total_pkt_size = le16_to_cpu(buf_desc->total_pkt_size); + + /* rx tag mismatch, throw a warning */ + if (total_pkt_size != rtwpci->rx_tag) + rtw_warn(rtwdev, "pci bus timeout, check dma status\n"); + + rtwpci->rx_tag = (rtwpci->rx_tag + 1) % RX_TAG_MAX; +} + +static int rtw_pci_xmit(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct sk_buff *skb, u8 queue) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_pci_tx_ring *ring; + struct rtw_pci_tx_data *tx_data; + dma_addr_t dma; + u32 tx_pkt_desc_sz = chip->tx_pkt_desc_sz; + u32 tx_buf_desc_sz = chip->tx_buf_desc_sz; + u32 size; + u32 psb_len; + u8 *pkt_desc; + struct rtw_pci_tx_buffer_desc *buf_desc; + u32 bd_idx; + + ring = &rtwpci->tx_rings[queue]; + + size = skb->len; + + if (queue == RTW_TX_QUEUE_BCN) + rtw_pci_release_rsvd_page(rtwpci, ring); + else if (!avail_desc(ring->r.wp, ring->r.rp, ring->r.len)) + return -ENOSPC; + + pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz); + memset(pkt_desc, 0, tx_pkt_desc_sz); + pkt_info->qsel = rtw_pci_get_tx_qsel(skb, queue); + rtw_tx_fill_tx_desc(pkt_info, skb); + dma = pci_map_single(rtwpci->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(rtwpci->pdev, dma)) + return -EBUSY; + + /* after this we got dma mapped, there is no way back */ + buf_desc = get_tx_buffer_desc(ring, tx_buf_desc_sz); + memset(buf_desc, 0, tx_buf_desc_sz); + psb_len = (skb->len - 1) / 128 + 1; + if (queue == RTW_TX_QUEUE_BCN) + psb_len |= 1 << RTK_PCI_TXBD_OWN_OFFSET; + + buf_desc[0].psb_len = cpu_to_le16(psb_len); + buf_desc[0].buf_size = cpu_to_le16(tx_pkt_desc_sz); + buf_desc[0].dma = cpu_to_le32(dma); + buf_desc[1].buf_size = cpu_to_le16(size); + buf_desc[1].dma = cpu_to_le32(dma + tx_pkt_desc_sz); + + tx_data = rtw_pci_get_tx_data(skb); + tx_data->dma = dma; + tx_data->sn = pkt_info->sn; + skb_queue_tail(&ring->queue, skb); + + /* kick off tx queue */ + if (queue != RTW_TX_QUEUE_BCN) { + if (++ring->r.wp >= ring->r.len) + ring->r.wp = 0; + bd_idx = rtw_pci_tx_queue_idx_addr[queue]; + rtw_write16(rtwdev, bd_idx, ring->r.wp & 0xfff); + } else { + u32 reg_bcn_work; + + reg_bcn_work = rtw_read8(rtwdev, RTK_PCI_TXBD_BCN_WORK); + reg_bcn_work |= BIT_PCI_BCNQ_FLAG; + rtw_write8(rtwdev, RTK_PCI_TXBD_BCN_WORK, reg_bcn_work); + } + + return 0; +} + +static int rtw_pci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, + u32 size) +{ + struct sk_buff *skb; + struct rtw_tx_pkt_info pkt_info; + u32 tx_pkt_desc_sz; + u32 length; + + tx_pkt_desc_sz = rtwdev->chip->tx_pkt_desc_sz; + length = size + tx_pkt_desc_sz; + skb = dev_alloc_skb(length); + if (!skb) + return -ENOMEM; + + skb_reserve(skb, tx_pkt_desc_sz); + memcpy((u8 *)skb_put(skb, size), buf, size); + memset(&pkt_info, 0, sizeof(pkt_info)); + pkt_info.tx_pkt_size = size; + pkt_info.offset = tx_pkt_desc_sz; + + return rtw_pci_xmit(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_BCN); +} + +static int rtw_pci_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size) +{ + struct sk_buff *skb; + struct rtw_tx_pkt_info pkt_info; + u32 tx_pkt_desc_sz; + u32 length; + + tx_pkt_desc_sz = rtwdev->chip->tx_pkt_desc_sz; + length = size + tx_pkt_desc_sz; + skb = dev_alloc_skb(length); + if (!skb) + return -ENOMEM; + + skb_reserve(skb, tx_pkt_desc_sz); + memcpy((u8 *)skb_put(skb, size), buf, size); + memset(&pkt_info, 0, sizeof(pkt_info)); + pkt_info.tx_pkt_size = size; + + return rtw_pci_xmit(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_H2C); +} + +static int rtw_pci_tx(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct sk_buff *skb) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + struct rtw_pci_tx_ring *ring; + u8 queue = rtw_hw_queue_mapping(skb); + int ret; + + ret = rtw_pci_xmit(rtwdev, pkt_info, skb, queue); + if (ret) + return ret; + + ring = &rtwpci->tx_rings[queue]; + if (avail_desc(ring->r.wp, ring->r.rp, ring->r.len) < 2) { + ieee80211_stop_queue(rtwdev->hw, skb_get_queue_mapping(skb)); + ring->queue_stopped = true; + } + + return 0; +} + +static void rtw_pci_tx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, + u8 hw_queue) +{ + struct ieee80211_hw *hw = rtwdev->hw; + struct ieee80211_tx_info *info; + struct rtw_pci_tx_ring *ring; + struct rtw_pci_tx_data *tx_data; + struct sk_buff *skb; + u32 count; + u32 bd_idx_addr; + u32 bd_idx, cur_rp; + u16 q_map; + + ring = &rtwpci->tx_rings[hw_queue]; + + bd_idx_addr = rtw_pci_tx_queue_idx_addr[hw_queue]; + bd_idx = rtw_read32(rtwdev, bd_idx_addr); + cur_rp = bd_idx >> 16; + cur_rp &= 0xfff; + if (cur_rp >= ring->r.rp) + count = cur_rp - ring->r.rp; + else + count = ring->r.len - (ring->r.rp - cur_rp); + + while (count--) { + skb = skb_dequeue(&ring->queue); + tx_data = rtw_pci_get_tx_data(skb); + pci_unmap_single(rtwpci->pdev, tx_data->dma, skb->len, + PCI_DMA_TODEVICE); + + /* just free command packets from host to card */ + if (hw_queue == RTW_TX_QUEUE_H2C) { + dev_kfree_skb_irq(skb); + continue; + } + + if (ring->queue_stopped && + avail_desc(ring->r.wp, ring->r.rp, ring->r.len) > 4) { + q_map = skb_get_queue_mapping(skb); + ieee80211_wake_queue(hw, q_map); + ring->queue_stopped = false; + } + + skb_pull(skb, rtwdev->chip->tx_pkt_desc_sz); + + info = IEEE80211_SKB_CB(skb); + + /* enqueue to wait for tx report */ + if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) { + rtw_tx_report_enqueue(rtwdev, skb, tx_data->sn); + continue; + } + + /* always ACK for others, then they won't be marked as drop */ + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; + else + info->flags |= IEEE80211_TX_STAT_ACK; + + ieee80211_tx_info_clear_status(info); + ieee80211_tx_status_irqsafe(hw, skb); + } + + ring->r.rp = cur_rp; +} + +static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, + u8 hw_queue) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_pci_rx_ring *ring; + struct rtw_rx_pkt_stat pkt_stat; + struct ieee80211_rx_status rx_status; + struct sk_buff *skb, *new; + u32 cur_wp, cur_rp, tmp; + u32 count; + u32 pkt_offset; + u32 pkt_desc_sz = chip->rx_pkt_desc_sz; + u32 buf_desc_sz = chip->rx_buf_desc_sz; + u8 *rx_desc; + dma_addr_t dma; + + ring = &rtwpci->rx_rings[RTW_RX_QUEUE_MPDU]; + + tmp = rtw_read32(rtwdev, RTK_PCI_RXBD_IDX_MPDUQ); + cur_wp = tmp >> 16; + cur_wp &= 0xfff; + if (cur_wp >= ring->r.wp) + count = cur_wp - ring->r.wp; + else + count = ring->r.len - (ring->r.wp - cur_wp); + + cur_rp = ring->r.rp; + while (count--) { + rtw_pci_dma_check(rtwdev, ring, cur_rp); + skb = ring->buf[cur_rp]; + dma = *((dma_addr_t *)skb->cb); + pci_unmap_single(rtwpci->pdev, dma, RTK_PCI_RX_BUF_SIZE, + PCI_DMA_FROMDEVICE); + rx_desc = skb->data; + chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status); + + /* offset from rx_desc to payload */ + pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz + + pkt_stat.shift; + + if (pkt_stat.is_c2h) { + /* keep rx_desc, halmac needs it */ + skb_put(skb, pkt_stat.pkt_len + pkt_offset); + + /* pass offset for further operation */ + *((u32 *)skb->cb) = pkt_offset; + skb_queue_tail(&rtwdev->c2h_queue, skb); + ieee80211_queue_work(rtwdev->hw, &rtwdev->c2h_work); + } else { + /* remove rx_desc, maybe use skb_pull? */ + skb_put(skb, pkt_stat.pkt_len); + skb_reserve(skb, pkt_offset); + + /* alloc a smaller skb to mac80211 */ + new = dev_alloc_skb(pkt_stat.pkt_len); + if (!new) { + new = skb; + } else { + skb_put_data(new, skb->data, skb->len); + dev_kfree_skb_any(skb); + } + /* TODO: merge into rx.c */ + rtw_rx_stats(rtwdev, pkt_stat.vif, skb); + memcpy(new->cb, &rx_status, sizeof(rx_status)); + ieee80211_rx_irqsafe(rtwdev->hw, new); + } + + /* skb delivered to mac80211, alloc a new one in rx ring */ + new = dev_alloc_skb(RTK_PCI_RX_BUF_SIZE); + if (WARN(!new, "rx routine starvation\n")) + return; + + ring->buf[cur_rp] = new; + rtw_pci_reset_rx_desc(rtwdev, new, ring, cur_rp, buf_desc_sz); + + /* host read next element in ring */ + if (++cur_rp >= ring->r.len) + cur_rp = 0; + } + + ring->r.rp = cur_rp; + ring->r.wp = cur_wp; + rtw_write16(rtwdev, RTK_PCI_RXBD_IDX_MPDUQ, ring->r.rp); +} + +static void rtw_pci_irq_recognized(struct rtw_dev *rtwdev, + struct rtw_pci *rtwpci, u32 *irq_status) +{ + irq_status[0] = rtw_read32(rtwdev, RTK_PCI_HISR0); + irq_status[1] = rtw_read32(rtwdev, RTK_PCI_HISR1); + irq_status[3] = rtw_read32(rtwdev, RTK_PCI_HISR3); + irq_status[0] &= rtwpci->irq_mask[0]; + irq_status[1] &= rtwpci->irq_mask[1]; + irq_status[3] &= rtwpci->irq_mask[3]; + rtw_write32(rtwdev, RTK_PCI_HISR0, irq_status[0]); + rtw_write32(rtwdev, RTK_PCI_HISR1, irq_status[1]); + rtw_write32(rtwdev, RTK_PCI_HISR3, irq_status[3]); +} + +static irqreturn_t rtw_pci_interrupt_handler(int irq, void *dev) +{ + struct rtw_dev *rtwdev = dev; + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + u32 irq_status[4]; + + spin_lock(&rtwpci->irq_lock); + if (!rtwpci->irq_enabled) + goto out; + + rtw_pci_irq_recognized(rtwdev, rtwpci, irq_status); + + if (irq_status[0] & IMR_MGNTDOK) + rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_MGMT); + if (irq_status[0] & IMR_HIGHDOK) + rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_HI0); + if (irq_status[0] & IMR_BEDOK) + rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_BE); + if (irq_status[0] & IMR_BKDOK) + rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_BK); + if (irq_status[0] & IMR_VODOK) + rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_VO); + if (irq_status[0] & IMR_VIDOK) + rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_VI); + if (irq_status[3] & IMR_H2CDOK) + rtw_pci_tx_isr(rtwdev, rtwpci, RTW_TX_QUEUE_H2C); + if (irq_status[0] & IMR_ROK) + rtw_pci_rx_isr(rtwdev, rtwpci, RTW_RX_QUEUE_MPDU); + +out: + spin_unlock(&rtwpci->irq_lock); + + return IRQ_HANDLED; +} + +static int rtw_pci_io_mapping(struct rtw_dev *rtwdev, + struct pci_dev *pdev) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + unsigned long len; + u8 bar_id = 2; + int ret; + + ret = pci_request_regions(pdev, KBUILD_MODNAME); + if (ret) { + rtw_err(rtwdev, "failed to request pci regions\n"); + return ret; + } + + len = pci_resource_len(pdev, bar_id); + rtwpci->mmap = pci_iomap(pdev, bar_id, len); + if (!rtwpci->mmap) { + rtw_err(rtwdev, "failed to map pci memory\n"); + return -ENOMEM; + } + + return 0; +} + +static void rtw_pci_io_unmapping(struct rtw_dev *rtwdev, + struct pci_dev *pdev) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + + if (rtwpci->mmap) { + pci_iounmap(pdev, rtwpci->mmap); + pci_release_regions(pdev); + } +} + +static void rtw_dbi_write8(struct rtw_dev *rtwdev, u16 addr, u8 data) +{ + u16 write_addr; + u16 remainder = addr & 0x3; + u8 flag; + u8 cnt = 20; + + write_addr = ((addr & 0x0ffc) | (BIT(0) << (remainder + 12))); + rtw_write8(rtwdev, REG_DBI_WDATA_V1 + remainder, data); + rtw_write16(rtwdev, REG_DBI_FLAG_V1, write_addr); + rtw_write8(rtwdev, REG_DBI_FLAG_V1 + 2, 0x01); + + flag = rtw_read8(rtwdev, REG_DBI_FLAG_V1 + 2); + while (flag && (cnt != 0)) { + udelay(10); + flag = rtw_read8(rtwdev, REG_DBI_FLAG_V1 + 2); + cnt--; + } + + WARN(flag, "DBI write fail\n"); +} + +static void rtw_mdio_write(struct rtw_dev *rtwdev, u8 addr, u16 data, bool g1) +{ + u8 page; + u8 wflag; + u8 cnt; + + rtw_write16(rtwdev, REG_MDIO_V1, data); + + page = addr < 0x20 ? 0 : 1; + page += g1 ? 0 : 2; + rtw_write8(rtwdev, REG_PCIE_MIX_CFG, addr & 0x1f); + rtw_write8(rtwdev, REG_PCIE_MIX_CFG + 3, page); + + rtw_write32_mask(rtwdev, REG_PCIE_MIX_CFG, BIT_MDIO_WFLAG_V1, 1); + wflag = rtw_read32_mask(rtwdev, REG_PCIE_MIX_CFG, BIT_MDIO_WFLAG_V1); + + cnt = 20; + while (wflag && (cnt != 0)) { + udelay(10); + wflag = rtw_read32_mask(rtwdev, REG_PCIE_MIX_CFG, + BIT_MDIO_WFLAG_V1); + cnt--; + } + + WARN(wflag, "MDIO write fail\n"); +} + +static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_intf_phy_para *para; + u16 cut; + u16 value; + u16 offset; + u16 ip_sel; + int i; + + cut = BIT(0) << rtwdev->hal.cut_version; + + for (i = 0; i < chip->intf_table->n_gen1_para; i++) { + para = &chip->intf_table->gen1_para[i]; + if (!(para->cut_mask & cut)) + continue; + if (para->offset == 0xffff) + break; + offset = para->offset; + value = para->value; + ip_sel = para->ip_sel; + if (para->ip_sel == RTW_IP_SEL_PHY) + rtw_mdio_write(rtwdev, offset, value, true); + else + rtw_dbi_write8(rtwdev, offset, value); + } + + for (i = 0; i < chip->intf_table->n_gen2_para; i++) { + para = &chip->intf_table->gen2_para[i]; + if (!(para->cut_mask & cut)) + continue; + if (para->offset == 0xffff) + break; + offset = para->offset; + value = para->value; + ip_sel = para->ip_sel; + if (para->ip_sel == RTW_IP_SEL_PHY) + rtw_mdio_write(rtwdev, offset, value, false); + else + rtw_dbi_write8(rtwdev, offset, value); + } +} + +static int rtw_pci_claim(struct rtw_dev *rtwdev, struct pci_dev *pdev) +{ + int ret; + + ret = pci_enable_device(pdev); + if (ret) { + rtw_err(rtwdev, "failed to enable pci device\n"); + return ret; + } + + pci_set_master(pdev); + pci_set_drvdata(pdev, rtwdev->hw); + SET_IEEE80211_DEV(rtwdev->hw, &pdev->dev); + + return 0; +} + +static void rtw_pci_declaim(struct rtw_dev *rtwdev, struct pci_dev *pdev) +{ + pci_clear_master(pdev); + pci_disable_device(pdev); +} + +static int rtw_pci_setup_resource(struct rtw_dev *rtwdev, struct pci_dev *pdev) +{ + struct rtw_pci *rtwpci; + int ret; + + rtwpci = (struct rtw_pci *)rtwdev->priv; + rtwpci->pdev = pdev; + + /* after this driver can access to hw registers */ + ret = rtw_pci_io_mapping(rtwdev, pdev); + if (ret) { + rtw_err(rtwdev, "failed to request pci io region\n"); + goto err_out; + } + + ret = rtw_pci_init(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to allocate pci resources\n"); + goto err_io_unmap; + } + + rtw_pci_phy_cfg(rtwdev); + + return 0; + +err_io_unmap: + rtw_pci_io_unmapping(rtwdev, pdev); + +err_out: + return ret; +} + +static void rtw_pci_destroy(struct rtw_dev *rtwdev, struct pci_dev *pdev) +{ + rtw_pci_deinit(rtwdev); + rtw_pci_io_unmapping(rtwdev, pdev); +} + +static struct rtw_hci_ops rtw_pci_ops = { + .tx = rtw_pci_tx, + .setup = rtw_pci_setup, + .start = rtw_pci_start, + .stop = rtw_pci_stop, + + .read8 = rtw_pci_read8, + .read16 = rtw_pci_read16, + .read32 = rtw_pci_read32, + .write8 = rtw_pci_write8, + .write16 = rtw_pci_write16, + .write32 = rtw_pci_write32, + .write_data_rsvd_page = rtw_pci_write_data_rsvd_page, + .write_data_h2c = rtw_pci_write_data_h2c, +}; + +static int rtw_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct ieee80211_hw *hw; + struct rtw_dev *rtwdev; + int drv_data_size; + int ret; + + drv_data_size = sizeof(struct rtw_dev) + sizeof(struct rtw_pci); + hw = ieee80211_alloc_hw(drv_data_size, &rtw_ops); + if (!hw) { + dev_err(&pdev->dev, "failed to allocate hw\n"); + return -ENOMEM; + } + + rtwdev = hw->priv; + rtwdev->hw = hw; + rtwdev->dev = &pdev->dev; + rtwdev->chip = (struct rtw_chip_info *)id->driver_data; + rtwdev->hci.ops = &rtw_pci_ops; + rtwdev->hci.type = RTW_HCI_TYPE_PCIE; + + ret = rtw_core_init(rtwdev); + if (ret) + goto err_release_hw; + + rtw_dbg(rtwdev, RTW_DBG_PCI, + "rtw88 pci probe: vendor=0x%4.04X device=0x%4.04X rev=%d\n", + pdev->vendor, pdev->device, pdev->revision); + + ret = rtw_pci_claim(rtwdev, pdev); + if (ret) { + rtw_err(rtwdev, "failed to claim pci device\n"); + goto err_deinit_core; + } + + ret = rtw_pci_setup_resource(rtwdev, pdev); + if (ret) { + rtw_err(rtwdev, "failed to setup pci resources\n"); + goto err_pci_declaim; + } + + ret = rtw_chip_info_setup(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to setup chip information\n"); + goto err_destroy_pci; + } + + ret = rtw_register_hw(rtwdev, hw); + if (ret) { + rtw_err(rtwdev, "failed to register hw\n"); + goto err_destroy_pci; + } + + ret = request_irq(pdev->irq, &rtw_pci_interrupt_handler, + IRQF_SHARED, KBUILD_MODNAME, rtwdev); + if (ret) { + ieee80211_unregister_hw(hw); + goto err_destroy_pci; + } + + return 0; + +err_destroy_pci: + rtw_pci_destroy(rtwdev, pdev); + +err_pci_declaim: + rtw_pci_declaim(rtwdev, pdev); + +err_deinit_core: + rtw_core_deinit(rtwdev); + +err_release_hw: + ieee80211_free_hw(hw); + + return ret; +} + +static void rtw_pci_remove(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct rtw_dev *rtwdev; + struct rtw_pci *rtwpci; + + if (!hw) + return; + + rtwdev = hw->priv; + rtwpci = (struct rtw_pci *)rtwdev->priv; + + rtw_unregister_hw(rtwdev, hw); + rtw_pci_disable_interrupt(rtwdev, rtwpci); + rtw_pci_destroy(rtwdev, pdev); + rtw_pci_declaim(rtwdev, pdev); + free_irq(rtwpci->pdev->irq, rtwdev); + rtw_core_deinit(rtwdev); + ieee80211_free_hw(hw); +} + +static const struct pci_device_id rtw_pci_id_table[] = { +#ifdef CONFIG_RTW88_8822BE + { RTK_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xB822, rtw8822b_hw_spec) }, +#endif +#ifdef CONFIG_RTW88_8822CE + { RTK_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xC822, rtw8822c_hw_spec) }, +#endif + {}, +}; +MODULE_DEVICE_TABLE(pci, rtw_pci_id_table); + +static struct pci_driver rtw_pci_driver = { + .name = "rtw_pci", + .id_table = rtw_pci_id_table, + .probe = rtw_pci_probe, + .remove = rtw_pci_remove, +}; +module_pci_driver(rtw_pci_driver); + +MODULE_AUTHOR("Realtek Corporation"); +MODULE_DESCRIPTION("Realtek 802.11ac wireless PCI driver"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/realtek/rtw88/pci.h b/drivers/net/wireless/realtek/rtw88/pci.h new file mode 100644 index 000000000000..87824a4caba9 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/pci.h @@ -0,0 +1,237 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTK_PCI_H_ +#define __RTK_PCI_H_ + +#define RTK_PCI_DEVICE(vend, dev, hw_config) \ + PCI_DEVICE(vend, dev), \ + .driver_data = (kernel_ulong_t)&(hw_config), + +#define RTK_DEFAULT_TX_DESC_NUM 128 +#define RTK_BEQ_TX_DESC_NUM 256 + +#define RTK_MAX_RX_DESC_NUM 512 +/* 8K + rx desc size */ +#define RTK_PCI_RX_BUF_SIZE (8192 + 24) + +#define RTK_PCI_CTRL 0x300 +#define BIT_RST_TRXDMA_INTF BIT(20) +#define BIT_RX_TAG_EN BIT(15) +#define REG_DBI_WDATA_V1 0x03E8 +#define REG_DBI_FLAG_V1 0x03F0 +#define REG_MDIO_V1 0x03F4 +#define REG_PCIE_MIX_CFG 0x03F8 +#define BIT_MDIO_WFLAG_V1 BIT(5) + +#define BIT_PCI_BCNQ_FLAG BIT(4) +#define RTK_PCI_TXBD_DESA_BCNQ 0x308 +#define RTK_PCI_TXBD_DESA_H2CQ 0x1320 +#define RTK_PCI_TXBD_DESA_MGMTQ 0x310 +#define RTK_PCI_TXBD_DESA_BKQ 0x330 +#define RTK_PCI_TXBD_DESA_BEQ 0x328 +#define RTK_PCI_TXBD_DESA_VIQ 0x320 +#define RTK_PCI_TXBD_DESA_VOQ 0x318 +#define RTK_PCI_TXBD_DESA_HI0Q 0x340 +#define RTK_PCI_RXBD_DESA_MPDUQ 0x338 + +/* BCNQ is specialized for rsvd page, does not need to specify a number */ +#define RTK_PCI_TXBD_NUM_H2CQ 0x1328 +#define RTK_PCI_TXBD_NUM_MGMTQ 0x380 +#define RTK_PCI_TXBD_NUM_BKQ 0x38A +#define RTK_PCI_TXBD_NUM_BEQ 0x388 +#define RTK_PCI_TXBD_NUM_VIQ 0x386 +#define RTK_PCI_TXBD_NUM_VOQ 0x384 +#define RTK_PCI_TXBD_NUM_HI0Q 0x38C +#define RTK_PCI_RXBD_NUM_MPDUQ 0x382 +#define RTK_PCI_TXBD_IDX_H2CQ 0x132C +#define RTK_PCI_TXBD_IDX_MGMTQ 0x3B0 +#define RTK_PCI_TXBD_IDX_BKQ 0x3AC +#define RTK_PCI_TXBD_IDX_BEQ 0x3A8 +#define RTK_PCI_TXBD_IDX_VIQ 0x3A4 +#define RTK_PCI_TXBD_IDX_VOQ 0x3A0 +#define RTK_PCI_TXBD_IDX_HI0Q 0x3B8 +#define RTK_PCI_RXBD_IDX_MPDUQ 0x3B4 + +#define RTK_PCI_TXBD_RWPTR_CLR 0x39C +#define RTK_PCI_TXBD_H2CQ_CSR 0x1330 + +#define BIT_CLR_H2CQ_HOST_IDX BIT(16) +#define BIT_CLR_H2CQ_HW_IDX BIT(8) + +#define RTK_PCI_HIMR0 0x0B0 +#define RTK_PCI_HISR0 0x0B4 +#define RTK_PCI_HIMR1 0x0B8 +#define RTK_PCI_HISR1 0x0BC +#define RTK_PCI_HIMR2 0x10B0 +#define RTK_PCI_HISR2 0x10B4 +#define RTK_PCI_HIMR3 0x10B8 +#define RTK_PCI_HISR3 0x10BC +/* IMR 0 */ +#define IMR_TIMER2 BIT(31) +#define IMR_TIMER1 BIT(30) +#define IMR_PSTIMEOUT BIT(29) +#define IMR_GTINT4 BIT(28) +#define IMR_GTINT3 BIT(27) +#define IMR_TBDER BIT(26) +#define IMR_TBDOK BIT(25) +#define IMR_TSF_BIT32_TOGGLE BIT(24) +#define IMR_BCNDMAINT0 BIT(20) +#define IMR_BCNDOK0 BIT(16) +#define IMR_HSISR_IND_ON_INT BIT(15) +#define IMR_BCNDMAINT_E BIT(14) +#define IMR_ATIMEND BIT(12) +#define IMR_HISR1_IND_INT BIT(11) +#define IMR_C2HCMD BIT(10) +#define IMR_CPWM2 BIT(9) +#define IMR_CPWM BIT(8) +#define IMR_HIGHDOK BIT(7) +#define IMR_MGNTDOK BIT(6) +#define IMR_BKDOK BIT(5) +#define IMR_BEDOK BIT(4) +#define IMR_VIDOK BIT(3) +#define IMR_VODOK BIT(2) +#define IMR_RDU BIT(1) +#define IMR_ROK BIT(0) +/* IMR 1 */ +#define IMR_TXFIFO_TH_INT BIT(30) +#define IMR_BTON_STS_UPDATE BIT(29) +#define IMR_MCUERR BIT(28) +#define IMR_BCNDMAINT7 BIT(27) +#define IMR_BCNDMAINT6 BIT(26) +#define IMR_BCNDMAINT5 BIT(25) +#define IMR_BCNDMAINT4 BIT(24) +#define IMR_BCNDMAINT3 BIT(23) +#define IMR_BCNDMAINT2 BIT(22) +#define IMR_BCNDMAINT1 BIT(21) +#define IMR_BCNDOK7 BIT(20) +#define IMR_BCNDOK6 BIT(19) +#define IMR_BCNDOK5 BIT(18) +#define IMR_BCNDOK4 BIT(17) +#define IMR_BCNDOK3 BIT(16) +#define IMR_BCNDOK2 BIT(15) +#define IMR_BCNDOK1 BIT(14) +#define IMR_ATIMEND_E BIT(13) +#define IMR_ATIMEND BIT(12) +#define IMR_TXERR BIT(11) +#define IMR_RXERR BIT(10) +#define IMR_TXFOVW BIT(9) +#define IMR_RXFOVW BIT(8) +#define IMR_CPU_MGQ_TXDONE BIT(5) +#define IMR_PS_TIMER_C BIT(4) +#define IMR_PS_TIMER_B BIT(3) +#define IMR_PS_TIMER_A BIT(2) +#define IMR_CPUMGQ_TX_TIMER BIT(1) +/* IMR 3 */ +#define IMR_H2CDOK BIT(16) + +/* one element is reserved to know if the ring is closed */ +static inline int avail_desc(u32 wp, u32 rp, u32 len) +{ + if (rp > wp) + return rp - wp - 1; + else + return len - wp + rp - 1; +} + +#define RTK_PCI_TXBD_OWN_OFFSET 15 +#define RTK_PCI_TXBD_BCN_WORK 0x383 + +struct rtw_pci_tx_buffer_desc { + __le16 buf_size; + __le16 psb_len; + __le32 dma; +}; + +struct rtw_pci_tx_data { + dma_addr_t dma; + u8 sn; +}; + +struct rtw_pci_ring { + u8 *head; + dma_addr_t dma; + + u8 desc_size; + + u32 len; + u32 wp; + u32 rp; +}; + +struct rtw_pci_tx_ring { + struct rtw_pci_ring r; + struct sk_buff_head queue; + bool queue_stopped; +}; + +struct rtw_pci_rx_buffer_desc { + __le16 buf_size; + __le16 total_pkt_size; + __le32 dma; +}; + +struct rtw_pci_rx_ring { + struct rtw_pci_ring r; + struct sk_buff *buf[RTK_MAX_RX_DESC_NUM]; +}; + +#define RX_TAG_MAX 8192 + +struct rtw_pci { + struct pci_dev *pdev; + + /* used for pci interrupt */ + spinlock_t irq_lock; + u32 irq_mask[4]; + bool irq_enabled; + + u16 rx_tag; + struct rtw_pci_tx_ring tx_rings[RTK_MAX_TX_QUEUE_NUM]; + struct rtw_pci_rx_ring rx_rings[RTK_MAX_RX_QUEUE_NUM]; + + void __iomem *mmap; +}; + +static u32 max_num_of_tx_queue(u8 queue) +{ + u32 max_num; + + switch (queue) { + case RTW_TX_QUEUE_BE: + max_num = RTK_BEQ_TX_DESC_NUM; + break; + case RTW_TX_QUEUE_BCN: + max_num = 1; + break; + default: + max_num = RTK_DEFAULT_TX_DESC_NUM; + break; + } + + return max_num; +} + +static inline struct +rtw_pci_tx_data *rtw_pci_get_tx_data(struct sk_buff *skb) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + + BUILD_BUG_ON(sizeof(struct rtw_pci_tx_data) > + sizeof(info->status.status_driver_data)); + + return (struct rtw_pci_tx_data *)info->status.status_driver_data; +} + +static inline +struct rtw_pci_tx_buffer_desc *get_tx_buffer_desc(struct rtw_pci_tx_ring *ring, + u32 size) +{ + u8 *buf_desc; + + buf_desc = ring->r.head + ring->r.wp * size; + return (struct rtw_pci_tx_buffer_desc *)buf_desc; +} + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c new file mode 100644 index 000000000000..4381b360b5b5 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -0,0 +1,1727 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include <linux/bcd.h> + +#include "main.h" +#include "reg.h" +#include "fw.h" +#include "phy.h" +#include "debug.h" + +struct phy_cfg_pair { + u32 addr; + u32 data; +}; + +union phy_table_tile { + struct rtw_phy_cond cond; + struct phy_cfg_pair cfg; +}; + +struct phy_pg_cfg_pair { + u32 band; + u32 rf_path; + u32 tx_num; + u32 addr; + u32 bitmask; + u32 data; +}; + +struct txpwr_lmt_cfg_pair { + u8 regd; + u8 band; + u8 bw; + u8 rs; + u8 ch; + s8 txpwr_lmt; +}; + +static const u32 db_invert_table[12][8] = { + {10, 13, 16, 20, + 25, 32, 40, 50}, + {64, 80, 101, 128, + 160, 201, 256, 318}, + {401, 505, 635, 800, + 1007, 1268, 1596, 2010}, + {316, 398, 501, 631, + 794, 1000, 1259, 1585}, + {1995, 2512, 3162, 3981, + 5012, 6310, 7943, 10000}, + {12589, 15849, 19953, 25119, + 31623, 39811, 50119, 63098}, + {79433, 100000, 125893, 158489, + 199526, 251189, 316228, 398107}, + {501187, 630957, 794328, 1000000, + 1258925, 1584893, 1995262, 2511886}, + {3162278, 3981072, 5011872, 6309573, + 7943282, 1000000, 12589254, 15848932}, + {19952623, 25118864, 31622777, 39810717, + 50118723, 63095734, 79432823, 100000000}, + {125892541, 158489319, 199526232, 251188643, + 316227766, 398107171, 501187234, 630957345}, + {794328235, 1000000000, 1258925412, 1584893192, + 1995262315, 2511886432U, 3162277660U, 3981071706U} +}; + +enum rtw_phy_band_type { + PHY_BAND_2G = 0, + PHY_BAND_5G = 1, +}; + +void rtw_phy_init(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u32 addr, mask; + + dm_info->fa_history[3] = 0; + dm_info->fa_history[2] = 0; + dm_info->fa_history[1] = 0; + dm_info->fa_history[0] = 0; + dm_info->igi_bitmap = 0; + dm_info->igi_history[3] = 0; + dm_info->igi_history[2] = 0; + dm_info->igi_history[1] = 0; + + addr = chip->dig[0].addr; + mask = chip->dig[0].mask; + dm_info->igi_history[0] = rtw_read32_mask(rtwdev, addr, mask); +} + +void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_hal *hal = &rtwdev->hal; + u32 addr, mask; + u8 path; + + for (path = 0; path < hal->rf_path_num; path++) { + addr = chip->dig[path].addr; + mask = chip->dig[path].mask; + rtw_write32_mask(rtwdev, addr, mask, igi); + } +} + +static void rtw_phy_stat_false_alarm(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + + chip->ops->false_alarm_statistics(rtwdev); +} + +#define RA_FLOOR_TABLE_SIZE 7 +#define RA_FLOOR_UP_GAP 3 + +static u8 rtw_phy_get_rssi_level(u8 old_level, u8 rssi) +{ + u8 table[RA_FLOOR_TABLE_SIZE] = {20, 34, 38, 42, 46, 50, 100}; + u8 new_level = 0; + int i; + + for (i = 0; i < RA_FLOOR_TABLE_SIZE; i++) + if (i >= old_level) + table[i] += RA_FLOOR_UP_GAP; + + for (i = 0; i < RA_FLOOR_TABLE_SIZE; i++) { + if (rssi < table[i]) { + new_level = i; + break; + } + } + + return new_level; +} + +struct rtw_phy_stat_iter_data { + struct rtw_dev *rtwdev; + u8 min_rssi; +}; + +static void rtw_phy_stat_rssi_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw_phy_stat_iter_data *iter_data = data; + struct rtw_dev *rtwdev = iter_data->rtwdev; + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; + u8 rssi, rssi_level; + + rssi = ewma_rssi_read(&si->avg_rssi); + rssi_level = rtw_phy_get_rssi_level(si->rssi_level, rssi); + + rtw_fw_send_rssi_info(rtwdev, si); + + iter_data->min_rssi = min_t(u8, rssi, iter_data->min_rssi); +} + +static void rtw_phy_stat_rssi(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_phy_stat_iter_data data = {}; + + data.rtwdev = rtwdev; + data.min_rssi = U8_MAX; + rtw_iterate_stas_atomic(rtwdev, rtw_phy_stat_rssi_iter, &data); + + dm_info->pre_min_rssi = dm_info->min_rssi; + dm_info->min_rssi = data.min_rssi; +} + +static void rtw_phy_statistics(struct rtw_dev *rtwdev) +{ + rtw_phy_stat_rssi(rtwdev); + rtw_phy_stat_false_alarm(rtwdev); +} + +#define DIG_PERF_FA_TH_LOW 250 +#define DIG_PERF_FA_TH_HIGH 500 +#define DIG_PERF_FA_TH_EXTRA_HIGH 750 +#define DIG_PERF_MAX 0x5a +#define DIG_PERF_MID 0x40 +#define DIG_CVRG_FA_TH_LOW 2000 +#define DIG_CVRG_FA_TH_HIGH 4000 +#define DIG_CVRG_FA_TH_EXTRA_HIGH 5000 +#define DIG_CVRG_MAX 0x2a +#define DIG_CVRG_MID 0x26 +#define DIG_CVRG_MIN 0x1c +#define DIG_RSSI_GAIN_OFFSET 15 + +static bool +rtw_phy_dig_check_damping(struct rtw_dm_info *dm_info) +{ + u16 fa_lo = DIG_PERF_FA_TH_LOW; + u16 fa_hi = DIG_PERF_FA_TH_HIGH; + u16 *fa_history; + u8 *igi_history; + u8 damping_rssi; + u8 min_rssi; + u8 diff; + u8 igi_bitmap; + bool damping = false; + + min_rssi = dm_info->min_rssi; + if (dm_info->damping) { + damping_rssi = dm_info->damping_rssi; + diff = min_rssi > damping_rssi ? min_rssi - damping_rssi : + damping_rssi - min_rssi; + if (diff > 3 || dm_info->damping_cnt++ > 20) { + dm_info->damping = false; + return false; + } + + return true; + } + + igi_history = dm_info->igi_history; + fa_history = dm_info->fa_history; + igi_bitmap = dm_info->igi_bitmap & 0xf; + switch (igi_bitmap) { + case 5: + /* down -> up -> down -> up */ + if (igi_history[0] > igi_history[1] && + igi_history[2] > igi_history[3] && + igi_history[0] - igi_history[1] >= 2 && + igi_history[2] - igi_history[3] >= 2 && + fa_history[0] > fa_hi && fa_history[1] < fa_lo && + fa_history[2] > fa_hi && fa_history[3] < fa_lo) + damping = true; + break; + case 9: + /* up -> down -> down -> up */ + if (igi_history[0] > igi_history[1] && + igi_history[3] > igi_history[2] && + igi_history[0] - igi_history[1] >= 4 && + igi_history[3] - igi_history[2] >= 2 && + fa_history[0] > fa_hi && fa_history[1] < fa_lo && + fa_history[2] < fa_lo && fa_history[3] > fa_hi) + damping = true; + break; + default: + return false; + } + + if (damping) { + dm_info->damping = true; + dm_info->damping_cnt = 0; + dm_info->damping_rssi = min_rssi; + } + + return damping; +} + +static void rtw_phy_dig_get_boundary(struct rtw_dm_info *dm_info, + u8 *upper, u8 *lower, bool linked) +{ + u8 dig_max, dig_min, dig_mid; + u8 min_rssi; + + if (linked) { + dig_max = DIG_PERF_MAX; + dig_mid = DIG_PERF_MID; + /* 22B=0x1c, 22C=0x20 */ + dig_min = 0x1c; + min_rssi = max_t(u8, dm_info->min_rssi, dig_min); + } else { + dig_max = DIG_CVRG_MAX; + dig_mid = DIG_CVRG_MID; + dig_min = DIG_CVRG_MIN; + min_rssi = dig_min; + } + + /* DIG MAX should be bounded by minimum RSSI with offset +15 */ + dig_max = min_t(u8, dig_max, min_rssi + DIG_RSSI_GAIN_OFFSET); + + *lower = clamp_t(u8, min_rssi, dig_min, dig_mid); + *upper = clamp_t(u8, *lower + DIG_RSSI_GAIN_OFFSET, dig_min, dig_max); +} + +static void rtw_phy_dig_get_threshold(struct rtw_dm_info *dm_info, + u16 *fa_th, u8 *step, bool linked) +{ + u8 min_rssi, pre_min_rssi; + + min_rssi = dm_info->min_rssi; + pre_min_rssi = dm_info->pre_min_rssi; + step[0] = 4; + step[1] = 3; + step[2] = 2; + + if (linked) { + fa_th[0] = DIG_PERF_FA_TH_EXTRA_HIGH; + fa_th[1] = DIG_PERF_FA_TH_HIGH; + fa_th[2] = DIG_PERF_FA_TH_LOW; + if (pre_min_rssi > min_rssi) { + step[0] = 6; + step[1] = 4; + step[2] = 2; + } + } else { + fa_th[0] = DIG_CVRG_FA_TH_EXTRA_HIGH; + fa_th[1] = DIG_CVRG_FA_TH_HIGH; + fa_th[2] = DIG_CVRG_FA_TH_LOW; + } +} + +static void rtw_phy_dig_recorder(struct rtw_dm_info *dm_info, u8 igi, u16 fa) +{ + u8 *igi_history; + u16 *fa_history; + u8 igi_bitmap; + bool up; + + igi_bitmap = dm_info->igi_bitmap << 1 & 0xfe; + igi_history = dm_info->igi_history; + fa_history = dm_info->fa_history; + + up = igi > igi_history[0]; + igi_bitmap |= up; + + igi_history[3] = igi_history[2]; + igi_history[2] = igi_history[1]; + igi_history[1] = igi_history[0]; + igi_history[0] = igi; + + fa_history[3] = fa_history[2]; + fa_history[2] = fa_history[1]; + fa_history[1] = fa_history[0]; + fa_history[0] = fa; + + dm_info->igi_bitmap = igi_bitmap; +} + +static void rtw_phy_dig(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u8 upper_bound, lower_bound; + u8 pre_igi, cur_igi; + u16 fa_th[3], fa_cnt; + u8 level; + u8 step[3]; + bool linked; + + if (rtw_flag_check(rtwdev, RTW_FLAG_DIG_DISABLE)) + return; + + if (rtw_phy_dig_check_damping(dm_info)) + return; + + linked = !!rtwdev->sta_cnt; + + fa_cnt = dm_info->total_fa_cnt; + pre_igi = dm_info->igi_history[0]; + + rtw_phy_dig_get_threshold(dm_info, fa_th, step, linked); + + /* test the false alarm count from the highest threshold level first, + * and increase it by corresponding step size + * + * note that the step size is offset by -2, compensate it afterall + */ + cur_igi = pre_igi; + for (level = 0; level < 3; level++) { + if (fa_cnt > fa_th[level]) { + cur_igi += step[level]; + break; + } + } + cur_igi -= 2; + + /* calculate the upper/lower bound by the minimum rssi we have among + * the peers connected with us, meanwhile make sure the igi value does + * not beyond the hardware limitation + */ + rtw_phy_dig_get_boundary(dm_info, &upper_bound, &lower_bound, linked); + cur_igi = clamp_t(u8, cur_igi, lower_bound, upper_bound); + + /* record current igi value and false alarm statistics for further + * damping checks, and record the trend of igi values + */ + rtw_phy_dig_recorder(dm_info, cur_igi, fa_cnt); + + if (cur_igi != pre_igi) + rtw_phy_dig_write(rtwdev, cur_igi); +} + +static void rtw_phy_ra_info_update_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw_dev *rtwdev = data; + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; + + rtw_update_sta_info(rtwdev, si); +} + +static void rtw_phy_ra_info_update(struct rtw_dev *rtwdev) +{ + if (rtwdev->watch_dog_cnt & 0x3) + return; + + rtw_iterate_stas_atomic(rtwdev, rtw_phy_ra_info_update_iter, rtwdev); +} + +void rtw_phy_dynamic_mechanism(struct rtw_dev *rtwdev) +{ + /* for further calculation */ + rtw_phy_statistics(rtwdev); + rtw_phy_dig(rtwdev); + rtw_phy_ra_info_update(rtwdev); +} + +#define FRAC_BITS 3 + +static u8 rtw_phy_power_2_db(s8 power) +{ + if (power <= -100 || power >= 20) + return 0; + else if (power >= 0) + return 100; + else + return 100 + power; +} + +static u64 rtw_phy_db_2_linear(u8 power_db) +{ + u8 i, j; + u64 linear; + + /* 1dB ~ 96dB */ + i = (power_db - 1) >> 3; + j = (power_db - 1) - (i << 3); + + linear = db_invert_table[i][j]; + linear = i > 2 ? linear << FRAC_BITS : linear; + + return linear; +} + +static u8 rtw_phy_linear_2_db(u64 linear) +{ + u8 i; + u8 j; + u32 dB; + + if (linear >= db_invert_table[11][7]) + return 96; /* maximum 96 dB */ + + for (i = 0; i < 12; i++) { + if (i <= 2 && (linear << FRAC_BITS) <= db_invert_table[i][7]) + break; + else if (i > 2 && linear <= db_invert_table[i][7]) + break; + } + + for (j = 0; j < 8; j++) { + if (i <= 2 && (linear << FRAC_BITS) <= db_invert_table[i][j]) + break; + else if (i > 2 && linear <= db_invert_table[i][j]) + break; + } + + if (j == 0 && i == 0) + goto end; + + if (j == 0) { + if (i != 3) { + if (db_invert_table[i][0] - linear > + linear - db_invert_table[i - 1][7]) { + i = i - 1; + j = 7; + } + } else { + if (db_invert_table[3][0] - linear > + linear - db_invert_table[2][7]) { + i = 2; + j = 7; + } + } + } else { + if (db_invert_table[i][j] - linear > + linear - db_invert_table[i][j - 1]) { + j = j - 1; + } + } +end: + dB = (i << 3) + j + 1; + + return dB; +} + +u8 rtw_phy_rf_power_2_rssi(s8 *rf_power, u8 path_num) +{ + s8 power; + u8 power_db; + u64 linear; + u64 sum = 0; + u8 path; + + for (path = 0; path < path_num; path++) { + power = rf_power[path]; + power_db = rtw_phy_power_2_db(power); + linear = rtw_phy_db_2_linear(power_db); + sum += linear; + } + + sum = (sum + (1 << (FRAC_BITS - 1))) >> FRAC_BITS; + switch (path_num) { + case 2: + sum >>= 1; + break; + case 3: + sum = ((sum) + ((sum) << 1) + ((sum) << 3)) >> 5; + break; + case 4: + sum >>= 2; + break; + default: + break; + } + + return rtw_phy_linear_2_db(sum); +} + +u32 rtw_phy_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask) +{ + struct rtw_hal *hal = &rtwdev->hal; + struct rtw_chip_info *chip = rtwdev->chip; + const u32 *base_addr = chip->rf_base_addr; + u32 val, direct_addr; + + if (rf_path >= hal->rf_path_num) { + rtw_err(rtwdev, "unsupported rf path (%d)\n", rf_path); + return INV_RF_DATA; + } + + addr &= 0xff; + direct_addr = base_addr[rf_path] + (addr << 2); + mask &= RFREG_MASK; + + val = rtw_read32_mask(rtwdev, direct_addr, mask); + + return val; +} + +bool rtw_phy_write_rf_reg_sipi(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask, u32 data) +{ + struct rtw_hal *hal = &rtwdev->hal; + struct rtw_chip_info *chip = rtwdev->chip; + u32 *sipi_addr = chip->rf_sipi_addr; + u32 data_and_addr; + u32 old_data = 0; + u32 shift; + + if (rf_path >= hal->rf_path_num) { + rtw_err(rtwdev, "unsupported rf path (%d)\n", rf_path); + return false; + } + + addr &= 0xff; + mask &= RFREG_MASK; + + if (mask != RFREG_MASK) { + old_data = rtw_phy_read_rf(rtwdev, rf_path, addr, RFREG_MASK); + + if (old_data == INV_RF_DATA) { + rtw_err(rtwdev, "Write fail, rf is disabled\n"); + return false; + } + + shift = __ffs(mask); + data = ((old_data) & (~mask)) | (data << shift); + } + + data_and_addr = ((addr << 20) | (data & 0x000fffff)) & 0x0fffffff; + + rtw_write32(rtwdev, sipi_addr[rf_path], data_and_addr); + + udelay(13); + + return true; +} + +bool rtw_phy_write_rf_reg(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask, u32 data) +{ + struct rtw_hal *hal = &rtwdev->hal; + struct rtw_chip_info *chip = rtwdev->chip; + const u32 *base_addr = chip->rf_base_addr; + u32 direct_addr; + + if (rf_path >= hal->rf_path_num) { + rtw_err(rtwdev, "unsupported rf path (%d)\n", rf_path); + return false; + } + + addr &= 0xff; + direct_addr = base_addr[rf_path] + (addr << 2); + mask &= RFREG_MASK; + + rtw_write32_mask(rtwdev, REG_RSV_CTRL, BITS_RFC_DIRECT, DISABLE_PI); + rtw_write32_mask(rtwdev, REG_WLRF1, BITS_RFC_DIRECT, DISABLE_PI); + rtw_write32_mask(rtwdev, direct_addr, mask, data); + + udelay(1); + + rtw_write32_mask(rtwdev, REG_RSV_CTRL, BITS_RFC_DIRECT, ENABLE_PI); + rtw_write32_mask(rtwdev, REG_WLRF1, BITS_RFC_DIRECT, ENABLE_PI); + + return true; +} + +bool rtw_phy_write_rf_reg_mix(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask, u32 data) +{ + if (addr != 0x00) + return rtw_phy_write_rf_reg(rtwdev, rf_path, addr, mask, data); + + return rtw_phy_write_rf_reg_sipi(rtwdev, rf_path, addr, mask, data); +} + +void rtw_phy_setup_phy_cond(struct rtw_dev *rtwdev, u32 pkg) +{ + struct rtw_hal *hal = &rtwdev->hal; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_phy_cond cond = {0}; + + cond.cut = hal->cut_version ? hal->cut_version : 15; + cond.pkg = pkg ? pkg : 15; + cond.plat = 0x04; + cond.rfe = efuse->rfe_option; + + switch (rtw_hci_type(rtwdev)) { + case RTW_HCI_TYPE_USB: + cond.intf = INTF_USB; + break; + case RTW_HCI_TYPE_SDIO: + cond.intf = INTF_SDIO; + break; + case RTW_HCI_TYPE_PCIE: + default: + cond.intf = INTF_PCIE; + break; + } + + hal->phy_cond = cond; + + rtw_dbg(rtwdev, RTW_DBG_PHY, "phy cond=0x%08x\n", *((u32 *)&hal->phy_cond)); +} + +static bool check_positive(struct rtw_dev *rtwdev, struct rtw_phy_cond cond) +{ + struct rtw_hal *hal = &rtwdev->hal; + struct rtw_phy_cond drv_cond = hal->phy_cond; + + if (cond.cut && cond.cut != drv_cond.cut) + return false; + + if (cond.pkg && cond.pkg != drv_cond.pkg) + return false; + + if (cond.intf && cond.intf != drv_cond.intf) + return false; + + if (cond.rfe != drv_cond.rfe) + return false; + + return true; +} + +void rtw_parse_tbl_phy_cond(struct rtw_dev *rtwdev, const struct rtw_table *tbl) +{ + const union phy_table_tile *p = tbl->data; + const union phy_table_tile *end = p + tbl->size / 2; + struct rtw_phy_cond pos_cond = {0}; + bool is_matched = true, is_skipped = false; + + BUILD_BUG_ON(sizeof(union phy_table_tile) != sizeof(struct phy_cfg_pair)); + + for (; p < end; p++) { + if (p->cond.pos) { + switch (p->cond.branch) { + case BRANCH_ENDIF: + is_matched = true; + is_skipped = false; + break; + case BRANCH_ELSE: + is_matched = is_skipped ? false : true; + break; + case BRANCH_IF: + case BRANCH_ELIF: + default: + pos_cond = p->cond; + break; + } + } else if (p->cond.neg) { + if (!is_skipped) { + if (check_positive(rtwdev, pos_cond)) { + is_matched = true; + is_skipped = true; + } else { + is_matched = false; + is_skipped = false; + } + } else { + is_matched = false; + } + } else if (is_matched) { + (*tbl->do_cfg)(rtwdev, tbl, p->cfg.addr, p->cfg.data); + } + } +} + +void rtw_parse_tbl_bb_pg(struct rtw_dev *rtwdev, const struct rtw_table *tbl) +{ + const struct phy_pg_cfg_pair *p = tbl->data; + const struct phy_pg_cfg_pair *end = p + tbl->size / 6; + + BUILD_BUG_ON(sizeof(struct phy_pg_cfg_pair) != sizeof(u32) * 6); + + for (; p < end; p++) { + if (p->addr == 0xfe || p->addr == 0xffe) { + msleep(50); + continue; + } + phy_store_tx_power_by_rate(rtwdev, p->band, p->rf_path, + p->tx_num, p->addr, p->bitmask, + p->data); + } +} + +void rtw_parse_tbl_txpwr_lmt(struct rtw_dev *rtwdev, + const struct rtw_table *tbl) +{ + const struct txpwr_lmt_cfg_pair *p = tbl->data; + const struct txpwr_lmt_cfg_pair *end = p + tbl->size / 6; + + BUILD_BUG_ON(sizeof(struct txpwr_lmt_cfg_pair) != sizeof(u8) * 6); + + for (; p < end; p++) { + phy_set_tx_power_limit(rtwdev, p->regd, p->band, + p->bw, p->rs, + p->ch, p->txpwr_lmt); + } +} + +void rtw_phy_cfg_mac(struct rtw_dev *rtwdev, const struct rtw_table *tbl, + u32 addr, u32 data) +{ + rtw_write8(rtwdev, addr, data); +} + +void rtw_phy_cfg_agc(struct rtw_dev *rtwdev, const struct rtw_table *tbl, + u32 addr, u32 data) +{ + rtw_write32(rtwdev, addr, data); +} + +void rtw_phy_cfg_bb(struct rtw_dev *rtwdev, const struct rtw_table *tbl, + u32 addr, u32 data) +{ + if (addr == 0xfe) + msleep(50); + else if (addr == 0xfd) + mdelay(5); + else if (addr == 0xfc) + mdelay(1); + else if (addr == 0xfb) + usleep_range(50, 60); + else if (addr == 0xfa) + udelay(5); + else if (addr == 0xf9) + udelay(1); + else + rtw_write32(rtwdev, addr, data); +} + +void rtw_phy_cfg_rf(struct rtw_dev *rtwdev, const struct rtw_table *tbl, + u32 addr, u32 data) +{ + if (addr == 0xffe) { + msleep(50); + } else if (addr == 0xfe) { + usleep_range(100, 110); + } else { + rtw_write_rf(rtwdev, tbl->rf_path, addr, RFREG_MASK, data); + udelay(1); + } +} + +static void rtw_load_rfk_table(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + + if (!chip->rfk_init_tbl) + return; + + rtw_load_table(rtwdev, chip->rfk_init_tbl); +} + +void rtw_phy_load_tables(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + u8 rf_path; + + rtw_load_table(rtwdev, chip->mac_tbl); + rtw_load_table(rtwdev, chip->bb_tbl); + rtw_load_table(rtwdev, chip->agc_tbl); + rtw_load_rfk_table(rtwdev); + + for (rf_path = 0; rf_path < rtwdev->hal.rf_path_num; rf_path++) { + const struct rtw_table *tbl; + + tbl = chip->rf_tbl[rf_path]; + rtw_load_table(rtwdev, tbl); + } +} + +#define bcd_to_dec_pwr_by_rate(val, i) bcd2bin(val >> (i * 8)) + +#define RTW_MAX_POWER_INDEX 0x3F + +u8 rtw_cck_rates[] = { DESC_RATE1M, DESC_RATE2M, DESC_RATE5_5M, DESC_RATE11M }; +u8 rtw_ofdm_rates[] = { + DESC_RATE6M, DESC_RATE9M, DESC_RATE12M, + DESC_RATE18M, DESC_RATE24M, DESC_RATE36M, + DESC_RATE48M, DESC_RATE54M +}; +u8 rtw_ht_1s_rates[] = { + DESC_RATEMCS0, DESC_RATEMCS1, DESC_RATEMCS2, + DESC_RATEMCS3, DESC_RATEMCS4, DESC_RATEMCS5, + DESC_RATEMCS6, DESC_RATEMCS7 +}; +u8 rtw_ht_2s_rates[] = { + DESC_RATEMCS8, DESC_RATEMCS9, DESC_RATEMCS10, + DESC_RATEMCS11, DESC_RATEMCS12, DESC_RATEMCS13, + DESC_RATEMCS14, DESC_RATEMCS15 +}; +u8 rtw_vht_1s_rates[] = { + DESC_RATEVHT1SS_MCS0, DESC_RATEVHT1SS_MCS1, + DESC_RATEVHT1SS_MCS2, DESC_RATEVHT1SS_MCS3, + DESC_RATEVHT1SS_MCS4, DESC_RATEVHT1SS_MCS5, + DESC_RATEVHT1SS_MCS6, DESC_RATEVHT1SS_MCS7, + DESC_RATEVHT1SS_MCS8, DESC_RATEVHT1SS_MCS9 +}; +u8 rtw_vht_2s_rates[] = { + DESC_RATEVHT2SS_MCS0, DESC_RATEVHT2SS_MCS1, + DESC_RATEVHT2SS_MCS2, DESC_RATEVHT2SS_MCS3, + DESC_RATEVHT2SS_MCS4, DESC_RATEVHT2SS_MCS5, + DESC_RATEVHT2SS_MCS6, DESC_RATEVHT2SS_MCS7, + DESC_RATEVHT2SS_MCS8, DESC_RATEVHT2SS_MCS9 +}; +u8 rtw_cck_size = ARRAY_SIZE(rtw_cck_rates); +u8 rtw_ofdm_size = ARRAY_SIZE(rtw_ofdm_rates); +u8 rtw_ht_1s_size = ARRAY_SIZE(rtw_ht_1s_rates); +u8 rtw_ht_2s_size = ARRAY_SIZE(rtw_ht_2s_rates); +u8 rtw_vht_1s_size = ARRAY_SIZE(rtw_vht_1s_rates); +u8 rtw_vht_2s_size = ARRAY_SIZE(rtw_vht_2s_rates); +u8 *rtw_rate_section[RTW_RATE_SECTION_MAX] = { + rtw_cck_rates, rtw_ofdm_rates, + rtw_ht_1s_rates, rtw_ht_2s_rates, + rtw_vht_1s_rates, rtw_vht_2s_rates +}; +u8 rtw_rate_size[RTW_RATE_SECTION_MAX] = { + ARRAY_SIZE(rtw_cck_rates), + ARRAY_SIZE(rtw_ofdm_rates), + ARRAY_SIZE(rtw_ht_1s_rates), + ARRAY_SIZE(rtw_ht_2s_rates), + ARRAY_SIZE(rtw_vht_1s_rates), + ARRAY_SIZE(rtw_vht_2s_rates) +}; + +static const u8 rtw_channel_idx_5g[RTW_MAX_CHANNEL_NUM_5G] = { + 36, 38, 40, 42, 44, 46, 48, /* Band 1 */ + 52, 54, 56, 58, 60, 62, 64, /* Band 2 */ + 100, 102, 104, 106, 108, 110, 112, /* Band 3 */ + 116, 118, 120, 122, 124, 126, 128, /* Band 3 */ + 132, 134, 136, 138, 140, 142, 144, /* Band 3 */ + 149, 151, 153, 155, 157, 159, 161, /* Band 4 */ + 165, 167, 169, 171, 173, 175, 177}; /* Band 4 */ + +static int rtw_channel_to_idx(u8 band, u8 channel) +{ + int ch_idx; + u8 n_channel; + + if (band == PHY_BAND_2G) { + ch_idx = channel - 1; + n_channel = RTW_MAX_CHANNEL_NUM_2G; + } else if (band == PHY_BAND_5G) { + n_channel = RTW_MAX_CHANNEL_NUM_5G; + for (ch_idx = 0; ch_idx < n_channel; ch_idx++) + if (rtw_channel_idx_5g[ch_idx] == channel) + break; + } else { + return -1; + } + + if (ch_idx >= n_channel) + return -1; + + return ch_idx; +} + +static u8 rtw_get_channel_group(u8 channel) +{ + switch (channel) { + default: + WARN_ON(1); + /* fall through */ + case 1: + case 2: + case 36: + case 38: + case 40: + case 42: + return 0; + case 3: + case 4: + case 5: + case 44: + case 46: + case 48: + case 50: + return 1; + case 6: + case 7: + case 8: + case 52: + case 54: + case 56: + case 58: + return 2; + case 9: + case 10: + case 11: + case 60: + case 62: + case 64: + return 3; + case 12: + case 13: + case 100: + case 102: + case 104: + case 106: + return 4; + case 14: + case 108: + case 110: + case 112: + case 114: + return 5; + case 116: + case 118: + case 120: + case 122: + return 6; + case 124: + case 126: + case 128: + case 130: + return 7; + case 132: + case 134: + case 136: + case 138: + return 8; + case 140: + case 142: + case 144: + return 9; + case 149: + case 151: + case 153: + case 155: + return 10; + case 157: + case 159: + case 161: + return 11; + case 165: + case 167: + case 169: + case 171: + return 12; + case 173: + case 175: + case 177: + return 13; + } +} + +static u8 phy_get_2g_tx_power_index(struct rtw_dev *rtwdev, + struct rtw_2g_txpwr_idx *pwr_idx_2g, + enum rtw_bandwidth bandwidth, + u8 rate, u8 group) +{ + struct rtw_chip_info *chip = rtwdev->chip; + u8 tx_power; + bool mcs_rate; + bool above_2ss; + u8 factor = chip->txgi_factor; + + if (rate <= DESC_RATE11M) + tx_power = pwr_idx_2g->cck_base[group]; + else + tx_power = pwr_idx_2g->bw40_base[group]; + + if (rate >= DESC_RATE6M && rate <= DESC_RATE54M) + tx_power += pwr_idx_2g->ht_1s_diff.ofdm * factor; + + mcs_rate = (rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS15) || + (rate >= DESC_RATEVHT1SS_MCS0 && + rate <= DESC_RATEVHT2SS_MCS9); + above_2ss = (rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) || + (rate >= DESC_RATEVHT2SS_MCS0); + + if (!mcs_rate) + return tx_power; + + switch (bandwidth) { + default: + WARN_ON(1); + /* fall through */ + case RTW_CHANNEL_WIDTH_20: + tx_power += pwr_idx_2g->ht_1s_diff.bw20 * factor; + if (above_2ss) + tx_power += pwr_idx_2g->ht_2s_diff.bw20 * factor; + break; + case RTW_CHANNEL_WIDTH_40: + /* bw40 is the base power */ + if (above_2ss) + tx_power += pwr_idx_2g->ht_2s_diff.bw40 * factor; + break; + } + + return tx_power; +} + +static u8 phy_get_5g_tx_power_index(struct rtw_dev *rtwdev, + struct rtw_5g_txpwr_idx *pwr_idx_5g, + enum rtw_bandwidth bandwidth, + u8 rate, u8 group) +{ + struct rtw_chip_info *chip = rtwdev->chip; + u8 tx_power; + u8 upper, lower; + bool mcs_rate; + bool above_2ss; + u8 factor = chip->txgi_factor; + + tx_power = pwr_idx_5g->bw40_base[group]; + + mcs_rate = (rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS15) || + (rate >= DESC_RATEVHT1SS_MCS0 && + rate <= DESC_RATEVHT2SS_MCS9); + above_2ss = (rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) || + (rate >= DESC_RATEVHT2SS_MCS0); + + if (!mcs_rate) { + tx_power += pwr_idx_5g->ht_1s_diff.ofdm * factor; + return tx_power; + } + + switch (bandwidth) { + default: + WARN_ON(1); + /* fall through */ + case RTW_CHANNEL_WIDTH_20: + tx_power += pwr_idx_5g->ht_1s_diff.bw20 * factor; + if (above_2ss) + tx_power += pwr_idx_5g->ht_2s_diff.bw20 * factor; + break; + case RTW_CHANNEL_WIDTH_40: + /* bw40 is the base power */ + if (above_2ss) + tx_power += pwr_idx_5g->ht_2s_diff.bw40 * factor; + break; + case RTW_CHANNEL_WIDTH_80: + /* the base idx of bw80 is the average of bw40+/bw40- */ + lower = pwr_idx_5g->bw40_base[group]; + upper = pwr_idx_5g->bw40_base[group + 1]; + + tx_power = (lower + upper) / 2; + tx_power += pwr_idx_5g->vht_1s_diff.bw80 * factor; + if (above_2ss) + tx_power += pwr_idx_5g->vht_2s_diff.bw80 * factor; + break; + } + + return tx_power; +} + +/* set tx power level by path for each rates, note that the order of the rates + * are *very* important, bacause 8822B/8821C combines every four bytes of tx + * power index into a four-byte power index register, and calls set_tx_agc to + * write these values into hardware + */ +static +void phy_set_tx_power_level_by_path(struct rtw_dev *rtwdev, u8 ch, u8 path) +{ + struct rtw_hal *hal = &rtwdev->hal; + u8 rs; + + /* do not need cck rates if we are not in 2.4G */ + if (hal->current_band_type == RTW_BAND_2G) + rs = RTW_RATE_SECTION_CCK; + else + rs = RTW_RATE_SECTION_OFDM; + + for (; rs < RTW_RATE_SECTION_MAX; rs++) + phy_set_tx_power_index_by_rs(rtwdev, ch, path, rs); +} + +void rtw_phy_set_tx_power_level(struct rtw_dev *rtwdev, u8 channel) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_hal *hal = &rtwdev->hal; + u8 path; + + mutex_lock(&hal->tx_power_mutex); + + for (path = 0; path < hal->rf_path_num; path++) + phy_set_tx_power_level_by_path(rtwdev, channel, path); + + chip->ops->set_tx_power_index(rtwdev); + mutex_unlock(&hal->tx_power_mutex); +} + +s8 phy_get_tx_power_limit(struct rtw_dev *rtwdev, u8 band, + enum rtw_bandwidth bandwidth, u8 rf_path, + u8 rate, u8 channel, u8 regd); + +static +u8 phy_get_tx_power_index(void *adapter, u8 rf_path, u8 rate, + enum rtw_bandwidth bandwidth, u8 channel, u8 regd) +{ + struct rtw_dev *rtwdev = adapter; + struct rtw_hal *hal = &rtwdev->hal; + struct rtw_txpwr_idx *pwr_idx; + u8 tx_power; + u8 group; + u8 band; + s8 offset, limit; + + pwr_idx = &rtwdev->efuse.txpwr_idx_table[rf_path]; + group = rtw_get_channel_group(channel); + + /* base power index for 2.4G/5G */ + if (channel <= 14) { + band = PHY_BAND_2G; + tx_power = phy_get_2g_tx_power_index(rtwdev, + &pwr_idx->pwr_idx_2g, + bandwidth, rate, group); + offset = hal->tx_pwr_by_rate_offset_2g[rf_path][rate]; + } else { + band = PHY_BAND_5G; + tx_power = phy_get_5g_tx_power_index(rtwdev, + &pwr_idx->pwr_idx_5g, + bandwidth, rate, group); + offset = hal->tx_pwr_by_rate_offset_5g[rf_path][rate]; + } + + limit = phy_get_tx_power_limit(rtwdev, band, bandwidth, rf_path, + rate, channel, regd); + + if (offset > limit) + offset = limit; + + tx_power += offset; + + if (tx_power > rtwdev->chip->max_power_index) + tx_power = rtwdev->chip->max_power_index; + + return tx_power; +} + +void phy_set_tx_power_index_by_rs(void *adapter, u8 ch, u8 path, u8 rs) +{ + struct rtw_dev *rtwdev = adapter; + struct rtw_hal *hal = &rtwdev->hal; + u8 regd = rtwdev->regd.txpwr_regd; + u8 *rates; + u8 size; + u8 rate; + u8 pwr_idx; + u8 bw; + int i; + + if (rs >= RTW_RATE_SECTION_MAX) + return; + + rates = rtw_rate_section[rs]; + size = rtw_rate_size[rs]; + bw = hal->current_band_width; + for (i = 0; i < size; i++) { + rate = rates[i]; + pwr_idx = phy_get_tx_power_index(adapter, path, rate, bw, ch, + regd); + hal->tx_pwr_tbl[path][rate] = pwr_idx; + } +} + +static u8 tbl_to_dec_pwr_by_rate(struct rtw_dev *rtwdev, u32 hex, u8 i) +{ + if (rtwdev->chip->is_pwr_by_rate_dec) + return bcd_to_dec_pwr_by_rate(hex, i); + else + return (hex >> (i * 8)) & 0xFF; +} + +static void phy_get_rate_values_of_txpwr_by_rate(struct rtw_dev *rtwdev, + u32 addr, u32 mask, + u32 val, u8 *rate, + u8 *pwr_by_rate, u8 *rate_num) +{ + int i; + + switch (addr) { + case 0xE00: + case 0x830: + rate[0] = DESC_RATE6M; + rate[1] = DESC_RATE9M; + rate[2] = DESC_RATE12M; + rate[3] = DESC_RATE18M; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xE04: + case 0x834: + rate[0] = DESC_RATE24M; + rate[1] = DESC_RATE36M; + rate[2] = DESC_RATE48M; + rate[3] = DESC_RATE54M; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xE08: + rate[0] = DESC_RATE1M; + pwr_by_rate[0] = bcd_to_dec_pwr_by_rate(val, 1); + *rate_num = 1; + break; + case 0x86C: + if (mask == 0xffffff00) { + rate[0] = DESC_RATE2M; + rate[1] = DESC_RATE5_5M; + rate[2] = DESC_RATE11M; + for (i = 1; i < 4; ++i) + pwr_by_rate[i - 1] = + tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 3; + } else if (mask == 0x000000ff) { + rate[0] = DESC_RATE11M; + pwr_by_rate[0] = bcd_to_dec_pwr_by_rate(val, 0); + *rate_num = 1; + } + break; + case 0xE10: + case 0x83C: + rate[0] = DESC_RATEMCS0; + rate[1] = DESC_RATEMCS1; + rate[2] = DESC_RATEMCS2; + rate[3] = DESC_RATEMCS3; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xE14: + case 0x848: + rate[0] = DESC_RATEMCS4; + rate[1] = DESC_RATEMCS5; + rate[2] = DESC_RATEMCS6; + rate[3] = DESC_RATEMCS7; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xE18: + case 0x84C: + rate[0] = DESC_RATEMCS8; + rate[1] = DESC_RATEMCS9; + rate[2] = DESC_RATEMCS10; + rate[3] = DESC_RATEMCS11; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xE1C: + case 0x868: + rate[0] = DESC_RATEMCS12; + rate[1] = DESC_RATEMCS13; + rate[2] = DESC_RATEMCS14; + rate[3] = DESC_RATEMCS15; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + + break; + case 0x838: + rate[0] = DESC_RATE1M; + rate[1] = DESC_RATE2M; + rate[2] = DESC_RATE5_5M; + for (i = 1; i < 4; ++i) + pwr_by_rate[i - 1] = tbl_to_dec_pwr_by_rate(rtwdev, + val, i); + *rate_num = 3; + break; + case 0xC20: + case 0xE20: + case 0x1820: + case 0x1A20: + rate[0] = DESC_RATE1M; + rate[1] = DESC_RATE2M; + rate[2] = DESC_RATE5_5M; + rate[3] = DESC_RATE11M; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xC24: + case 0xE24: + case 0x1824: + case 0x1A24: + rate[0] = DESC_RATE6M; + rate[1] = DESC_RATE9M; + rate[2] = DESC_RATE12M; + rate[3] = DESC_RATE18M; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xC28: + case 0xE28: + case 0x1828: + case 0x1A28: + rate[0] = DESC_RATE24M; + rate[1] = DESC_RATE36M; + rate[2] = DESC_RATE48M; + rate[3] = DESC_RATE54M; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xC2C: + case 0xE2C: + case 0x182C: + case 0x1A2C: + rate[0] = DESC_RATEMCS0; + rate[1] = DESC_RATEMCS1; + rate[2] = DESC_RATEMCS2; + rate[3] = DESC_RATEMCS3; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xC30: + case 0xE30: + case 0x1830: + case 0x1A30: + rate[0] = DESC_RATEMCS4; + rate[1] = DESC_RATEMCS5; + rate[2] = DESC_RATEMCS6; + rate[3] = DESC_RATEMCS7; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xC34: + case 0xE34: + case 0x1834: + case 0x1A34: + rate[0] = DESC_RATEMCS8; + rate[1] = DESC_RATEMCS9; + rate[2] = DESC_RATEMCS10; + rate[3] = DESC_RATEMCS11; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xC38: + case 0xE38: + case 0x1838: + case 0x1A38: + rate[0] = DESC_RATEMCS12; + rate[1] = DESC_RATEMCS13; + rate[2] = DESC_RATEMCS14; + rate[3] = DESC_RATEMCS15; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xC3C: + case 0xE3C: + case 0x183C: + case 0x1A3C: + rate[0] = DESC_RATEVHT1SS_MCS0; + rate[1] = DESC_RATEVHT1SS_MCS1; + rate[2] = DESC_RATEVHT1SS_MCS2; + rate[3] = DESC_RATEVHT1SS_MCS3; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xC40: + case 0xE40: + case 0x1840: + case 0x1A40: + rate[0] = DESC_RATEVHT1SS_MCS4; + rate[1] = DESC_RATEVHT1SS_MCS5; + rate[2] = DESC_RATEVHT1SS_MCS6; + rate[3] = DESC_RATEVHT1SS_MCS7; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xC44: + case 0xE44: + case 0x1844: + case 0x1A44: + rate[0] = DESC_RATEVHT1SS_MCS8; + rate[1] = DESC_RATEVHT1SS_MCS9; + rate[2] = DESC_RATEVHT2SS_MCS0; + rate[3] = DESC_RATEVHT2SS_MCS1; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xC48: + case 0xE48: + case 0x1848: + case 0x1A48: + rate[0] = DESC_RATEVHT2SS_MCS2; + rate[1] = DESC_RATEVHT2SS_MCS3; + rate[2] = DESC_RATEVHT2SS_MCS4; + rate[3] = DESC_RATEVHT2SS_MCS5; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xC4C: + case 0xE4C: + case 0x184C: + case 0x1A4C: + rate[0] = DESC_RATEVHT2SS_MCS6; + rate[1] = DESC_RATEVHT2SS_MCS7; + rate[2] = DESC_RATEVHT2SS_MCS8; + rate[3] = DESC_RATEVHT2SS_MCS9; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xCD8: + case 0xED8: + case 0x18D8: + case 0x1AD8: + rate[0] = DESC_RATEMCS16; + rate[1] = DESC_RATEMCS17; + rate[2] = DESC_RATEMCS18; + rate[3] = DESC_RATEMCS19; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xCDC: + case 0xEDC: + case 0x18DC: + case 0x1ADC: + rate[0] = DESC_RATEMCS20; + rate[1] = DESC_RATEMCS21; + rate[2] = DESC_RATEMCS22; + rate[3] = DESC_RATEMCS23; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xCE0: + case 0xEE0: + case 0x18E0: + case 0x1AE0: + rate[0] = DESC_RATEVHT3SS_MCS0; + rate[1] = DESC_RATEVHT3SS_MCS1; + rate[2] = DESC_RATEVHT3SS_MCS2; + rate[3] = DESC_RATEVHT3SS_MCS3; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xCE4: + case 0xEE4: + case 0x18E4: + case 0x1AE4: + rate[0] = DESC_RATEVHT3SS_MCS4; + rate[1] = DESC_RATEVHT3SS_MCS5; + rate[2] = DESC_RATEVHT3SS_MCS6; + rate[3] = DESC_RATEVHT3SS_MCS7; + for (i = 0; i < 4; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 4; + break; + case 0xCE8: + case 0xEE8: + case 0x18E8: + case 0x1AE8: + rate[0] = DESC_RATEVHT3SS_MCS8; + rate[1] = DESC_RATEVHT3SS_MCS9; + for (i = 0; i < 2; ++i) + pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, val, i); + *rate_num = 2; + break; + default: + rtw_warn(rtwdev, "invalid tx power index addr 0x%08x\n", addr); + break; + } +} + +void phy_store_tx_power_by_rate(void *adapter, u32 band, u32 rfpath, u32 txnum, + u32 regaddr, u32 bitmask, u32 data) +{ + struct rtw_dev *rtwdev = adapter; + struct rtw_hal *hal = &rtwdev->hal; + u8 rate_num = 0; + u8 rate; + u8 rates[RTW_RF_PATH_MAX] = {0}; + s8 offset; + s8 pwr_by_rate[RTW_RF_PATH_MAX] = {0}; + int i; + + phy_get_rate_values_of_txpwr_by_rate(rtwdev, regaddr, bitmask, data, + rates, pwr_by_rate, &rate_num); + + if (WARN_ON(rfpath >= RTW_RF_PATH_MAX || + (band != PHY_BAND_2G && band != PHY_BAND_5G) || + rate_num > RTW_RF_PATH_MAX)) + return; + + for (i = 0; i < rate_num; i++) { + offset = pwr_by_rate[i]; + rate = rates[i]; + if (band == PHY_BAND_2G) + hal->tx_pwr_by_rate_offset_2g[rfpath][rate] = offset; + else if (band == PHY_BAND_5G) + hal->tx_pwr_by_rate_offset_5g[rfpath][rate] = offset; + else + continue; + } +} + +static +void phy_tx_power_by_rate_config_by_path(struct rtw_hal *hal, u8 path, + u8 rs, u8 size, u8 *rates) +{ + u8 rate; + u8 base_idx, rate_idx; + s8 base_2g, base_5g; + + if (rs >= RTW_RATE_SECTION_VHT_1S) + base_idx = rates[size - 3]; + else + base_idx = rates[size - 1]; + base_2g = hal->tx_pwr_by_rate_offset_2g[path][base_idx]; + base_5g = hal->tx_pwr_by_rate_offset_5g[path][base_idx]; + hal->tx_pwr_by_rate_base_2g[path][rs] = base_2g; + hal->tx_pwr_by_rate_base_5g[path][rs] = base_5g; + for (rate = 0; rate < size; rate++) { + rate_idx = rates[rate]; + hal->tx_pwr_by_rate_offset_2g[path][rate_idx] -= base_2g; + hal->tx_pwr_by_rate_offset_5g[path][rate_idx] -= base_5g; + } +} + +void rtw_phy_tx_power_by_rate_config(struct rtw_hal *hal) +{ + u8 path; + + for (path = 0; path < RTW_RF_PATH_MAX; path++) { + phy_tx_power_by_rate_config_by_path(hal, path, + RTW_RATE_SECTION_CCK, + rtw_cck_size, rtw_cck_rates); + phy_tx_power_by_rate_config_by_path(hal, path, + RTW_RATE_SECTION_OFDM, + rtw_ofdm_size, rtw_ofdm_rates); + phy_tx_power_by_rate_config_by_path(hal, path, + RTW_RATE_SECTION_HT_1S, + rtw_ht_1s_size, rtw_ht_1s_rates); + phy_tx_power_by_rate_config_by_path(hal, path, + RTW_RATE_SECTION_HT_2S, + rtw_ht_2s_size, rtw_ht_2s_rates); + phy_tx_power_by_rate_config_by_path(hal, path, + RTW_RATE_SECTION_VHT_1S, + rtw_vht_1s_size, rtw_vht_1s_rates); + phy_tx_power_by_rate_config_by_path(hal, path, + RTW_RATE_SECTION_VHT_2S, + rtw_vht_2s_size, rtw_vht_2s_rates); + } +} + +static void +phy_tx_power_limit_config(struct rtw_hal *hal, u8 regd, u8 bw, u8 rs) +{ + s8 base, orig; + u8 ch; + + for (ch = 0; ch < RTW_MAX_CHANNEL_NUM_2G; ch++) { + base = hal->tx_pwr_by_rate_base_2g[0][rs]; + orig = hal->tx_pwr_limit_2g[regd][bw][rs][ch]; + hal->tx_pwr_limit_2g[regd][bw][rs][ch] -= base; + } + + for (ch = 0; ch < RTW_MAX_CHANNEL_NUM_5G; ch++) { + base = hal->tx_pwr_by_rate_base_5g[0][rs]; + hal->tx_pwr_limit_5g[regd][bw][rs][ch] -= base; + } +} + +void rtw_phy_tx_power_limit_config(struct rtw_hal *hal) +{ + u8 regd, bw, rs; + + for (regd = 0; regd < RTW_REGD_MAX; regd++) + for (bw = 0; bw < RTW_CHANNEL_WIDTH_MAX; bw++) + for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++) + phy_tx_power_limit_config(hal, regd, bw, rs); +} + +static s8 get_tx_power_limit(struct rtw_hal *hal, u8 bw, u8 rs, u8 ch, u8 regd) +{ + if (regd > RTW_REGD_WW) + return RTW_MAX_POWER_INDEX; + + return hal->tx_pwr_limit_2g[regd][bw][rs][ch]; +} + +s8 phy_get_tx_power_limit(struct rtw_dev *rtwdev, u8 band, + enum rtw_bandwidth bw, u8 rf_path, + u8 rate, u8 channel, u8 regd) +{ + struct rtw_hal *hal = &rtwdev->hal; + s8 power_limit; + u8 rs; + int ch_idx; + + if (rate >= DESC_RATE1M && rate <= DESC_RATE11M) + rs = RTW_RATE_SECTION_CCK; + else if (rate >= DESC_RATE6M && rate <= DESC_RATE54M) + rs = RTW_RATE_SECTION_OFDM; + else if (rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS7) + rs = RTW_RATE_SECTION_HT_1S; + else if (rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) + rs = RTW_RATE_SECTION_HT_2S; + else if (rate >= DESC_RATEVHT1SS_MCS0 && rate <= DESC_RATEVHT1SS_MCS9) + rs = RTW_RATE_SECTION_VHT_1S; + else if (rate >= DESC_RATEVHT2SS_MCS0 && rate <= DESC_RATEVHT2SS_MCS9) + rs = RTW_RATE_SECTION_VHT_2S; + else + goto err; + + ch_idx = rtw_channel_to_idx(band, channel); + if (ch_idx < 0) + goto err; + + power_limit = get_tx_power_limit(hal, bw, rs, ch_idx, regd); + + return power_limit; + +err: + WARN(1, "invalid arguments, band=%d, bw=%d, path=%d, rate=%d, ch=%d\n", + band, bw, rf_path, rate, channel); + return RTW_MAX_POWER_INDEX; +} + +void phy_set_tx_power_limit(struct rtw_dev *rtwdev, u8 regd, u8 band, + u8 bw, u8 rs, u8 ch, s8 pwr_limit) +{ + struct rtw_hal *hal = &rtwdev->hal; + int ch_idx; + + pwr_limit = clamp_t(s8, pwr_limit, + -RTW_MAX_POWER_INDEX, RTW_MAX_POWER_INDEX); + ch_idx = rtw_channel_to_idx(band, ch); + + if (regd >= RTW_REGD_MAX || bw >= RTW_CHANNEL_WIDTH_MAX || + rs >= RTW_RATE_SECTION_MAX || ch_idx < 0) { + WARN(1, + "wrong txpwr_lmt regd=%u, band=%u bw=%u, rs=%u, ch_idx=%u, pwr_limit=%d\n", + regd, band, bw, rs, ch_idx, pwr_limit); + return; + } + + if (band == PHY_BAND_2G) + hal->tx_pwr_limit_2g[regd][bw][rs][ch_idx] = pwr_limit; + else if (band == PHY_BAND_5G) + hal->tx_pwr_limit_5g[regd][bw][rs][ch_idx] = pwr_limit; +} + +static +void rtw_hw_tx_power_limit_init(struct rtw_hal *hal, u8 regd, u8 bw, u8 rs) +{ + u8 ch; + + /* 2.4G channels */ + for (ch = 0; ch < RTW_MAX_CHANNEL_NUM_2G; ch++) + hal->tx_pwr_limit_2g[regd][bw][rs][ch] = RTW_MAX_POWER_INDEX; + + /* 5G channels */ + for (ch = 0; ch < RTW_MAX_CHANNEL_NUM_5G; ch++) + hal->tx_pwr_limit_5g[regd][bw][rs][ch] = RTW_MAX_POWER_INDEX; +} + +void rtw_hw_init_tx_power(struct rtw_hal *hal) +{ + u8 regd, path, rate, rs, bw; + + /* init tx power by rate offset */ + for (path = 0; path < RTW_RF_PATH_MAX; path++) { + for (rate = 0; rate < DESC_RATE_MAX; rate++) { + hal->tx_pwr_by_rate_offset_2g[path][rate] = 0; + hal->tx_pwr_by_rate_offset_5g[path][rate] = 0; + } + } + + /* init tx power limit */ + for (regd = 0; regd < RTW_REGD_MAX; regd++) + for (bw = 0; bw < RTW_CHANNEL_WIDTH_MAX; bw++) + for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++) + rtw_hw_tx_power_limit_init(hal, regd, bw, rs); +} diff --git a/drivers/net/wireless/realtek/rtw88/phy.h b/drivers/net/wireless/realtek/rtw88/phy.h new file mode 100644 index 000000000000..ec03a2051e52 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/phy.h @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW_PHY_H_ +#define __RTW_PHY_H_ + +#include "debug.h" + +extern u8 rtw_cck_rates[]; +extern u8 rtw_ofdm_rates[]; +extern u8 rtw_ht_1s_rates[]; +extern u8 rtw_ht_2s_rates[]; +extern u8 rtw_vht_1s_rates[]; +extern u8 rtw_vht_2s_rates[]; +extern u8 *rtw_rate_section[]; +extern u8 rtw_rate_size[]; + +void rtw_phy_init(struct rtw_dev *rtwdev); +void rtw_phy_dynamic_mechanism(struct rtw_dev *rtwdev); +u8 rtw_phy_rf_power_2_rssi(s8 *rf_power, u8 path_num); +u32 rtw_phy_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask); +bool rtw_phy_write_rf_reg_sipi(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask, u32 data); +bool rtw_phy_write_rf_reg(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask, u32 data); +bool rtw_phy_write_rf_reg_mix(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, + u32 addr, u32 mask, u32 data); +void phy_store_tx_power_by_rate(void *adapter, u32 band, u32 rfpath, u32 txnum, + u32 regaddr, u32 bitmask, u32 data); +void phy_set_tx_power_limit(struct rtw_dev *rtwdev, u8 regd, u8 band, + u8 bw, u8 rs, u8 ch, s8 pwr_limit); +void phy_set_tx_power_index_by_rs(void *adapter, u8 ch, u8 path, u8 rs); +void rtw_phy_setup_phy_cond(struct rtw_dev *rtwdev, u32 pkg); +void rtw_parse_tbl_phy_cond(struct rtw_dev *rtwdev, const struct rtw_table *tbl); +void rtw_parse_tbl_bb_pg(struct rtw_dev *rtwdev, const struct rtw_table *tbl); +void rtw_parse_tbl_txpwr_lmt(struct rtw_dev *rtwdev, const struct rtw_table *tbl); +void rtw_phy_cfg_mac(struct rtw_dev *rtwdev, const struct rtw_table *tbl, + u32 addr, u32 data); +void rtw_phy_cfg_agc(struct rtw_dev *rtwdev, const struct rtw_table *tbl, + u32 addr, u32 data); +void rtw_phy_cfg_bb(struct rtw_dev *rtwdev, const struct rtw_table *tbl, + u32 addr, u32 data); +void rtw_phy_cfg_rf(struct rtw_dev *rtwdev, const struct rtw_table *tbl, + u32 addr, u32 data); +void rtw_hw_init_tx_power(struct rtw_hal *hal); +void rtw_phy_load_tables(struct rtw_dev *rtwdev); +void rtw_phy_set_tx_power_level(struct rtw_dev *rtwdev, u8 channel); +void rtw_phy_tx_power_by_rate_config(struct rtw_hal *hal); +void rtw_phy_tx_power_limit_config(struct rtw_hal *hal); + +#define RTW_DECL_TABLE_PHY_COND_CORE(name, cfg, path) \ +const struct rtw_table name ## _tbl = { \ + .data = name, \ + .size = ARRAY_SIZE(name), \ + .parse = rtw_parse_tbl_phy_cond, \ + .do_cfg = cfg, \ + .rf_path = path, \ +} + +#define RTW_DECL_TABLE_PHY_COND(name, cfg) \ + RTW_DECL_TABLE_PHY_COND_CORE(name, cfg, 0) + +#define RTW_DECL_TABLE_RF_RADIO(name, path) \ + RTW_DECL_TABLE_PHY_COND_CORE(name, rtw_phy_cfg_rf, RF_PATH_ ## path) + +#define RTW_DECL_TABLE_BB_PG(name) \ +const struct rtw_table name ## _tbl = { \ + .data = name, \ + .size = ARRAY_SIZE(name), \ + .parse = rtw_parse_tbl_bb_pg, \ +} + +#define RTW_DECL_TABLE_TXPWR_LMT(name) \ +const struct rtw_table name ## _tbl = { \ + .data = name, \ + .size = ARRAY_SIZE(name), \ + .parse = rtw_parse_tbl_txpwr_lmt, \ +} + +static inline const struct rtw_rfe_def *rtw_get_rfe_def(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; + const struct rtw_rfe_def *rfe_def = NULL; + + if (chip->rfe_defs_size == 0) + return NULL; + + if (efuse->rfe_option < chip->rfe_defs_size) + rfe_def = &chip->rfe_defs[efuse->rfe_option]; + + rtw_dbg(rtwdev, RTW_DBG_PHY, "use rfe_def[%d]\n", efuse->rfe_option); + return rfe_def; +} + +static inline int rtw_check_supported_rfe(struct rtw_dev *rtwdev) +{ + const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev); + + if (!rfe_def || !rfe_def->phy_pg_tbl || !rfe_def->txpwr_lmt_tbl) { + rtw_err(rtwdev, "rfe %d isn't supported\n", + rtwdev->efuse.rfe_option); + return -ENODEV; + } + + return 0; +} + +void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi); + +#define MASKBYTE0 0xff +#define MASKBYTE1 0xff00 +#define MASKBYTE2 0xff0000 +#define MASKBYTE3 0xff000000 +#define MASKHWORD 0xffff0000 +#define MASKLWORD 0x0000ffff +#define MASKDWORD 0xffffffff +#define RFREG_MASK 0xfffff + +#define MASK7BITS 0x7f +#define MASK12BITS 0xfff +#define MASKH4BITS 0xf0000000 +#define MASK20BITS 0xfffff +#define MASK24BITS 0xffffff + +#define MASKH3BYTES 0xffffff00 +#define MASKL3BYTES 0x00ffffff +#define MASKBYTE2HIGHNIBBLE 0x00f00000 +#define MASKBYTE3LOWNIBBLE 0x0f000000 +#define MASKL3BYTES 0x00ffffff + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/ps.c b/drivers/net/wireless/realtek/rtw88/ps.c new file mode 100644 index 000000000000..607bfa4317d9 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/ps.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "fw.h" +#include "ps.h" +#include "mac.h" +#include "debug.h" + +static int rtw_ips_pwr_up(struct rtw_dev *rtwdev) +{ + int ret; + + ret = rtw_core_start(rtwdev); + if (ret) + rtw_err(rtwdev, "leave idle state failed\n"); + + rtw_set_channel(rtwdev); + rtw_flag_clear(rtwdev, RTW_FLAG_INACTIVE_PS); + + return ret; +} + +int rtw_enter_ips(struct rtw_dev *rtwdev) +{ + rtw_flag_set(rtwdev, RTW_FLAG_INACTIVE_PS); + + rtw_core_stop(rtwdev); + + return 0; +} + +static void rtw_restore_port_cfg_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct rtw_dev *rtwdev = data; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + u32 config = ~0; + + rtw_vif_port_config(rtwdev, rtwvif, config); +} + +int rtw_leave_ips(struct rtw_dev *rtwdev) +{ + int ret; + + ret = rtw_ips_pwr_up(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to leave ips state\n"); + return ret; + } + + rtw_iterate_vifs_atomic(rtwdev, rtw_restore_port_cfg_iter, rtwdev); + + return 0; +} + +static void rtw_leave_lps_core(struct rtw_dev *rtwdev) +{ + struct rtw_lps_conf *conf = &rtwdev->lps_conf; + + conf->state = RTW_ALL_ON; + conf->awake_interval = 1; + conf->rlbm = 0; + conf->smart_ps = 0; + + rtw_fw_set_pwr_mode(rtwdev); + rtw_flag_clear(rtwdev, RTW_FLAG_LEISURE_PS); +} + +static void rtw_enter_lps_core(struct rtw_dev *rtwdev) +{ + struct rtw_lps_conf *conf = &rtwdev->lps_conf; + + conf->state = RTW_RF_OFF; + conf->awake_interval = 1; + conf->rlbm = 1; + conf->smart_ps = 2; + + rtw_fw_set_pwr_mode(rtwdev); + rtw_flag_set(rtwdev, RTW_FLAG_LEISURE_PS); +} + +void rtw_lps_work(struct work_struct *work) +{ + struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, + lps_work.work); + struct rtw_lps_conf *conf = &rtwdev->lps_conf; + struct rtw_vif *rtwvif = conf->rtwvif; + + if (WARN_ON(!rtwvif)) + return; + + if (conf->mode == RTW_MODE_LPS) + rtw_enter_lps_core(rtwdev); + else + rtw_leave_lps_core(rtwdev); +} + +void rtw_enter_lps_irqsafe(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif) +{ + struct rtw_lps_conf *conf = &rtwdev->lps_conf; + + if (rtwvif->in_lps) + return; + + conf->mode = RTW_MODE_LPS; + conf->rtwvif = rtwvif; + rtwvif->in_lps = true; + + ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->lps_work, 0); +} + +void rtw_leave_lps_irqsafe(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif) +{ + struct rtw_lps_conf *conf = &rtwdev->lps_conf; + + if (!rtwvif->in_lps) + return; + + conf->mode = RTW_MODE_ACTIVE; + conf->rtwvif = rtwvif; + rtwvif->in_lps = false; + + ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->lps_work, 0); +} + +bool rtw_in_lps(struct rtw_dev *rtwdev) +{ + return rtw_flag_check(rtwdev, RTW_FLAG_LEISURE_PS); +} + +void rtw_enter_lps(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif) +{ + struct rtw_lps_conf *conf = &rtwdev->lps_conf; + + if (WARN_ON(!rtwvif)) + return; + + if (rtwvif->in_lps) + return; + + conf->mode = RTW_MODE_LPS; + conf->rtwvif = rtwvif; + rtwvif->in_lps = true; + + rtw_enter_lps_core(rtwdev); +} + +void rtw_leave_lps(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif) +{ + struct rtw_lps_conf *conf = &rtwdev->lps_conf; + + if (WARN_ON(!rtwvif)) + return; + + if (!rtwvif->in_lps) + return; + + conf->mode = RTW_MODE_ACTIVE; + conf->rtwvif = rtwvif; + rtwvif->in_lps = false; + + rtw_leave_lps_core(rtwdev); +} diff --git a/drivers/net/wireless/realtek/rtw88/ps.h b/drivers/net/wireless/realtek/rtw88/ps.h new file mode 100644 index 000000000000..09e57405dc1b --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/ps.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW_PS_H_ +#define __RTW_PS_H_ + +#define RTW_LPS_THRESHOLD 2 + +int rtw_enter_ips(struct rtw_dev *rtwdev); +int rtw_leave_ips(struct rtw_dev *rtwdev); + +void rtw_lps_work(struct work_struct *work); +void rtw_enter_lps_irqsafe(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif); +void rtw_leave_lps_irqsafe(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif); +void rtw_enter_lps(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif); +void rtw_leave_lps(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif); +bool rtw_in_lps(struct rtw_dev *rtwdev); + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h new file mode 100644 index 000000000000..e2628f05812c --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/reg.h @@ -0,0 +1,421 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW_REG_DEF_H__ +#define __RTW_REG_DEF_H__ + +#define REG_SYS_FUNC_EN 0x0002 +#define BIT_FEN_CPUEN BIT(2) +#define BIT_FEN_BB_GLB_RST BIT(1) +#define BIT_FEN_BB_RSTB BIT(0) +#define REG_SYS_PW_CTRL 0x0004 +#define REG_SYS_CLK_CTRL 0x0008 +#define BIT_CPU_CLK_EN BIT(14) + +#define REG_RSV_CTRL 0x001C +#define DISABLE_PI 0x3 +#define ENABLE_PI 0x2 +#define BITS_RFC_DIRECT (BIT(31) | BIT(30)) +#define BIT_WLMCU_IOIF BIT(0) +#define REG_RF_CTRL 0x001F +#define BIT_RF_SDM_RSTB BIT(2) +#define BIT_RF_RSTB BIT(1) +#define BIT_RF_EN BIT(0) + +#define REG_AFE_CTRL1 0x0024 +#define BIT_MAC_CLK_SEL (BIT(20) | BIT(21)) +#define REG_EFUSE_CTRL 0x0030 +#define BIT_EF_FLAG BIT(31) +#define BIT_SHIFT_EF_ADDR 8 +#define BIT_MASK_EF_ADDR 0x3ff +#define BIT_MASK_EF_DATA 0xff +#define BITS_EF_ADDR (BIT_MASK_EF_ADDR << BIT_SHIFT_EF_ADDR) + +#define REG_LDO_EFUSE_CTRL 0x0034 +#define BIT_MASK_EFUSE_BANK_SEL (BIT(8) | BIT(9)) + +#define REG_GPIO_MUXCFG 0x0040 +#define BIT_FSPI_EN BIT(19) +#define BIT_WLRFE_4_5_EN BIT(2) + +#define REG_LED_CFG 0x004C +#define BIT_LNAON_SEL_EN BIT(26) +#define BIT_PAPE_SEL_EN BIT(25) +#define REG_PAD_CTRL1 0x0064 +#define BIT_PAPE_WLBT_SEL BIT(29) +#define BIT_LNAON_WLBT_SEL BIT(28) +#define REG_WL_BT_PWR_CTRL 0x0068 +#define BIT_BT_FUNC_EN BIT(18) +#define BIT_BT_DIG_CLK_EN BIT(8) +#define REG_HCI_OPT_CTRL 0x0074 + +#define REG_MCUFW_CTRL 0x0080 +#define BIT_ANA_PORT_EN BIT(22) +#define BIT_MAC_PORT_EN BIT(21) +#define BIT_BOOT_FSPI_EN BIT(20) +#define BIT_FW_INIT_RDY BIT(15) +#define BIT_FW_DW_RDY BIT(14) +#define BIT_RPWM_TOGGLE BIT(7) +#define BIT_DMEM_CHKSUM_OK BIT(6) +#define BIT_DMEM_DW_OK BIT(5) +#define BIT_IMEM_CHKSUM_OK BIT(4) +#define BIT_IMEM_DW_OK BIT(3) +#define BIT_IMEM_BOOT_LOAD_CHECKSUM_OK BIT(2) +#define BIT_MCUFWDL_EN BIT(0) +#define BIT_CHECK_SUM_OK (BIT(4) | BIT(6)) +#define FW_READY (BIT_FW_INIT_RDY | BIT_FW_DW_RDY | \ + BIT_IMEM_DW_OK | BIT_DMEM_DW_OK | \ + BIT_CHECK_SUM_OK) +#define FW_READY_MASK 0xffff + +#define REG_WLRF1 0x00EC +#define REG_SYS_CFG1 0x00F0 +#define BIT_RTL_ID BIT(23) +#define BIT_RF_TYPE_ID BIT(27) +#define BIT_SHIFT_VENDOR_ID 16 +#define BIT_MASK_VENDOR_ID 0xf +#define BIT_VENDOR_ID(x) (((x) & BIT_MASK_VENDOR_ID) << BIT_SHIFT_VENDOR_ID) +#define BITS_VENDOR_ID (BIT_MASK_VENDOR_ID << BIT_SHIFT_VENDOR_ID) +#define BIT_CLEAR_VENDOR_ID(x) ((x) & (~BITS_VENDOR_ID)) +#define BIT_GET_VENDOR_ID(x) (((x) >> BIT_SHIFT_VENDOR_ID) & BIT_MASK_VENDOR_ID) +#define BIT_SHIFT_CHIP_VER 12 +#define BIT_MASK_CHIP_VER 0xf +#define BIT_CHIP_VER(x) (((x) & BIT_MASK_CHIP_VER) << BIT_SHIFT_CHIP_VER) +#define BITS_CHIP_VER (BIT_MASK_CHIP_VER << BIT_SHIFT_CHIP_VER) +#define BIT_CLEAR_CHIP_VER(x) ((x) & (~BITS_CHIP_VER)) +#define BIT_GET_CHIP_VER(x) (((x) >> BIT_SHIFT_CHIP_VER) & BIT_MASK_CHIP_VER) +#define REG_SYS_STATUS1 0x00F4 +#define REG_SYS_STATUS2 0x00F8 +#define REG_SYS_CFG2 0x00FC +#define REG_WLRF1 0x00EC +#define BIT_WLRF1_BBRF_EN (BIT(24) | BIT(25) | BIT(26)) +#define REG_CR 0x0100 +#define BIT_32K_CAL_TMR_EN BIT(10) +#define BIT_MAC_SEC_EN BIT(9) +#define BIT_ENSWBCN BIT(8) +#define BIT_MACRXEN BIT(7) +#define BIT_MACTXEN BIT(6) +#define BIT_SCHEDULE_EN BIT(5) +#define BIT_PROTOCOL_EN BIT(4) +#define BIT_RXDMA_EN BIT(3) +#define BIT_TXDMA_EN BIT(2) +#define BIT_HCI_RXDMA_EN BIT(1) +#define BIT_HCI_TXDMA_EN BIT(0) +#define MAC_TRX_ENABLE (BIT_HCI_TXDMA_EN | BIT_HCI_RXDMA_EN | BIT_TXDMA_EN | \ + BIT_RXDMA_EN | BIT_PROTOCOL_EN | BIT_SCHEDULE_EN | \ + BIT_MACTXEN | BIT_MACRXEN) +#define BIT_SHIFT_TXDMA_VOQ_MAP 4 +#define BIT_MASK_TXDMA_VOQ_MAP 0x3 +#define BIT_TXDMA_VOQ_MAP(x) \ + (((x) & BIT_MASK_TXDMA_VOQ_MAP) << BIT_SHIFT_TXDMA_VOQ_MAP) +#define BIT_SHIFT_TXDMA_VIQ_MAP 6 +#define BIT_MASK_TXDMA_VIQ_MAP 0x3 +#define BIT_TXDMA_VIQ_MAP(x) \ + (((x) & BIT_MASK_TXDMA_VIQ_MAP) << BIT_SHIFT_TXDMA_VIQ_MAP) +#define REG_TXDMA_PQ_MAP 0x010C +#define BIT_SHIFT_TXDMA_BEQ_MAP 8 +#define BIT_MASK_TXDMA_BEQ_MAP 0x3 +#define BIT_TXDMA_BEQ_MAP(x) \ + (((x) & BIT_MASK_TXDMA_BEQ_MAP) << BIT_SHIFT_TXDMA_BEQ_MAP) +#define BIT_SHIFT_TXDMA_BKQ_MAP 10 +#define BIT_MASK_TXDMA_BKQ_MAP 0x3 +#define BIT_TXDMA_BKQ_MAP(x) \ + (((x) & BIT_MASK_TXDMA_BKQ_MAP) << BIT_SHIFT_TXDMA_BKQ_MAP) +#define BIT_SHIFT_TXDMA_MGQ_MAP 12 +#define BIT_MASK_TXDMA_MGQ_MAP 0x3 +#define BIT_TXDMA_MGQ_MAP(x) \ + (((x) & BIT_MASK_TXDMA_MGQ_MAP) << BIT_SHIFT_TXDMA_MGQ_MAP) +#define BIT_SHIFT_TXDMA_HIQ_MAP 14 +#define BIT_MASK_TXDMA_HIQ_MAP 0x3 +#define BIT_TXDMA_HIQ_MAP(x) \ + (((x) & BIT_MASK_TXDMA_HIQ_MAP) << BIT_SHIFT_TXDMA_HIQ_MAP) +#define BIT_SHIFT_TXSC_40M 4 +#define BIT_MASK_TXSC_40M 0xf +#define BIT_TXSC_40M(x) \ + (((x) & BIT_MASK_TXSC_40M) << BIT_SHIFT_TXSC_40M) +#define BIT_SHIFT_TXSC_20M 0 +#define BIT_MASK_TXSC_20M 0xf +#define BIT_TXSC_20M(x) \ + (((x) & BIT_MASK_TXSC_20M) << BIT_SHIFT_TXSC_20M) +#define BIT_SHIFT_MAC_CLK_SEL 20 +#define MAC_CLK_HW_DEF_80M 0 +#define MAC_CLK_HW_DEF_40M 1 +#define MAC_CLK_HW_DEF_20M 2 +#define MAC_CLK_SPEED 80 + +#define REG_CR 0x0100 +#define REG_TRXFF_BNDY 0x0114 +#define REG_RXFF_BNDY 0x011C +#define REG_PKTBUF_DBG_CTRL 0x0140 +#define REG_C2HEVT 0x01A0 +#define REG_HMETFR 0x01CC +#define REG_HMEBOX0 0x01D0 +#define REG_HMEBOX1 0x01D4 +#define REG_HMEBOX2 0x01D8 +#define REG_HMEBOX3 0x01DC +#define REG_HMEBOX0_EX 0x01F0 +#define REG_HMEBOX1_EX 0x01F4 +#define REG_HMEBOX2_EX 0x01F8 +#define REG_HMEBOX3_EX 0x01FC + +#define REG_FIFOPAGE_CTRL_2 0x0204 +#define BIT_BCN_VALID_V1 BIT(15) +#define BIT_MASK_BCN_HEAD_1_V1 0xfff +#define REG_AUTO_LLT_V1 0x0208 +#define BIT_AUTO_INIT_LLT_V1 BIT(0) +#define REG_TXDMA_OFFSET_CHK 0x020C +#define REG_TXDMA_STATUS 0x0210 +#define BTI_PAGE_OVF BIT(2) +#define REG_RQPN_CTRL_1 0x0228 +#define REG_RQPN_CTRL_2 0x022C +#define BIT_LD_RQPN BIT(31) +#define REG_FIFOPAGE_INFO_1 0x0230 +#define REG_FIFOPAGE_INFO_2 0x0234 +#define REG_FIFOPAGE_INFO_3 0x0238 +#define REG_FIFOPAGE_INFO_4 0x023C +#define REG_FIFOPAGE_INFO_5 0x0240 +#define REG_H2C_HEAD 0x0244 +#define REG_H2C_TAIL 0x0248 +#define REG_H2C_READ_ADDR 0x024C +#define REG_H2C_INFO 0x0254 + +#define REG_FWHW_TXQ_CTRL 0x0420 +#define BIT_EN_BCNQ_DL BIT(22) +#define BIT_EN_WR_FREE_TAIL BIT(20) +#define REG_BCNQ_BDNY_V1 0x0424 +#define REG_LIFETIME_EN 0x0426 +#define BIT_BA_PARSER_EN BIT(5) +#define REG_SPEC_SIFS 0x0428 +#define REG_DARFRC 0x0430 +#define REG_DARFRCH 0x0434 +#define REG_RARFRCH 0x043C +#define REG_ARFR0 0x0444 +#define REG_ARFRH0 0x0448 +#define REG_ARFR1_V1 0x044C +#define REG_ARFRH1_V1 0x0450 +#define REG_CCK_CHECK 0x0454 +#define BIT_CHECK_CCK_EN BIT(7) +#define REG_AMPDU_MAX_TIME_V1 0x0455 +#define REG_BCNQ1_BDNY_V1 0x0456 +#define REG_TX_HANG_CTRL 0x045E +#define BIT_EN_EOF_V1 BIT(2) +#define REG_DATA_SC 0x0483 +#define REG_ARFR4 0x049C +#define REG_ARFRH4 0x04A0 +#define REG_ARFR5 0x04A4 +#define REG_ARFRH5 0x04A8 +#define REG_SW_AMPDU_BURST_MODE_CTRL 0x04BC +#define BIT_PRE_TX_CMD BIT(6) +#define REG_PROT_MODE_CTRL 0x04C8 +#define REG_BAR_MODE_CTRL 0x04CC +#define REG_PRECNT_CTRL 0x04E5 +#define BIT_EN_PRECNT BIT(11) + +#define REG_EDCA_VO_PARAM 0x0500 +#define REG_EDCA_VI_PARAM 0x0504 +#define REG_EDCA_BE_PARAM 0x0508 +#define REG_EDCA_BK_PARAM 0x050C +#define REG_PIFS 0x0512 +#define REG_SIFS 0x0514 +#define BIT_SHIFT_SIFS_OFDM_CTX 8 +#define BIT_SHIFT_SIFS_CCK_TRX 16 +#define BIT_SHIFT_SIFS_OFDM_TRX 24 +#define REG_SLOT 0x051B +#define REG_TX_PTCL_CTRL 0x0520 +#define BIT_SIFS_BK_EN BIT(12) +#define REG_TXPAUSE 0x0522 +#define REG_RD_CTRL 0x0524 +#define BIT_DIS_TXOP_CFE BIT(10) +#define BIT_DIS_LSIG_CFE BIT(9) +#define BIT_DIS_STBC_CFE BIT(8) +#define REG_TBTT_PROHIBIT 0x0540 +#define BIT_SHIFT_TBTT_HOLD_TIME_AP 8 +#define REG_RD_NAV_NXT 0x0544 +#define REG_BCN_CTRL 0x0550 +#define BIT_DIS_TSF_UDT BIT(4) +#define BIT_EN_BCN_FUNCTION BIT(3) +#define REG_BCN_CTRL_CLINT0 0x0551 +#define REG_DRVERLYINT 0x0558 +#define REG_BCNDMATIM 0x0559 +#define REG_USTIME_TSF 0x055C +#define REG_BCN_MAX_ERR 0x055D +#define REG_RXTSF_OFFSET_CCK 0x055E +#define REG_MISC_CTRL 0x0577 +#define BIT_EN_FREE_CNT BIT(3) +#define BIT_DIS_SECOND_CCA (BIT(0) | BIT(1)) +#define REG_TIMER0_SRC_SEL 0x05B4 +#define BIT_TSFT_SEL_TIMER0 (BIT(4) | BIT(5) | BIT(6)) + +#define REG_TCR 0x0604 +#define REG_RCR 0x0608 +#define BIT_APP_FCS BIT(31) +#define BIT_APP_MIC BIT(30) +#define BIT_APP_ICV BIT(29) +#define BIT_APP_PHYSTS BIT(28) +#define BIT_APP_BASSN BIT(27) +#define BIT_VHT_DACK BIT(26) +#define BIT_TCPOFLD_EN BIT(25) +#define BIT_ENMBID BIT(24) +#define BIT_LSIGEN BIT(23) +#define BIT_MFBEN BIT(22) +#define BIT_DISCHKPPDLLEN BIT(21) +#define BIT_PKTCTL_DLEN BIT(20) +#define BIT_TIM_PARSER_EN BIT(18) +#define BIT_BC_MD_EN BIT(17) +#define BIT_UC_MD_EN BIT(16) +#define BIT_RXSK_PERPKT BIT(15) +#define BIT_HTC_LOC_CTRL BIT(14) +#define BIT_RPFM_CAM_ENABLE BIT(12) +#define BIT_TA_BCN BIT(11) +#define BIT_DISDECMYPKT BIT(10) +#define BIT_AICV BIT(9) +#define BIT_ACRC32 BIT(8) +#define BIT_CBSSID_BCN BIT(7) +#define BIT_CBSSID_DATA BIT(6) +#define BIT_APWRMGT BIT(5) +#define BIT_ADD3 BIT(4) +#define BIT_AB BIT(3) +#define BIT_AM BIT(2) +#define BIT_APM BIT(1) +#define BIT_AAP BIT(0) +#define REG_RX_PKT_LIMIT 0x060C +#define REG_RX_DRVINFO_SZ 0x060F +#define BIT_APP_PHYSTS BIT(28) +#define REG_USTIME_EDCA 0x0638 +#define REG_ACKTO_CCK 0x0639 +#define REG_RESP_SIFS_CCK 0x063C +#define REG_RESP_SIFS_OFDM 0x063E +#define REG_ACKTO 0x0640 +#define REG_EIFS 0x0642 +#define REG_NAV_CTRL 0x0650 +#define REG_WMAC_TRXPTCL_CTL 0x0668 +#define BIT_RFMOD (BIT(7) | BIT(8)) +#define BIT_RFMOD_80M BIT(8) +#define BIT_RFMOD_40M BIT(7) +#define REG_WMAC_TRXPTCL_CTL_H 0x066C +#define REG_RXFLTMAP0 0x06A0 +#define REG_RXFLTMAP1 0x06A2 +#define REG_RXFLTMAP2 0x06A4 +#define REG_BBPSF_CTRL 0x06DC + +#define REG_WMAC_OPTION_FUNCTION 0x07D0 +#define REG_WMAC_OPTION_FUNCTION_1 0x07D4 + +#define REG_ANAPAR_XTAL_0 0x1040 +#define REG_CPU_DMEM_CON 0x1080 +#define BIT_WL_PLATFORM_RST BIT(16) +#define BIT_WL_SECURITY_CLK BIT(15) +#define BIT_DDMA_EN BIT(8) + +#define REG_H2C_PKT_READADDR 0x10D0 +#define REG_H2C_PKT_WRITEADDR 0x10D4 +#define REG_FW_DBG7 0x10FC +#define FW_KEY_MASK 0xffffff00 + +#define REG_CR_EXT 0x1100 + +#define REG_DDMA_CH0SA 0x1200 +#define REG_DDMA_CH0DA 0x1204 +#define REG_DDMA_CH0CTRL 0x1208 +#define BIT_DDMACH0_OWN BIT(31) +#define BIT_DDMACH0_CHKSUM_EN BIT(29) +#define BIT_DDMACH0_CHKSUM_STS BIT(27) +#define BIT_DDMACH0_RESET_CHKSUM_STS BIT(25) +#define BIT_DDMACH0_CHKSUM_CONT BIT(24) +#define BIT_MASK_DDMACH0_DLEN 0x3ffff + +#define REG_H2CQ_CSR 0x1330 +#define BIT_H2CQ_FULL BIT(31) +#define REG_FAST_EDCA_VOVI_SETTING 0x1448 +#define REG_FAST_EDCA_BEBK_SETTING 0x144C + +#define REG_RXPSF_CTRL 0x1610 +#define BIT_RXGCK_FIFOTHR_EN BIT(28) + +#define BIT_SHIFT_RXGCK_VHT_FIFOTHR 26 +#define BIT_MASK_RXGCK_VHT_FIFOTHR 0x3 +#define BIT_RXGCK_VHT_FIFOTHR(x) \ + (((x) & BIT_MASK_RXGCK_VHT_FIFOTHR) << BIT_SHIFT_RXGCK_VHT_FIFOTHR) +#define BITS_RXGCK_VHT_FIFOTHR \ + (BIT_MASK_RXGCK_VHT_FIFOTHR << BIT_SHIFT_RXGCK_VHT_FIFOTHR) + +#define BIT_SHIFT_RXGCK_HT_FIFOTHR 24 +#define BIT_MASK_RXGCK_HT_FIFOTHR 0x3 +#define BIT_RXGCK_HT_FIFOTHR(x) \ + (((x) & BIT_MASK_RXGCK_HT_FIFOTHR) << BIT_SHIFT_RXGCK_HT_FIFOTHR) +#define BITS_RXGCK_HT_FIFOTHR \ + (BIT_MASK_RXGCK_HT_FIFOTHR << BIT_SHIFT_RXGCK_HT_FIFOTHR) + +#define BIT_SHIFT_RXGCK_OFDM_FIFOTHR 22 +#define BIT_MASK_RXGCK_OFDM_FIFOTHR 0x3 +#define BIT_RXGCK_OFDM_FIFOTHR(x) \ + (((x) & BIT_MASK_RXGCK_OFDM_FIFOTHR) << BIT_SHIFT_RXGCK_OFDM_FIFOTHR) +#define BITS_RXGCK_OFDM_FIFOTHR \ + (BIT_MASK_RXGCK_OFDM_FIFOTHR << BIT_SHIFT_RXGCK_OFDM_FIFOTHR) + +#define BIT_SHIFT_RXGCK_CCK_FIFOTHR 20 +#define BIT_MASK_RXGCK_CCK_FIFOTHR 0x3 +#define BIT_RXGCK_CCK_FIFOTHR(x) \ + (((x) & BIT_MASK_RXGCK_CCK_FIFOTHR) << BIT_SHIFT_RXGCK_CCK_FIFOTHR) +#define BITS_RXGCK_CCK_FIFOTHR \ + (BIT_MASK_RXGCK_CCK_FIFOTHR << BIT_SHIFT_RXGCK_CCK_FIFOTHR) + +#define BIT_RXGCK_OFDMCCA_EN BIT(16) + +#define BIT_SHIFT_RXPSF_PKTLENTHR 13 +#define BIT_MASK_RXPSF_PKTLENTHR 0x7 +#define BIT_RXPSF_PKTLENTHR(x) \ + (((x) & BIT_MASK_RXPSF_PKTLENTHR) << BIT_SHIFT_RXPSF_PKTLENTHR) +#define BITS_RXPSF_PKTLENTHR \ + (BIT_MASK_RXPSF_PKTLENTHR << BIT_SHIFT_RXPSF_PKTLENTHR) +#define BIT_CLEAR_RXPSF_PKTLENTHR(x) ((x) & (~BITS_RXPSF_PKTLENTHR)) +#define BIT_SET_RXPSF_PKTLENTHR(x, v) \ + (BIT_CLEAR_RXPSF_PKTLENTHR(x) | BIT_RXPSF_PKTLENTHR(v)) + +#define BIT_RXPSF_CTRLEN BIT(12) +#define BIT_RXPSF_VHTCHKEN BIT(11) +#define BIT_RXPSF_HTCHKEN BIT(10) +#define BIT_RXPSF_OFDMCHKEN BIT(9) +#define BIT_RXPSF_CCKCHKEN BIT(8) +#define BIT_RXPSF_OFDMRST BIT(7) +#define BIT_RXPSF_CCKRST BIT(6) +#define BIT_RXPSF_MHCHKEN BIT(5) +#define BIT_RXPSF_CONT_ERRCHKEN BIT(4) +#define BIT_RXPSF_ALL_ERRCHKEN BIT(3) + +#define BIT_SHIFT_RXPSF_ERRTHR 0 +#define BIT_MASK_RXPSF_ERRTHR 0x7 +#define BIT_RXPSF_ERRTHR(x) \ + (((x) & BIT_MASK_RXPSF_ERRTHR) << BIT_SHIFT_RXPSF_ERRTHR) +#define BITS_RXPSF_ERRTHR (BIT_MASK_RXPSF_ERRTHR << BIT_SHIFT_RXPSF_ERRTHR) +#define BIT_CLEAR_RXPSF_ERRTHR(x) ((x) & (~BITS_RXPSF_ERRTHR)) +#define BIT_GET_RXPSF_ERRTHR(x) \ + (((x) >> BIT_SHIFT_RXPSF_ERRTHR) & BIT_MASK_RXPSF_ERRTHR) +#define BIT_SET_RXPSF_ERRTHR(x, v) \ + (BIT_CLEAR_RXPSF_ERRTHR(x) | BIT_RXPSF_ERRTHR(v)) + +#define REG_RXPSF_TYPE_CTRL 0x1614 +#define REG_GENERAL_OPTION 0x1664 +#define BIT_DUMMY_FCS_READY_MASK_EN BIT(9) + +#define REG_WL2LTECOEX_INDIRECT_ACCESS_CTRL_V1 0x1700 +#define REG_WL2LTECOEX_INDIRECT_ACCESS_WRITE_DATA_V1 0x1704 +#define REG_WL2LTECOEX_INDIRECT_ACCESS_READ_DATA_V1 0x1708 +#define LTECOEX_READY BIT(29) +#define LTECOEX_ACCESS_CTRL REG_WL2LTECOEX_INDIRECT_ACCESS_CTRL_V1 +#define LTECOEX_WRITE_DATA REG_WL2LTECOEX_INDIRECT_ACCESS_WRITE_DATA_V1 +#define LTECOEX_READ_DATA REG_WL2LTECOEX_INDIRECT_ACCESS_READ_DATA_V1 + +#define RF_DTXLOK 0x08 +#define RF_CFGCH 0x18 +#define RF_LUTWA 0x33 +#define RF_LUTWD1 0x3e +#define RF_LUTWD0 0x3f +#define RF_XTALX2 0xb8 +#define RF_MALSEL 0xbe +#define RF_LUTDBG 0xdf +#define RF_LUTWE2 0xee +#define RF_LUTWE 0xef + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/regd.c b/drivers/net/wireless/realtek/rtw88/regd.c new file mode 100644 index 000000000000..e7750a833a8e --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/regd.c @@ -0,0 +1,391 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "regd.h" +#include "debug.h" +#include "phy.h" + +#define COUNTRY_CHPLAN_ENT(_alpha2, _chplan, _txpwr_regd) \ + {.alpha2 = (_alpha2), \ + .chplan = (_chplan), \ + .txpwr_regd = (_txpwr_regd) \ + } + +/* If country code is not correctly defined in efuse, + * use worldwide country code and txpwr regd. + */ +static const struct rtw_regulatory rtw_defined_chplan = + COUNTRY_CHPLAN_ENT("00", RTW_CHPLAN_REALTEK_DEFINE, RTW_REGD_WW); + +static const struct rtw_regulatory all_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("AE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("AF", RTW_CHPLAN_ETSI1_ETSI4, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("AG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("AI", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("AL", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("AM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("AN", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("AO", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("AQ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("AR", RTW_CHPLAN_FCC2_FCC7, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("AS", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("AT", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("AU", RTW_CHPLAN_WORLD_ACMA1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("AW", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("AZ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("BA", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("BB", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("BD", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("BE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("BF", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("BG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("BH", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("BI", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("BJ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("BN", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("BO", RTW_CHPLAN_WORLD_FCC7, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("BR", RTW_CHPLAN_FCC2_FCC1, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("BS", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("BW", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("BY", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("BZ", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("CA", RTW_CHPLAN_IC1_IC2, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("CC", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("CD", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("CF", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("CG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("CH", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("CI", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("CK", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("CL", RTW_CHPLAN_WORLD_CHILE1, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("CM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("CN", RTW_CHPLAN_WORLD_ETSI7, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("CO", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("CR", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("CV", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("CX", RTW_CHPLAN_WORLD_ACMA1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("CY", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("CZ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("DE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("DJ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("DK", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("DM", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("DO", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("DZ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("EC", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("EE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("EG", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("EH", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("ER", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("ES", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("ET", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("FI", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("FJ", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("FK", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("FM", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("FO", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("FR", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("GA", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("GB", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("GD", RTW_CHPLAN_FCC1_FCC7, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("GE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("GF", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("GG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("GH", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("GI", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("GL", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("GM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("GN", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("GP", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("GQ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("GR", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("GS", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("GT", RTW_CHPLAN_FCC2_FCC7, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("GU", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("GW", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("GY", RTW_CHPLAN_FCC1_NCC3, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("HK", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("HM", RTW_CHPLAN_WORLD_ACMA1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("HN", RTW_CHPLAN_WORLD_FCC5, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("HR", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("HT", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("HU", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("ID", RTW_CHPLAN_ETSI1_ETSI12, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("IE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("IL", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("IM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("IN", RTW_CHPLAN_WORLD_ETSI7, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("IQ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("IR", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("IS", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("IT", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("JE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("JM", RTW_CHPLAN_WORLD_ETSI10, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("JO", RTW_CHPLAN_WORLD_ETSI8, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("JP", RTW_CHPLAN_MKK1_MKK1, RTW_REGD_MKK), + COUNTRY_CHPLAN_ENT("KE", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("KG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("KH", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("KI", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("KN", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("KR", RTW_CHPLAN_KCC1_KCC2, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("KW", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("KY", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("KZ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("LA", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("LB", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("LC", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("LI", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("LK", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("LR", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("LS", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("LT", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("LU", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("LV", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("LY", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MA", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MC", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MD", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("ME", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MF", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("MG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MH", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("MK", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("ML", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MN", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MO", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MP", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("MQ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MR", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MS", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MT", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MU", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MV", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MW", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MX", RTW_CHPLAN_FCC2_FCC7, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("MY", RTW_CHPLAN_WORLD_ETSI20, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("MZ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("NA", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("NC", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("NE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("NF", RTW_CHPLAN_WORLD_ACMA1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("NG", RTW_CHPLAN_WORLD_ETSI20, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("NI", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("NL", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("NO", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("NP", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("NR", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("NU", RTW_CHPLAN_WORLD_ACMA1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("NZ", RTW_CHPLAN_WORLD_ACMA1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("OM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("PA", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("PE", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("PF", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("PG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("PH", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("PK", RTW_CHPLAN_WORLD_ETSI10, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("PL", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("PM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("PR", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("PT", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("PW", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("PY", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("QA", RTW_CHPLAN_WORLD_ETSI10, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("RE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("RO", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("RS", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("RU", RTW_CHPLAN_WORLD_ETSI14, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("RW", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("SA", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("SB", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("SC", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("SE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("SG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("SH", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("SI", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("SJ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("SK", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("SL", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("SM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("SN", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("SO", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("SR", RTW_CHPLAN_FCC2_FCC17, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("ST", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("SV", RTW_CHPLAN_WORLD_FCC3, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("SX", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("SZ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("TC", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("TD", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("TF", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("TG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("TH", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("TJ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("TK", RTW_CHPLAN_WORLD_ACMA1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("TM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("TN", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("TO", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("TR", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("TT", RTW_CHPLAN_ETSI1_ETSI4, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("TW", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("TZ", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("UA", RTW_CHPLAN_WORLD_ETSI3, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("UG", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("US", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("UY", RTW_CHPLAN_WORLD_FCC3, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("UZ", RTW_CHPLAN_WORLD_ETSI6, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("VA", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("VC", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("VE", RTW_CHPLAN_WORLD_FCC3, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("VI", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("VN", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("VU", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("WF", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("WS", RTW_CHPLAN_FCC2_FCC11, RTW_REGD_FCC), + COUNTRY_CHPLAN_ENT("YE", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("YT", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("ZA", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("ZM", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), + COUNTRY_CHPLAN_ENT("ZW", RTW_CHPLAN_WORLD_ETSI1, RTW_REGD_ETSI), +}; + +static void rtw_regd_apply_beaconing_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) +{ + enum nl80211_band band; + struct ieee80211_supported_band *sband; + const struct ieee80211_reg_rule *reg_rule; + struct ieee80211_channel *ch; + unsigned int i; + + for (band = 0; band < NUM_NL80211_BANDS; band++) { + if (!wiphy->bands[band]) + continue; + + sband = wiphy->bands[band]; + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + + reg_rule = freq_reg_info(wiphy, + MHZ_TO_KHZ(ch->center_freq)); + if (IS_ERR(reg_rule)) + continue; + + ch->flags &= ~IEEE80211_CHAN_DISABLED; + + if (!(reg_rule->flags & NL80211_RRF_NO_IR)) + ch->flags &= ~IEEE80211_CHAN_NO_IR; + } + } +} + +static void rtw_regd_apply_hw_cap_flags(struct wiphy *wiphy) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + struct rtw_dev *rtwdev = hw->priv; + struct rtw_efuse *efuse = &rtwdev->efuse; + int i; + + if (efuse->hw_cap.bw & BIT(RTW_CHANNEL_WIDTH_80)) + return; + + sband = wiphy->bands[NL80211_BAND_2GHZ]; + if (!sband) + goto out_5g; + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + ch->flags |= IEEE80211_CHAN_NO_80MHZ; + } + +out_5g: + sband = wiphy->bands[NL80211_BAND_5GHZ]; + if (!sband) + return; + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + ch->flags |= IEEE80211_CHAN_NO_80MHZ; + } +} + +static void rtw_regd_apply_world_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) +{ + rtw_regd_apply_beaconing_flags(wiphy, initiator); +} + +static struct rtw_regulatory rtw_regd_find_reg_by_name(char *alpha2) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(all_chplan_map); i++) { + if (!memcmp(all_chplan_map[i].alpha2, alpha2, 2)) + return all_chplan_map[i]; + } + + return rtw_defined_chplan; +} + +static int rtw_regd_notifier_apply(struct rtw_dev *rtwdev, + struct wiphy *wiphy, + struct regulatory_request *request) +{ + if (request->initiator == NL80211_REGDOM_SET_BY_USER) + return 0; + rtwdev->regd = rtw_regd_find_reg_by_name(request->alpha2); + rtw_regd_apply_world_flags(wiphy, request->initiator); + + return 0; +} + +static int +rtw_regd_init_wiphy(struct rtw_regulatory *reg, struct wiphy *wiphy, + void (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request)) +{ + wiphy->reg_notifier = reg_notifier; + + wiphy->regulatory_flags &= ~REGULATORY_CUSTOM_REG; + wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG; + wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS; + + rtw_regd_apply_hw_cap_flags(wiphy); + + return 0; +} + +int rtw_regd_init(struct rtw_dev *rtwdev, + void (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request)) +{ + struct wiphy *wiphy = rtwdev->hw->wiphy; + + if (!wiphy) + return -EINVAL; + + rtwdev->regd = rtw_regd_find_reg_by_name(rtwdev->efuse.country_code); + rtw_regd_init_wiphy(&rtwdev->regd, wiphy, reg_notifier); + + return 0; +} + +void rtw_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct rtw_dev *rtwdev = hw->priv; + struct rtw_hal *hal = &rtwdev->hal; + + rtw_regd_notifier_apply(rtwdev, wiphy, request); + rtw_dbg(rtwdev, RTW_DBG_REGD, + "get alpha2 %c%c from initiator %d, mapping to chplan 0x%x, txregd %d\n", + request->alpha2[0], request->alpha2[1], request->initiator, + rtwdev->regd.chplan, rtwdev->regd.txpwr_regd); + + rtw_phy_set_tx_power_level(rtwdev, hal->current_channel); +} diff --git a/drivers/net/wireless/realtek/rtw88/regd.h b/drivers/net/wireless/realtek/rtw88/regd.h new file mode 100644 index 000000000000..7784bb6d3ba7 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/regd.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW_REGD_H_ +#define __RTW_REGD_H_ + +#define IEEE80211_CHAN_NO_IBSS IEEE80211_CHAN_NO_IR +#define IEEE80211_CHAN_PASSIVE_SCAN IEEE80211_CHAN_NO_IR +enum rtw_chplan_id { + RTW_CHPLAN_WORLD_ETSI1 = 0x26, + RTW_CHPLAN_MKK1_MKK1 = 0x27, + RTW_CHPLAN_IC1_IC2 = 0x2B, + RTW_CHPLAN_WORLD_CHILE1 = 0x2D, + RTW_CHPLAN_WORLD_FCC3 = 0x30, + RTW_CHPLAN_WORLD_FCC5 = 0x32, + RTW_CHPLAN_FCC1_FCC7 = 0x34, + RTW_CHPLAN_WORLD_ETSI3 = 0x36, + RTW_CHPLAN_ETSI1_ETSI12 = 0x3D, + RTW_CHPLAN_KCC1_KCC2 = 0x3E, + RTW_CHPLAN_ETSI1_ETSI4 = 0x42, + RTW_CHPLAN_FCC1_NCC3 = 0x44, + RTW_CHPLAN_WORLD_ACMA1 = 0x45, + RTW_CHPLAN_WORLD_ETSI6 = 0x47, + RTW_CHPLAN_WORLD_ETSI7 = 0x48, + RTW_CHPLAN_WORLD_ETSI8 = 0x49, + RTW_CHPLAN_WORLD_ETSI10 = 0x51, + RTW_CHPLAN_WORLD_ETSI14 = 0x59, + RTW_CHPLAN_FCC2_FCC7 = 0x61, + RTW_CHPLAN_FCC2_FCC1 = 0x62, + RTW_CHPLAN_WORLD_FCC7 = 0x73, + RTW_CHPLAN_FCC2_FCC17 = 0x74, + RTW_CHPLAN_WORLD_ETSI20 = 0x75, + RTW_CHPLAN_FCC2_FCC11 = 0x76, + RTW_CHPLAN_REALTEK_DEFINE = 0x7f, +}; + +struct country_code_to_enum_rd { + u16 countrycode; + const char *iso_name; +}; + +enum country_code_type { + COUNTRY_CODE_FCC = 0, + COUNTRY_CODE_IC = 1, + COUNTRY_CODE_ETSI = 2, + COUNTRY_CODE_SPAIN = 3, + COUNTRY_CODE_FRANCE = 4, + COUNTRY_CODE_MKK = 5, + COUNTRY_CODE_MKK1 = 6, + COUNTRY_CODE_ISRAEL = 7, + COUNTRY_CODE_TELEC = 8, + COUNTRY_CODE_MIC = 9, + COUNTRY_CODE_GLOBAL_DOMAIN = 10, + COUNTRY_CODE_WORLD_WIDE_13 = 11, + COUNTRY_CODE_TELEC_NETGEAR = 12, + COUNTRY_CODE_WORLD_WIDE_13_5G_ALL = 13, + + /* new channel plan above this */ + COUNTRY_CODE_MAX +}; + +int rtw_regd_init(struct rtw_dev *rtwdev, + void (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request)); +void rtw_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request); +#endif diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c new file mode 100644 index 000000000000..1172f6c0605b --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -0,0 +1,1594 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "fw.h" +#include "tx.h" +#include "rx.h" +#include "phy.h" +#include "rtw8822b.h" +#include "rtw8822b_table.h" +#include "mac.h" +#include "reg.h" +#include "debug.h" + +static void rtw8822b_config_trx_mode(struct rtw_dev *rtwdev, u8 tx_path, + u8 rx_path, bool is_tx2_path); + +static void rtw8822be_efuse_parsing(struct rtw_efuse *efuse, + struct rtw8822b_efuse *map) +{ + ether_addr_copy(efuse->addr, map->e.mac_addr); +} + +static int rtw8822b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw8822b_efuse *map; + int i; + + map = (struct rtw8822b_efuse *)log_map; + + efuse->rfe_option = map->rfe_option; + efuse->crystal_cap = map->xtal_k; + efuse->pa_type_2g = map->pa_type; + efuse->pa_type_5g = map->pa_type; + efuse->lna_type_2g = map->lna_type_2g[0]; + efuse->lna_type_5g = map->lna_type_5g[0]; + efuse->channel_plan = map->channel_plan; + efuse->country_code[0] = map->country_code[0]; + efuse->country_code[1] = map->country_code[1]; + efuse->bt_setting = map->rf_bt_setting; + efuse->regd = map->rf_board_option & 0x7; + + for (i = 0; i < 4; i++) + efuse->txpwr_idx_table[i] = map->txpwr_idx_table[i]; + + switch (rtw_hci_type(rtwdev)) { + case RTW_HCI_TYPE_PCIE: + rtw8822be_efuse_parsing(efuse, map); + break; + default: + /* unsupported now */ + return -ENOTSUPP; + } + + return 0; +} + +static void rtw8822b_phy_rfe_init(struct rtw_dev *rtwdev) +{ + /* chip top mux */ + rtw_write32_mask(rtwdev, 0x64, BIT(29) | BIT(28), 0x3); + rtw_write32_mask(rtwdev, 0x4c, BIT(26) | BIT(25), 0x0); + rtw_write32_mask(rtwdev, 0x40, BIT(2), 0x1); + + /* from s0 or s1 */ + rtw_write32_mask(rtwdev, 0x1990, 0x3f, 0x30); + rtw_write32_mask(rtwdev, 0x1990, (BIT(11) | BIT(10)), 0x3); + + /* input or output */ + rtw_write32_mask(rtwdev, 0x974, 0x3f, 0x3f); + rtw_write32_mask(rtwdev, 0x974, (BIT(11) | BIT(10)), 0x3); +} + +static void rtw8822b_phy_set_param(struct rtw_dev *rtwdev) +{ + struct rtw_hal *hal = &rtwdev->hal; + u8 crystal_cap; + bool is_tx2_path; + + /* power on BB/RF domain */ + rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, + BIT_FEN_BB_RSTB | BIT_FEN_BB_GLB_RST); + rtw_write8_set(rtwdev, REG_RF_CTRL, + BIT_RF_EN | BIT_RF_RSTB | BIT_RF_SDM_RSTB); + rtw_write32_set(rtwdev, REG_WLRF1, BIT_WLRF1_BBRF_EN); + + /* pre init before header files config */ + rtw_write32_clr(rtwdev, REG_RXPSEL, BIT_RX_PSEL_RST); + + rtw_phy_load_tables(rtwdev); + + crystal_cap = rtwdev->efuse.crystal_cap & 0x3F; + rtw_write32_mask(rtwdev, 0x24, 0x7e000000, crystal_cap); + rtw_write32_mask(rtwdev, 0x28, 0x7e, crystal_cap); + + /* post init after header files config */ + rtw_write32_set(rtwdev, REG_RXPSEL, BIT_RX_PSEL_RST); + + is_tx2_path = false; + rtw8822b_config_trx_mode(rtwdev, hal->antenna_tx, hal->antenna_rx, + is_tx2_path); + rtw_phy_init(rtwdev); + + rtw8822b_phy_rfe_init(rtwdev); + + /* wifi path controller */ + rtw_write32_mask(rtwdev, 0x70, 0x4000000, 1); + /* BB control */ + rtw_write32_mask(rtwdev, 0x4c, 0x01800000, 0x2); + /* antenna mux switch */ + rtw_write8(rtwdev, 0x974, 0xff); + rtw_write32_mask(rtwdev, 0x1990, 0x300, 0); + rtw_write32_mask(rtwdev, 0xcbc, 0x80000, 0x0); + /* SW control */ + rtw_write8(rtwdev, 0xcb4, 0x77); + /* switch to WL side controller and gnt_wl gnt_bt debug signal */ + rtw_write32_mask(rtwdev, 0x70, 0xff000000, 0x0e); + /* gnt_wl = 1, gnt_bt = 0 */ + rtw_write32(rtwdev, 0x1704, 0x7700); + rtw_write32(rtwdev, 0x1700, 0xc00f0038); + /* switch for WL 2G */ + rtw_write8(rtwdev, 0xcbd, 0x2); +} + +#define WLAN_SLOT_TIME 0x09 +#define WLAN_PIFS_TIME 0x19 +#define WLAN_SIFS_CCK_CONT_TX 0xA +#define WLAN_SIFS_OFDM_CONT_TX 0xE +#define WLAN_SIFS_CCK_TRX 0x10 +#define WLAN_SIFS_OFDM_TRX 0x10 +#define WLAN_VO_TXOP_LIMIT 0x186 /* unit : 32us */ +#define WLAN_VI_TXOP_LIMIT 0x3BC /* unit : 32us */ +#define WLAN_RDG_NAV 0x05 +#define WLAN_TXOP_NAV 0x1B +#define WLAN_CCK_RX_TSF 0x30 +#define WLAN_OFDM_RX_TSF 0x30 +#define WLAN_TBTT_PROHIBIT 0x04 /* unit : 32us */ +#define WLAN_TBTT_HOLD_TIME 0x064 /* unit : 32us */ +#define WLAN_DRV_EARLY_INT 0x04 +#define WLAN_BCN_DMA_TIME 0x02 + +#define WLAN_RX_FILTER0 0x0FFFFFFF +#define WLAN_RX_FILTER2 0xFFFF +#define WLAN_RCR_CFG 0xE400220E +#define WLAN_RXPKT_MAX_SZ 12288 +#define WLAN_RXPKT_MAX_SZ_512 (WLAN_RXPKT_MAX_SZ >> 9) + +#define WLAN_AMPDU_MAX_TIME 0x70 +#define WLAN_RTS_LEN_TH 0xFF +#define WLAN_RTS_TX_TIME_TH 0x08 +#define WLAN_MAX_AGG_PKT_LIMIT 0x20 +#define WLAN_RTS_MAX_AGG_PKT_LIMIT 0x20 +#define FAST_EDCA_VO_TH 0x06 +#define FAST_EDCA_VI_TH 0x06 +#define FAST_EDCA_BE_TH 0x06 +#define FAST_EDCA_BK_TH 0x06 +#define WLAN_BAR_RETRY_LIMIT 0x01 +#define WLAN_RA_TRY_RATE_AGG_LIMIT 0x08 + +#define WLAN_TX_FUNC_CFG1 0x30 +#define WLAN_TX_FUNC_CFG2 0x30 +#define WLAN_MAC_OPT_NORM_FUNC1 0x98 +#define WLAN_MAC_OPT_LB_FUNC1 0x80 +#define WLAN_MAC_OPT_FUNC2 0x30810041 + +#define WLAN_SIFS_CFG (WLAN_SIFS_CCK_CONT_TX | \ + (WLAN_SIFS_OFDM_CONT_TX << BIT_SHIFT_SIFS_OFDM_CTX) | \ + (WLAN_SIFS_CCK_TRX << BIT_SHIFT_SIFS_CCK_TRX) | \ + (WLAN_SIFS_OFDM_TRX << BIT_SHIFT_SIFS_OFDM_TRX)) + +#define WLAN_TBTT_TIME (WLAN_TBTT_PROHIBIT |\ + (WLAN_TBTT_HOLD_TIME << BIT_SHIFT_TBTT_HOLD_TIME_AP)) + +#define WLAN_NAV_CFG (WLAN_RDG_NAV | (WLAN_TXOP_NAV << 16)) +#define WLAN_RX_TSF_CFG (WLAN_CCK_RX_TSF | (WLAN_OFDM_RX_TSF) << 8) + +static int rtw8822b_mac_init(struct rtw_dev *rtwdev) +{ + u32 value32; + + /* protocol configuration */ + rtw_write8_clr(rtwdev, REG_SW_AMPDU_BURST_MODE_CTRL, BIT_PRE_TX_CMD); + rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, WLAN_AMPDU_MAX_TIME); + rtw_write8_set(rtwdev, REG_TX_HANG_CTRL, BIT_EN_EOF_V1); + value32 = WLAN_RTS_LEN_TH | (WLAN_RTS_TX_TIME_TH << 8) | + (WLAN_MAX_AGG_PKT_LIMIT << 16) | + (WLAN_RTS_MAX_AGG_PKT_LIMIT << 24); + rtw_write32(rtwdev, REG_PROT_MODE_CTRL, value32); + rtw_write16(rtwdev, REG_BAR_MODE_CTRL + 2, + WLAN_BAR_RETRY_LIMIT | WLAN_RA_TRY_RATE_AGG_LIMIT << 8); + rtw_write8(rtwdev, REG_FAST_EDCA_VOVI_SETTING, FAST_EDCA_VO_TH); + rtw_write8(rtwdev, REG_FAST_EDCA_VOVI_SETTING + 2, FAST_EDCA_VI_TH); + rtw_write8(rtwdev, REG_FAST_EDCA_BEBK_SETTING, FAST_EDCA_BE_TH); + rtw_write8(rtwdev, REG_FAST_EDCA_BEBK_SETTING + 2, FAST_EDCA_BK_TH); + /* EDCA configuration */ + rtw_write8_clr(rtwdev, REG_TIMER0_SRC_SEL, BIT_TSFT_SEL_TIMER0); + rtw_write16(rtwdev, REG_TXPAUSE, 0x0000); + rtw_write8(rtwdev, REG_SLOT, WLAN_SLOT_TIME); + rtw_write8(rtwdev, REG_PIFS, WLAN_PIFS_TIME); + rtw_write32(rtwdev, REG_SIFS, WLAN_SIFS_CFG); + rtw_write16(rtwdev, REG_EDCA_VO_PARAM + 2, WLAN_VO_TXOP_LIMIT); + rtw_write16(rtwdev, REG_EDCA_VI_PARAM + 2, WLAN_VI_TXOP_LIMIT); + rtw_write32(rtwdev, REG_RD_NAV_NXT, WLAN_NAV_CFG); + rtw_write16(rtwdev, REG_RXTSF_OFFSET_CCK, WLAN_RX_TSF_CFG); + /* Set beacon cotnrol - enable TSF and other related functions */ + rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); + /* Set send beacon related registers */ + rtw_write32(rtwdev, REG_TBTT_PROHIBIT, WLAN_TBTT_TIME); + rtw_write8(rtwdev, REG_DRVERLYINT, WLAN_DRV_EARLY_INT); + rtw_write8(rtwdev, REG_BCNDMATIM, WLAN_BCN_DMA_TIME); + rtw_write8_clr(rtwdev, REG_TX_PTCL_CTRL + 1, BIT_SIFS_BK_EN >> 8); + /* WMAC configuration */ + rtw_write32(rtwdev, REG_RXFLTMAP0, WLAN_RX_FILTER0); + rtw_write16(rtwdev, REG_RXFLTMAP2, WLAN_RX_FILTER2); + rtw_write32(rtwdev, REG_RCR, WLAN_RCR_CFG); + rtw_write8(rtwdev, REG_RX_PKT_LIMIT, WLAN_RXPKT_MAX_SZ_512); + rtw_write8(rtwdev, REG_TCR + 2, WLAN_TX_FUNC_CFG2); + rtw_write8(rtwdev, REG_TCR + 1, WLAN_TX_FUNC_CFG1); + rtw_write32(rtwdev, REG_WMAC_OPTION_FUNCTION + 8, WLAN_MAC_OPT_FUNC2); + rtw_write8(rtwdev, REG_WMAC_OPTION_FUNCTION + 4, WLAN_MAC_OPT_NORM_FUNC1); + + return 0; +} + +static void rtw8822b_set_channel_rfe_efem(struct rtw_dev *rtwdev, u8 channel) +{ + struct rtw_hal *hal = &rtwdev->hal; + bool is_channel_2g = (channel <= 14) ? true : false; + + if (is_channel_2g) { + rtw_write32s_mask(rtwdev, REG_RFESEL0, 0xffffff, 0x705770); + rtw_write32s_mask(rtwdev, REG_RFESEL8, MASKBYTE1, 0x57); + rtw_write32s_mask(rtwdev, REG_RFECTL, BIT(4), 0); + } else { + rtw_write32s_mask(rtwdev, REG_RFESEL0, 0xffffff, 0x177517); + rtw_write32s_mask(rtwdev, REG_RFESEL8, MASKBYTE1, 0x75); + rtw_write32s_mask(rtwdev, REG_RFECTL, BIT(5), 0); + } + + rtw_write32s_mask(rtwdev, REG_RFEINV, BIT(11) | BIT(10) | 0x3f, 0x0); + + if (hal->antenna_rx == BB_PATH_AB || + hal->antenna_tx == BB_PATH_AB) { + /* 2TX or 2RX */ + rtw_write32s_mask(rtwdev, REG_TRSW, MASKLWORD, 0xa501); + } else if (hal->antenna_rx == hal->antenna_tx) { + /* TXA+RXA or TXB+RXB */ + rtw_write32s_mask(rtwdev, REG_TRSW, MASKLWORD, 0xa500); + } else { + /* TXB+RXA or TXA+RXB */ + rtw_write32s_mask(rtwdev, REG_TRSW, MASKLWORD, 0xa005); + } +} + +static void rtw8822b_set_channel_rfe_ifem(struct rtw_dev *rtwdev, u8 channel) +{ + struct rtw_hal *hal = &rtwdev->hal; + bool is_channel_2g = (channel <= 14) ? true : false; + + if (is_channel_2g) { + /* signal source */ + rtw_write32s_mask(rtwdev, REG_RFESEL0, 0xffffff, 0x745774); + rtw_write32s_mask(rtwdev, REG_RFESEL8, MASKBYTE1, 0x57); + } else { + /* signal source */ + rtw_write32s_mask(rtwdev, REG_RFESEL0, 0xffffff, 0x477547); + rtw_write32s_mask(rtwdev, REG_RFESEL8, MASKBYTE1, 0x75); + } + + rtw_write32s_mask(rtwdev, REG_RFEINV, BIT(11) | BIT(10) | 0x3f, 0x0); + + if (is_channel_2g) { + if (hal->antenna_rx == BB_PATH_AB || + hal->antenna_tx == BB_PATH_AB) { + /* 2TX or 2RX */ + rtw_write32s_mask(rtwdev, REG_TRSW, MASKLWORD, 0xa501); + } else if (hal->antenna_rx == hal->antenna_tx) { + /* TXA+RXA or TXB+RXB */ + rtw_write32s_mask(rtwdev, REG_TRSW, MASKLWORD, 0xa500); + } else { + /* TXB+RXA or TXA+RXB */ + rtw_write32s_mask(rtwdev, REG_TRSW, MASKLWORD, 0xa005); + } + } else { + rtw_write32s_mask(rtwdev, REG_TRSW, MASKLWORD, 0xa5a5); + } +} + +enum { + CCUT_IDX_1R_2G, + CCUT_IDX_2R_2G, + CCUT_IDX_1R_5G, + CCUT_IDX_2R_5G, + CCUT_IDX_NR, +}; + +struct cca_ccut { + u32 reg82c[CCUT_IDX_NR]; + u32 reg830[CCUT_IDX_NR]; + u32 reg838[CCUT_IDX_NR]; +}; + +static const struct cca_ccut cca_ifem_ccut = { + {0x75C97010, 0x75C97010, 0x75C97010, 0x75C97010}, /*Reg82C*/ + {0x79a0eaaa, 0x79A0EAAC, 0x79a0eaaa, 0x79a0eaaa}, /*Reg830*/ + {0x87765541, 0x87746341, 0x87765541, 0x87746341}, /*Reg838*/ +}; + +static const struct cca_ccut cca_efem_ccut = { + {0x75B86010, 0x75B76010, 0x75B86010, 0x75B76010}, /*Reg82C*/ + {0x79A0EAA8, 0x79A0EAAC, 0x79A0EAA8, 0x79a0eaaa}, /*Reg830*/ + {0x87766451, 0x87766431, 0x87766451, 0x87766431}, /*Reg838*/ +}; + +static const struct cca_ccut cca_ifem_ccut_ext = { + {0x75da8010, 0x75da8010, 0x75da8010, 0x75da8010}, /*Reg82C*/ + {0x79a0eaaa, 0x97A0EAAC, 0x79a0eaaa, 0x79a0eaaa}, /*Reg830*/ + {0x87765541, 0x86666341, 0x87765561, 0x86666361}, /*Reg838*/ +}; + +static void rtw8822b_get_cca_val(const struct cca_ccut *cca_ccut, u8 col, + u32 *reg82c, u32 *reg830, u32 *reg838) +{ + *reg82c = cca_ccut->reg82c[col]; + *reg830 = cca_ccut->reg830[col]; + *reg838 = cca_ccut->reg838[col]; +} + +struct rtw8822b_rfe_info { + const struct cca_ccut *cca_ccut_2g; + const struct cca_ccut *cca_ccut_5g; + enum rtw_rfe_fem fem; + bool ifem_ext; + void (*rtw_set_channel_rfe)(struct rtw_dev *rtwdev, u8 channel); +}; + +#define I2GE5G_CCUT(set_ch) { \ + .cca_ccut_2g = &cca_ifem_ccut, \ + .cca_ccut_5g = &cca_efem_ccut, \ + .fem = RTW_RFE_IFEM2G_EFEM5G, \ + .ifem_ext = false, \ + .rtw_set_channel_rfe = &rtw8822b_set_channel_rfe_ ## set_ch, \ + } +#define IFEM_EXT_CCUT(set_ch) { \ + .cca_ccut_2g = &cca_ifem_ccut_ext, \ + .cca_ccut_5g = &cca_ifem_ccut_ext, \ + .fem = RTW_RFE_IFEM, \ + .ifem_ext = true, \ + .rtw_set_channel_rfe = &rtw8822b_set_channel_rfe_ ## set_ch, \ + } + +static const struct rtw8822b_rfe_info rtw8822b_rfe_info[] = { + [2] = I2GE5G_CCUT(efem), + [5] = IFEM_EXT_CCUT(ifem), +}; + +static void rtw8822b_set_channel_cca(struct rtw_dev *rtwdev, u8 channel, u8 bw, + const struct rtw8822b_rfe_info *rfe_info) +{ + struct rtw_hal *hal = &rtwdev->hal; + struct rtw_efuse *efuse = &rtwdev->efuse; + const struct cca_ccut *cca_ccut; + u8 col; + u32 reg82c, reg830, reg838; + bool is_efem_cca = false, is_ifem_cca = false, is_rfe_type = false; + + if (channel <= 14) { + cca_ccut = rfe_info->cca_ccut_2g; + + if (hal->antenna_rx == BB_PATH_A || + hal->antenna_rx == BB_PATH_B) + col = CCUT_IDX_1R_2G; + else + col = CCUT_IDX_2R_2G; + } else { + cca_ccut = rfe_info->cca_ccut_5g; + + if (hal->antenna_rx == BB_PATH_A || + hal->antenna_rx == BB_PATH_B) + col = CCUT_IDX_1R_5G; + else + col = CCUT_IDX_2R_5G; + } + + rtw8822b_get_cca_val(cca_ccut, col, ®82c, ®830, ®838); + + switch (rfe_info->fem) { + case RTW_RFE_IFEM: + default: + is_ifem_cca = true; + if (rfe_info->ifem_ext) + is_rfe_type = true; + break; + case RTW_RFE_EFEM: + is_efem_cca = true; + break; + case RTW_RFE_IFEM2G_EFEM5G: + if (channel <= 14) + is_ifem_cca = true; + else + is_efem_cca = true; + break; + } + + if (is_ifem_cca) { + if ((hal->cut_version == RTW_CHIP_VER_CUT_B && + (col == CCUT_IDX_2R_2G || col == CCUT_IDX_2R_5G) && + bw == RTW_CHANNEL_WIDTH_40) || + (!is_rfe_type && col == CCUT_IDX_2R_5G && + bw == RTW_CHANNEL_WIDTH_40) || + (efuse->rfe_option == 5 && col == CCUT_IDX_2R_5G)) + reg830 = 0x79a0ea28; + } + + rtw_write32_mask(rtwdev, REG_CCASEL, MASKDWORD, reg82c); + rtw_write32_mask(rtwdev, REG_PDMFTH, MASKDWORD, reg830); + rtw_write32_mask(rtwdev, REG_CCA2ND, MASKDWORD, reg838); + + if (is_efem_cca && !(hal->cut_version == RTW_CHIP_VER_CUT_B)) + rtw_write32_mask(rtwdev, REG_L1WT, MASKDWORD, 0x9194b2b9); + + if (bw == RTW_CHANNEL_WIDTH_20 && + ((channel >= 52 && channel <= 64) || + (channel >= 100 && channel <= 144))) + rtw_write32_mask(rtwdev, REG_CCA2ND, 0xf0, 0x4); +} + +static const u8 low_band[15] = {0x7, 0x6, 0x6, 0x5, 0x0, 0x0, 0x7, 0xff, 0x6, + 0x5, 0x0, 0x0, 0x7, 0x6, 0x6}; +static const u8 middle_band[23] = {0x6, 0x5, 0x0, 0x0, 0x7, 0x6, 0x6, 0xff, 0x0, + 0x0, 0x7, 0x6, 0x6, 0x5, 0x0, 0xff, 0x7, 0x6, + 0x6, 0x5, 0x0, 0x0, 0x7}; +static const u8 high_band[15] = {0x5, 0x5, 0x0, 0x7, 0x7, 0x6, 0x5, 0xff, 0x0, + 0x7, 0x7, 0x6, 0x5, 0x5, 0x0}; + +static void rtw8822b_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw) +{ +#define RF18_BAND_MASK (BIT(16) | BIT(9) | BIT(8)) +#define RF18_BAND_2G (0) +#define RF18_BAND_5G (BIT(16) | BIT(8)) +#define RF18_CHANNEL_MASK (MASKBYTE0) +#define RF18_RFSI_MASK (BIT(18) | BIT(17)) +#define RF18_RFSI_GE_CH80 (BIT(17)) +#define RF18_RFSI_GT_CH144 (BIT(18)) +#define RF18_BW_MASK (BIT(11) | BIT(10)) +#define RF18_BW_20M (BIT(11) | BIT(10)) +#define RF18_BW_40M (BIT(11)) +#define RF18_BW_80M (BIT(10)) +#define RFBE_MASK (BIT(17) | BIT(16) | BIT(15)) + + struct rtw_hal *hal = &rtwdev->hal; + u32 rf_reg18, rf_reg_be; + + rf_reg18 = rtw_read_rf(rtwdev, RF_PATH_A, 0x18, RFREG_MASK); + + rf_reg18 &= ~(RF18_BAND_MASK | RF18_CHANNEL_MASK | RF18_RFSI_MASK | + RF18_BW_MASK); + + rf_reg18 |= (channel <= 14 ? RF18_BAND_2G : RF18_BAND_5G); + rf_reg18 |= (channel & RF18_CHANNEL_MASK); + if (channel > 144) + rf_reg18 |= RF18_RFSI_GT_CH144; + else if (channel >= 80) + rf_reg18 |= RF18_RFSI_GE_CH80; + + switch (bw) { + case RTW_CHANNEL_WIDTH_5: + case RTW_CHANNEL_WIDTH_10: + case RTW_CHANNEL_WIDTH_20: + default: + rf_reg18 |= RF18_BW_20M; + break; + case RTW_CHANNEL_WIDTH_40: + rf_reg18 |= RF18_BW_40M; + break; + case RTW_CHANNEL_WIDTH_80: + rf_reg18 |= RF18_BW_80M; + break; + } + + if (channel <= 14) + rf_reg_be = 0x0; + else if (channel >= 36 && channel <= 64) + rf_reg_be = low_band[(channel - 36) >> 1]; + else if (channel >= 100 && channel <= 144) + rf_reg_be = middle_band[(channel - 100) >> 1]; + else if (channel >= 149 && channel <= 177) + rf_reg_be = high_band[(channel - 149) >> 1]; + else + goto err; + + rtw_write_rf(rtwdev, RF_PATH_A, RF_MALSEL, RFBE_MASK, rf_reg_be); + + /* need to set 0xdf[18]=1 before writing RF18 when channel 144 */ + if (channel == 144) + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTDBG, BIT(18), 0x1); + else + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTDBG, BIT(18), 0x0); + + rtw_write_rf(rtwdev, RF_PATH_A, 0x18, RFREG_MASK, rf_reg18); + if (hal->rf_type > RF_1T1R) + rtw_write_rf(rtwdev, RF_PATH_B, 0x18, RFREG_MASK, rf_reg18); + + rtw_write_rf(rtwdev, RF_PATH_A, RF_XTALX2, BIT(19), 0); + rtw_write_rf(rtwdev, RF_PATH_A, RF_XTALX2, BIT(19), 1); + + return; + +err: + WARN_ON(1); +} + +static void rtw8822b_toggle_igi(struct rtw_dev *rtwdev) +{ + struct rtw_hal *hal = &rtwdev->hal; + u32 igi; + + igi = rtw_read32_mask(rtwdev, REG_RXIGI_A, 0x7f); + rtw_write32_mask(rtwdev, REG_RXIGI_A, 0x7f, igi - 2); + rtw_write32_mask(rtwdev, REG_RXIGI_A, 0x7f, igi); + rtw_write32_mask(rtwdev, REG_RXIGI_B, 0x7f, igi - 2); + rtw_write32_mask(rtwdev, REG_RXIGI_B, 0x7f, igi); + + rtw_write32_mask(rtwdev, REG_RXPSEL, MASKBYTE0, 0x0); + rtw_write32_mask(rtwdev, REG_RXPSEL, MASKBYTE0, + hal->antenna_rx | (hal->antenna_rx << 4)); +} + +static void rtw8822b_set_channel_rxdfir(struct rtw_dev *rtwdev, u8 bw) +{ + if (bw == RTW_CHANNEL_WIDTH_40) { + /* RX DFIR for BW40 */ + rtw_write32_mask(rtwdev, REG_ACBB0, BIT(29) | BIT(28), 0x1); + rtw_write32_mask(rtwdev, REG_ACBBRXFIR, BIT(29) | BIT(28), 0x0); + rtw_write32s_mask(rtwdev, REG_TXDFIR, BIT(31), 0x0); + } else if (bw == RTW_CHANNEL_WIDTH_80) { + /* RX DFIR for BW80 */ + rtw_write32_mask(rtwdev, REG_ACBB0, BIT(29) | BIT(28), 0x2); + rtw_write32_mask(rtwdev, REG_ACBBRXFIR, BIT(29) | BIT(28), 0x1); + rtw_write32s_mask(rtwdev, REG_TXDFIR, BIT(31), 0x0); + } else { + /* RX DFIR for BW20, BW10 and BW5*/ + rtw_write32_mask(rtwdev, REG_ACBB0, BIT(29) | BIT(28), 0x2); + rtw_write32_mask(rtwdev, REG_ACBBRXFIR, BIT(29) | BIT(28), 0x2); + rtw_write32s_mask(rtwdev, REG_TXDFIR, BIT(31), 0x1); + } +} + +static void rtw8822b_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw, + u8 primary_ch_idx) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + u8 rfe_option = efuse->rfe_option; + u32 val32; + + if (channel <= 14) { + rtw_write32_mask(rtwdev, REG_RXPSEL, BIT(28), 0x1); + rtw_write32_mask(rtwdev, REG_CCK_CHECK, BIT(7), 0x0); + rtw_write32_mask(rtwdev, REG_ENTXCCK, BIT(18), 0x0); + rtw_write32_mask(rtwdev, REG_RXCCAMSK, 0x0000FC00, 15); + + rtw_write32_mask(rtwdev, REG_ACGG2TBL, 0x1f, 0x0); + rtw_write32_mask(rtwdev, REG_CLKTRK, 0x1ffe0000, 0x96a); + if (channel == 14) { + rtw_write32_mask(rtwdev, REG_TXSF2, MASKDWORD, 0x00006577); + rtw_write32_mask(rtwdev, REG_TXSF6, MASKLWORD, 0x0000); + } else { + rtw_write32_mask(rtwdev, REG_TXSF2, MASKDWORD, 0x384f6577); + rtw_write32_mask(rtwdev, REG_TXSF6, MASKLWORD, 0x1525); + } + + rtw_write32_mask(rtwdev, REG_RFEINV, 0x300, 0x2); + } else if (channel > 35) { + rtw_write32_mask(rtwdev, REG_ENTXCCK, BIT(18), 0x1); + rtw_write32_mask(rtwdev, REG_CCK_CHECK, BIT(7), 0x1); + rtw_write32_mask(rtwdev, REG_RXPSEL, BIT(28), 0x0); + rtw_write32_mask(rtwdev, REG_RXCCAMSK, 0x0000FC00, 34); + + if (channel >= 36 && channel <= 64) + rtw_write32_mask(rtwdev, REG_ACGG2TBL, 0x1f, 0x1); + else if (channel >= 100 && channel <= 144) + rtw_write32_mask(rtwdev, REG_ACGG2TBL, 0x1f, 0x2); + else if (channel >= 149) + rtw_write32_mask(rtwdev, REG_ACGG2TBL, 0x1f, 0x3); + + if (channel >= 36 && channel <= 48) + rtw_write32_mask(rtwdev, REG_CLKTRK, 0x1ffe0000, 0x494); + else if (channel >= 52 && channel <= 64) + rtw_write32_mask(rtwdev, REG_CLKTRK, 0x1ffe0000, 0x453); + else if (channel >= 100 && channel <= 116) + rtw_write32_mask(rtwdev, REG_CLKTRK, 0x1ffe0000, 0x452); + else if (channel >= 118 && channel <= 177) + rtw_write32_mask(rtwdev, REG_CLKTRK, 0x1ffe0000, 0x412); + + rtw_write32_mask(rtwdev, 0xcbc, 0x300, 0x1); + } + + switch (bw) { + case RTW_CHANNEL_WIDTH_20: + default: + val32 = rtw_read32_mask(rtwdev, REG_ADCCLK, MASKDWORD); + val32 &= 0xFFCFFC00; + val32 |= (RTW_CHANNEL_WIDTH_20); + rtw_write32_mask(rtwdev, REG_ADCCLK, MASKDWORD, val32); + + rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0x1); + break; + case RTW_CHANNEL_WIDTH_40: + if (primary_ch_idx == 1) + rtw_write32_set(rtwdev, REG_RXSB, BIT(4)); + else + rtw_write32_clr(rtwdev, REG_RXSB, BIT(4)); + + val32 = rtw_read32_mask(rtwdev, REG_ADCCLK, MASKDWORD); + val32 &= 0xFF3FF300; + val32 |= (((primary_ch_idx & 0xf) << 2) | RTW_CHANNEL_WIDTH_40); + rtw_write32_mask(rtwdev, REG_ADCCLK, MASKDWORD, val32); + + rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0x1); + break; + case RTW_CHANNEL_WIDTH_80: + val32 = rtw_read32_mask(rtwdev, REG_ADCCLK, MASKDWORD); + val32 &= 0xFCEFCF00; + val32 |= (((primary_ch_idx & 0xf) << 2) | RTW_CHANNEL_WIDTH_80); + rtw_write32_mask(rtwdev, REG_ADCCLK, MASKDWORD, val32); + + rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0x1); + + if (rfe_option == 2) { + rtw_write32_mask(rtwdev, REG_L1PKWT, 0x0000f000, 0x6); + rtw_write32_mask(rtwdev, REG_ADC40, BIT(10), 0x1); + } + break; + case RTW_CHANNEL_WIDTH_5: + val32 = rtw_read32_mask(rtwdev, REG_ADCCLK, MASKDWORD); + val32 &= 0xEFEEFE00; + val32 |= ((BIT(6) | RTW_CHANNEL_WIDTH_20)); + rtw_write32_mask(rtwdev, REG_ADCCLK, MASKDWORD, val32); + + rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0x0); + rtw_write32_mask(rtwdev, REG_ADC40, BIT(31), 0x1); + break; + case RTW_CHANNEL_WIDTH_10: + val32 = rtw_read32_mask(rtwdev, REG_ADCCLK, MASKDWORD); + val32 &= 0xEFFEFF00; + val32 |= ((BIT(7) | RTW_CHANNEL_WIDTH_20)); + rtw_write32_mask(rtwdev, REG_ADCCLK, MASKDWORD, val32); + + rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0x0); + rtw_write32_mask(rtwdev, REG_ADC40, BIT(31), 0x1); + break; + } +} + +static void rtw8822b_set_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw, + u8 primary_chan_idx) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + const struct rtw8822b_rfe_info *rfe_info; + + if (WARN(efuse->rfe_option >= ARRAY_SIZE(rtw8822b_rfe_info), + "rfe_option %d is out of boundary\n", efuse->rfe_option)) + return; + + rfe_info = &rtw8822b_rfe_info[efuse->rfe_option]; + + rtw8822b_set_channel_bb(rtwdev, channel, bw, primary_chan_idx); + rtw_set_channel_mac(rtwdev, channel, bw, primary_chan_idx); + rtw8822b_set_channel_rf(rtwdev, channel, bw); + rtw8822b_set_channel_rxdfir(rtwdev, bw); + rtw8822b_toggle_igi(rtwdev); + rtw8822b_set_channel_cca(rtwdev, channel, bw, rfe_info); + (*rfe_info->rtw_set_channel_rfe)(rtwdev, channel); +} + +static void rtw8822b_config_trx_mode(struct rtw_dev *rtwdev, u8 tx_path, + u8 rx_path, bool is_tx2_path) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + const struct rtw8822b_rfe_info *rfe_info; + u8 ch = rtwdev->hal.current_channel; + u8 tx_path_sel, rx_path_sel; + int counter; + + if (WARN(efuse->rfe_option >= ARRAY_SIZE(rtw8822b_rfe_info), + "rfe_option %d is out of boundary\n", efuse->rfe_option)) + return; + + rfe_info = &rtw8822b_rfe_info[efuse->rfe_option]; + + if ((tx_path | rx_path) & BB_PATH_A) + rtw_write32_mask(rtwdev, REG_AGCTR_A, MASKLWORD, 0x3231); + else + rtw_write32_mask(rtwdev, REG_AGCTR_A, MASKLWORD, 0x1111); + + if ((tx_path | rx_path) & BB_PATH_B) + rtw_write32_mask(rtwdev, REG_AGCTR_B, MASKLWORD, 0x3231); + else + rtw_write32_mask(rtwdev, REG_AGCTR_B, MASKLWORD, 0x1111); + + rtw_write32_mask(rtwdev, REG_CDDTXP, (BIT(19) | BIT(18)), 0x3); + rtw_write32_mask(rtwdev, REG_TXPSEL, (BIT(29) | BIT(28)), 0x1); + rtw_write32_mask(rtwdev, REG_TXPSEL, BIT(30), 0x1); + + if (tx_path & BB_PATH_A) { + rtw_write32_mask(rtwdev, REG_CDDTXP, 0xfff00000, 0x001); + rtw_write32_mask(rtwdev, REG_ADCINI, 0xf0000000, 0x8); + } else if (tx_path & BB_PATH_B) { + rtw_write32_mask(rtwdev, REG_CDDTXP, 0xfff00000, 0x002); + rtw_write32_mask(rtwdev, REG_ADCINI, 0xf0000000, 0x4); + } + + if (tx_path == BB_PATH_A || tx_path == BB_PATH_B) + rtw_write32_mask(rtwdev, REG_TXPSEL1, 0xfff0, 0x01); + else + rtw_write32_mask(rtwdev, REG_TXPSEL1, 0xfff0, 0x43); + + tx_path_sel = (tx_path << 4) | tx_path; + rtw_write32_mask(rtwdev, REG_TXPSEL, MASKBYTE0, tx_path_sel); + + if (tx_path != BB_PATH_A && tx_path != BB_PATH_B) { + if (is_tx2_path || rtwdev->mp_mode) { + rtw_write32_mask(rtwdev, REG_CDDTXP, 0xfff00000, 0x043); + rtw_write32_mask(rtwdev, REG_ADCINI, 0xf0000000, 0xc); + } + } + + rtw_write32_mask(rtwdev, REG_RXDESC, BIT(22), 0x0); + rtw_write32_mask(rtwdev, REG_RXDESC, BIT(18), 0x0); + + if (rx_path & BB_PATH_A) + rtw_write32_mask(rtwdev, REG_ADCINI, 0x0f000000, 0x0); + else if (rx_path & BB_PATH_B) + rtw_write32_mask(rtwdev, REG_ADCINI, 0x0f000000, 0x5); + + rx_path_sel = (rx_path << 4) | rx_path; + rtw_write32_mask(rtwdev, REG_RXPSEL, MASKBYTE0, rx_path_sel); + + if (rx_path == BB_PATH_A || rx_path == BB_PATH_B) { + rtw_write32_mask(rtwdev, REG_ANTWT, BIT(16), 0x0); + rtw_write32_mask(rtwdev, REG_HTSTFWT, BIT(28), 0x0); + rtw_write32_mask(rtwdev, REG_MRC, BIT(23), 0x0); + } else { + rtw_write32_mask(rtwdev, REG_ANTWT, BIT(16), 0x1); + rtw_write32_mask(rtwdev, REG_HTSTFWT, BIT(28), 0x1); + rtw_write32_mask(rtwdev, REG_MRC, BIT(23), 0x1); + } + + for (counter = 100; counter > 0; counter--) { + u32 rf_reg33; + + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x00001); + + udelay(2); + rf_reg33 = rtw_read_rf(rtwdev, RF_PATH_A, 0x33, RFREG_MASK); + + if (rf_reg33 == 0x00001) + break; + } + + if (WARN(counter <= 0, "write RF mode table fail\n")) + return; + + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x00001); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD1, RFREG_MASK, 0x00034); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x4080c); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x00000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x00000); + + rtw8822b_toggle_igi(rtwdev); + rtw8822b_set_channel_cca(rtwdev, 1, RTW_CHANNEL_WIDTH_20, rfe_info); + (*rfe_info->rtw_set_channel_rfe)(rtwdev, ch); +} + +static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status, + struct rtw_rx_pkt_stat *pkt_stat) +{ + s8 min_rx_power = -120; + u8 pwdb = GET_PHY_STAT_P0_PWDB(phy_status); + + pkt_stat->rx_power[RF_PATH_A] = pwdb - 110; + pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1); + pkt_stat->bw = RTW_CHANNEL_WIDTH_20; + pkt_stat->signal_power = max(pkt_stat->rx_power[RF_PATH_A], + min_rx_power); +} + +static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status, + struct rtw_rx_pkt_stat *pkt_stat) +{ + u8 rxsc, bw; + s8 min_rx_power = -120; + + if (pkt_stat->rate > DESC_RATE11M && pkt_stat->rate < DESC_RATEMCS0) + rxsc = GET_PHY_STAT_P1_L_RXSC(phy_status); + else + rxsc = GET_PHY_STAT_P1_HT_RXSC(phy_status); + + if (rxsc >= 1 && rxsc <= 8) + bw = RTW_CHANNEL_WIDTH_20; + else if (rxsc >= 9 && rxsc <= 12) + bw = RTW_CHANNEL_WIDTH_40; + else if (rxsc >= 13) + bw = RTW_CHANNEL_WIDTH_80; + else + bw = GET_PHY_STAT_P1_RF_MODE(phy_status); + + pkt_stat->rx_power[RF_PATH_A] = GET_PHY_STAT_P1_PWDB_A(phy_status) - 110; + pkt_stat->rx_power[RF_PATH_B] = GET_PHY_STAT_P1_PWDB_B(phy_status) - 110; + pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 2); + pkt_stat->bw = bw; + pkt_stat->signal_power = max3(pkt_stat->rx_power[RF_PATH_A], + pkt_stat->rx_power[RF_PATH_B], + min_rx_power); +} + +static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, + struct rtw_rx_pkt_stat *pkt_stat) +{ + u8 page; + + page = *phy_status & 0xf; + + switch (page) { + case 0: + query_phy_status_page0(rtwdev, phy_status, pkt_stat); + break; + case 1: + query_phy_status_page1(rtwdev, phy_status, pkt_stat); + break; + default: + rtw_warn(rtwdev, "unused phy status page (%d)\n", page); + return; + } +} + +static void rtw8822b_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, + struct rtw_rx_pkt_stat *pkt_stat, + struct ieee80211_rx_status *rx_status) +{ + struct ieee80211_hdr *hdr; + u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; + u8 *phy_status = NULL; + + memset(pkt_stat, 0, sizeof(*pkt_stat)); + + pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); + pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); + pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); + pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc); + pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); + pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); + pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); + pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); + pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); + pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); + pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc); + pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); + + /* drv_info_sz is in unit of 8-bytes */ + pkt_stat->drv_info_sz *= 8; + + /* c2h cmd pkt's rx/phy status is not interested */ + if (pkt_stat->is_c2h) + return; + + hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + + pkt_stat->drv_info_sz); + if (pkt_stat->phy_status) { + phy_status = rx_desc + desc_sz + pkt_stat->shift; + query_phy_status(rtwdev, phy_status, pkt_stat); + } + + rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); +} + +static void +rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs) +{ + struct rtw_hal *hal = &rtwdev->hal; + static const u32 offset_txagc[2] = {0x1d00, 0x1d80}; + static u32 phy_pwr_idx; + u8 rate, rate_idx, pwr_index, shift; + int j; + + for (j = 0; j < rtw_rate_size[rs]; j++) { + rate = rtw_rate_section[rs][j]; + pwr_index = hal->tx_pwr_tbl[path][rate]; + shift = rate & 0x3; + phy_pwr_idx |= ((u32)pwr_index << (shift * 8)); + if (shift == 0x3) { + rate_idx = rate & 0xfc; + rtw_write32(rtwdev, offset_txagc[path] + rate_idx, + phy_pwr_idx); + phy_pwr_idx = 0; + } + } +} + +static void rtw8822b_set_tx_power_index(struct rtw_dev *rtwdev) +{ + struct rtw_hal *hal = &rtwdev->hal; + int rs, path; + + for (path = 0; path < hal->rf_path_num; path++) { + for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++) + rtw8822b_set_tx_power_index_by_rate(rtwdev, path, rs); + } +} + +static bool rtw8822b_check_rf_path(u8 antenna) +{ + switch (antenna) { + case BB_PATH_A: + case BB_PATH_B: + case BB_PATH_AB: + return true; + default: + return false; + } +} + +static void rtw8822b_set_antenna(struct rtw_dev *rtwdev, u8 antenna_tx, + u8 antenna_rx) +{ + struct rtw_hal *hal = &rtwdev->hal; + + rtw_dbg(rtwdev, RTW_DBG_PHY, "config RF path, tx=0x%x rx=0x%x\n", + antenna_tx, antenna_rx); + + if (!rtw8822b_check_rf_path(antenna_tx)) { + rtw_info(rtwdev, "unsupport tx path, set to default path ab\n"); + antenna_tx = BB_PATH_AB; + } + if (!rtw8822b_check_rf_path(antenna_rx)) { + rtw_info(rtwdev, "unsupport rx path, set to default path ab\n"); + antenna_rx = BB_PATH_AB; + } + hal->antenna_tx = antenna_tx; + hal->antenna_rx = antenna_rx; + rtw8822b_config_trx_mode(rtwdev, antenna_tx, antenna_rx, false); +} + +static void rtw8822b_cfg_ldo25(struct rtw_dev *rtwdev, bool enable) +{ + u8 ldo_pwr; + + ldo_pwr = rtw_read8(rtwdev, REG_LDO_EFUSE_CTRL + 3); + ldo_pwr = enable ? ldo_pwr | BIT(7) : ldo_pwr & ~BIT(7); + rtw_write8(rtwdev, REG_LDO_EFUSE_CTRL + 3, ldo_pwr); +} + +static void rtw8822b_false_alarm_statistics(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u32 cck_enable; + u32 cck_fa_cnt; + u32 ofdm_fa_cnt; + + cck_enable = rtw_read32(rtwdev, 0x808) & BIT(28); + cck_fa_cnt = rtw_read16(rtwdev, 0xa5c); + ofdm_fa_cnt = rtw_read16(rtwdev, 0xf48); + + dm_info->cck_fa_cnt = cck_fa_cnt; + dm_info->ofdm_fa_cnt = ofdm_fa_cnt; + dm_info->total_fa_cnt = ofdm_fa_cnt; + dm_info->total_fa_cnt += cck_enable ? cck_fa_cnt : 0; + + rtw_write32_set(rtwdev, 0x9a4, BIT(17)); + rtw_write32_clr(rtwdev, 0x9a4, BIT(17)); + rtw_write32_clr(rtwdev, 0xa2c, BIT(15)); + rtw_write32_set(rtwdev, 0xa2c, BIT(15)); + rtw_write32_set(rtwdev, 0xb58, BIT(0)); + rtw_write32_clr(rtwdev, 0xb58, BIT(0)); +} + +static void rtw8822b_do_iqk(struct rtw_dev *rtwdev) +{ + static int do_iqk_cnt; + struct rtw_iqk_para para = {.clear = 0, .segment_iqk = 0}; + u32 rf_reg, iqk_fail_mask; + int counter; + bool reload; + + rtw_fw_do_iqk(rtwdev, ¶); + + for (counter = 0; counter < 300; counter++) { + rf_reg = rtw_read_rf(rtwdev, RF_PATH_A, RF_DTXLOK, RFREG_MASK); + if (rf_reg == 0xabcde) + break; + msleep(20); + } + rtw_write_rf(rtwdev, RF_PATH_A, RF_DTXLOK, RFREG_MASK, 0x0); + + reload = !!rtw_read32_mask(rtwdev, REG_IQKFAILMSK, BIT(16)); + iqk_fail_mask = rtw_read32_mask(rtwdev, REG_IQKFAILMSK, GENMASK(0, 7)); + rtw_dbg(rtwdev, RTW_DBG_PHY, + "iqk counter=%d reload=%d do_iqk_cnt=%d n_iqk_fail(mask)=0x%02x\n", + counter, reload, ++do_iqk_cnt, iqk_fail_mask); +} + +static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = { + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, BIT(0), 0}, + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_POLLING, BIT(1), BIT(1)}, + {0x004A, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), 0}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(3) | BIT(4) | BIT(7), 0}, + {0x0300, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_PCI_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0}, + {0x0301, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_PCI_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0}, + {0xFFFF, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + 0, + RTW_PWR_CMD_END, 0, 0}, +}; + +static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822b[] = { + {0x0012, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(1), 0}, + {0x0012, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, + {0x0020, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, + {0x0001, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_DELAY, 1, RTW_PWR_DELAY_MS}, + {0x0000, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(5), 0}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, (BIT(4) | BIT(3) | BIT(2)), 0}, + {0x0075, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_PCI_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, + {0x0006, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_POLLING, BIT(1), BIT(1)}, + {0x0075, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_PCI_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), 0}, + {0xFF1A, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0}, + {0x0006, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(7), 0}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, (BIT(4) | BIT(3)), 0}, + {0x10C3, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_POLLING, BIT(0), 0}, + {0x0020, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(3), BIT(3)}, + {0x10A8, + RTW_PWR_CUT_C_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0}, + {0x10A9, + RTW_PWR_CUT_C_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0xef}, + {0x10AA, + RTW_PWR_CUT_C_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0x0c}, + {0x0068, + RTW_PWR_CUT_C_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(4), BIT(4)}, + {0x0029, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0xF9}, + {0x0024, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(2), 0}, + {0x0074, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_PCI_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(5), BIT(5)}, + {0x00AF, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(5), BIT(5)}, + {0xFFFF, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + 0, + RTW_PWR_CMD_END, 0, 0}, +}; + +static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822b[] = { + {0x0003, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(2), 0}, + {0x0093, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(3), 0}, + {0x001F, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0}, + {0x00EF, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0}, + {0xFF1A, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0x30}, + {0x0049, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(1), 0}, + {0x0006, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, + {0x0002, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(1), 0}, + {0x10C3, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), 0}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(1), BIT(1)}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_POLLING, BIT(1), 0}, + {0x0020, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(3), 0}, + {0x0000, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(5), BIT(5)}, + {0xFFFF, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + 0, + RTW_PWR_CMD_END, 0, 0}, +}; + +static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = { + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(7), BIT(7)}, + {0x0007, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0x20}, + {0x0067, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(5), 0}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_PCI_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(2), BIT(2)}, + {0x004A, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), 0}, + {0x0067, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(5), 0}, + {0x0067, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(4), 0}, + {0x004F, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), 0}, + {0x0067, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(1), 0}, + {0x0046, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(6), BIT(6)}, + {0x0067, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(2), 0}, + {0x0046, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(7), BIT(7)}, + {0x0062, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(4), BIT(4)}, + {0x0081, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(7) | BIT(6), 0}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)}, + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_POLLING, BIT(1), 0}, + {0x0090, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_PCI_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(1), 0}, + {0x0044, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, 0xFF, 0}, + {0x0040, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, 0xFF, 0x90}, + {0x0041, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, 0xFF, 0x00}, + {0x0042, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, 0xFF, 0x04}, + {0xFFFF, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + 0, + RTW_PWR_CMD_END, 0, 0}, +}; + +static struct rtw_pwr_seq_cmd *card_enable_flow_8822b[] = { + trans_carddis_to_cardemu_8822b, + trans_cardemu_to_act_8822b, + NULL +}; + +static struct rtw_pwr_seq_cmd *card_disable_flow_8822b[] = { + trans_act_to_cardemu_8822b, + trans_cardemu_to_carddis_8822b, + NULL +}; + +static struct rtw_intf_phy_para usb2_param_8822b[] = { + {0xFFFF, 0x00, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_ALL, + RTW_INTF_PHY_PLATFORM_ALL}, +}; + +static struct rtw_intf_phy_para usb3_param_8822b[] = { + {0x0001, 0xA841, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_D, + RTW_INTF_PHY_PLATFORM_ALL}, + {0xFFFF, 0x0000, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_ALL, + RTW_INTF_PHY_PLATFORM_ALL}, +}; + +static struct rtw_intf_phy_para pcie_gen1_param_8822b[] = { + {0x0001, 0xA841, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x0002, 0x60C6, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x0008, 0x3596, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x0009, 0x321C, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x000A, 0x9623, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x0020, 0x94FF, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x0021, 0xFFCF, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x0026, 0xC006, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x0029, 0xFF0E, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x002A, 0x1840, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0xFFFF, 0x0000, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_ALL, + RTW_INTF_PHY_PLATFORM_ALL}, +}; + +static struct rtw_intf_phy_para pcie_gen2_param_8822b[] = { + {0x0001, 0xA841, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x0002, 0x60C6, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x0008, 0x3597, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x0009, 0x321C, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x000A, 0x9623, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x0020, 0x94FF, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x0021, 0xFFCF, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x0026, 0xC006, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x0029, 0xFF0E, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0x002A, 0x3040, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_C, + RTW_INTF_PHY_PLATFORM_ALL}, + {0xFFFF, 0x0000, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_ALL, + RTW_INTF_PHY_PLATFORM_ALL}, +}; + +static struct rtw_intf_phy_para_table phy_para_table_8822b = { + .usb2_para = usb2_param_8822b, + .usb3_para = usb3_param_8822b, + .gen1_para = pcie_gen1_param_8822b, + .gen2_para = pcie_gen2_param_8822b, + .n_usb2_para = ARRAY_SIZE(usb2_param_8822b), + .n_usb3_para = ARRAY_SIZE(usb2_param_8822b), + .n_gen1_para = ARRAY_SIZE(pcie_gen1_param_8822b), + .n_gen2_para = ARRAY_SIZE(pcie_gen2_param_8822b), +}; + +static const struct rtw_rfe_def rtw8822b_rfe_defs[] = { + [2] = RTW_DEF_RFE(8822b, 2, 2), + [5] = RTW_DEF_RFE(8822b, 5, 5), +}; + +static struct rtw_hw_reg rtw8822b_dig[] = { + [0] = { .addr = 0xc50, .mask = 0x7f }, + [1] = { .addr = 0xe50, .mask = 0x7f }, +}; + +static struct rtw_page_table page_table_8822b[] = { + {64, 64, 64, 64, 1}, + {64, 64, 64, 64, 1}, + {64, 64, 0, 0, 1}, + {64, 64, 64, 0, 1}, + {64, 64, 64, 64, 1}, +}; + +static struct rtw_rqpn rqpn_table_8822b[] = { + {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, + RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, + RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, + {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, + RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, + RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, + {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, + RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_HIGH, + RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH}, + {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, + RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, + RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH}, + {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, + RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, + RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, +}; + +static struct rtw_chip_ops rtw8822b_ops = { + .phy_set_param = rtw8822b_phy_set_param, + .read_efuse = rtw8822b_read_efuse, + .query_rx_desc = rtw8822b_query_rx_desc, + .set_channel = rtw8822b_set_channel, + .mac_init = rtw8822b_mac_init, + .read_rf = rtw_phy_read_rf, + .write_rf = rtw_phy_write_rf_reg_sipi, + .set_tx_power_index = rtw8822b_set_tx_power_index, + .set_antenna = rtw8822b_set_antenna, + .cfg_ldo25 = rtw8822b_cfg_ldo25, + .false_alarm_statistics = rtw8822b_false_alarm_statistics, + .do_iqk = rtw8822b_do_iqk, +}; + +struct rtw_chip_info rtw8822b_hw_spec = { + .ops = &rtw8822b_ops, + .id = RTW_CHIP_TYPE_8822B, + .fw_name = "rtw88/rtw8822b_fw.bin", + .tx_pkt_desc_sz = 48, + .tx_buf_desc_sz = 16, + .rx_pkt_desc_sz = 24, + .rx_buf_desc_sz = 8, + .phy_efuse_size = 1024, + .log_efuse_size = 768, + .ptct_efuse_size = 96, + .txff_size = 262144, + .rxff_size = 24576, + .txgi_factor = 1, + .is_pwr_by_rate_dec = true, + .max_power_index = 0x3f, + .csi_buf_pg_num = 0, + .band = RTW_BAND_2G | RTW_BAND_5G, + .page_size = 128, + .dig_min = 0x1c, + .ht_supported = true, + .vht_supported = true, + .sys_func_en = 0xDC, + .pwr_on_seq = card_enable_flow_8822b, + .pwr_off_seq = card_disable_flow_8822b, + .page_table = page_table_8822b, + .rqpn_table = rqpn_table_8822b, + .intf_table = &phy_para_table_8822b, + .dig = rtw8822b_dig, + .rf_base_addr = {0x2800, 0x2c00}, + .rf_sipi_addr = {0xc90, 0xe90}, + .mac_tbl = &rtw8822b_mac_tbl, + .agc_tbl = &rtw8822b_agc_tbl, + .bb_tbl = &rtw8822b_bb_tbl, + .rf_tbl = {&rtw8822b_rf_a_tbl, &rtw8822b_rf_b_tbl}, + .rfe_defs = rtw8822b_rfe_defs, + .rfe_defs_size = ARRAY_SIZE(rtw8822b_rfe_defs), +}; +EXPORT_SYMBOL(rtw8822b_hw_spec); + +MODULE_FIRMWARE("rtw88/rtw8822b_fw.bin"); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.h b/drivers/net/wireless/realtek/rtw88/rtw8822b.h new file mode 100644 index 000000000000..0cb93d7d4cfd --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.h @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW8822B_H__ +#define __RTW8822B_H__ + +#include <asm/byteorder.h> + +#define RCR_VHT_ACK BIT(26) + +struct rtw8822bu_efuse { + u8 res4[4]; /* 0xd0 */ + u8 usb_optional_function; + u8 res5[0x1e]; + u8 res6[2]; + u8 serial[0x0b]; /* 0xf5 */ + u8 vid; /* 0x100 */ + u8 res7; + u8 pid; + u8 res8[4]; + u8 mac_addr[ETH_ALEN]; /* 0x107 */ + u8 res9[2]; + u8 vendor_name[0x07]; + u8 res10[2]; + u8 device_name[0x14]; + u8 res11[0xcf]; + u8 package_type; /* 0x1fb */ + u8 res12[0x4]; +}; + +struct rtw8822be_efuse { + u8 mac_addr[ETH_ALEN]; /* 0xd0 */ + u8 vender_id[2]; + u8 device_id[2]; + u8 sub_vender_id[2]; + u8 sub_device_id[2]; + u8 pmc[2]; + u8 exp_device_cap[2]; + u8 msi_cap; + u8 ltr_cap; /* 0xe3 */ + u8 exp_link_control[2]; + u8 link_cap[4]; + u8 link_control[2]; + u8 serial_number[8]; + u8 res0:2; /* 0xf4 */ + u8 ltr_en:1; + u8 res1:2; + u8 obff:2; + u8 res2:3; + u8 obff_cap:2; + u8 res3:4; + u8 res4[3]; + u8 class_code[3]; + u8 pci_pm_L1_2_supp:1; + u8 pci_pm_L1_1_supp:1; + u8 aspm_pm_L1_2_supp:1; + u8 aspm_pm_L1_1_supp:1; + u8 L1_pm_substates_supp:1; + u8 res5:3; + u8 port_common_mode_restore_time; + u8 port_t_power_on_scale:2; + u8 res6:1; + u8 port_t_power_on_value:5; + u8 res7; +}; + +struct rtw8822b_efuse { + __le16 rtl_id; + u8 res0[0x0e]; + + /* power index for four RF paths */ + struct rtw_txpwr_idx txpwr_idx_table[4]; + + u8 channel_plan; /* 0xb8 */ + u8 xtal_k; + u8 thermal_meter; + u8 iqk_lck; + u8 pa_type; /* 0xbc */ + u8 lna_type_2g[2]; /* 0xbd */ + u8 lna_type_5g[2]; + u8 rf_board_option; + u8 rf_feature_option; + u8 rf_bt_setting; + u8 eeprom_version; + u8 eeprom_customer_id; + u8 tx_bb_swing_setting_2g; + u8 tx_bb_swing_setting_5g; + u8 tx_pwr_calibrate_rate; + u8 rf_antenna_option; /* 0xc9 */ + u8 rfe_option; + u8 country_code[2]; + u8 res[3]; + union { + struct rtw8822bu_efuse u; + struct rtw8822be_efuse e; + }; +}; + +static inline void +_rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) +{ + /* 0xC00-0xCFF and 0xE00-0xEFF have the same layout */ + rtw_write32_mask(rtwdev, addr, mask, data); + rtw_write32_mask(rtwdev, addr + 0x200, mask, data); +} + +#define rtw_write32s_mask(rtwdev, addr, mask, data) \ + do { \ + BUILD_BUG_ON((addr) < 0xC00 || (addr) >= 0xD00); \ + \ + _rtw_write32s_mask(rtwdev, addr, mask, data); \ + } while (0) + +/* phy status page0 */ +#define GET_PHY_STAT_P0_PWDB(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8)) + +/* phy status page1 */ +#define GET_PHY_STAT_P1_PWDB_A(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8)) +#define GET_PHY_STAT_P1_PWDB_B(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(23, 16)) +#define GET_PHY_STAT_P1_RF_MODE(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x03), GENMASK(29, 28)) +#define GET_PHY_STAT_P1_L_RXSC(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(11, 8)) +#define GET_PHY_STAT_P1_HT_RXSC(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(15, 12)) + +#define REG_HTSTFWT 0x800 +#define REG_RXPSEL 0x808 +#define BIT_RX_PSEL_RST (BIT(28) | BIT(29)) +#define REG_TXPSEL 0x80c +#define REG_RXCCAMSK 0x814 +#define REG_CCASEL 0x82c +#define REG_PDMFTH 0x830 +#define REG_CCA2ND 0x838 +#define REG_L1WT 0x83c +#define REG_L1PKWT 0x840 +#define REG_MRC 0x850 +#define REG_CLKTRK 0x860 +#define REG_ADCCLK 0x8ac +#define REG_ADC160 0x8c4 +#define REG_ADC40 0x8c8 +#define REG_CDDTXP 0x93c +#define REG_TXPSEL1 0x940 +#define REG_ACBB0 0x948 +#define REG_ACBBRXFIR 0x94c +#define REG_ACGG2TBL 0x958 +#define REG_RXSB 0xa00 +#define REG_ADCINI 0xa04 +#define REG_TXSF2 0xa24 +#define REG_TXSF6 0xa28 +#define REG_RXDESC 0xa2c +#define REG_ENTXCCK 0xa80 +#define REG_AGCTR_A 0xc08 +#define REG_TXDFIR 0xc20 +#define REG_RXIGI_A 0xc50 +#define REG_TRSW 0xca0 +#define REG_RFESEL0 0xcb0 +#define REG_RFESEL8 0xcb4 +#define REG_RFECTL 0xcb8 +#define REG_RFEINV 0xcbc +#define REG_AGCTR_B 0xe08 +#define REG_RXIGI_B 0xe50 +#define REG_ANTWT 0x1904 +#define REG_IQKFAILMSK 0x1bf0 + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b_table.c b/drivers/net/wireless/realtek/rtw88/rtw8822b_table.c new file mode 100644 index 000000000000..2d2dfb495ce1 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b_table.c @@ -0,0 +1,20783 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "phy.h" +#include "rtw8822b_table.h" + +static const u32 rtw8822b_mac[] = { + 0x029, 0x000000F9, + 0x420, 0x00000080, + 0x421, 0x0000001F, + 0x428, 0x0000000A, + 0x429, 0x00000010, + 0x430, 0x00000000, + 0x431, 0x00000000, + 0x432, 0x00000000, + 0x433, 0x00000001, + 0x434, 0x00000004, + 0x435, 0x00000005, + 0x436, 0x00000007, + 0x437, 0x00000008, + 0x43C, 0x00000004, + 0x43D, 0x00000005, + 0x43E, 0x00000007, + 0x43F, 0x00000008, + 0x440, 0x0000005D, + 0x441, 0x00000001, + 0x442, 0x00000000, + 0x444, 0x00000010, + 0x445, 0x000000F0, + 0x446, 0x00000001, + 0x447, 0x000000FE, + 0x448, 0x00000000, + 0x449, 0x00000000, + 0x44A, 0x00000000, + 0x44B, 0x00000040, + 0x44C, 0x00000010, + 0x44D, 0x000000F0, + 0x44E, 0x0000003F, + 0x44F, 0x00000000, + 0x450, 0x00000000, + 0x451, 0x00000000, + 0x452, 0x00000000, + 0x453, 0x00000040, + 0x455, 0x00000070, + 0x45E, 0x00000004, + 0x49C, 0x00000010, + 0x49D, 0x000000F0, + 0x49E, 0x00000000, + 0x49F, 0x00000006, + 0x4A0, 0x000000E0, + 0x4A1, 0x00000003, + 0x4A2, 0x00000000, + 0x4A3, 0x00000040, + 0x4A4, 0x00000015, + 0x4A5, 0x000000F0, + 0x4A6, 0x00000000, + 0x4A7, 0x00000006, + 0x4A8, 0x000000E0, + 0x4A9, 0x00000000, + 0x4AA, 0x00000000, + 0x4AB, 0x00000000, + 0x7DA, 0x00000008, + 0x1448, 0x00000006, + 0x144A, 0x00000006, + 0x144C, 0x00000006, + 0x144E, 0x00000006, + 0x4C8, 0x000000FF, + 0x4C9, 0x00000008, + 0x4CA, 0x00000020, + 0x4CB, 0x00000020, + 0x4CC, 0x000000FF, + 0x4CD, 0x000000FF, + 0x4CE, 0x00000001, + 0x4CF, 0x00000008, + 0x500, 0x00000026, + 0x501, 0x000000A2, + 0x502, 0x0000002F, + 0x503, 0x00000000, + 0x504, 0x00000028, + 0x505, 0x000000A3, + 0x506, 0x0000005E, + 0x507, 0x00000000, + 0x508, 0x0000002B, + 0x509, 0x000000A4, + 0x50A, 0x0000005E, + 0x50B, 0x00000000, + 0x50C, 0x0000004F, + 0x50D, 0x000000A4, + 0x50E, 0x00000000, + 0x50F, 0x00000000, + 0x512, 0x0000001C, + 0x514, 0x0000000A, + 0x516, 0x0000000A, + 0x521, 0x0000002F, + 0x525, 0x0000004F, + 0x551, 0x00000010, + 0x559, 0x00000002, + 0x55C, 0x00000050, + 0x55D, 0x000000FF, + 0x577, 0x0000000B, + 0x5BE, 0x00000064, + 0x605, 0x00000030, + 0x608, 0x0000000E, + 0x609, 0x00000022, + 0x60C, 0x00000018, + 0x6A0, 0x000000FF, + 0x6A1, 0x000000FF, + 0x6A2, 0x000000FF, + 0x6A3, 0x000000FF, + 0x6A4, 0x000000FF, + 0x6A5, 0x000000FF, + 0x6DE, 0x00000084, + 0x620, 0x000000FF, + 0x621, 0x000000FF, + 0x622, 0x000000FF, + 0x623, 0x000000FF, + 0x624, 0x000000FF, + 0x625, 0x000000FF, + 0x626, 0x000000FF, + 0x627, 0x000000FF, + 0x638, 0x00000050, + 0x63C, 0x0000000A, + 0x63D, 0x0000000A, + 0x63E, 0x0000000E, + 0x63F, 0x0000000E, + 0x640, 0x00000040, + 0x642, 0x00000040, + 0x643, 0x00000000, + 0x652, 0x000000C8, + 0x66E, 0x00000005, + 0x718, 0x00000040, + 0x7D4, 0x00000098, +}; + +RTW_DECL_TABLE_PHY_COND(rtw8822b_mac, rtw_phy_cfg_mac); + +static const u32 rtw8822b_agc[] = { + 0x80000000, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xFE000003, + 0x81C, 0xFD020003, + 0x81C, 0xFC040003, + 0x81C, 0xFB060003, + 0x81C, 0xFA080003, + 0x81C, 0xF90A0003, + 0x81C, 0xF80C0003, + 0x81C, 0xF70E0003, + 0x81C, 0xF6100003, + 0x81C, 0xF5120003, + 0x81C, 0xF4140003, + 0x81C, 0xF3160003, + 0x81C, 0xF2180003, + 0x81C, 0xF11A0003, + 0x81C, 0xF01C0003, + 0x81C, 0xEF1E0003, + 0x81C, 0xEE200003, + 0x81C, 0xED220003, + 0x81C, 0xEC240003, + 0x81C, 0xEB260003, + 0x81C, 0xEA280003, + 0x81C, 0xE92A0003, + 0x81C, 0xE82C0003, + 0x81C, 0xE72E0003, + 0x81C, 0xE6300003, + 0x81C, 0xE5320003, + 0x81C, 0xC8340003, + 0x81C, 0xC7360003, + 0x81C, 0xC6380003, + 0x81C, 0xC53A0003, + 0x81C, 0xC43C0003, + 0x81C, 0xC33E0003, + 0x81C, 0xC2400003, + 0x81C, 0xC1420003, + 0x81C, 0xC0440003, + 0x81C, 0xA3460003, + 0x81C, 0xA2480003, + 0x81C, 0xA14A0003, + 0x81C, 0xA04C0003, + 0x81C, 0x824E0003, + 0x81C, 0x81500003, + 0x81C, 0x80520003, + 0x81C, 0x64540003, + 0x81C, 0x63560003, + 0x81C, 0x62580003, + 0x81C, 0x445A0003, + 0x81C, 0x435C0003, + 0x81C, 0x425E0003, + 0x81C, 0x41600003, + 0x81C, 0x40620003, + 0x81C, 0x05640003, + 0x81C, 0x04660003, + 0x81C, 0x03680003, + 0x81C, 0x026A0003, + 0x81C, 0x016C0003, + 0x81C, 0x006E0003, + 0x81C, 0x00700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xF5000003, + 0x81C, 0xF4020003, + 0x81C, 0xF3040003, + 0x81C, 0xF2060003, + 0x81C, 0xF1080003, + 0x81C, 0xF00A0003, + 0x81C, 0xEF0C0003, + 0x81C, 0xEE0E0003, + 0x81C, 0xED100003, + 0x81C, 0xEC120003, + 0x81C, 0xEB140003, + 0x81C, 0xEA160003, + 0x81C, 0xE9180003, + 0x81C, 0xE81A0003, + 0x81C, 0xE71C0003, + 0x81C, 0xE61E0003, + 0x81C, 0xE5200003, + 0x81C, 0xE4220003, + 0x81C, 0xE3240003, + 0x81C, 0xE2260003, + 0x81C, 0xE1280003, + 0x81C, 0xE02A0003, + 0x81C, 0xC32C0003, + 0x81C, 0xC22E0003, + 0x81C, 0xC1300003, + 0x81C, 0xC0320003, + 0x81C, 0xA4340003, + 0x81C, 0xA3360003, + 0x81C, 0xA2380003, + 0x81C, 0xA13A0003, + 0x81C, 0xA03C0003, + 0x81C, 0x823E0003, + 0x81C, 0x81400003, + 0x81C, 0x80420003, + 0x81C, 0x64440003, + 0x81C, 0x63460003, + 0x81C, 0x62480003, + 0x81C, 0x614A0003, + 0x81C, 0x604C0003, + 0x81C, 0x454E0003, + 0x81C, 0x44500003, + 0x81C, 0x43520003, + 0x81C, 0x42540003, + 0x81C, 0x41560003, + 0x81C, 0x40580003, + 0x81C, 0x055A0003, + 0x81C, 0x045C0003, + 0x81C, 0x035E0003, + 0x81C, 0x02600003, + 0x81C, 0x01620003, + 0x81C, 0x00640003, + 0x81C, 0x00660003, + 0x81C, 0x00680003, + 0x81C, 0x006A0003, + 0x81C, 0x006C0003, + 0x81C, 0x006E0003, + 0x81C, 0x00700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xFD000003, + 0x81C, 0xFC020003, + 0x81C, 0xFB040003, + 0x81C, 0xFA060003, + 0x81C, 0xF9080003, + 0x81C, 0xF80A0003, + 0x81C, 0xF70C0003, + 0x81C, 0xF60E0003, + 0x81C, 0xF5100003, + 0x81C, 0xF4120003, + 0x81C, 0xF3140003, + 0x81C, 0xF2160003, + 0x81C, 0xF1180003, + 0x81C, 0xF01A0003, + 0x81C, 0xEF1C0003, + 0x81C, 0xEE1E0003, + 0x81C, 0xED200003, + 0x81C, 0xEC220003, + 0x81C, 0xEB240003, + 0x81C, 0xEA260003, + 0x81C, 0xE9280003, + 0x81C, 0xE82A0003, + 0x81C, 0xE72C0003, + 0x81C, 0xE62E0003, + 0x81C, 0xE5300003, + 0x81C, 0xC8320003, + 0x81C, 0xC7340003, + 0x81C, 0xC6360003, + 0x81C, 0xC5380003, + 0x81C, 0xC43A0003, + 0x81C, 0xC33C0003, + 0x81C, 0xC23E0003, + 0x81C, 0xC1400003, + 0x81C, 0xC0420003, + 0x81C, 0xA5440003, + 0x81C, 0xA4460003, + 0x81C, 0xA3480003, + 0x81C, 0xA24A0003, + 0x81C, 0xA14C0003, + 0x81C, 0x834E0003, + 0x81C, 0x82500003, + 0x81C, 0x81520003, + 0x81C, 0x80540003, + 0x81C, 0x65560003, + 0x81C, 0x64580003, + 0x81C, 0x635A0003, + 0x81C, 0x625C0003, + 0x81C, 0x435E0003, + 0x81C, 0x42600003, + 0x81C, 0x41620003, + 0x81C, 0x40640003, + 0x81C, 0x06660003, + 0x81C, 0x05680003, + 0x81C, 0x046A0003, + 0x81C, 0x036C0003, + 0x81C, 0x026E0003, + 0x81C, 0x01700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xFD000003, + 0x81C, 0xFC020003, + 0x81C, 0xFB040003, + 0x81C, 0xFA060003, + 0x81C, 0xF9080003, + 0x81C, 0xF80A0003, + 0x81C, 0xF70C0003, + 0x81C, 0xF60E0003, + 0x81C, 0xF5100003, + 0x81C, 0xF4120003, + 0x81C, 0xF3140003, + 0x81C, 0xF2160003, + 0x81C, 0xF1180003, + 0x81C, 0xF01A0003, + 0x81C, 0xEF1C0003, + 0x81C, 0xEE1E0003, + 0x81C, 0xED200003, + 0x81C, 0xEC220003, + 0x81C, 0xEB240003, + 0x81C, 0xEA260003, + 0x81C, 0xE9280003, + 0x81C, 0xE82A0003, + 0x81C, 0xE72C0003, + 0x81C, 0xE62E0003, + 0x81C, 0xE5300003, + 0x81C, 0xC8320003, + 0x81C, 0xC7340003, + 0x81C, 0xC6360003, + 0x81C, 0xC5380003, + 0x81C, 0xC43A0003, + 0x81C, 0xC33C0003, + 0x81C, 0xC23E0003, + 0x81C, 0xC1400003, + 0x81C, 0xC0420003, + 0x81C, 0xA5440003, + 0x81C, 0xA4460003, + 0x81C, 0xA3480003, + 0x81C, 0xA24A0003, + 0x81C, 0xA14C0003, + 0x81C, 0x834E0003, + 0x81C, 0x82500003, + 0x81C, 0x81520003, + 0x81C, 0x80540003, + 0x81C, 0x65560003, + 0x81C, 0x64580003, + 0x81C, 0x635A0003, + 0x81C, 0x625C0003, + 0x81C, 0x435E0003, + 0x81C, 0x42600003, + 0x81C, 0x41620003, + 0x81C, 0x40640003, + 0x81C, 0x06660003, + 0x81C, 0x05680003, + 0x81C, 0x046A0003, + 0x81C, 0x036C0003, + 0x81C, 0x026E0003, + 0x81C, 0x01700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xDC000003, + 0x81C, 0xDB020003, + 0x81C, 0xDA040003, + 0x81C, 0xD9060003, + 0x81C, 0xD8080003, + 0x81C, 0xD70A0003, + 0x81C, 0xD60C0003, + 0x81C, 0xD50E0003, + 0x81C, 0xD4100003, + 0x81C, 0xD3120003, + 0x81C, 0xD2140003, + 0x81C, 0xD1160003, + 0x81C, 0xD0180003, + 0x81C, 0xB41A0003, + 0x81C, 0xB31C0003, + 0x81C, 0xB21E0003, + 0x81C, 0xB1200003, + 0x81C, 0xB0220003, + 0x81C, 0xAF240003, + 0x81C, 0xAE260003, + 0x81C, 0xAD280003, + 0x81C, 0xAC2A0003, + 0x81C, 0xAB2C0003, + 0x81C, 0x8C2E0003, + 0x81C, 0x8B300003, + 0x81C, 0x8A320003, + 0x81C, 0x89340003, + 0x81C, 0x88360003, + 0x81C, 0x87380003, + 0x81C, 0x863A0003, + 0x81C, 0x853C0003, + 0x81C, 0x693E0003, + 0x81C, 0x68400003, + 0x81C, 0x67420003, + 0x81C, 0x66440003, + 0x81C, 0x65460003, + 0x81C, 0x48480003, + 0x81C, 0x474A0003, + 0x81C, 0x464C0003, + 0x81C, 0x454E0003, + 0x81C, 0x44500003, + 0x81C, 0x43520003, + 0x81C, 0x27540003, + 0x81C, 0x26560003, + 0x81C, 0x25580003, + 0x81C, 0x245A0003, + 0x81C, 0x235C0003, + 0x81C, 0x045E0003, + 0x81C, 0x03600003, + 0x81C, 0x02620003, + 0x81C, 0x01640003, + 0x81C, 0x00660003, + 0x81C, 0x00680003, + 0x81C, 0x006A0003, + 0x81C, 0x006C0003, + 0x81C, 0x006E0003, + 0x81C, 0x00700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xFD000003, + 0x81C, 0xFC020003, + 0x81C, 0xFB040003, + 0x81C, 0xFA060003, + 0x81C, 0xF9080003, + 0x81C, 0xF80A0003, + 0x81C, 0xF70C0003, + 0x81C, 0xF60E0003, + 0x81C, 0xF5100003, + 0x81C, 0xF4120003, + 0x81C, 0xF3140003, + 0x81C, 0xF2160003, + 0x81C, 0xF1180003, + 0x81C, 0xF01A0003, + 0x81C, 0xEF1C0003, + 0x81C, 0xEE1E0003, + 0x81C, 0xED200003, + 0x81C, 0xEC220003, + 0x81C, 0xEB240003, + 0x81C, 0xEA260003, + 0x81C, 0xE9280003, + 0x81C, 0xE82A0003, + 0x81C, 0xE72C0003, + 0x81C, 0xE62E0003, + 0x81C, 0xE5300003, + 0x81C, 0xC8320003, + 0x81C, 0xC7340003, + 0x81C, 0xC6360003, + 0x81C, 0xC5380003, + 0x81C, 0xC43A0003, + 0x81C, 0xC33C0003, + 0x81C, 0xC23E0003, + 0x81C, 0xC1400003, + 0x81C, 0xC0420003, + 0x81C, 0xA5440003, + 0x81C, 0xA4460003, + 0x81C, 0xA3480003, + 0x81C, 0xA24A0003, + 0x81C, 0xA14C0003, + 0x81C, 0x834E0003, + 0x81C, 0x82500003, + 0x81C, 0x81520003, + 0x81C, 0x80540003, + 0x81C, 0x65560003, + 0x81C, 0x64580003, + 0x81C, 0x635A0003, + 0x81C, 0x625C0003, + 0x81C, 0x435E0003, + 0x81C, 0x42600003, + 0x81C, 0x41620003, + 0x81C, 0x40640003, + 0x81C, 0x06660003, + 0x81C, 0x05680003, + 0x81C, 0x046A0003, + 0x81C, 0x036C0003, + 0x81C, 0x026E0003, + 0x81C, 0x01700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xF5000003, + 0x81C, 0xF4020003, + 0x81C, 0xF3040003, + 0x81C, 0xF2060003, + 0x81C, 0xF1080003, + 0x81C, 0xF00A0003, + 0x81C, 0xEF0C0003, + 0x81C, 0xEE0E0003, + 0x81C, 0xED100003, + 0x81C, 0xEC120003, + 0x81C, 0xEB140003, + 0x81C, 0xEA160003, + 0x81C, 0xE9180003, + 0x81C, 0xE81A0003, + 0x81C, 0xE71C0003, + 0x81C, 0xE61E0003, + 0x81C, 0xE5200003, + 0x81C, 0xE4220003, + 0x81C, 0xE3240003, + 0x81C, 0xE2260003, + 0x81C, 0xE1280003, + 0x81C, 0xE02A0003, + 0x81C, 0xC32C0003, + 0x81C, 0xC22E0003, + 0x81C, 0xC1300003, + 0x81C, 0xC0320003, + 0x81C, 0xA4340003, + 0x81C, 0xA3360003, + 0x81C, 0xA2380003, + 0x81C, 0xA13A0003, + 0x81C, 0xA03C0003, + 0x81C, 0x823E0003, + 0x81C, 0x81400003, + 0x81C, 0x80420003, + 0x81C, 0x64440003, + 0x81C, 0x63460003, + 0x81C, 0x62480003, + 0x81C, 0x614A0003, + 0x81C, 0x604C0003, + 0x81C, 0x454E0003, + 0x81C, 0x44500003, + 0x81C, 0x43520003, + 0x81C, 0x42540003, + 0x81C, 0x41560003, + 0x81C, 0x40580003, + 0x81C, 0x055A0003, + 0x81C, 0x045C0003, + 0x81C, 0x035E0003, + 0x81C, 0x02600003, + 0x81C, 0x01620003, + 0x81C, 0x00640003, + 0x81C, 0x00660003, + 0x81C, 0x00680003, + 0x81C, 0x006A0003, + 0x81C, 0x006C0003, + 0x81C, 0x006E0003, + 0x81C, 0x00700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xF5000003, + 0x81C, 0xF4020003, + 0x81C, 0xF3040003, + 0x81C, 0xF2060003, + 0x81C, 0xF1080003, + 0x81C, 0xF00A0003, + 0x81C, 0xEF0C0003, + 0x81C, 0xEE0E0003, + 0x81C, 0xED100003, + 0x81C, 0xEC120003, + 0x81C, 0xEB140003, + 0x81C, 0xEA160003, + 0x81C, 0xE9180003, + 0x81C, 0xE81A0003, + 0x81C, 0xE71C0003, + 0x81C, 0xE61E0003, + 0x81C, 0xE5200003, + 0x81C, 0xE4220003, + 0x81C, 0xE3240003, + 0x81C, 0xE2260003, + 0x81C, 0xE1280003, + 0x81C, 0xE02A0003, + 0x81C, 0xC32C0003, + 0x81C, 0xC22E0003, + 0x81C, 0xC1300003, + 0x81C, 0xC0320003, + 0x81C, 0xA4340003, + 0x81C, 0xA3360003, + 0x81C, 0xA2380003, + 0x81C, 0xA13A0003, + 0x81C, 0xA03C0003, + 0x81C, 0x823E0003, + 0x81C, 0x81400003, + 0x81C, 0x80420003, + 0x81C, 0x64440003, + 0x81C, 0x63460003, + 0x81C, 0x62480003, + 0x81C, 0x614A0003, + 0x81C, 0x604C0003, + 0x81C, 0x454E0003, + 0x81C, 0x44500003, + 0x81C, 0x43520003, + 0x81C, 0x42540003, + 0x81C, 0x41560003, + 0x81C, 0x40580003, + 0x81C, 0x055A0003, + 0x81C, 0x045C0003, + 0x81C, 0x035E0003, + 0x81C, 0x02600003, + 0x81C, 0x01620003, + 0x81C, 0x00640003, + 0x81C, 0x00660003, + 0x81C, 0x00680003, + 0x81C, 0x006A0003, + 0x81C, 0x006C0003, + 0x81C, 0x006E0003, + 0x81C, 0x00700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x90000008, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xFE000003, + 0x81C, 0xFD020003, + 0x81C, 0xFC040003, + 0x81C, 0xFB060003, + 0x81C, 0xFA080003, + 0x81C, 0xF90A0003, + 0x81C, 0xF80C0003, + 0x81C, 0xF70E0003, + 0x81C, 0xF6100003, + 0x81C, 0xF5120003, + 0x81C, 0xF4140003, + 0x81C, 0xF3160003, + 0x81C, 0xF2180003, + 0x81C, 0xF11A0003, + 0x81C, 0xF01C0003, + 0x81C, 0xEF1E0003, + 0x81C, 0xEE200003, + 0x81C, 0xED220003, + 0x81C, 0xEC240003, + 0x81C, 0xEB260003, + 0x81C, 0xEA280003, + 0x81C, 0xE92A0003, + 0x81C, 0xE82C0003, + 0x81C, 0xE72E0003, + 0x81C, 0xE6300003, + 0x81C, 0xE5320003, + 0x81C, 0xC8340003, + 0x81C, 0xC7360003, + 0x81C, 0xC6380003, + 0x81C, 0xC53A0003, + 0x81C, 0xC43C0003, + 0x81C, 0xC33E0003, + 0x81C, 0xC2400003, + 0x81C, 0xC1420003, + 0x81C, 0xC0440003, + 0x81C, 0xA3460003, + 0x81C, 0xA2480003, + 0x81C, 0xA14A0003, + 0x81C, 0xA04C0003, + 0x81C, 0x824E0003, + 0x81C, 0x81500003, + 0x81C, 0x80520003, + 0x81C, 0x64540003, + 0x81C, 0x63560003, + 0x81C, 0x62580003, + 0x81C, 0x445A0003, + 0x81C, 0x435C0003, + 0x81C, 0x425E0003, + 0x81C, 0x41600003, + 0x81C, 0x40620003, + 0x81C, 0x05640003, + 0x81C, 0x04660003, + 0x81C, 0x03680003, + 0x81C, 0x026A0003, + 0x81C, 0x016C0003, + 0x81C, 0x006E0003, + 0x81C, 0x00700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x90000009, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xF5000003, + 0x81C, 0xF4020003, + 0x81C, 0xF3040003, + 0x81C, 0xF2060003, + 0x81C, 0xF1080003, + 0x81C, 0xF00A0003, + 0x81C, 0xEF0C0003, + 0x81C, 0xEE0E0003, + 0x81C, 0xED100003, + 0x81C, 0xEC120003, + 0x81C, 0xEB140003, + 0x81C, 0xEA160003, + 0x81C, 0xE9180003, + 0x81C, 0xE81A0003, + 0x81C, 0xE71C0003, + 0x81C, 0xE61E0003, + 0x81C, 0xE5200003, + 0x81C, 0xE4220003, + 0x81C, 0xE3240003, + 0x81C, 0xE2260003, + 0x81C, 0xE1280003, + 0x81C, 0xE02A0003, + 0x81C, 0xC32C0003, + 0x81C, 0xC22E0003, + 0x81C, 0xC1300003, + 0x81C, 0xC0320003, + 0x81C, 0xA4340003, + 0x81C, 0xA3360003, + 0x81C, 0xA2380003, + 0x81C, 0xA13A0003, + 0x81C, 0xA03C0003, + 0x81C, 0x823E0003, + 0x81C, 0x81400003, + 0x81C, 0x80420003, + 0x81C, 0x64440003, + 0x81C, 0x63460003, + 0x81C, 0x62480003, + 0x81C, 0x614A0003, + 0x81C, 0x604C0003, + 0x81C, 0x454E0003, + 0x81C, 0x44500003, + 0x81C, 0x43520003, + 0x81C, 0x42540003, + 0x81C, 0x41560003, + 0x81C, 0x40580003, + 0x81C, 0x055A0003, + 0x81C, 0x045C0003, + 0x81C, 0x035E0003, + 0x81C, 0x02600003, + 0x81C, 0x01620003, + 0x81C, 0x00640003, + 0x81C, 0x00660003, + 0x81C, 0x00680003, + 0x81C, 0x006A0003, + 0x81C, 0x006C0003, + 0x81C, 0x006E0003, + 0x81C, 0x00700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x9000000a, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xFE000003, + 0x81C, 0xFD020003, + 0x81C, 0xFC040003, + 0x81C, 0xFB060003, + 0x81C, 0xFA080003, + 0x81C, 0xF90A0003, + 0x81C, 0xF80C0003, + 0x81C, 0xF70E0003, + 0x81C, 0xF6100003, + 0x81C, 0xF5120003, + 0x81C, 0xF4140003, + 0x81C, 0xF3160003, + 0x81C, 0xF2180003, + 0x81C, 0xF11A0003, + 0x81C, 0xF01C0003, + 0x81C, 0xEF1E0003, + 0x81C, 0xEE200003, + 0x81C, 0xED220003, + 0x81C, 0xEC240003, + 0x81C, 0xEB260003, + 0x81C, 0xEA280003, + 0x81C, 0xE92A0003, + 0x81C, 0xE82C0003, + 0x81C, 0xE72E0003, + 0x81C, 0xE6300003, + 0x81C, 0xE5320003, + 0x81C, 0xC8340003, + 0x81C, 0xC7360003, + 0x81C, 0xC6380003, + 0x81C, 0xC53A0003, + 0x81C, 0xC43C0003, + 0x81C, 0xC33E0003, + 0x81C, 0xC2400003, + 0x81C, 0xC1420003, + 0x81C, 0xC0440003, + 0x81C, 0xA3460003, + 0x81C, 0xA2480003, + 0x81C, 0xA14A0003, + 0x81C, 0xA04C0003, + 0x81C, 0x824E0003, + 0x81C, 0x81500003, + 0x81C, 0x80520003, + 0x81C, 0x64540003, + 0x81C, 0x63560003, + 0x81C, 0x62580003, + 0x81C, 0x445A0003, + 0x81C, 0x435C0003, + 0x81C, 0x425E0003, + 0x81C, 0x41600003, + 0x81C, 0x40620003, + 0x81C, 0x05640003, + 0x81C, 0x04660003, + 0x81C, 0x03680003, + 0x81C, 0x026A0003, + 0x81C, 0x016C0003, + 0x81C, 0x006E0003, + 0x81C, 0x00700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x9000000b, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xF5000003, + 0x81C, 0xF4020003, + 0x81C, 0xF3040003, + 0x81C, 0xF2060003, + 0x81C, 0xF1080003, + 0x81C, 0xF00A0003, + 0x81C, 0xEF0C0003, + 0x81C, 0xEE0E0003, + 0x81C, 0xED100003, + 0x81C, 0xEC120003, + 0x81C, 0xEB140003, + 0x81C, 0xEA160003, + 0x81C, 0xE9180003, + 0x81C, 0xE81A0003, + 0x81C, 0xE71C0003, + 0x81C, 0xE61E0003, + 0x81C, 0xE5200003, + 0x81C, 0xE4220003, + 0x81C, 0xE3240003, + 0x81C, 0xE2260003, + 0x81C, 0xE1280003, + 0x81C, 0xE02A0003, + 0x81C, 0xC32C0003, + 0x81C, 0xC22E0003, + 0x81C, 0xC1300003, + 0x81C, 0xC0320003, + 0x81C, 0xA4340003, + 0x81C, 0xA3360003, + 0x81C, 0xA2380003, + 0x81C, 0xA13A0003, + 0x81C, 0xA03C0003, + 0x81C, 0x823E0003, + 0x81C, 0x81400003, + 0x81C, 0x80420003, + 0x81C, 0x64440003, + 0x81C, 0x63460003, + 0x81C, 0x62480003, + 0x81C, 0x614A0003, + 0x81C, 0x604C0003, + 0x81C, 0x454E0003, + 0x81C, 0x44500003, + 0x81C, 0x43520003, + 0x81C, 0x42540003, + 0x81C, 0x41560003, + 0x81C, 0x40580003, + 0x81C, 0x055A0003, + 0x81C, 0x045C0003, + 0x81C, 0x035E0003, + 0x81C, 0x02600003, + 0x81C, 0x01620003, + 0x81C, 0x00640003, + 0x81C, 0x00660003, + 0x81C, 0x00680003, + 0x81C, 0x006A0003, + 0x81C, 0x006C0003, + 0x81C, 0x006E0003, + 0x81C, 0x00700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x9000000c, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xFD000003, + 0x81C, 0xFC020003, + 0x81C, 0xFB040003, + 0x81C, 0xFA060003, + 0x81C, 0xF9080003, + 0x81C, 0xF80A0003, + 0x81C, 0xF70C0003, + 0x81C, 0xF60E0003, + 0x81C, 0xF5100003, + 0x81C, 0xF4120003, + 0x81C, 0xF3140003, + 0x81C, 0xF2160003, + 0x81C, 0xF1180003, + 0x81C, 0xF01A0003, + 0x81C, 0xEF1C0003, + 0x81C, 0xEE1E0003, + 0x81C, 0xED200003, + 0x81C, 0xEC220003, + 0x81C, 0xEB240003, + 0x81C, 0xEA260003, + 0x81C, 0xE9280003, + 0x81C, 0xE82A0003, + 0x81C, 0xE72C0003, + 0x81C, 0xE62E0003, + 0x81C, 0xE5300003, + 0x81C, 0xC8320003, + 0x81C, 0xC7340003, + 0x81C, 0xC6360003, + 0x81C, 0xC5380003, + 0x81C, 0xC43A0003, + 0x81C, 0xC33C0003, + 0x81C, 0xC23E0003, + 0x81C, 0xC1400003, + 0x81C, 0xC0420003, + 0x81C, 0xA5440003, + 0x81C, 0xA4460003, + 0x81C, 0xA3480003, + 0x81C, 0xA24A0003, + 0x81C, 0xA14C0003, + 0x81C, 0x834E0003, + 0x81C, 0x82500003, + 0x81C, 0x81520003, + 0x81C, 0x80540003, + 0x81C, 0x65560003, + 0x81C, 0x64580003, + 0x81C, 0x635A0003, + 0x81C, 0x625C0003, + 0x81C, 0x435E0003, + 0x81C, 0x42600003, + 0x81C, 0x41620003, + 0x81C, 0x40640003, + 0x81C, 0x06660003, + 0x81C, 0x05680003, + 0x81C, 0x046A0003, + 0x81C, 0x036C0003, + 0x81C, 0x026E0003, + 0x81C, 0x01700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x9000000d, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xFE000003, + 0x81C, 0xFD020003, + 0x81C, 0xFC040003, + 0x81C, 0xFB060003, + 0x81C, 0xFA080003, + 0x81C, 0xF90A0003, + 0x81C, 0xF80C0003, + 0x81C, 0xF70E0003, + 0x81C, 0xF6100003, + 0x81C, 0xF5120003, + 0x81C, 0xF4140003, + 0x81C, 0xF3160003, + 0x81C, 0xF2180003, + 0x81C, 0xF11A0003, + 0x81C, 0xF01C0003, + 0x81C, 0xEF1E0003, + 0x81C, 0xEE200003, + 0x81C, 0xED220003, + 0x81C, 0xEC240003, + 0x81C, 0xEB260003, + 0x81C, 0xEA280003, + 0x81C, 0xE92A0003, + 0x81C, 0xE82C0003, + 0x81C, 0xE72E0003, + 0x81C, 0xE6300003, + 0x81C, 0xE5320003, + 0x81C, 0xC8340003, + 0x81C, 0xC7360003, + 0x81C, 0xC6380003, + 0x81C, 0xC53A0003, + 0x81C, 0xC43C0003, + 0x81C, 0xC33E0003, + 0x81C, 0xC2400003, + 0x81C, 0xC1420003, + 0x81C, 0xC0440003, + 0x81C, 0xA3460003, + 0x81C, 0xA2480003, + 0x81C, 0xA14A0003, + 0x81C, 0xA04C0003, + 0x81C, 0x824E0003, + 0x81C, 0x81500003, + 0x81C, 0x80520003, + 0x81C, 0x64540003, + 0x81C, 0x63560003, + 0x81C, 0x62580003, + 0x81C, 0x445A0003, + 0x81C, 0x435C0003, + 0x81C, 0x425E0003, + 0x81C, 0x41600003, + 0x81C, 0x40620003, + 0x81C, 0x05640003, + 0x81C, 0x04660003, + 0x81C, 0x03680003, + 0x81C, 0x026A0003, + 0x81C, 0x016C0003, + 0x81C, 0x006E0003, + 0x81C, 0x00700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x9000000e, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xFE000003, + 0x81C, 0xFD020003, + 0x81C, 0xFC040003, + 0x81C, 0xFB060003, + 0x81C, 0xFA080003, + 0x81C, 0xF90A0003, + 0x81C, 0xF80C0003, + 0x81C, 0xF70E0003, + 0x81C, 0xF6100003, + 0x81C, 0xF5120003, + 0x81C, 0xF4140003, + 0x81C, 0xF3160003, + 0x81C, 0xF2180003, + 0x81C, 0xF11A0003, + 0x81C, 0xF01C0003, + 0x81C, 0xEF1E0003, + 0x81C, 0xEE200003, + 0x81C, 0xED220003, + 0x81C, 0xEC240003, + 0x81C, 0xEB260003, + 0x81C, 0xEA280003, + 0x81C, 0xE92A0003, + 0x81C, 0xE82C0003, + 0x81C, 0xE72E0003, + 0x81C, 0xE6300003, + 0x81C, 0xE5320003, + 0x81C, 0xC8340003, + 0x81C, 0xC7360003, + 0x81C, 0xC6380003, + 0x81C, 0xC53A0003, + 0x81C, 0xC43C0003, + 0x81C, 0xC33E0003, + 0x81C, 0xC2400003, + 0x81C, 0xC1420003, + 0x81C, 0xC0440003, + 0x81C, 0xA3460003, + 0x81C, 0xA2480003, + 0x81C, 0xA14A0003, + 0x81C, 0xA04C0003, + 0x81C, 0x824E0003, + 0x81C, 0x81500003, + 0x81C, 0x80520003, + 0x81C, 0x64540003, + 0x81C, 0x63560003, + 0x81C, 0x62580003, + 0x81C, 0x445A0003, + 0x81C, 0x435C0003, + 0x81C, 0x425E0003, + 0x81C, 0x41600003, + 0x81C, 0x40620003, + 0x81C, 0x05640003, + 0x81C, 0x04660003, + 0x81C, 0x03680003, + 0x81C, 0x026A0003, + 0x81C, 0x016C0003, + 0x81C, 0x006E0003, + 0x81C, 0x00700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x9000000f, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xFC000003, + 0x81C, 0xFB020003, + 0x81C, 0xFA040003, + 0x81C, 0xF9060003, + 0x81C, 0xF8080003, + 0x81C, 0xF70A0003, + 0x81C, 0xF60C0003, + 0x81C, 0xF50E0003, + 0x81C, 0xF4100003, + 0x81C, 0xF3120003, + 0x81C, 0xF2140003, + 0x81C, 0xF1160003, + 0x81C, 0xF0180003, + 0x81C, 0xEF1A0003, + 0x81C, 0xEE1C0003, + 0x81C, 0xED1E0003, + 0x81C, 0xEC200003, + 0x81C, 0xEB220003, + 0x81C, 0xEA240003, + 0x81C, 0xE9260003, + 0x81C, 0xE8280003, + 0x81C, 0xE72A0003, + 0x81C, 0xE62C0003, + 0x81C, 0xE52E0003, + 0x81C, 0xC8300003, + 0x81C, 0xC7320003, + 0x81C, 0xC6340003, + 0x81C, 0xC5360003, + 0x81C, 0xC4380003, + 0x81C, 0xC33A0003, + 0x81C, 0xC23C0003, + 0x81C, 0xC13E0003, + 0x81C, 0xA4400003, + 0x81C, 0xA3420003, + 0x81C, 0xA2440003, + 0x81C, 0xA1460003, + 0x81C, 0xA0480003, + 0x81C, 0x684A0003, + 0x81C, 0x674C0003, + 0x81C, 0x664E0003, + 0x81C, 0x65500003, + 0x81C, 0x64520003, + 0x81C, 0x63540003, + 0x81C, 0x44560003, + 0x81C, 0x43580003, + 0x81C, 0x425A0003, + 0x81C, 0x415C0003, + 0x81C, 0x405E0003, + 0x81C, 0x23600003, + 0x81C, 0x22620003, + 0x81C, 0x21640003, + 0x81C, 0x03660003, + 0x81C, 0x02680003, + 0x81C, 0x016A0003, + 0x81C, 0x006C0003, + 0x81C, 0x006E0003, + 0x81C, 0x00700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x90000010, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xFD000003, + 0x81C, 0xFC020003, + 0x81C, 0xFB040003, + 0x81C, 0xFA060003, + 0x81C, 0xF9080003, + 0x81C, 0xF80A0003, + 0x81C, 0xF70C0003, + 0x81C, 0xF60E0003, + 0x81C, 0xF5100003, + 0x81C, 0xF4120003, + 0x81C, 0xF3140003, + 0x81C, 0xF2160003, + 0x81C, 0xF1180003, + 0x81C, 0xF01A0003, + 0x81C, 0xEF1C0003, + 0x81C, 0xEE1E0003, + 0x81C, 0xED200003, + 0x81C, 0xEC220003, + 0x81C, 0xEB240003, + 0x81C, 0xEA260003, + 0x81C, 0xE9280003, + 0x81C, 0xE82A0003, + 0x81C, 0xE72C0003, + 0x81C, 0xE62E0003, + 0x81C, 0xE5300003, + 0x81C, 0xC8320003, + 0x81C, 0xC7340003, + 0x81C, 0xC6360003, + 0x81C, 0xC5380003, + 0x81C, 0xC43A0003, + 0x81C, 0xC33C0003, + 0x81C, 0xC23E0003, + 0x81C, 0xC1400003, + 0x81C, 0xC0420003, + 0x81C, 0xA5440003, + 0x81C, 0xA4460003, + 0x81C, 0xA3480003, + 0x81C, 0xA24A0003, + 0x81C, 0xA14C0003, + 0x81C, 0x834E0003, + 0x81C, 0x82500003, + 0x81C, 0x81520003, + 0x81C, 0x80540003, + 0x81C, 0x65560003, + 0x81C, 0x64580003, + 0x81C, 0x635A0003, + 0x81C, 0x625C0003, + 0x81C, 0x435E0003, + 0x81C, 0x42600003, + 0x81C, 0x41620003, + 0x81C, 0x40640003, + 0x81C, 0x06660003, + 0x81C, 0x05680003, + 0x81C, 0x046A0003, + 0x81C, 0x036C0003, + 0x81C, 0x026E0003, + 0x81C, 0x01700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0x90000012, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xDC000003, + 0x81C, 0xDB020003, + 0x81C, 0xDA040003, + 0x81C, 0xD9060003, + 0x81C, 0xD8080003, + 0x81C, 0xD70A0003, + 0x81C, 0xD60C0003, + 0x81C, 0xD50E0003, + 0x81C, 0xD4100003, + 0x81C, 0xD3120003, + 0x81C, 0xD2140003, + 0x81C, 0xD1160003, + 0x81C, 0xD0180003, + 0x81C, 0xB41A0003, + 0x81C, 0xB31C0003, + 0x81C, 0xB21E0003, + 0x81C, 0xB1200003, + 0x81C, 0xB0220003, + 0x81C, 0xAF240003, + 0x81C, 0xAE260003, + 0x81C, 0xAD280003, + 0x81C, 0xAC2A0003, + 0x81C, 0xAB2C0003, + 0x81C, 0x8C2E0003, + 0x81C, 0x8B300003, + 0x81C, 0x8A320003, + 0x81C, 0x89340003, + 0x81C, 0x88360003, + 0x81C, 0x87380003, + 0x81C, 0x863A0003, + 0x81C, 0x853C0003, + 0x81C, 0x693E0003, + 0x81C, 0x68400003, + 0x81C, 0x67420003, + 0x81C, 0x66440003, + 0x81C, 0x65460003, + 0x81C, 0x48480003, + 0x81C, 0x474A0003, + 0x81C, 0x464C0003, + 0x81C, 0x454E0003, + 0x81C, 0x44500003, + 0x81C, 0x43520003, + 0x81C, 0x27540003, + 0x81C, 0x26560003, + 0x81C, 0x25580003, + 0x81C, 0x245A0003, + 0x81C, 0x235C0003, + 0x81C, 0x045E0003, + 0x81C, 0x03600003, + 0x81C, 0x02620003, + 0x81C, 0x01640003, + 0x81C, 0x00660003, + 0x81C, 0x00680003, + 0x81C, 0x006A0003, + 0x81C, 0x006C0003, + 0x81C, 0x006E0003, + 0x81C, 0x00700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0xA0000000, 0x00000000, + 0x81C, 0xFF000003, + 0x81C, 0xFE000003, + 0x81C, 0xFD020003, + 0x81C, 0xFC040003, + 0x81C, 0xFB060003, + 0x81C, 0xFA080003, + 0x81C, 0xF90A0003, + 0x81C, 0xF80C0003, + 0x81C, 0xF70E0003, + 0x81C, 0xF6100003, + 0x81C, 0xF5120003, + 0x81C, 0xF4140003, + 0x81C, 0xF3160003, + 0x81C, 0xF2180003, + 0x81C, 0xF11A0003, + 0x81C, 0xF01C0003, + 0x81C, 0xEF1E0003, + 0x81C, 0xEE200003, + 0x81C, 0xED220003, + 0x81C, 0xEC240003, + 0x81C, 0xEB260003, + 0x81C, 0xEA280003, + 0x81C, 0xE92A0003, + 0x81C, 0xE82C0003, + 0x81C, 0xE72E0003, + 0x81C, 0xE6300003, + 0x81C, 0xE5320003, + 0x81C, 0xC8340003, + 0x81C, 0xC7360003, + 0x81C, 0xC6380003, + 0x81C, 0xC53A0003, + 0x81C, 0xC43C0003, + 0x81C, 0xC33E0003, + 0x81C, 0xC2400003, + 0x81C, 0xC1420003, + 0x81C, 0xC0440003, + 0x81C, 0xA3460003, + 0x81C, 0xA2480003, + 0x81C, 0xA14A0003, + 0x81C, 0xA04C0003, + 0x81C, 0x824E0003, + 0x81C, 0x81500003, + 0x81C, 0x80520003, + 0x81C, 0x64540003, + 0x81C, 0x63560003, + 0x81C, 0x62580003, + 0x81C, 0x445A0003, + 0x81C, 0x435C0003, + 0x81C, 0x425E0003, + 0x81C, 0x41600003, + 0x81C, 0x40620003, + 0x81C, 0x05640003, + 0x81C, 0x04660003, + 0x81C, 0x03680003, + 0x81C, 0x026A0003, + 0x81C, 0x016C0003, + 0x81C, 0x006E0003, + 0x81C, 0x00700003, + 0x81C, 0x00720003, + 0x81C, 0x00740003, + 0x81C, 0x00760003, + 0x81C, 0x00780003, + 0x81C, 0x007A0003, + 0x81C, 0x007C0003, + 0x81C, 0x007E0003, + 0xB0000000, 0x00000000, + 0x80000000, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFD000103, + 0x81C, 0xFC020103, + 0x81C, 0xFB040103, + 0x81C, 0xFA060103, + 0x81C, 0xF9080103, + 0x81C, 0xF80A0103, + 0x81C, 0xF70C0103, + 0x81C, 0xF60E0103, + 0x81C, 0xF5100103, + 0x81C, 0xF4120103, + 0x81C, 0xF3140103, + 0x81C, 0xF2160103, + 0x81C, 0xF1180103, + 0x81C, 0xF01A0103, + 0x81C, 0xEE1C0103, + 0x81C, 0xED1E0103, + 0x81C, 0xEC200103, + 0x81C, 0xEB220103, + 0x81C, 0xEA240103, + 0x81C, 0xE9260103, + 0x81C, 0xE8280103, + 0x81C, 0xE72A0103, + 0x81C, 0xE62C0103, + 0x81C, 0xE52E0103, + 0x81C, 0xE4300103, + 0x81C, 0xE3320103, + 0x81C, 0xE2340103, + 0x81C, 0xC5360103, + 0x81C, 0xC4380103, + 0x81C, 0xC33A0103, + 0x81C, 0xC23C0103, + 0x81C, 0xA53E0103, + 0x81C, 0xA4400103, + 0x81C, 0xA3420103, + 0x81C, 0xA2440103, + 0x81C, 0xA1460103, + 0x81C, 0x83480103, + 0x81C, 0x824A0103, + 0x81C, 0x814C0103, + 0x81C, 0x804E0103, + 0x81C, 0x63500103, + 0x81C, 0x62520103, + 0x81C, 0x61540103, + 0x81C, 0x43560103, + 0x81C, 0x42580103, + 0x81C, 0x415A0103, + 0x81C, 0x405C0103, + 0x81C, 0x225E0103, + 0x81C, 0x21600103, + 0x81C, 0x20620103, + 0x81C, 0x03640103, + 0x81C, 0x02660103, + 0x81C, 0x01680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000103, + 0x81C, 0xF7020103, + 0x81C, 0xF6040103, + 0x81C, 0xF5060103, + 0x81C, 0xF4080103, + 0x81C, 0xF30A0103, + 0x81C, 0xF20C0103, + 0x81C, 0xF10E0103, + 0x81C, 0xF0100103, + 0x81C, 0xEF120103, + 0x81C, 0xEE140103, + 0x81C, 0xED160103, + 0x81C, 0xEC180103, + 0x81C, 0xEB1A0103, + 0x81C, 0xEA1C0103, + 0x81C, 0xE91E0103, + 0x81C, 0xE8200103, + 0x81C, 0xE7220103, + 0x81C, 0xE6240103, + 0x81C, 0xE5260103, + 0x81C, 0xE4280103, + 0x81C, 0xE32A0103, + 0x81C, 0xC32C0103, + 0x81C, 0xC22E0103, + 0x81C, 0xC1300103, + 0x81C, 0xC0320103, + 0x81C, 0xA3340103, + 0x81C, 0xA2360103, + 0x81C, 0xA1380103, + 0x81C, 0xA03A0103, + 0x81C, 0x823C0103, + 0x81C, 0x813E0103, + 0x81C, 0x80400103, + 0x81C, 0x63420103, + 0x81C, 0x62440103, + 0x81C, 0x61460103, + 0x81C, 0x60480103, + 0x81C, 0x424A0103, + 0x81C, 0x414C0103, + 0x81C, 0x404E0103, + 0x81C, 0x06500103, + 0x81C, 0x05520103, + 0x81C, 0x04540103, + 0x81C, 0x03560103, + 0x81C, 0x02580103, + 0x81C, 0x015A0103, + 0x81C, 0x005C0103, + 0x81C, 0x005E0103, + 0x81C, 0x00600103, + 0x81C, 0x00620103, + 0x81C, 0x00640103, + 0x81C, 0x00660103, + 0x81C, 0x00680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000103, + 0x81C, 0xF7020103, + 0x81C, 0xF6040103, + 0x81C, 0xF5060103, + 0x81C, 0xF4080103, + 0x81C, 0xF30A0103, + 0x81C, 0xF20C0103, + 0x81C, 0xF10E0103, + 0x81C, 0xF0100103, + 0x81C, 0xEF120103, + 0x81C, 0xEE140103, + 0x81C, 0xED160103, + 0x81C, 0xEC180103, + 0x81C, 0xEB1A0103, + 0x81C, 0xEA1C0103, + 0x81C, 0xE91E0103, + 0x81C, 0xE8200103, + 0x81C, 0xE7220103, + 0x81C, 0xE6240103, + 0x81C, 0xE5260103, + 0x81C, 0xE4280103, + 0x81C, 0xE32A0103, + 0x81C, 0xC32C0103, + 0x81C, 0xC22E0103, + 0x81C, 0xC1300103, + 0x81C, 0xC0320103, + 0x81C, 0xA3340103, + 0x81C, 0xA2360103, + 0x81C, 0xA1380103, + 0x81C, 0xA03A0103, + 0x81C, 0x823C0103, + 0x81C, 0x813E0103, + 0x81C, 0x80400103, + 0x81C, 0x63420103, + 0x81C, 0x62440103, + 0x81C, 0x61460103, + 0x81C, 0x60480103, + 0x81C, 0x424A0103, + 0x81C, 0x414C0103, + 0x81C, 0x404E0103, + 0x81C, 0x22500103, + 0x81C, 0x21520103, + 0x81C, 0x20540103, + 0x81C, 0x03560103, + 0x81C, 0x02580103, + 0x81C, 0x015A0103, + 0x81C, 0x005C0103, + 0x81C, 0x005E0103, + 0x81C, 0x00600103, + 0x81C, 0x00620103, + 0x81C, 0x00640103, + 0x81C, 0x00660103, + 0x81C, 0x00680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFE000103, + 0x81C, 0xFD020103, + 0x81C, 0xFC040103, + 0x81C, 0xFB060103, + 0x81C, 0xFA080103, + 0x81C, 0xF90A0103, + 0x81C, 0xF80C0103, + 0x81C, 0xF70E0103, + 0x81C, 0xF6100103, + 0x81C, 0xF5120103, + 0x81C, 0xF4140103, + 0x81C, 0xF3160103, + 0x81C, 0xF2180103, + 0x81C, 0xF11A0103, + 0x81C, 0xF01C0103, + 0x81C, 0xEF1E0103, + 0x81C, 0xEE200103, + 0x81C, 0xED220103, + 0x81C, 0xEC240103, + 0x81C, 0xEB260103, + 0x81C, 0xEA280103, + 0x81C, 0xE92A0103, + 0x81C, 0xE82C0103, + 0x81C, 0xE72E0103, + 0x81C, 0xE6300103, + 0x81C, 0xE5320103, + 0x81C, 0xE4340103, + 0x81C, 0xE3360103, + 0x81C, 0xC6380103, + 0x81C, 0xC53A0103, + 0x81C, 0xC43C0103, + 0x81C, 0xC33E0103, + 0x81C, 0xA5400103, + 0x81C, 0xA4420103, + 0x81C, 0xA3440103, + 0x81C, 0xA2460103, + 0x81C, 0xA1480103, + 0x81C, 0xA04A0103, + 0x81C, 0x824C0103, + 0x81C, 0x814E0103, + 0x81C, 0x80500103, + 0x81C, 0x64520103, + 0x81C, 0x63540103, + 0x81C, 0x62560103, + 0x81C, 0x61580103, + 0x81C, 0x605A0103, + 0x81C, 0x235C0103, + 0x81C, 0x225E0103, + 0x81C, 0x21600103, + 0x81C, 0x20620103, + 0x81C, 0x03640103, + 0x81C, 0x02660103, + 0x81C, 0x01680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000103, + 0x81C, 0xF7020103, + 0x81C, 0xF6040103, + 0x81C, 0xF5060103, + 0x81C, 0xF4080103, + 0x81C, 0xF30A0103, + 0x81C, 0xF20C0103, + 0x81C, 0xF10E0103, + 0x81C, 0xF0100103, + 0x81C, 0xEF120103, + 0x81C, 0xEE140103, + 0x81C, 0xED160103, + 0x81C, 0xEC180103, + 0x81C, 0xEB1A0103, + 0x81C, 0xEA1C0103, + 0x81C, 0xE91E0103, + 0x81C, 0xE8200103, + 0x81C, 0xE7220103, + 0x81C, 0xE6240103, + 0x81C, 0xE5260103, + 0x81C, 0xE4280103, + 0x81C, 0xE32A0103, + 0x81C, 0xC32C0103, + 0x81C, 0xC22E0103, + 0x81C, 0xC1300103, + 0x81C, 0xC0320103, + 0x81C, 0xA3340103, + 0x81C, 0xA2360103, + 0x81C, 0xA1380103, + 0x81C, 0xA03A0103, + 0x81C, 0x823C0103, + 0x81C, 0x813E0103, + 0x81C, 0x80400103, + 0x81C, 0x63420103, + 0x81C, 0x62440103, + 0x81C, 0x61460103, + 0x81C, 0x60480103, + 0x81C, 0x424A0103, + 0x81C, 0x414C0103, + 0x81C, 0x404E0103, + 0x81C, 0x22500103, + 0x81C, 0x21520103, + 0x81C, 0x20540103, + 0x81C, 0x03560103, + 0x81C, 0x02580103, + 0x81C, 0x015A0103, + 0x81C, 0x005C0103, + 0x81C, 0x005E0103, + 0x81C, 0x00600103, + 0x81C, 0x00620103, + 0x81C, 0x00640103, + 0x81C, 0x00660103, + 0x81C, 0x00680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFD000103, + 0x81C, 0xFC020103, + 0x81C, 0xFB040103, + 0x81C, 0xFA060103, + 0x81C, 0xF9080103, + 0x81C, 0xF80A0103, + 0x81C, 0xF70C0103, + 0x81C, 0xF60E0103, + 0x81C, 0xF5100103, + 0x81C, 0xF4120103, + 0x81C, 0xF3140103, + 0x81C, 0xF2160103, + 0x81C, 0xF1180103, + 0x81C, 0xF01A0103, + 0x81C, 0xEF1C0103, + 0x81C, 0xEE1E0103, + 0x81C, 0xED200103, + 0x81C, 0xEC220103, + 0x81C, 0xEB240103, + 0x81C, 0xEA260103, + 0x81C, 0xE9280103, + 0x81C, 0xE82A0103, + 0x81C, 0xE72C0103, + 0x81C, 0xE62E0103, + 0x81C, 0xE5300103, + 0x81C, 0xE4320103, + 0x81C, 0xE3340103, + 0x81C, 0xE2360103, + 0x81C, 0xC5380103, + 0x81C, 0xC43A0103, + 0x81C, 0xC33C0103, + 0x81C, 0xC23E0103, + 0x81C, 0xA5400103, + 0x81C, 0xA4420103, + 0x81C, 0xA3440103, + 0x81C, 0xA2460103, + 0x81C, 0xA1480103, + 0x81C, 0x834A0103, + 0x81C, 0x824C0103, + 0x81C, 0x814E0103, + 0x81C, 0x64500103, + 0x81C, 0x63520103, + 0x81C, 0x62540103, + 0x81C, 0x61560103, + 0x81C, 0x42580103, + 0x81C, 0x415A0103, + 0x81C, 0x405C0103, + 0x81C, 0x065E0103, + 0x81C, 0x05600103, + 0x81C, 0x04620103, + 0x81C, 0x03640103, + 0x81C, 0x02660103, + 0x81C, 0x01680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFA000103, + 0x81C, 0xF9020103, + 0x81C, 0xF8040103, + 0x81C, 0xF7060103, + 0x81C, 0xF6080103, + 0x81C, 0xF50A0103, + 0x81C, 0xF40C0103, + 0x81C, 0xF30E0103, + 0x81C, 0xF2100103, + 0x81C, 0xF1120103, + 0x81C, 0xF0140103, + 0x81C, 0xEF160103, + 0x81C, 0xEE180103, + 0x81C, 0xED1A0103, + 0x81C, 0xEC1C0103, + 0x81C, 0xEB1E0103, + 0x81C, 0xEA200103, + 0x81C, 0xE9220103, + 0x81C, 0xE8240103, + 0x81C, 0xE7260103, + 0x81C, 0xE6280103, + 0x81C, 0xE52A0103, + 0x81C, 0xC42C0103, + 0x81C, 0xC32E0103, + 0x81C, 0xC2300103, + 0x81C, 0xC1320103, + 0x81C, 0xA4340103, + 0x81C, 0xA3360103, + 0x81C, 0xA2380103, + 0x81C, 0xA13A0103, + 0x81C, 0x833C0103, + 0x81C, 0x823E0103, + 0x81C, 0x81400103, + 0x81C, 0x63420103, + 0x81C, 0x62440103, + 0x81C, 0x61460103, + 0x81C, 0x60480103, + 0x81C, 0x424A0103, + 0x81C, 0x414C0103, + 0x81C, 0x404E0103, + 0x81C, 0x22500103, + 0x81C, 0x21520103, + 0x81C, 0x20540103, + 0x81C, 0x03560103, + 0x81C, 0x02580103, + 0x81C, 0x015A0103, + 0x81C, 0x005C0103, + 0x81C, 0x005E0103, + 0x81C, 0x00600103, + 0x81C, 0x00620103, + 0x81C, 0x00640103, + 0x81C, 0x00660103, + 0x81C, 0x00680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000103, + 0x81C, 0xF7020103, + 0x81C, 0xF6040103, + 0x81C, 0xF5060103, + 0x81C, 0xF4080103, + 0x81C, 0xF30A0103, + 0x81C, 0xF20C0103, + 0x81C, 0xF10E0103, + 0x81C, 0xF0100103, + 0x81C, 0xEF120103, + 0x81C, 0xEE140103, + 0x81C, 0xED160103, + 0x81C, 0xEC180103, + 0x81C, 0xEB1A0103, + 0x81C, 0xEA1C0103, + 0x81C, 0xE91E0103, + 0x81C, 0xE8200103, + 0x81C, 0xE7220103, + 0x81C, 0xE6240103, + 0x81C, 0xE5260103, + 0x81C, 0xE4280103, + 0x81C, 0xE32A0103, + 0x81C, 0xE22C0103, + 0x81C, 0xC32E0103, + 0x81C, 0xC2300103, + 0x81C, 0xC1320103, + 0x81C, 0xA3340103, + 0x81C, 0xA2360103, + 0x81C, 0xA1380103, + 0x81C, 0xA03A0103, + 0x81C, 0x823C0103, + 0x81C, 0x813E0103, + 0x81C, 0x80400103, + 0x81C, 0x64420103, + 0x81C, 0x63440103, + 0x81C, 0x62460103, + 0x81C, 0x61480103, + 0x81C, 0x434A0103, + 0x81C, 0x424C0103, + 0x81C, 0x414E0103, + 0x81C, 0x40500103, + 0x81C, 0x22520103, + 0x81C, 0x21540103, + 0x81C, 0x20560103, + 0x81C, 0x04580103, + 0x81C, 0x035A0103, + 0x81C, 0x025C0103, + 0x81C, 0x015E0103, + 0x81C, 0x00600103, + 0x81C, 0x00620103, + 0x81C, 0x00640103, + 0x81C, 0x00660103, + 0x81C, 0x00680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x90000008, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFD000103, + 0x81C, 0xFC020103, + 0x81C, 0xFB040103, + 0x81C, 0xFA060103, + 0x81C, 0xF9080103, + 0x81C, 0xF80A0103, + 0x81C, 0xF70C0103, + 0x81C, 0xF60E0103, + 0x81C, 0xF5100103, + 0x81C, 0xF4120103, + 0x81C, 0xF3140103, + 0x81C, 0xF2160103, + 0x81C, 0xF1180103, + 0x81C, 0xF01A0103, + 0x81C, 0xEF1C0103, + 0x81C, 0xEE1E0103, + 0x81C, 0xED200103, + 0x81C, 0xEC220103, + 0x81C, 0xEB240103, + 0x81C, 0xEA260103, + 0x81C, 0xE9280103, + 0x81C, 0xE82A0103, + 0x81C, 0xE72C0103, + 0x81C, 0xE62E0103, + 0x81C, 0xE5300103, + 0x81C, 0xE4320103, + 0x81C, 0xE3340103, + 0x81C, 0xC6360103, + 0x81C, 0xC5380103, + 0x81C, 0xC43A0103, + 0x81C, 0xC33C0103, + 0x81C, 0xC23E0103, + 0x81C, 0xA5400103, + 0x81C, 0xA4420103, + 0x81C, 0xA3440103, + 0x81C, 0xA2460103, + 0x81C, 0xA1480103, + 0x81C, 0x834A0103, + 0x81C, 0x824C0103, + 0x81C, 0x814E0103, + 0x81C, 0x63500103, + 0x81C, 0x62520103, + 0x81C, 0x61540103, + 0x81C, 0x43560103, + 0x81C, 0x42580103, + 0x81C, 0x245A0103, + 0x81C, 0x235C0103, + 0x81C, 0x225E0103, + 0x81C, 0x21600103, + 0x81C, 0x04620103, + 0x81C, 0x03640103, + 0x81C, 0x02660103, + 0x81C, 0x01680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x90000009, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000103, + 0x81C, 0xF7020103, + 0x81C, 0xF6040103, + 0x81C, 0xF5060103, + 0x81C, 0xF4080103, + 0x81C, 0xF30A0103, + 0x81C, 0xF20C0103, + 0x81C, 0xF10E0103, + 0x81C, 0xF0100103, + 0x81C, 0xEF120103, + 0x81C, 0xEE140103, + 0x81C, 0xED160103, + 0x81C, 0xEC180103, + 0x81C, 0xEB1A0103, + 0x81C, 0xEA1C0103, + 0x81C, 0xE91E0103, + 0x81C, 0xE8200103, + 0x81C, 0xE7220103, + 0x81C, 0xE6240103, + 0x81C, 0xE5260103, + 0x81C, 0xE4280103, + 0x81C, 0xE32A0103, + 0x81C, 0xE22C0103, + 0x81C, 0xC32E0103, + 0x81C, 0xC2300103, + 0x81C, 0xC1320103, + 0x81C, 0xA3340103, + 0x81C, 0xA2360103, + 0x81C, 0xA1380103, + 0x81C, 0xA03A0103, + 0x81C, 0x823C0103, + 0x81C, 0x813E0103, + 0x81C, 0x80400103, + 0x81C, 0x64420103, + 0x81C, 0x63440103, + 0x81C, 0x62460103, + 0x81C, 0x61480103, + 0x81C, 0x434A0103, + 0x81C, 0x424C0103, + 0x81C, 0x414E0103, + 0x81C, 0x40500103, + 0x81C, 0x22520103, + 0x81C, 0x21540103, + 0x81C, 0x20560103, + 0x81C, 0x04580103, + 0x81C, 0x035A0103, + 0x81C, 0x025C0103, + 0x81C, 0x015E0103, + 0x81C, 0x00600103, + 0x81C, 0x00620103, + 0x81C, 0x00640103, + 0x81C, 0x00660103, + 0x81C, 0x00680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x9000000a, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFD000103, + 0x81C, 0xFC020103, + 0x81C, 0xFB040103, + 0x81C, 0xFA060103, + 0x81C, 0xF9080103, + 0x81C, 0xF80A0103, + 0x81C, 0xF70C0103, + 0x81C, 0xF60E0103, + 0x81C, 0xF5100103, + 0x81C, 0xF4120103, + 0x81C, 0xF3140103, + 0x81C, 0xF2160103, + 0x81C, 0xF1180103, + 0x81C, 0xF01A0103, + 0x81C, 0xEE1C0103, + 0x81C, 0xED1E0103, + 0x81C, 0xEC200103, + 0x81C, 0xEB220103, + 0x81C, 0xEA240103, + 0x81C, 0xE9260103, + 0x81C, 0xE8280103, + 0x81C, 0xE72A0103, + 0x81C, 0xE62C0103, + 0x81C, 0xE52E0103, + 0x81C, 0xE4300103, + 0x81C, 0xE3320103, + 0x81C, 0xE2340103, + 0x81C, 0xC5360103, + 0x81C, 0xC4380103, + 0x81C, 0xC33A0103, + 0x81C, 0xC23C0103, + 0x81C, 0xA53E0103, + 0x81C, 0xA4400103, + 0x81C, 0xA3420103, + 0x81C, 0xA2440103, + 0x81C, 0xA1460103, + 0x81C, 0x83480103, + 0x81C, 0x824A0103, + 0x81C, 0x814C0103, + 0x81C, 0x804E0103, + 0x81C, 0x63500103, + 0x81C, 0x62520103, + 0x81C, 0x61540103, + 0x81C, 0x43560103, + 0x81C, 0x42580103, + 0x81C, 0x415A0103, + 0x81C, 0x405C0103, + 0x81C, 0x225E0103, + 0x81C, 0x21600103, + 0x81C, 0x20620103, + 0x81C, 0x03640103, + 0x81C, 0x02660103, + 0x81C, 0x01680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x9000000b, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF9000103, + 0x81C, 0xF8020103, + 0x81C, 0xF7040103, + 0x81C, 0xF6060103, + 0x81C, 0xF5080103, + 0x81C, 0xF40A0103, + 0x81C, 0xF30C0103, + 0x81C, 0xF20E0103, + 0x81C, 0xF1100103, + 0x81C, 0xF0120103, + 0x81C, 0xEF140103, + 0x81C, 0xEE160103, + 0x81C, 0xED180103, + 0x81C, 0xEC1A0103, + 0x81C, 0xEB1C0103, + 0x81C, 0xEA1E0103, + 0x81C, 0xE9200103, + 0x81C, 0xE8220103, + 0x81C, 0xE7240103, + 0x81C, 0xE6260103, + 0x81C, 0xE5280103, + 0x81C, 0xE42A0103, + 0x81C, 0xE32C0103, + 0x81C, 0xC32E0103, + 0x81C, 0xC2300103, + 0x81C, 0xC1320103, + 0x81C, 0xA4340103, + 0x81C, 0xA3360103, + 0x81C, 0xA2380103, + 0x81C, 0xA13A0103, + 0x81C, 0xA03C0103, + 0x81C, 0x823E0103, + 0x81C, 0x81400103, + 0x81C, 0x80420103, + 0x81C, 0x63440103, + 0x81C, 0x62460103, + 0x81C, 0x61480103, + 0x81C, 0x604A0103, + 0x81C, 0x244C0103, + 0x81C, 0x234E0103, + 0x81C, 0x22500103, + 0x81C, 0x21520103, + 0x81C, 0x20540103, + 0x81C, 0x05560103, + 0x81C, 0x04580103, + 0x81C, 0x035A0103, + 0x81C, 0x025C0103, + 0x81C, 0x015E0103, + 0x81C, 0x00600103, + 0x81C, 0x00620103, + 0x81C, 0x00640103, + 0x81C, 0x00660103, + 0x81C, 0x00680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x9000000c, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFE000103, + 0x81C, 0xFD020103, + 0x81C, 0xFC040103, + 0x81C, 0xFB060103, + 0x81C, 0xFA080103, + 0x81C, 0xF90A0103, + 0x81C, 0xF80C0103, + 0x81C, 0xF70E0103, + 0x81C, 0xF6100103, + 0x81C, 0xF5120103, + 0x81C, 0xF4140103, + 0x81C, 0xF3160103, + 0x81C, 0xF2180103, + 0x81C, 0xF11A0103, + 0x81C, 0xF01C0103, + 0x81C, 0xEF1E0103, + 0x81C, 0xEE200103, + 0x81C, 0xED220103, + 0x81C, 0xEC240103, + 0x81C, 0xEB260103, + 0x81C, 0xEA280103, + 0x81C, 0xE92A0103, + 0x81C, 0xE82C0103, + 0x81C, 0xE72E0103, + 0x81C, 0xE6300103, + 0x81C, 0xE5320103, + 0x81C, 0xE4340103, + 0x81C, 0xE3360103, + 0x81C, 0xC6380103, + 0x81C, 0xC53A0103, + 0x81C, 0xC43C0103, + 0x81C, 0xC33E0103, + 0x81C, 0xA5400103, + 0x81C, 0xA4420103, + 0x81C, 0xA3440103, + 0x81C, 0xA2460103, + 0x81C, 0xA1480103, + 0x81C, 0xA04A0103, + 0x81C, 0x824C0103, + 0x81C, 0x814E0103, + 0x81C, 0x80500103, + 0x81C, 0x64520103, + 0x81C, 0x63540103, + 0x81C, 0x62560103, + 0x81C, 0x61580103, + 0x81C, 0x605A0103, + 0x81C, 0x235C0103, + 0x81C, 0x225E0103, + 0x81C, 0x21600103, + 0x81C, 0x20620103, + 0x81C, 0x03640103, + 0x81C, 0x02660103, + 0x81C, 0x01680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x9000000d, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000103, + 0x81C, 0xFB020103, + 0x81C, 0xFA040103, + 0x81C, 0xF9060103, + 0x81C, 0xF8080103, + 0x81C, 0xF70A0103, + 0x81C, 0xF60C0103, + 0x81C, 0xF50E0103, + 0x81C, 0xF4100103, + 0x81C, 0xF3120103, + 0x81C, 0xF2140103, + 0x81C, 0xF1160103, + 0x81C, 0xF0180103, + 0x81C, 0xEE1A0103, + 0x81C, 0xED1C0103, + 0x81C, 0xEC1E0103, + 0x81C, 0xEB200103, + 0x81C, 0xEA220103, + 0x81C, 0xE9240103, + 0x81C, 0xE8260103, + 0x81C, 0xE7280103, + 0x81C, 0xE62A0103, + 0x81C, 0xE52C0103, + 0x81C, 0xE42E0103, + 0x81C, 0xE3300103, + 0x81C, 0xE2320103, + 0x81C, 0xE1340103, + 0x81C, 0xC5360103, + 0x81C, 0xC4380103, + 0x81C, 0xC33A0103, + 0x81C, 0xC23C0103, + 0x81C, 0xA53E0103, + 0x81C, 0xA4400103, + 0x81C, 0xA3420103, + 0x81C, 0xA2440103, + 0x81C, 0xA1460103, + 0x81C, 0x83480103, + 0x81C, 0x824A0103, + 0x81C, 0x814C0103, + 0x81C, 0x804E0103, + 0x81C, 0x63500103, + 0x81C, 0x62520103, + 0x81C, 0x61540103, + 0x81C, 0x43560103, + 0x81C, 0x42580103, + 0x81C, 0x415A0103, + 0x81C, 0x405C0103, + 0x81C, 0x225E0103, + 0x81C, 0x21600103, + 0x81C, 0x20620103, + 0x81C, 0x03640103, + 0x81C, 0x02660103, + 0x81C, 0x01680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x9000000e, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFD000103, + 0x81C, 0xFC020103, + 0x81C, 0xFB040103, + 0x81C, 0xFA060103, + 0x81C, 0xF9080103, + 0x81C, 0xF80A0103, + 0x81C, 0xF70C0103, + 0x81C, 0xF60E0103, + 0x81C, 0xF5100103, + 0x81C, 0xF4120103, + 0x81C, 0xF3140103, + 0x81C, 0xF2160103, + 0x81C, 0xF1180103, + 0x81C, 0xF01A0103, + 0x81C, 0xEE1C0103, + 0x81C, 0xED1E0103, + 0x81C, 0xEC200103, + 0x81C, 0xEB220103, + 0x81C, 0xEA240103, + 0x81C, 0xE9260103, + 0x81C, 0xE8280103, + 0x81C, 0xE72A0103, + 0x81C, 0xE62C0103, + 0x81C, 0xE52E0103, + 0x81C, 0xE4300103, + 0x81C, 0xE3320103, + 0x81C, 0xE2340103, + 0x81C, 0xC5360103, + 0x81C, 0xC4380103, + 0x81C, 0xC33A0103, + 0x81C, 0xC23C0103, + 0x81C, 0xA53E0103, + 0x81C, 0xA4400103, + 0x81C, 0xA3420103, + 0x81C, 0xA2440103, + 0x81C, 0xA1460103, + 0x81C, 0x83480103, + 0x81C, 0x824A0103, + 0x81C, 0x814C0103, + 0x81C, 0x804E0103, + 0x81C, 0x63500103, + 0x81C, 0x62520103, + 0x81C, 0x61540103, + 0x81C, 0x43560103, + 0x81C, 0x42580103, + 0x81C, 0x415A0103, + 0x81C, 0x405C0103, + 0x81C, 0x225E0103, + 0x81C, 0x21600103, + 0x81C, 0x20620103, + 0x81C, 0x03640103, + 0x81C, 0x02660103, + 0x81C, 0x01680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x9000000f, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000103, + 0x81C, 0xFB020103, + 0x81C, 0xFA040103, + 0x81C, 0xF9060103, + 0x81C, 0xF8080103, + 0x81C, 0xF70A0103, + 0x81C, 0xF60C0103, + 0x81C, 0xF50E0103, + 0x81C, 0xF4100103, + 0x81C, 0xF3120103, + 0x81C, 0xF2140103, + 0x81C, 0xF1160103, + 0x81C, 0xF0180103, + 0x81C, 0xEF1A0103, + 0x81C, 0xEE1C0103, + 0x81C, 0xED1E0103, + 0x81C, 0xEC200103, + 0x81C, 0xEB220103, + 0x81C, 0xEA240103, + 0x81C, 0xE9260103, + 0x81C, 0xE8280103, + 0x81C, 0xE72A0103, + 0x81C, 0xE62C0103, + 0x81C, 0xE52E0103, + 0x81C, 0xE4300103, + 0x81C, 0xE3320103, + 0x81C, 0xE2340103, + 0x81C, 0xE1360103, + 0x81C, 0xC3380103, + 0x81C, 0xC23A0103, + 0x81C, 0xC13C0103, + 0x81C, 0xC03E0103, + 0x81C, 0xA4400103, + 0x81C, 0xA3420103, + 0x81C, 0xA2440103, + 0x81C, 0xA1460103, + 0x81C, 0x82480103, + 0x81C, 0x814A0103, + 0x81C, 0x804C0103, + 0x81C, 0x634E0103, + 0x81C, 0x62500103, + 0x81C, 0x61520103, + 0x81C, 0x42540103, + 0x81C, 0x41560103, + 0x81C, 0x24580103, + 0x81C, 0x235A0103, + 0x81C, 0x225C0103, + 0x81C, 0x215E0103, + 0x81C, 0x20600103, + 0x81C, 0x03620103, + 0x81C, 0x02640103, + 0x81C, 0x01660103, + 0x81C, 0x00680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x90000010, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFE000103, + 0x81C, 0xFD020103, + 0x81C, 0xFC040103, + 0x81C, 0xFB060103, + 0x81C, 0xFA080103, + 0x81C, 0xF90A0103, + 0x81C, 0xF80C0103, + 0x81C, 0xF70E0103, + 0x81C, 0xF6100103, + 0x81C, 0xF5120103, + 0x81C, 0xF4140103, + 0x81C, 0xF3160103, + 0x81C, 0xF2180103, + 0x81C, 0xF11A0103, + 0x81C, 0xF01C0103, + 0x81C, 0xEF1E0103, + 0x81C, 0xEE200103, + 0x81C, 0xED220103, + 0x81C, 0xEC240103, + 0x81C, 0xEB260103, + 0x81C, 0xEA280103, + 0x81C, 0xE92A0103, + 0x81C, 0xE82C0103, + 0x81C, 0xE72E0103, + 0x81C, 0xE6300103, + 0x81C, 0xE5320103, + 0x81C, 0xE4340103, + 0x81C, 0xE3360103, + 0x81C, 0xC6380103, + 0x81C, 0xC53A0103, + 0x81C, 0xC43C0103, + 0x81C, 0xC33E0103, + 0x81C, 0xA5400103, + 0x81C, 0xA4420103, + 0x81C, 0xA3440103, + 0x81C, 0xA2460103, + 0x81C, 0xA1480103, + 0x81C, 0xA04A0103, + 0x81C, 0x824C0103, + 0x81C, 0x814E0103, + 0x81C, 0x80500103, + 0x81C, 0x64520103, + 0x81C, 0x63540103, + 0x81C, 0x62560103, + 0x81C, 0x61580103, + 0x81C, 0x605A0103, + 0x81C, 0x235C0103, + 0x81C, 0x225E0103, + 0x81C, 0x21600103, + 0x81C, 0x20620103, + 0x81C, 0x03640103, + 0x81C, 0x02660103, + 0x81C, 0x01680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0x90000012, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000103, + 0x81C, 0xF7020103, + 0x81C, 0xF6040103, + 0x81C, 0xF5060103, + 0x81C, 0xF4080103, + 0x81C, 0xF30A0103, + 0x81C, 0xF20C0103, + 0x81C, 0xF10E0103, + 0x81C, 0xF0100103, + 0x81C, 0xEF120103, + 0x81C, 0xEE140103, + 0x81C, 0xED160103, + 0x81C, 0xEC180103, + 0x81C, 0xEB1A0103, + 0x81C, 0xEA1C0103, + 0x81C, 0xE91E0103, + 0x81C, 0xE8200103, + 0x81C, 0xE7220103, + 0x81C, 0xE6240103, + 0x81C, 0xE5260103, + 0x81C, 0xE4280103, + 0x81C, 0xE32A0103, + 0x81C, 0xC32C0103, + 0x81C, 0xC22E0103, + 0x81C, 0xC1300103, + 0x81C, 0xC0320103, + 0x81C, 0xA3340103, + 0x81C, 0xA2360103, + 0x81C, 0xA1380103, + 0x81C, 0xA03A0103, + 0x81C, 0x823C0103, + 0x81C, 0x813E0103, + 0x81C, 0x80400103, + 0x81C, 0x63420103, + 0x81C, 0x62440103, + 0x81C, 0x61460103, + 0x81C, 0x60480103, + 0x81C, 0x424A0103, + 0x81C, 0x414C0103, + 0x81C, 0x404E0103, + 0x81C, 0x22500103, + 0x81C, 0x21520103, + 0x81C, 0x20540103, + 0x81C, 0x03560103, + 0x81C, 0x02580103, + 0x81C, 0x015A0103, + 0x81C, 0x005C0103, + 0x81C, 0x005E0103, + 0x81C, 0x00600103, + 0x81C, 0x00620103, + 0x81C, 0x00640103, + 0x81C, 0x00660103, + 0x81C, 0x00680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0xA0000000, 0x00000000, + 0x81C, 0xFE000103, + 0x81C, 0xFD020103, + 0x81C, 0xFC040103, + 0x81C, 0xFB060103, + 0x81C, 0xFA080103, + 0x81C, 0xF90A0103, + 0x81C, 0xF80C0103, + 0x81C, 0xF70E0103, + 0x81C, 0xF6100103, + 0x81C, 0xF5120103, + 0x81C, 0xF4140103, + 0x81C, 0xF3160103, + 0x81C, 0xF2180103, + 0x81C, 0xF11A0103, + 0x81C, 0xF01C0103, + 0x81C, 0xEF1E0103, + 0x81C, 0xEE200103, + 0x81C, 0xED220103, + 0x81C, 0xEC240103, + 0x81C, 0xEB260103, + 0x81C, 0xEA280103, + 0x81C, 0xE92A0103, + 0x81C, 0xE82C0103, + 0x81C, 0xE72E0103, + 0x81C, 0xE6300103, + 0x81C, 0xE5320103, + 0x81C, 0xE4340103, + 0x81C, 0xE3360103, + 0x81C, 0xC6380103, + 0x81C, 0xC53A0103, + 0x81C, 0xC43C0103, + 0x81C, 0xC33E0103, + 0x81C, 0xA5400103, + 0x81C, 0xA4420103, + 0x81C, 0xA3440103, + 0x81C, 0xA2460103, + 0x81C, 0xA1480103, + 0x81C, 0xA04A0103, + 0x81C, 0x824C0103, + 0x81C, 0x814E0103, + 0x81C, 0x80500103, + 0x81C, 0x64520103, + 0x81C, 0x63540103, + 0x81C, 0x62560103, + 0x81C, 0x61580103, + 0x81C, 0x605A0103, + 0x81C, 0x235C0103, + 0x81C, 0x225E0103, + 0x81C, 0x21600103, + 0x81C, 0x20620103, + 0x81C, 0x03640103, + 0x81C, 0x02660103, + 0x81C, 0x01680103, + 0x81C, 0x006A0103, + 0x81C, 0x006C0103, + 0x81C, 0x006E0103, + 0x81C, 0x00700103, + 0x81C, 0x00720103, + 0x81C, 0x00740103, + 0x81C, 0x00760103, + 0x81C, 0x00780103, + 0x81C, 0x007A0103, + 0x81C, 0x007C0103, + 0x81C, 0x007E0103, + 0xB0000000, 0x00000000, + 0x80000000, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000203, + 0x81C, 0xFB020203, + 0x81C, 0xFA040203, + 0x81C, 0xF9060203, + 0x81C, 0xF8080203, + 0x81C, 0xF70A0203, + 0x81C, 0xF60C0203, + 0x81C, 0xF50E0203, + 0x81C, 0xF4100203, + 0x81C, 0xF3120203, + 0x81C, 0xF2140203, + 0x81C, 0xF1160203, + 0x81C, 0xF0180203, + 0x81C, 0xEE1A0203, + 0x81C, 0xED1C0203, + 0x81C, 0xEC1E0203, + 0x81C, 0xEB200203, + 0x81C, 0xEA220203, + 0x81C, 0xE9240203, + 0x81C, 0xE8260203, + 0x81C, 0xE7280203, + 0x81C, 0xE62A0203, + 0x81C, 0xE52C0203, + 0x81C, 0xE42E0203, + 0x81C, 0xE3300203, + 0x81C, 0xE2320203, + 0x81C, 0xC6340203, + 0x81C, 0xC5360203, + 0x81C, 0xC4380203, + 0x81C, 0xC33A0203, + 0x81C, 0xA63C0203, + 0x81C, 0xA53E0203, + 0x81C, 0xA4400203, + 0x81C, 0xA3420203, + 0x81C, 0xA2440203, + 0x81C, 0xA1460203, + 0x81C, 0x83480203, + 0x81C, 0x824A0203, + 0x81C, 0x814C0203, + 0x81C, 0x804E0203, + 0x81C, 0x63500203, + 0x81C, 0x62520203, + 0x81C, 0x61540203, + 0x81C, 0x42560203, + 0x81C, 0x41580203, + 0x81C, 0x405A0203, + 0x81C, 0x225C0203, + 0x81C, 0x215E0203, + 0x81C, 0x20600203, + 0x81C, 0x04620203, + 0x81C, 0x03640203, + 0x81C, 0x02660203, + 0x81C, 0x01680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF7000203, + 0x81C, 0xF6020203, + 0x81C, 0xF5040203, + 0x81C, 0xF4060203, + 0x81C, 0xF3080203, + 0x81C, 0xF20A0203, + 0x81C, 0xF10C0203, + 0x81C, 0xF00E0203, + 0x81C, 0xEF100203, + 0x81C, 0xEE120203, + 0x81C, 0xED140203, + 0x81C, 0xEC160203, + 0x81C, 0xEB180203, + 0x81C, 0xEA1A0203, + 0x81C, 0xE91C0203, + 0x81C, 0xE81E0203, + 0x81C, 0xE7200203, + 0x81C, 0xE6220203, + 0x81C, 0xE5240203, + 0x81C, 0xE4260203, + 0x81C, 0xE3280203, + 0x81C, 0xC42A0203, + 0x81C, 0xC32C0203, + 0x81C, 0xC22E0203, + 0x81C, 0xC1300203, + 0x81C, 0xC0320203, + 0x81C, 0xA3340203, + 0x81C, 0xA2360203, + 0x81C, 0xA1380203, + 0x81C, 0xA03A0203, + 0x81C, 0x823C0203, + 0x81C, 0x813E0203, + 0x81C, 0x80400203, + 0x81C, 0x63420203, + 0x81C, 0x62440203, + 0x81C, 0x61460203, + 0x81C, 0x60480203, + 0x81C, 0x424A0203, + 0x81C, 0x414C0203, + 0x81C, 0x404E0203, + 0x81C, 0x06500203, + 0x81C, 0x05520203, + 0x81C, 0x04540203, + 0x81C, 0x03560203, + 0x81C, 0x02580203, + 0x81C, 0x015A0203, + 0x81C, 0x005C0203, + 0x81C, 0x005E0203, + 0x81C, 0x00600203, + 0x81C, 0x00620203, + 0x81C, 0x00640203, + 0x81C, 0x00660203, + 0x81C, 0x00680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF7000203, + 0x81C, 0xF6020203, + 0x81C, 0xF5040203, + 0x81C, 0xF4060203, + 0x81C, 0xF3080203, + 0x81C, 0xF20A0203, + 0x81C, 0xF10C0203, + 0x81C, 0xF00E0203, + 0x81C, 0xEF100203, + 0x81C, 0xEE120203, + 0x81C, 0xED140203, + 0x81C, 0xEC160203, + 0x81C, 0xEB180203, + 0x81C, 0xEA1A0203, + 0x81C, 0xE91C0203, + 0x81C, 0xE81E0203, + 0x81C, 0xE7200203, + 0x81C, 0xE6220203, + 0x81C, 0xE5240203, + 0x81C, 0xE4260203, + 0x81C, 0xE3280203, + 0x81C, 0xC42A0203, + 0x81C, 0xC32C0203, + 0x81C, 0xC22E0203, + 0x81C, 0xC1300203, + 0x81C, 0xC0320203, + 0x81C, 0xA3340203, + 0x81C, 0xA2360203, + 0x81C, 0xA1380203, + 0x81C, 0xA03A0203, + 0x81C, 0x823C0203, + 0x81C, 0x813E0203, + 0x81C, 0x80400203, + 0x81C, 0x64420203, + 0x81C, 0x63440203, + 0x81C, 0x62460203, + 0x81C, 0x61480203, + 0x81C, 0x604A0203, + 0x81C, 0x414C0203, + 0x81C, 0x404E0203, + 0x81C, 0x22500203, + 0x81C, 0x21520203, + 0x81C, 0x20540203, + 0x81C, 0x03560203, + 0x81C, 0x02580203, + 0x81C, 0x015A0203, + 0x81C, 0x005C0203, + 0x81C, 0x005E0203, + 0x81C, 0x00600203, + 0x81C, 0x00620203, + 0x81C, 0x00640203, + 0x81C, 0x00660203, + 0x81C, 0x00680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000203, + 0x81C, 0xFB020203, + 0x81C, 0xFA040203, + 0x81C, 0xF9060203, + 0x81C, 0xF8080203, + 0x81C, 0xF70A0203, + 0x81C, 0xF60C0203, + 0x81C, 0xF50E0203, + 0x81C, 0xF4100203, + 0x81C, 0xF3120203, + 0x81C, 0xF2140203, + 0x81C, 0xF1160203, + 0x81C, 0xF0180203, + 0x81C, 0xEF1A0203, + 0x81C, 0xEE1C0203, + 0x81C, 0xED1E0203, + 0x81C, 0xEC200203, + 0x81C, 0xEB220203, + 0x81C, 0xEA240203, + 0x81C, 0xE9260203, + 0x81C, 0xE8280203, + 0x81C, 0xE72A0203, + 0x81C, 0xE62C0203, + 0x81C, 0xE52E0203, + 0x81C, 0xE4300203, + 0x81C, 0xE3320203, + 0x81C, 0xE2340203, + 0x81C, 0xC6360203, + 0x81C, 0xC5380203, + 0x81C, 0xC43A0203, + 0x81C, 0xC33C0203, + 0x81C, 0xA63E0203, + 0x81C, 0xA5400203, + 0x81C, 0xA4420203, + 0x81C, 0xA3440203, + 0x81C, 0xA2460203, + 0x81C, 0xA1480203, + 0x81C, 0x834A0203, + 0x81C, 0x824C0203, + 0x81C, 0x814E0203, + 0x81C, 0x64500203, + 0x81C, 0x63520203, + 0x81C, 0x62540203, + 0x81C, 0x61560203, + 0x81C, 0x60580203, + 0x81C, 0x405A0203, + 0x81C, 0x215C0203, + 0x81C, 0x205E0203, + 0x81C, 0x03600203, + 0x81C, 0x02620203, + 0x81C, 0x01640203, + 0x81C, 0x00660203, + 0x81C, 0x00680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF7000203, + 0x81C, 0xF6020203, + 0x81C, 0xF5040203, + 0x81C, 0xF4060203, + 0x81C, 0xF3080203, + 0x81C, 0xF20A0203, + 0x81C, 0xF10C0203, + 0x81C, 0xF00E0203, + 0x81C, 0xEF100203, + 0x81C, 0xEE120203, + 0x81C, 0xED140203, + 0x81C, 0xEC160203, + 0x81C, 0xEB180203, + 0x81C, 0xEA1A0203, + 0x81C, 0xE91C0203, + 0x81C, 0xE81E0203, + 0x81C, 0xE7200203, + 0x81C, 0xE6220203, + 0x81C, 0xE5240203, + 0x81C, 0xE4260203, + 0x81C, 0xE3280203, + 0x81C, 0xC42A0203, + 0x81C, 0xC32C0203, + 0x81C, 0xC22E0203, + 0x81C, 0xC1300203, + 0x81C, 0xC0320203, + 0x81C, 0xA3340203, + 0x81C, 0xA2360203, + 0x81C, 0xA1380203, + 0x81C, 0xA03A0203, + 0x81C, 0x823C0203, + 0x81C, 0x813E0203, + 0x81C, 0x80400203, + 0x81C, 0x64420203, + 0x81C, 0x63440203, + 0x81C, 0x62460203, + 0x81C, 0x61480203, + 0x81C, 0x604A0203, + 0x81C, 0x414C0203, + 0x81C, 0x404E0203, + 0x81C, 0x22500203, + 0x81C, 0x21520203, + 0x81C, 0x20540203, + 0x81C, 0x03560203, + 0x81C, 0x02580203, + 0x81C, 0x015A0203, + 0x81C, 0x005C0203, + 0x81C, 0x005E0203, + 0x81C, 0x00600203, + 0x81C, 0x00620203, + 0x81C, 0x00640203, + 0x81C, 0x00660203, + 0x81C, 0x00680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000203, + 0x81C, 0xFB020203, + 0x81C, 0xFA040203, + 0x81C, 0xF9060203, + 0x81C, 0xF8080203, + 0x81C, 0xF70A0203, + 0x81C, 0xF60C0203, + 0x81C, 0xF50E0203, + 0x81C, 0xF4100203, + 0x81C, 0xF3120203, + 0x81C, 0xF2140203, + 0x81C, 0xF1160203, + 0x81C, 0xF0180203, + 0x81C, 0xEF1A0203, + 0x81C, 0xEE1C0203, + 0x81C, 0xED1E0203, + 0x81C, 0xEC200203, + 0x81C, 0xEB220203, + 0x81C, 0xEA240203, + 0x81C, 0xE9260203, + 0x81C, 0xE8280203, + 0x81C, 0xE72A0203, + 0x81C, 0xE62C0203, + 0x81C, 0xE52E0203, + 0x81C, 0xE4300203, + 0x81C, 0xE3320203, + 0x81C, 0xE2340203, + 0x81C, 0xE1360203, + 0x81C, 0xC5380203, + 0x81C, 0xC43A0203, + 0x81C, 0xC33C0203, + 0x81C, 0xC23E0203, + 0x81C, 0xC1400203, + 0x81C, 0xA3420203, + 0x81C, 0xA2440203, + 0x81C, 0xA1460203, + 0x81C, 0xA0480203, + 0x81C, 0x834A0203, + 0x81C, 0x824C0203, + 0x81C, 0x814E0203, + 0x81C, 0x64500203, + 0x81C, 0x63520203, + 0x81C, 0x62540203, + 0x81C, 0x61560203, + 0x81C, 0x25580203, + 0x81C, 0x245A0203, + 0x81C, 0x235C0203, + 0x81C, 0x225E0203, + 0x81C, 0x21600203, + 0x81C, 0x04620203, + 0x81C, 0x03640203, + 0x81C, 0x02660203, + 0x81C, 0x01680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF9000203, + 0x81C, 0xF8020203, + 0x81C, 0xF7040203, + 0x81C, 0xF6060203, + 0x81C, 0xF5080203, + 0x81C, 0xF40A0203, + 0x81C, 0xF30C0203, + 0x81C, 0xF20E0203, + 0x81C, 0xF1100203, + 0x81C, 0xF0120203, + 0x81C, 0xEF140203, + 0x81C, 0xEE160203, + 0x81C, 0xED180203, + 0x81C, 0xEC1A0203, + 0x81C, 0xEB1C0203, + 0x81C, 0xEA1E0203, + 0x81C, 0xE9200203, + 0x81C, 0xE8220203, + 0x81C, 0xE7240203, + 0x81C, 0xE6260203, + 0x81C, 0xE5280203, + 0x81C, 0xC42A0203, + 0x81C, 0xC32C0203, + 0x81C, 0xC22E0203, + 0x81C, 0xC1300203, + 0x81C, 0xC0320203, + 0x81C, 0xA3340203, + 0x81C, 0xA2360203, + 0x81C, 0xA1380203, + 0x81C, 0xA03A0203, + 0x81C, 0x823C0203, + 0x81C, 0x813E0203, + 0x81C, 0x80400203, + 0x81C, 0x64420203, + 0x81C, 0x63440203, + 0x81C, 0x62460203, + 0x81C, 0x61480203, + 0x81C, 0x604A0203, + 0x81C, 0x414C0203, + 0x81C, 0x404E0203, + 0x81C, 0x22500203, + 0x81C, 0x21520203, + 0x81C, 0x20540203, + 0x81C, 0x03560203, + 0x81C, 0x02580203, + 0x81C, 0x015A0203, + 0x81C, 0x005C0203, + 0x81C, 0x005E0203, + 0x81C, 0x00600203, + 0x81C, 0x00620203, + 0x81C, 0x00640203, + 0x81C, 0x00660203, + 0x81C, 0x00680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000203, + 0x81C, 0xF7020203, + 0x81C, 0xF6040203, + 0x81C, 0xF5060203, + 0x81C, 0xF4080203, + 0x81C, 0xF30A0203, + 0x81C, 0xF20C0203, + 0x81C, 0xF10E0203, + 0x81C, 0xF0100203, + 0x81C, 0xEF120203, + 0x81C, 0xEE140203, + 0x81C, 0xED160203, + 0x81C, 0xEC180203, + 0x81C, 0xEB1A0203, + 0x81C, 0xEA1C0203, + 0x81C, 0xE91E0203, + 0x81C, 0xE8200203, + 0x81C, 0xE7220203, + 0x81C, 0xE6240203, + 0x81C, 0xE5260203, + 0x81C, 0xE4280203, + 0x81C, 0xE32A0203, + 0x81C, 0xC42C0203, + 0x81C, 0xC32E0203, + 0x81C, 0xC2300203, + 0x81C, 0xC1320203, + 0x81C, 0xA3340203, + 0x81C, 0xA2360203, + 0x81C, 0xA1380203, + 0x81C, 0xA03A0203, + 0x81C, 0x823C0203, + 0x81C, 0x813E0203, + 0x81C, 0x80400203, + 0x81C, 0x65420203, + 0x81C, 0x64440203, + 0x81C, 0x63460203, + 0x81C, 0x62480203, + 0x81C, 0x614A0203, + 0x81C, 0x424C0203, + 0x81C, 0x414E0203, + 0x81C, 0x40500203, + 0x81C, 0x22520203, + 0x81C, 0x21540203, + 0x81C, 0x20560203, + 0x81C, 0x04580203, + 0x81C, 0x035A0203, + 0x81C, 0x025C0203, + 0x81C, 0x015E0203, + 0x81C, 0x00600203, + 0x81C, 0x00620203, + 0x81C, 0x00640203, + 0x81C, 0x00660203, + 0x81C, 0x00680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x90000008, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFB000203, + 0x81C, 0xFA020203, + 0x81C, 0xF9040203, + 0x81C, 0xF8060203, + 0x81C, 0xF7080203, + 0x81C, 0xF60A0203, + 0x81C, 0xF50C0203, + 0x81C, 0xF40E0203, + 0x81C, 0xF3100203, + 0x81C, 0xF2120203, + 0x81C, 0xF1140203, + 0x81C, 0xF0160203, + 0x81C, 0xEF180203, + 0x81C, 0xEE1A0203, + 0x81C, 0xED1C0203, + 0x81C, 0xEC1E0203, + 0x81C, 0xEB200203, + 0x81C, 0xEA220203, + 0x81C, 0xE9240203, + 0x81C, 0xE8260203, + 0x81C, 0xE7280203, + 0x81C, 0xE62A0203, + 0x81C, 0xE52C0203, + 0x81C, 0xE42E0203, + 0x81C, 0xE3300203, + 0x81C, 0xE2320203, + 0x81C, 0xC6340203, + 0x81C, 0xC5360203, + 0x81C, 0xC4380203, + 0x81C, 0xC33A0203, + 0x81C, 0xC23C0203, + 0x81C, 0xC13E0203, + 0x81C, 0xC0400203, + 0x81C, 0xA3420203, + 0x81C, 0xA2440203, + 0x81C, 0xA1460203, + 0x81C, 0xA0480203, + 0x81C, 0x824A0203, + 0x81C, 0x814C0203, + 0x81C, 0x804E0203, + 0x81C, 0x63500203, + 0x81C, 0x62520203, + 0x81C, 0x61540203, + 0x81C, 0x60560203, + 0x81C, 0x24580203, + 0x81C, 0x235A0203, + 0x81C, 0x225C0203, + 0x81C, 0x215E0203, + 0x81C, 0x20600203, + 0x81C, 0x03620203, + 0x81C, 0x02640203, + 0x81C, 0x01660203, + 0x81C, 0x00680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x90000009, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000203, + 0x81C, 0xF7020203, + 0x81C, 0xF6040203, + 0x81C, 0xF5060203, + 0x81C, 0xF4080203, + 0x81C, 0xF30A0203, + 0x81C, 0xF20C0203, + 0x81C, 0xF10E0203, + 0x81C, 0xF0100203, + 0x81C, 0xEF120203, + 0x81C, 0xEE140203, + 0x81C, 0xED160203, + 0x81C, 0xEC180203, + 0x81C, 0xEB1A0203, + 0x81C, 0xEA1C0203, + 0x81C, 0xE91E0203, + 0x81C, 0xE8200203, + 0x81C, 0xE7220203, + 0x81C, 0xE6240203, + 0x81C, 0xE5260203, + 0x81C, 0xE4280203, + 0x81C, 0xE32A0203, + 0x81C, 0xC42C0203, + 0x81C, 0xC32E0203, + 0x81C, 0xC2300203, + 0x81C, 0xC1320203, + 0x81C, 0xA3340203, + 0x81C, 0xA2360203, + 0x81C, 0xA1380203, + 0x81C, 0xA03A0203, + 0x81C, 0x823C0203, + 0x81C, 0x813E0203, + 0x81C, 0x80400203, + 0x81C, 0x65420203, + 0x81C, 0x64440203, + 0x81C, 0x63460203, + 0x81C, 0x62480203, + 0x81C, 0x614A0203, + 0x81C, 0x424C0203, + 0x81C, 0x414E0203, + 0x81C, 0x40500203, + 0x81C, 0x22520203, + 0x81C, 0x21540203, + 0x81C, 0x20560203, + 0x81C, 0x04580203, + 0x81C, 0x035A0203, + 0x81C, 0x025C0203, + 0x81C, 0x015E0203, + 0x81C, 0x00600203, + 0x81C, 0x00620203, + 0x81C, 0x00640203, + 0x81C, 0x00660203, + 0x81C, 0x00680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x9000000a, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000203, + 0x81C, 0xFB020203, + 0x81C, 0xFA040203, + 0x81C, 0xF9060203, + 0x81C, 0xF8080203, + 0x81C, 0xF70A0203, + 0x81C, 0xF60C0203, + 0x81C, 0xF50E0203, + 0x81C, 0xF4100203, + 0x81C, 0xF3120203, + 0x81C, 0xF2140203, + 0x81C, 0xF1160203, + 0x81C, 0xF0180203, + 0x81C, 0xEE1A0203, + 0x81C, 0xED1C0203, + 0x81C, 0xEC1E0203, + 0x81C, 0xEB200203, + 0x81C, 0xEA220203, + 0x81C, 0xE9240203, + 0x81C, 0xE8260203, + 0x81C, 0xE7280203, + 0x81C, 0xE62A0203, + 0x81C, 0xE52C0203, + 0x81C, 0xE42E0203, + 0x81C, 0xE3300203, + 0x81C, 0xE2320203, + 0x81C, 0xC6340203, + 0x81C, 0xC5360203, + 0x81C, 0xC4380203, + 0x81C, 0xC33A0203, + 0x81C, 0xA63C0203, + 0x81C, 0xA53E0203, + 0x81C, 0xA4400203, + 0x81C, 0xA3420203, + 0x81C, 0xA2440203, + 0x81C, 0xA1460203, + 0x81C, 0x83480203, + 0x81C, 0x824A0203, + 0x81C, 0x814C0203, + 0x81C, 0x804E0203, + 0x81C, 0x63500203, + 0x81C, 0x62520203, + 0x81C, 0x61540203, + 0x81C, 0x42560203, + 0x81C, 0x41580203, + 0x81C, 0x405A0203, + 0x81C, 0x225C0203, + 0x81C, 0x215E0203, + 0x81C, 0x20600203, + 0x81C, 0x04620203, + 0x81C, 0x03640203, + 0x81C, 0x02660203, + 0x81C, 0x01680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x9000000b, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF9000203, + 0x81C, 0xF8020203, + 0x81C, 0xF7040203, + 0x81C, 0xF6060203, + 0x81C, 0xF5080203, + 0x81C, 0xF40A0203, + 0x81C, 0xF30C0203, + 0x81C, 0xF20E0203, + 0x81C, 0xF1100203, + 0x81C, 0xF0120203, + 0x81C, 0xEF140203, + 0x81C, 0xEE160203, + 0x81C, 0xED180203, + 0x81C, 0xEC1A0203, + 0x81C, 0xEB1C0203, + 0x81C, 0xEA1E0203, + 0x81C, 0xE9200203, + 0x81C, 0xE8220203, + 0x81C, 0xE7240203, + 0x81C, 0xE6260203, + 0x81C, 0xE5280203, + 0x81C, 0xE42A0203, + 0x81C, 0xC42C0203, + 0x81C, 0xC32E0203, + 0x81C, 0xC2300203, + 0x81C, 0xC1320203, + 0x81C, 0xA3340203, + 0x81C, 0xA2360203, + 0x81C, 0xA1380203, + 0x81C, 0xA03A0203, + 0x81C, 0x823C0203, + 0x81C, 0x813E0203, + 0x81C, 0x80400203, + 0x81C, 0x64420203, + 0x81C, 0x63440203, + 0x81C, 0x62460203, + 0x81C, 0x61480203, + 0x81C, 0x604A0203, + 0x81C, 0x244C0203, + 0x81C, 0x234E0203, + 0x81C, 0x22500203, + 0x81C, 0x21520203, + 0x81C, 0x20540203, + 0x81C, 0x05560203, + 0x81C, 0x04580203, + 0x81C, 0x035A0203, + 0x81C, 0x025C0203, + 0x81C, 0x015E0203, + 0x81C, 0x00600203, + 0x81C, 0x00620203, + 0x81C, 0x00640203, + 0x81C, 0x00660203, + 0x81C, 0x00680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x9000000c, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000203, + 0x81C, 0xFB020203, + 0x81C, 0xFA040203, + 0x81C, 0xF9060203, + 0x81C, 0xF8080203, + 0x81C, 0xF70A0203, + 0x81C, 0xF60C0203, + 0x81C, 0xF50E0203, + 0x81C, 0xF4100203, + 0x81C, 0xF3120203, + 0x81C, 0xF2140203, + 0x81C, 0xF1160203, + 0x81C, 0xF0180203, + 0x81C, 0xEF1A0203, + 0x81C, 0xEE1C0203, + 0x81C, 0xED1E0203, + 0x81C, 0xEC200203, + 0x81C, 0xEB220203, + 0x81C, 0xEA240203, + 0x81C, 0xE9260203, + 0x81C, 0xE8280203, + 0x81C, 0xE72A0203, + 0x81C, 0xE62C0203, + 0x81C, 0xE52E0203, + 0x81C, 0xE4300203, + 0x81C, 0xE3320203, + 0x81C, 0xE2340203, + 0x81C, 0xC6360203, + 0x81C, 0xC5380203, + 0x81C, 0xC43A0203, + 0x81C, 0xC33C0203, + 0x81C, 0xA63E0203, + 0x81C, 0xA5400203, + 0x81C, 0xA4420203, + 0x81C, 0xA3440203, + 0x81C, 0xA2460203, + 0x81C, 0xA1480203, + 0x81C, 0x834A0203, + 0x81C, 0x824C0203, + 0x81C, 0x814E0203, + 0x81C, 0x64500203, + 0x81C, 0x63520203, + 0x81C, 0x62540203, + 0x81C, 0x61560203, + 0x81C, 0x60580203, + 0x81C, 0x405A0203, + 0x81C, 0x215C0203, + 0x81C, 0x205E0203, + 0x81C, 0x03600203, + 0x81C, 0x02620203, + 0x81C, 0x01640203, + 0x81C, 0x00660203, + 0x81C, 0x00680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x9000000d, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000203, + 0x81C, 0xFB020203, + 0x81C, 0xFA040203, + 0x81C, 0xF9060203, + 0x81C, 0xF8080203, + 0x81C, 0xF70A0203, + 0x81C, 0xF60C0203, + 0x81C, 0xF50E0203, + 0x81C, 0xF4100203, + 0x81C, 0xF3120203, + 0x81C, 0xF2140203, + 0x81C, 0xF1160203, + 0x81C, 0xF0180203, + 0x81C, 0xEE1A0203, + 0x81C, 0xED1C0203, + 0x81C, 0xEC1E0203, + 0x81C, 0xEB200203, + 0x81C, 0xEA220203, + 0x81C, 0xE9240203, + 0x81C, 0xE8260203, + 0x81C, 0xE7280203, + 0x81C, 0xE62A0203, + 0x81C, 0xE52C0203, + 0x81C, 0xE42E0203, + 0x81C, 0xE3300203, + 0x81C, 0xE2320203, + 0x81C, 0xC6340203, + 0x81C, 0xC5360203, + 0x81C, 0xC4380203, + 0x81C, 0xC33A0203, + 0x81C, 0xA63C0203, + 0x81C, 0xA53E0203, + 0x81C, 0xA4400203, + 0x81C, 0xA3420203, + 0x81C, 0xA2440203, + 0x81C, 0xA1460203, + 0x81C, 0x83480203, + 0x81C, 0x824A0203, + 0x81C, 0x814C0203, + 0x81C, 0x804E0203, + 0x81C, 0x63500203, + 0x81C, 0x62520203, + 0x81C, 0x61540203, + 0x81C, 0x42560203, + 0x81C, 0x41580203, + 0x81C, 0x405A0203, + 0x81C, 0x225C0203, + 0x81C, 0x215E0203, + 0x81C, 0x20600203, + 0x81C, 0x04620203, + 0x81C, 0x03640203, + 0x81C, 0x02660203, + 0x81C, 0x01680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x9000000e, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000203, + 0x81C, 0xFB020203, + 0x81C, 0xFA040203, + 0x81C, 0xF9060203, + 0x81C, 0xF8080203, + 0x81C, 0xF70A0203, + 0x81C, 0xF60C0203, + 0x81C, 0xF50E0203, + 0x81C, 0xF4100203, + 0x81C, 0xF3120203, + 0x81C, 0xF2140203, + 0x81C, 0xF1160203, + 0x81C, 0xF0180203, + 0x81C, 0xEE1A0203, + 0x81C, 0xED1C0203, + 0x81C, 0xEC1E0203, + 0x81C, 0xEB200203, + 0x81C, 0xEA220203, + 0x81C, 0xE9240203, + 0x81C, 0xE8260203, + 0x81C, 0xE7280203, + 0x81C, 0xE62A0203, + 0x81C, 0xE52C0203, + 0x81C, 0xE42E0203, + 0x81C, 0xE3300203, + 0x81C, 0xE2320203, + 0x81C, 0xC6340203, + 0x81C, 0xC5360203, + 0x81C, 0xC4380203, + 0x81C, 0xC33A0203, + 0x81C, 0xA63C0203, + 0x81C, 0xA53E0203, + 0x81C, 0xA4400203, + 0x81C, 0xA3420203, + 0x81C, 0xA2440203, + 0x81C, 0xA1460203, + 0x81C, 0x83480203, + 0x81C, 0x824A0203, + 0x81C, 0x814C0203, + 0x81C, 0x804E0203, + 0x81C, 0x63500203, + 0x81C, 0x62520203, + 0x81C, 0x61540203, + 0x81C, 0x42560203, + 0x81C, 0x41580203, + 0x81C, 0x405A0203, + 0x81C, 0x225C0203, + 0x81C, 0x215E0203, + 0x81C, 0x20600203, + 0x81C, 0x04620203, + 0x81C, 0x03640203, + 0x81C, 0x02660203, + 0x81C, 0x01680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x9000000f, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000203, + 0x81C, 0xFB020203, + 0x81C, 0xFA040203, + 0x81C, 0xF9060203, + 0x81C, 0xF8080203, + 0x81C, 0xF70A0203, + 0x81C, 0xF60C0203, + 0x81C, 0xF50E0203, + 0x81C, 0xF4100203, + 0x81C, 0xF3120203, + 0x81C, 0xF2140203, + 0x81C, 0xF1160203, + 0x81C, 0xF0180203, + 0x81C, 0xEF1A0203, + 0x81C, 0xEE1C0203, + 0x81C, 0xED1E0203, + 0x81C, 0xEC200203, + 0x81C, 0xEB220203, + 0x81C, 0xEA240203, + 0x81C, 0xE9260203, + 0x81C, 0xE8280203, + 0x81C, 0xE72A0203, + 0x81C, 0xE62C0203, + 0x81C, 0xE52E0203, + 0x81C, 0xE4300203, + 0x81C, 0xE3320203, + 0x81C, 0xE2340203, + 0x81C, 0xE1360203, + 0x81C, 0xE0380203, + 0x81C, 0xC33A0203, + 0x81C, 0xC23C0203, + 0x81C, 0xC13E0203, + 0x81C, 0xA3400203, + 0x81C, 0xA2420203, + 0x81C, 0xA1440203, + 0x81C, 0xA0460203, + 0x81C, 0x83480203, + 0x81C, 0x824A0203, + 0x81C, 0x814C0203, + 0x81C, 0x644E0203, + 0x81C, 0x63500203, + 0x81C, 0x62520203, + 0x81C, 0x61540203, + 0x81C, 0x42560203, + 0x81C, 0x41580203, + 0x81C, 0x235A0203, + 0x81C, 0x225C0203, + 0x81C, 0x215E0203, + 0x81C, 0x04600203, + 0x81C, 0x03620203, + 0x81C, 0x02640203, + 0x81C, 0x01660203, + 0x81C, 0x00680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x90000010, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000203, + 0x81C, 0xFB020203, + 0x81C, 0xFA040203, + 0x81C, 0xF9060203, + 0x81C, 0xF8080203, + 0x81C, 0xF70A0203, + 0x81C, 0xF60C0203, + 0x81C, 0xF50E0203, + 0x81C, 0xF4100203, + 0x81C, 0xF3120203, + 0x81C, 0xF2140203, + 0x81C, 0xF1160203, + 0x81C, 0xF0180203, + 0x81C, 0xEF1A0203, + 0x81C, 0xEE1C0203, + 0x81C, 0xED1E0203, + 0x81C, 0xEC200203, + 0x81C, 0xEB220203, + 0x81C, 0xEA240203, + 0x81C, 0xE9260203, + 0x81C, 0xE8280203, + 0x81C, 0xE72A0203, + 0x81C, 0xE62C0203, + 0x81C, 0xE52E0203, + 0x81C, 0xE4300203, + 0x81C, 0xE3320203, + 0x81C, 0xE2340203, + 0x81C, 0xC6360203, + 0x81C, 0xC5380203, + 0x81C, 0xC43A0203, + 0x81C, 0xC33C0203, + 0x81C, 0xA63E0203, + 0x81C, 0xA5400203, + 0x81C, 0xA4420203, + 0x81C, 0xA3440203, + 0x81C, 0xA2460203, + 0x81C, 0xA1480203, + 0x81C, 0x834A0203, + 0x81C, 0x824C0203, + 0x81C, 0x814E0203, + 0x81C, 0x64500203, + 0x81C, 0x63520203, + 0x81C, 0x62540203, + 0x81C, 0x61560203, + 0x81C, 0x60580203, + 0x81C, 0x405A0203, + 0x81C, 0x215C0203, + 0x81C, 0x205E0203, + 0x81C, 0x03600203, + 0x81C, 0x02620203, + 0x81C, 0x01640203, + 0x81C, 0x00660203, + 0x81C, 0x00680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0x90000012, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF7000203, + 0x81C, 0xF6020203, + 0x81C, 0xF5040203, + 0x81C, 0xF4060203, + 0x81C, 0xF3080203, + 0x81C, 0xF20A0203, + 0x81C, 0xF10C0203, + 0x81C, 0xF00E0203, + 0x81C, 0xEF100203, + 0x81C, 0xEE120203, + 0x81C, 0xED140203, + 0x81C, 0xEC160203, + 0x81C, 0xEB180203, + 0x81C, 0xEA1A0203, + 0x81C, 0xE91C0203, + 0x81C, 0xE81E0203, + 0x81C, 0xE7200203, + 0x81C, 0xE6220203, + 0x81C, 0xE5240203, + 0x81C, 0xE4260203, + 0x81C, 0xE3280203, + 0x81C, 0xC42A0203, + 0x81C, 0xC32C0203, + 0x81C, 0xC22E0203, + 0x81C, 0xC1300203, + 0x81C, 0xC0320203, + 0x81C, 0xA3340203, + 0x81C, 0xA2360203, + 0x81C, 0xA1380203, + 0x81C, 0xA03A0203, + 0x81C, 0x823C0203, + 0x81C, 0x813E0203, + 0x81C, 0x80400203, + 0x81C, 0x64420203, + 0x81C, 0x63440203, + 0x81C, 0x62460203, + 0x81C, 0x61480203, + 0x81C, 0x604A0203, + 0x81C, 0x414C0203, + 0x81C, 0x404E0203, + 0x81C, 0x22500203, + 0x81C, 0x21520203, + 0x81C, 0x20540203, + 0x81C, 0x03560203, + 0x81C, 0x02580203, + 0x81C, 0x015A0203, + 0x81C, 0x005C0203, + 0x81C, 0x005E0203, + 0x81C, 0x00600203, + 0x81C, 0x00620203, + 0x81C, 0x00640203, + 0x81C, 0x00660203, + 0x81C, 0x00680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0xA0000000, 0x00000000, + 0x81C, 0xFD000203, + 0x81C, 0xFC020203, + 0x81C, 0xFB040203, + 0x81C, 0xFA060203, + 0x81C, 0xF9080203, + 0x81C, 0xF80A0203, + 0x81C, 0xF70C0203, + 0x81C, 0xF60E0203, + 0x81C, 0xF5100203, + 0x81C, 0xF4120203, + 0x81C, 0xF3140203, + 0x81C, 0xF2160203, + 0x81C, 0xF1180203, + 0x81C, 0xF01A0203, + 0x81C, 0xEF1C0203, + 0x81C, 0xEE1E0203, + 0x81C, 0xED200203, + 0x81C, 0xEC220203, + 0x81C, 0xEB240203, + 0x81C, 0xEA260203, + 0x81C, 0xE9280203, + 0x81C, 0xE82A0203, + 0x81C, 0xE72C0203, + 0x81C, 0xE62E0203, + 0x81C, 0xE5300203, + 0x81C, 0xE4320203, + 0x81C, 0xE3340203, + 0x81C, 0xC6360203, + 0x81C, 0xC5380203, + 0x81C, 0xC43A0203, + 0x81C, 0xC33C0203, + 0x81C, 0xA63E0203, + 0x81C, 0xA5400203, + 0x81C, 0xA4420203, + 0x81C, 0xA3440203, + 0x81C, 0xA2460203, + 0x81C, 0xA1480203, + 0x81C, 0x834A0203, + 0x81C, 0x824C0203, + 0x81C, 0x814E0203, + 0x81C, 0x64500203, + 0x81C, 0x63520203, + 0x81C, 0x62540203, + 0x81C, 0x61560203, + 0x81C, 0x60580203, + 0x81C, 0x235A0203, + 0x81C, 0x225C0203, + 0x81C, 0x215E0203, + 0x81C, 0x20600203, + 0x81C, 0x03620203, + 0x81C, 0x02640203, + 0x81C, 0x01660203, + 0x81C, 0x00680203, + 0x81C, 0x006A0203, + 0x81C, 0x006C0203, + 0x81C, 0x006E0203, + 0x81C, 0x00700203, + 0x81C, 0x00720203, + 0x81C, 0x00740203, + 0x81C, 0x00760203, + 0x81C, 0x00780203, + 0x81C, 0x007A0203, + 0x81C, 0x007C0203, + 0x81C, 0x007E0203, + 0xB0000000, 0x00000000, + 0x80000000, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000303, + 0x81C, 0xFB020303, + 0x81C, 0xFA040303, + 0x81C, 0xF9060303, + 0x81C, 0xF8080303, + 0x81C, 0xF70A0303, + 0x81C, 0xF60C0303, + 0x81C, 0xF50E0303, + 0x81C, 0xF4100303, + 0x81C, 0xF3120303, + 0x81C, 0xF2140303, + 0x81C, 0xF1160303, + 0x81C, 0xEF180303, + 0x81C, 0xEE1A0303, + 0x81C, 0xED1C0303, + 0x81C, 0xEC1E0303, + 0x81C, 0xEB200303, + 0x81C, 0xEA220303, + 0x81C, 0xE9240303, + 0x81C, 0xE8260303, + 0x81C, 0xE7280303, + 0x81C, 0xE62A0303, + 0x81C, 0xE52C0303, + 0x81C, 0xE42E0303, + 0x81C, 0xE3300303, + 0x81C, 0xE2320303, + 0x81C, 0xC6340303, + 0x81C, 0xC5360303, + 0x81C, 0xC4380303, + 0x81C, 0xC33A0303, + 0x81C, 0xA63C0303, + 0x81C, 0xA53E0303, + 0x81C, 0xA4400303, + 0x81C, 0xA3420303, + 0x81C, 0xA2440303, + 0x81C, 0xA1460303, + 0x81C, 0x83480303, + 0x81C, 0x824A0303, + 0x81C, 0x814C0303, + 0x81C, 0x804E0303, + 0x81C, 0x63500303, + 0x81C, 0x62520303, + 0x81C, 0x61540303, + 0x81C, 0x42560303, + 0x81C, 0x41580303, + 0x81C, 0x405A0303, + 0x81C, 0x225C0303, + 0x81C, 0x215E0303, + 0x81C, 0x20600303, + 0x81C, 0x04620303, + 0x81C, 0x03640303, + 0x81C, 0x02660303, + 0x81C, 0x01680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF7000303, + 0x81C, 0xF6020303, + 0x81C, 0xF5040303, + 0x81C, 0xF4060303, + 0x81C, 0xF3080303, + 0x81C, 0xF20A0303, + 0x81C, 0xF10C0303, + 0x81C, 0xF00E0303, + 0x81C, 0xEF100303, + 0x81C, 0xEE120303, + 0x81C, 0xED140303, + 0x81C, 0xEC160303, + 0x81C, 0xEB180303, + 0x81C, 0xEA1A0303, + 0x81C, 0xE91C0303, + 0x81C, 0xCA1E0303, + 0x81C, 0xC9200303, + 0x81C, 0xC8220303, + 0x81C, 0xC7240303, + 0x81C, 0xC6260303, + 0x81C, 0xC5280303, + 0x81C, 0xC42A0303, + 0x81C, 0xC32C0303, + 0x81C, 0xC22E0303, + 0x81C, 0xC1300303, + 0x81C, 0xA4320303, + 0x81C, 0xA3340303, + 0x81C, 0xA2360303, + 0x81C, 0xA1380303, + 0x81C, 0xA03A0303, + 0x81C, 0x823C0303, + 0x81C, 0x813E0303, + 0x81C, 0x80400303, + 0x81C, 0x64420303, + 0x81C, 0x63440303, + 0x81C, 0x62460303, + 0x81C, 0x61480303, + 0x81C, 0x604A0303, + 0x81C, 0x414C0303, + 0x81C, 0x404E0303, + 0x81C, 0x06500303, + 0x81C, 0x05520303, + 0x81C, 0x04540303, + 0x81C, 0x03560303, + 0x81C, 0x02580303, + 0x81C, 0x015A0303, + 0x81C, 0x005C0303, + 0x81C, 0x005E0303, + 0x81C, 0x00600303, + 0x81C, 0x00620303, + 0x81C, 0x00640303, + 0x81C, 0x00660303, + 0x81C, 0x00680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF7000303, + 0x81C, 0xF6020303, + 0x81C, 0xF5040303, + 0x81C, 0xF4060303, + 0x81C, 0xF3080303, + 0x81C, 0xF20A0303, + 0x81C, 0xF10C0303, + 0x81C, 0xF00E0303, + 0x81C, 0xEF100303, + 0x81C, 0xEE120303, + 0x81C, 0xED140303, + 0x81C, 0xEC160303, + 0x81C, 0xEB180303, + 0x81C, 0xEA1A0303, + 0x81C, 0xE91C0303, + 0x81C, 0xCA1E0303, + 0x81C, 0xC9200303, + 0x81C, 0xC8220303, + 0x81C, 0xC7240303, + 0x81C, 0xC6260303, + 0x81C, 0xC5280303, + 0x81C, 0xC42A0303, + 0x81C, 0xC32C0303, + 0x81C, 0xC22E0303, + 0x81C, 0xC1300303, + 0x81C, 0xA4320303, + 0x81C, 0xA3340303, + 0x81C, 0xA2360303, + 0x81C, 0xA1380303, + 0x81C, 0xA03A0303, + 0x81C, 0x823C0303, + 0x81C, 0x813E0303, + 0x81C, 0x80400303, + 0x81C, 0x64420303, + 0x81C, 0x63440303, + 0x81C, 0x62460303, + 0x81C, 0x61480303, + 0x81C, 0x604A0303, + 0x81C, 0x414C0303, + 0x81C, 0x404E0303, + 0x81C, 0x22500303, + 0x81C, 0x21520303, + 0x81C, 0x20540303, + 0x81C, 0x03560303, + 0x81C, 0x02580303, + 0x81C, 0x015A0303, + 0x81C, 0x005C0303, + 0x81C, 0x005E0303, + 0x81C, 0x00600303, + 0x81C, 0x00620303, + 0x81C, 0x00640303, + 0x81C, 0x00660303, + 0x81C, 0x00680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000303, + 0x81C, 0xFB020303, + 0x81C, 0xFA040303, + 0x81C, 0xF9060303, + 0x81C, 0xF8080303, + 0x81C, 0xF70A0303, + 0x81C, 0xF60C0303, + 0x81C, 0xF50E0303, + 0x81C, 0xF4100303, + 0x81C, 0xF3120303, + 0x81C, 0xF2140303, + 0x81C, 0xF1160303, + 0x81C, 0xF0180303, + 0x81C, 0xEF1A0303, + 0x81C, 0xEE1C0303, + 0x81C, 0xED1E0303, + 0x81C, 0xEC200303, + 0x81C, 0xEB220303, + 0x81C, 0xEA240303, + 0x81C, 0xE9260303, + 0x81C, 0xE8280303, + 0x81C, 0xE72A0303, + 0x81C, 0xE62C0303, + 0x81C, 0xE52E0303, + 0x81C, 0xE4300303, + 0x81C, 0xE3320303, + 0x81C, 0xE2340303, + 0x81C, 0xC6360303, + 0x81C, 0xC5380303, + 0x81C, 0xC43A0303, + 0x81C, 0xC33C0303, + 0x81C, 0xA63E0303, + 0x81C, 0xA5400303, + 0x81C, 0xA4420303, + 0x81C, 0xA3440303, + 0x81C, 0xA2460303, + 0x81C, 0x84480303, + 0x81C, 0x834A0303, + 0x81C, 0x824C0303, + 0x81C, 0x814E0303, + 0x81C, 0x80500303, + 0x81C, 0x63520303, + 0x81C, 0x62540303, + 0x81C, 0x61560303, + 0x81C, 0x60580303, + 0x81C, 0x225A0303, + 0x81C, 0x055C0303, + 0x81C, 0x045E0303, + 0x81C, 0x03600303, + 0x81C, 0x02620303, + 0x81C, 0x01640303, + 0x81C, 0x00660303, + 0x81C, 0x00680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF7000303, + 0x81C, 0xF6020303, + 0x81C, 0xF5040303, + 0x81C, 0xF4060303, + 0x81C, 0xF3080303, + 0x81C, 0xF20A0303, + 0x81C, 0xF10C0303, + 0x81C, 0xF00E0303, + 0x81C, 0xEF100303, + 0x81C, 0xEE120303, + 0x81C, 0xED140303, + 0x81C, 0xEC160303, + 0x81C, 0xEB180303, + 0x81C, 0xEA1A0303, + 0x81C, 0xE91C0303, + 0x81C, 0xCA1E0303, + 0x81C, 0xC9200303, + 0x81C, 0xC8220303, + 0x81C, 0xC7240303, + 0x81C, 0xC6260303, + 0x81C, 0xC5280303, + 0x81C, 0xC42A0303, + 0x81C, 0xC32C0303, + 0x81C, 0xC22E0303, + 0x81C, 0xC1300303, + 0x81C, 0xA4320303, + 0x81C, 0xA3340303, + 0x81C, 0xA2360303, + 0x81C, 0xA1380303, + 0x81C, 0xA03A0303, + 0x81C, 0x823C0303, + 0x81C, 0x813E0303, + 0x81C, 0x80400303, + 0x81C, 0x64420303, + 0x81C, 0x63440303, + 0x81C, 0x62460303, + 0x81C, 0x61480303, + 0x81C, 0x604A0303, + 0x81C, 0x414C0303, + 0x81C, 0x404E0303, + 0x81C, 0x22500303, + 0x81C, 0x21520303, + 0x81C, 0x20540303, + 0x81C, 0x03560303, + 0x81C, 0x02580303, + 0x81C, 0x015A0303, + 0x81C, 0x005C0303, + 0x81C, 0x005E0303, + 0x81C, 0x00600303, + 0x81C, 0x00620303, + 0x81C, 0x00640303, + 0x81C, 0x00660303, + 0x81C, 0x00680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFB000303, + 0x81C, 0xFA020303, + 0x81C, 0xF9040303, + 0x81C, 0xF8060303, + 0x81C, 0xF7080303, + 0x81C, 0xF60A0303, + 0x81C, 0xF50C0303, + 0x81C, 0xF40E0303, + 0x81C, 0xF3100303, + 0x81C, 0xF2120303, + 0x81C, 0xF1140303, + 0x81C, 0xF0160303, + 0x81C, 0xEF180303, + 0x81C, 0xEE1A0303, + 0x81C, 0xED1C0303, + 0x81C, 0xEC1E0303, + 0x81C, 0xEB200303, + 0x81C, 0xEA220303, + 0x81C, 0xE9240303, + 0x81C, 0xE8260303, + 0x81C, 0xE7280303, + 0x81C, 0xE62A0303, + 0x81C, 0xE52C0303, + 0x81C, 0xE42E0303, + 0x81C, 0xE3300303, + 0x81C, 0xE2320303, + 0x81C, 0xE1340303, + 0x81C, 0xC5360303, + 0x81C, 0xC4380303, + 0x81C, 0xC33A0303, + 0x81C, 0xC23C0303, + 0x81C, 0xC13E0303, + 0x81C, 0xA4400303, + 0x81C, 0xA3420303, + 0x81C, 0xA2440303, + 0x81C, 0xA1460303, + 0x81C, 0x83480303, + 0x81C, 0x824A0303, + 0x81C, 0x814C0303, + 0x81C, 0x804E0303, + 0x81C, 0x64500303, + 0x81C, 0x63520303, + 0x81C, 0x62540303, + 0x81C, 0x61560303, + 0x81C, 0x60580303, + 0x81C, 0x235A0303, + 0x81C, 0x225C0303, + 0x81C, 0x215E0303, + 0x81C, 0x20600303, + 0x81C, 0x04620303, + 0x81C, 0x03640303, + 0x81C, 0x02660303, + 0x81C, 0x01680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF9000303, + 0x81C, 0xF8020303, + 0x81C, 0xF7040303, + 0x81C, 0xF6060303, + 0x81C, 0xF5080303, + 0x81C, 0xF40A0303, + 0x81C, 0xF30C0303, + 0x81C, 0xF20E0303, + 0x81C, 0xF1100303, + 0x81C, 0xF0120303, + 0x81C, 0xEF140303, + 0x81C, 0xEE160303, + 0x81C, 0xED180303, + 0x81C, 0xEC1A0303, + 0x81C, 0xEB1C0303, + 0x81C, 0xEA1E0303, + 0x81C, 0xC9200303, + 0x81C, 0xC8220303, + 0x81C, 0xC7240303, + 0x81C, 0xC6260303, + 0x81C, 0xC5280303, + 0x81C, 0xC42A0303, + 0x81C, 0xC32C0303, + 0x81C, 0xC22E0303, + 0x81C, 0xC1300303, + 0x81C, 0xC0320303, + 0x81C, 0xA3340303, + 0x81C, 0xA2360303, + 0x81C, 0xA1380303, + 0x81C, 0xA03A0303, + 0x81C, 0x823C0303, + 0x81C, 0x813E0303, + 0x81C, 0x80400303, + 0x81C, 0x64420303, + 0x81C, 0x63440303, + 0x81C, 0x62460303, + 0x81C, 0x61480303, + 0x81C, 0x604A0303, + 0x81C, 0x414C0303, + 0x81C, 0x404E0303, + 0x81C, 0x22500303, + 0x81C, 0x21520303, + 0x81C, 0x20540303, + 0x81C, 0x03560303, + 0x81C, 0x02580303, + 0x81C, 0x015A0303, + 0x81C, 0x005C0303, + 0x81C, 0x005E0303, + 0x81C, 0x00600303, + 0x81C, 0x00620303, + 0x81C, 0x00640303, + 0x81C, 0x00660303, + 0x81C, 0x00680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000303, + 0x81C, 0xF7020303, + 0x81C, 0xF6040303, + 0x81C, 0xF5060303, + 0x81C, 0xF4080303, + 0x81C, 0xF30A0303, + 0x81C, 0xF20C0303, + 0x81C, 0xF10E0303, + 0x81C, 0xF0100303, + 0x81C, 0xEF120303, + 0x81C, 0xEE140303, + 0x81C, 0xED160303, + 0x81C, 0xEC180303, + 0x81C, 0xEB1A0303, + 0x81C, 0xEA1C0303, + 0x81C, 0xE91E0303, + 0x81C, 0xCA200303, + 0x81C, 0xC9220303, + 0x81C, 0xC8240303, + 0x81C, 0xC7260303, + 0x81C, 0xC6280303, + 0x81C, 0xC52A0303, + 0x81C, 0xC42C0303, + 0x81C, 0xC32E0303, + 0x81C, 0xC2300303, + 0x81C, 0xC1320303, + 0x81C, 0xA3340303, + 0x81C, 0xA2360303, + 0x81C, 0xA1380303, + 0x81C, 0xA03A0303, + 0x81C, 0x823C0303, + 0x81C, 0x813E0303, + 0x81C, 0x80400303, + 0x81C, 0x65420303, + 0x81C, 0x64440303, + 0x81C, 0x63460303, + 0x81C, 0x62480303, + 0x81C, 0x614A0303, + 0x81C, 0x424C0303, + 0x81C, 0x414E0303, + 0x81C, 0x40500303, + 0x81C, 0x22520303, + 0x81C, 0x21540303, + 0x81C, 0x20560303, + 0x81C, 0x04580303, + 0x81C, 0x035A0303, + 0x81C, 0x025C0303, + 0x81C, 0x015E0303, + 0x81C, 0x00600303, + 0x81C, 0x00620303, + 0x81C, 0x00640303, + 0x81C, 0x00660303, + 0x81C, 0x00680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x90000008, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFB000303, + 0x81C, 0xFA020303, + 0x81C, 0xF9040303, + 0x81C, 0xF8060303, + 0x81C, 0xF7080303, + 0x81C, 0xF60A0303, + 0x81C, 0xF50C0303, + 0x81C, 0xF40E0303, + 0x81C, 0xF3100303, + 0x81C, 0xF2120303, + 0x81C, 0xF1140303, + 0x81C, 0xF0160303, + 0x81C, 0xEF180303, + 0x81C, 0xEE1A0303, + 0x81C, 0xED1C0303, + 0x81C, 0xEC1E0303, + 0x81C, 0xEB200303, + 0x81C, 0xEA220303, + 0x81C, 0xE9240303, + 0x81C, 0xE8260303, + 0x81C, 0xE7280303, + 0x81C, 0xE62A0303, + 0x81C, 0xE52C0303, + 0x81C, 0xE42E0303, + 0x81C, 0xE3300303, + 0x81C, 0xE2320303, + 0x81C, 0xC6340303, + 0x81C, 0xC5360303, + 0x81C, 0xC4380303, + 0x81C, 0xC33A0303, + 0x81C, 0xC23C0303, + 0x81C, 0xC13E0303, + 0x81C, 0xA4400303, + 0x81C, 0xA3420303, + 0x81C, 0xA2440303, + 0x81C, 0xA1460303, + 0x81C, 0x83480303, + 0x81C, 0x824A0303, + 0x81C, 0x814C0303, + 0x81C, 0x804E0303, + 0x81C, 0x63500303, + 0x81C, 0x62520303, + 0x81C, 0x43540303, + 0x81C, 0x42560303, + 0x81C, 0x41580303, + 0x81C, 0x235A0303, + 0x81C, 0x225C0303, + 0x81C, 0x215E0303, + 0x81C, 0x20600303, + 0x81C, 0x04620303, + 0x81C, 0x03640303, + 0x81C, 0x02660303, + 0x81C, 0x01680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x90000009, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000303, + 0x81C, 0xF7020303, + 0x81C, 0xF6040303, + 0x81C, 0xF5060303, + 0x81C, 0xF4080303, + 0x81C, 0xF30A0303, + 0x81C, 0xF20C0303, + 0x81C, 0xF10E0303, + 0x81C, 0xF0100303, + 0x81C, 0xEF120303, + 0x81C, 0xEE140303, + 0x81C, 0xED160303, + 0x81C, 0xEC180303, + 0x81C, 0xEB1A0303, + 0x81C, 0xEA1C0303, + 0x81C, 0xE91E0303, + 0x81C, 0xCA200303, + 0x81C, 0xC9220303, + 0x81C, 0xC8240303, + 0x81C, 0xC7260303, + 0x81C, 0xC6280303, + 0x81C, 0xC52A0303, + 0x81C, 0xC42C0303, + 0x81C, 0xC32E0303, + 0x81C, 0xC2300303, + 0x81C, 0xC1320303, + 0x81C, 0xA3340303, + 0x81C, 0xA2360303, + 0x81C, 0xA1380303, + 0x81C, 0xA03A0303, + 0x81C, 0x823C0303, + 0x81C, 0x813E0303, + 0x81C, 0x80400303, + 0x81C, 0x65420303, + 0x81C, 0x64440303, + 0x81C, 0x63460303, + 0x81C, 0x62480303, + 0x81C, 0x614A0303, + 0x81C, 0x424C0303, + 0x81C, 0x414E0303, + 0x81C, 0x40500303, + 0x81C, 0x22520303, + 0x81C, 0x21540303, + 0x81C, 0x20560303, + 0x81C, 0x04580303, + 0x81C, 0x035A0303, + 0x81C, 0x025C0303, + 0x81C, 0x015E0303, + 0x81C, 0x00600303, + 0x81C, 0x00620303, + 0x81C, 0x00640303, + 0x81C, 0x00660303, + 0x81C, 0x00680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x9000000a, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000303, + 0x81C, 0xFB020303, + 0x81C, 0xFA040303, + 0x81C, 0xF9060303, + 0x81C, 0xF8080303, + 0x81C, 0xF70A0303, + 0x81C, 0xF60C0303, + 0x81C, 0xF50E0303, + 0x81C, 0xF4100303, + 0x81C, 0xF3120303, + 0x81C, 0xF2140303, + 0x81C, 0xF1160303, + 0x81C, 0xEF180303, + 0x81C, 0xEE1A0303, + 0x81C, 0xED1C0303, + 0x81C, 0xEC1E0303, + 0x81C, 0xEB200303, + 0x81C, 0xEA220303, + 0x81C, 0xE9240303, + 0x81C, 0xE8260303, + 0x81C, 0xE7280303, + 0x81C, 0xE62A0303, + 0x81C, 0xE52C0303, + 0x81C, 0xE42E0303, + 0x81C, 0xE3300303, + 0x81C, 0xE2320303, + 0x81C, 0xC6340303, + 0x81C, 0xC5360303, + 0x81C, 0xC4380303, + 0x81C, 0xC33A0303, + 0x81C, 0xA63C0303, + 0x81C, 0xA53E0303, + 0x81C, 0xA4400303, + 0x81C, 0xA3420303, + 0x81C, 0xA2440303, + 0x81C, 0xA1460303, + 0x81C, 0x83480303, + 0x81C, 0x824A0303, + 0x81C, 0x814C0303, + 0x81C, 0x804E0303, + 0x81C, 0x63500303, + 0x81C, 0x62520303, + 0x81C, 0x61540303, + 0x81C, 0x42560303, + 0x81C, 0x41580303, + 0x81C, 0x405A0303, + 0x81C, 0x225C0303, + 0x81C, 0x215E0303, + 0x81C, 0x20600303, + 0x81C, 0x04620303, + 0x81C, 0x03640303, + 0x81C, 0x02660303, + 0x81C, 0x01680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x9000000b, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000303, + 0x81C, 0xF7020303, + 0x81C, 0xF6040303, + 0x81C, 0xF5060303, + 0x81C, 0xF4080303, + 0x81C, 0xF30A0303, + 0x81C, 0xF20C0303, + 0x81C, 0xF10E0303, + 0x81C, 0xF0100303, + 0x81C, 0xEF120303, + 0x81C, 0xEE140303, + 0x81C, 0xED160303, + 0x81C, 0xEC180303, + 0x81C, 0xEB1A0303, + 0x81C, 0xEA1C0303, + 0x81C, 0xE91E0303, + 0x81C, 0xCA200303, + 0x81C, 0xC9220303, + 0x81C, 0xC8240303, + 0x81C, 0xC7260303, + 0x81C, 0xC6280303, + 0x81C, 0xC52A0303, + 0x81C, 0xC42C0303, + 0x81C, 0xC32E0303, + 0x81C, 0xC2300303, + 0x81C, 0xC1320303, + 0x81C, 0xA3340303, + 0x81C, 0xA2360303, + 0x81C, 0xA1380303, + 0x81C, 0xA03A0303, + 0x81C, 0x823C0303, + 0x81C, 0x813E0303, + 0x81C, 0x80400303, + 0x81C, 0x64420303, + 0x81C, 0x63440303, + 0x81C, 0x62460303, + 0x81C, 0x61480303, + 0x81C, 0x604A0303, + 0x81C, 0x234C0303, + 0x81C, 0x224E0303, + 0x81C, 0x21500303, + 0x81C, 0x20520303, + 0x81C, 0x06540303, + 0x81C, 0x05560303, + 0x81C, 0x04580303, + 0x81C, 0x035A0303, + 0x81C, 0x025C0303, + 0x81C, 0x015E0303, + 0x81C, 0x00600303, + 0x81C, 0x00620303, + 0x81C, 0x00640303, + 0x81C, 0x00660303, + 0x81C, 0x00680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x9000000c, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000303, + 0x81C, 0xFB020303, + 0x81C, 0xFA040303, + 0x81C, 0xF9060303, + 0x81C, 0xF8080303, + 0x81C, 0xF70A0303, + 0x81C, 0xF60C0303, + 0x81C, 0xF50E0303, + 0x81C, 0xF4100303, + 0x81C, 0xF3120303, + 0x81C, 0xF2140303, + 0x81C, 0xF1160303, + 0x81C, 0xF0180303, + 0x81C, 0xEF1A0303, + 0x81C, 0xEE1C0303, + 0x81C, 0xED1E0303, + 0x81C, 0xEC200303, + 0x81C, 0xEB220303, + 0x81C, 0xEA240303, + 0x81C, 0xE9260303, + 0x81C, 0xE8280303, + 0x81C, 0xE72A0303, + 0x81C, 0xE62C0303, + 0x81C, 0xE52E0303, + 0x81C, 0xE4300303, + 0x81C, 0xE3320303, + 0x81C, 0xE2340303, + 0x81C, 0xC6360303, + 0x81C, 0xC5380303, + 0x81C, 0xC43A0303, + 0x81C, 0xC33C0303, + 0x81C, 0xA63E0303, + 0x81C, 0xA5400303, + 0x81C, 0xA4420303, + 0x81C, 0xA3440303, + 0x81C, 0xA2460303, + 0x81C, 0x84480303, + 0x81C, 0x834A0303, + 0x81C, 0x824C0303, + 0x81C, 0x814E0303, + 0x81C, 0x80500303, + 0x81C, 0x63520303, + 0x81C, 0x62540303, + 0x81C, 0x61560303, + 0x81C, 0x60580303, + 0x81C, 0x225A0303, + 0x81C, 0x055C0303, + 0x81C, 0x045E0303, + 0x81C, 0x03600303, + 0x81C, 0x02620303, + 0x81C, 0x01640303, + 0x81C, 0x00660303, + 0x81C, 0x00680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x9000000d, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFB000303, + 0x81C, 0xFA020303, + 0x81C, 0xF9040303, + 0x81C, 0xF8060303, + 0x81C, 0xF7080303, + 0x81C, 0xF60A0303, + 0x81C, 0xF50C0303, + 0x81C, 0xF40E0303, + 0x81C, 0xF3100303, + 0x81C, 0xF2120303, + 0x81C, 0xF1140303, + 0x81C, 0xEF160303, + 0x81C, 0xEE180303, + 0x81C, 0xED1A0303, + 0x81C, 0xEC1C0303, + 0x81C, 0xEB1E0303, + 0x81C, 0xEA200303, + 0x81C, 0xE9220303, + 0x81C, 0xE8240303, + 0x81C, 0xE7260303, + 0x81C, 0xE6280303, + 0x81C, 0xE52A0303, + 0x81C, 0xE42C0303, + 0x81C, 0xE32E0303, + 0x81C, 0xE2300303, + 0x81C, 0xE1320303, + 0x81C, 0xC6340303, + 0x81C, 0xC5360303, + 0x81C, 0xC4380303, + 0x81C, 0xC33A0303, + 0x81C, 0xA63C0303, + 0x81C, 0xA53E0303, + 0x81C, 0xA4400303, + 0x81C, 0xA3420303, + 0x81C, 0xA2440303, + 0x81C, 0xA1460303, + 0x81C, 0x83480303, + 0x81C, 0x824A0303, + 0x81C, 0x814C0303, + 0x81C, 0x804E0303, + 0x81C, 0x63500303, + 0x81C, 0x62520303, + 0x81C, 0x61540303, + 0x81C, 0x42560303, + 0x81C, 0x41580303, + 0x81C, 0x405A0303, + 0x81C, 0x225C0303, + 0x81C, 0x215E0303, + 0x81C, 0x20600303, + 0x81C, 0x04620303, + 0x81C, 0x03640303, + 0x81C, 0x02660303, + 0x81C, 0x01680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x9000000e, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFB000303, + 0x81C, 0xFA020303, + 0x81C, 0xF9040303, + 0x81C, 0xF8060303, + 0x81C, 0xF7080303, + 0x81C, 0xF60A0303, + 0x81C, 0xF50C0303, + 0x81C, 0xF40E0303, + 0x81C, 0xF3100303, + 0x81C, 0xF2120303, + 0x81C, 0xF1140303, + 0x81C, 0xEF160303, + 0x81C, 0xEE180303, + 0x81C, 0xED1A0303, + 0x81C, 0xEC1C0303, + 0x81C, 0xEB1E0303, + 0x81C, 0xEA200303, + 0x81C, 0xE9220303, + 0x81C, 0xE8240303, + 0x81C, 0xE7260303, + 0x81C, 0xE6280303, + 0x81C, 0xE52A0303, + 0x81C, 0xE42C0303, + 0x81C, 0xE32E0303, + 0x81C, 0xE2300303, + 0x81C, 0xE1320303, + 0x81C, 0xC6340303, + 0x81C, 0xC5360303, + 0x81C, 0xC4380303, + 0x81C, 0xC33A0303, + 0x81C, 0xA63C0303, + 0x81C, 0xA53E0303, + 0x81C, 0xA4400303, + 0x81C, 0xA3420303, + 0x81C, 0xA2440303, + 0x81C, 0xA1460303, + 0x81C, 0x83480303, + 0x81C, 0x824A0303, + 0x81C, 0x814C0303, + 0x81C, 0x804E0303, + 0x81C, 0x63500303, + 0x81C, 0x62520303, + 0x81C, 0x61540303, + 0x81C, 0x42560303, + 0x81C, 0x41580303, + 0x81C, 0x405A0303, + 0x81C, 0x225C0303, + 0x81C, 0x215E0303, + 0x81C, 0x20600303, + 0x81C, 0x04620303, + 0x81C, 0x03640303, + 0x81C, 0x02660303, + 0x81C, 0x01680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x9000000f, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFB000303, + 0x81C, 0xFA020303, + 0x81C, 0xF9040303, + 0x81C, 0xF8060303, + 0x81C, 0xF7080303, + 0x81C, 0xF60A0303, + 0x81C, 0xF50C0303, + 0x81C, 0xF40E0303, + 0x81C, 0xF3100303, + 0x81C, 0xF2120303, + 0x81C, 0xF1140303, + 0x81C, 0xF0160303, + 0x81C, 0xEF180303, + 0x81C, 0xEE1A0303, + 0x81C, 0xED1C0303, + 0x81C, 0xEC1E0303, + 0x81C, 0xEB200303, + 0x81C, 0xEA220303, + 0x81C, 0xE9240303, + 0x81C, 0xE8260303, + 0x81C, 0xE7280303, + 0x81C, 0xE62A0303, + 0x81C, 0xE52C0303, + 0x81C, 0xE42E0303, + 0x81C, 0xE3300303, + 0x81C, 0xE2320303, + 0x81C, 0xE1340303, + 0x81C, 0xE0360303, + 0x81C, 0xC3380303, + 0x81C, 0xC23A0303, + 0x81C, 0xC13C0303, + 0x81C, 0xC03E0303, + 0x81C, 0xA3400303, + 0x81C, 0xA2420303, + 0x81C, 0xA1440303, + 0x81C, 0xA0460303, + 0x81C, 0x83480303, + 0x81C, 0x824A0303, + 0x81C, 0x814C0303, + 0x81C, 0x644E0303, + 0x81C, 0x63500303, + 0x81C, 0x62520303, + 0x81C, 0x61540303, + 0x81C, 0x24560303, + 0x81C, 0x23580303, + 0x81C, 0x225A0303, + 0x81C, 0x215C0303, + 0x81C, 0x055E0303, + 0x81C, 0x04600303, + 0x81C, 0x03620303, + 0x81C, 0x02640303, + 0x81C, 0x01660303, + 0x81C, 0x00680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x90000010, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000303, + 0x81C, 0xFB020303, + 0x81C, 0xFA040303, + 0x81C, 0xF9060303, + 0x81C, 0xF8080303, + 0x81C, 0xF70A0303, + 0x81C, 0xF60C0303, + 0x81C, 0xF50E0303, + 0x81C, 0xF4100303, + 0x81C, 0xF3120303, + 0x81C, 0xF2140303, + 0x81C, 0xF1160303, + 0x81C, 0xF0180303, + 0x81C, 0xEF1A0303, + 0x81C, 0xEE1C0303, + 0x81C, 0xED1E0303, + 0x81C, 0xEC200303, + 0x81C, 0xEB220303, + 0x81C, 0xEA240303, + 0x81C, 0xE9260303, + 0x81C, 0xE8280303, + 0x81C, 0xE72A0303, + 0x81C, 0xE62C0303, + 0x81C, 0xE52E0303, + 0x81C, 0xE4300303, + 0x81C, 0xE3320303, + 0x81C, 0xE2340303, + 0x81C, 0xC6360303, + 0x81C, 0xC5380303, + 0x81C, 0xC43A0303, + 0x81C, 0xC33C0303, + 0x81C, 0xA63E0303, + 0x81C, 0xA5400303, + 0x81C, 0xA4420303, + 0x81C, 0xA3440303, + 0x81C, 0xA2460303, + 0x81C, 0x84480303, + 0x81C, 0x834A0303, + 0x81C, 0x824C0303, + 0x81C, 0x814E0303, + 0x81C, 0x80500303, + 0x81C, 0x63520303, + 0x81C, 0x62540303, + 0x81C, 0x61560303, + 0x81C, 0x60580303, + 0x81C, 0x225A0303, + 0x81C, 0x055C0303, + 0x81C, 0x045E0303, + 0x81C, 0x03600303, + 0x81C, 0x02620303, + 0x81C, 0x01640303, + 0x81C, 0x00660303, + 0x81C, 0x00680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0x90000012, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF7000303, + 0x81C, 0xF6020303, + 0x81C, 0xF5040303, + 0x81C, 0xF4060303, + 0x81C, 0xF3080303, + 0x81C, 0xF20A0303, + 0x81C, 0xF10C0303, + 0x81C, 0xF00E0303, + 0x81C, 0xEF100303, + 0x81C, 0xEE120303, + 0x81C, 0xED140303, + 0x81C, 0xEC160303, + 0x81C, 0xEB180303, + 0x81C, 0xEA1A0303, + 0x81C, 0xE91C0303, + 0x81C, 0xCA1E0303, + 0x81C, 0xC9200303, + 0x81C, 0xC8220303, + 0x81C, 0xC7240303, + 0x81C, 0xC6260303, + 0x81C, 0xC5280303, + 0x81C, 0xC42A0303, + 0x81C, 0xC32C0303, + 0x81C, 0xC22E0303, + 0x81C, 0xC1300303, + 0x81C, 0xA4320303, + 0x81C, 0xA3340303, + 0x81C, 0xA2360303, + 0x81C, 0xA1380303, + 0x81C, 0xA03A0303, + 0x81C, 0x823C0303, + 0x81C, 0x813E0303, + 0x81C, 0x80400303, + 0x81C, 0x64420303, + 0x81C, 0x63440303, + 0x81C, 0x62460303, + 0x81C, 0x61480303, + 0x81C, 0x604A0303, + 0x81C, 0x414C0303, + 0x81C, 0x404E0303, + 0x81C, 0x22500303, + 0x81C, 0x21520303, + 0x81C, 0x20540303, + 0x81C, 0x03560303, + 0x81C, 0x02580303, + 0x81C, 0x015A0303, + 0x81C, 0x005C0303, + 0x81C, 0x005E0303, + 0x81C, 0x00600303, + 0x81C, 0x00620303, + 0x81C, 0x00640303, + 0x81C, 0x00660303, + 0x81C, 0x00680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0xA0000000, 0x00000000, + 0x81C, 0xFC000303, + 0x81C, 0xFB020303, + 0x81C, 0xFA040303, + 0x81C, 0xF9060303, + 0x81C, 0xF8080303, + 0x81C, 0xF70A0303, + 0x81C, 0xF60C0303, + 0x81C, 0xF50E0303, + 0x81C, 0xF4100303, + 0x81C, 0xF3120303, + 0x81C, 0xF2140303, + 0x81C, 0xF1160303, + 0x81C, 0xF0180303, + 0x81C, 0xEF1A0303, + 0x81C, 0xEE1C0303, + 0x81C, 0xED1E0303, + 0x81C, 0xEC200303, + 0x81C, 0xEB220303, + 0x81C, 0xEA240303, + 0x81C, 0xE9260303, + 0x81C, 0xE8280303, + 0x81C, 0xE72A0303, + 0x81C, 0xE62C0303, + 0x81C, 0xE52E0303, + 0x81C, 0xE4300303, + 0x81C, 0xE3320303, + 0x81C, 0xE2340303, + 0x81C, 0xC6360303, + 0x81C, 0xC5380303, + 0x81C, 0xC43A0303, + 0x81C, 0xC33C0303, + 0x81C, 0xA63E0303, + 0x81C, 0xA5400303, + 0x81C, 0xA4420303, + 0x81C, 0xA3440303, + 0x81C, 0xA2460303, + 0x81C, 0x84480303, + 0x81C, 0x834A0303, + 0x81C, 0x824C0303, + 0x81C, 0x814E0303, + 0x81C, 0x80500303, + 0x81C, 0x63520303, + 0x81C, 0x62540303, + 0x81C, 0x61560303, + 0x81C, 0x60580303, + 0x81C, 0x235A0303, + 0x81C, 0x225C0303, + 0x81C, 0x215E0303, + 0x81C, 0x20600303, + 0x81C, 0x03620303, + 0x81C, 0x02640303, + 0x81C, 0x01660303, + 0x81C, 0x00680303, + 0x81C, 0x006A0303, + 0x81C, 0x006C0303, + 0x81C, 0x006E0303, + 0x81C, 0x00700303, + 0x81C, 0x00720303, + 0x81C, 0x00740303, + 0x81C, 0x00760303, + 0x81C, 0x00780303, + 0x81C, 0x007A0303, + 0x81C, 0x007C0303, + 0x81C, 0x007E0303, + 0xB0000000, 0x00000000, + 0x80000000, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xFF000403, + 0x81C, 0xFF020403, + 0x81C, 0xFE040403, + 0x81C, 0xFD060403, + 0x81C, 0xFC080403, + 0x81C, 0xFB0A0403, + 0x81C, 0xFA0C0403, + 0x81C, 0xF90E0403, + 0x81C, 0xF8100403, + 0x81C, 0xF7120403, + 0x81C, 0xF6140403, + 0x81C, 0xF5160403, + 0x81C, 0xF4180403, + 0x81C, 0xF31A0403, + 0x81C, 0xF21C0403, + 0x81C, 0xD51E0403, + 0x81C, 0xD4200403, + 0x81C, 0xD3220403, + 0x81C, 0xD2240403, + 0x81C, 0xB6260403, + 0x81C, 0xB5280403, + 0x81C, 0xB42A0403, + 0x81C, 0xB32C0403, + 0x81C, 0xB22E0403, + 0x81C, 0xB1300403, + 0x81C, 0xB0320403, + 0x81C, 0xAF340403, + 0x81C, 0xAE360403, + 0x81C, 0xAD380403, + 0x81C, 0xAC3A0403, + 0x81C, 0xAB3C0403, + 0x81C, 0xAA3E0403, + 0x81C, 0xA9400403, + 0x81C, 0xA8420403, + 0x81C, 0xA7440403, + 0x81C, 0xA6460403, + 0x81C, 0xA5480403, + 0x81C, 0xA44A0403, + 0x81C, 0xA34C0403, + 0x81C, 0x854E0403, + 0x81C, 0x84500403, + 0x81C, 0x83520403, + 0x81C, 0x82540403, + 0x81C, 0x81560403, + 0x81C, 0x80580403, + 0x81C, 0x485A0403, + 0x81C, 0x475C0403, + 0x81C, 0x465E0403, + 0x81C, 0x45600403, + 0x81C, 0x44620403, + 0x81C, 0x0A640403, + 0x81C, 0x09660403, + 0x81C, 0x08680403, + 0x81C, 0x076A0403, + 0x81C, 0x066C0403, + 0x81C, 0x056E0403, + 0x81C, 0x04700403, + 0x81C, 0x03720403, + 0x81C, 0x02740403, + 0x81C, 0x01760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xF5000403, + 0x81C, 0xF4020403, + 0x81C, 0xF3040403, + 0x81C, 0xF2060403, + 0x81C, 0xF1080403, + 0x81C, 0xF00A0403, + 0x81C, 0xEF0C0403, + 0x81C, 0xEE0E0403, + 0x81C, 0xED100403, + 0x81C, 0xEC120403, + 0x81C, 0xEB140403, + 0x81C, 0xEA160403, + 0x81C, 0xE9180403, + 0x81C, 0xE81A0403, + 0x81C, 0xE71C0403, + 0x81C, 0xE61E0403, + 0x81C, 0xE5200403, + 0x81C, 0xE4220403, + 0x81C, 0xE3240403, + 0x81C, 0xE2260403, + 0x81C, 0xE1280403, + 0x81C, 0xE02A0403, + 0x81C, 0xC32C0403, + 0x81C, 0xC22E0403, + 0x81C, 0xC1300403, + 0x81C, 0xC0320403, + 0x81C, 0xA4340403, + 0x81C, 0xA3360403, + 0x81C, 0xA2380403, + 0x81C, 0xA13A0403, + 0x81C, 0xA03C0403, + 0x81C, 0x823E0403, + 0x81C, 0x81400403, + 0x81C, 0x80420403, + 0x81C, 0x64440403, + 0x81C, 0x63460403, + 0x81C, 0x62480403, + 0x81C, 0x614A0403, + 0x81C, 0x604C0403, + 0x81C, 0x454E0403, + 0x81C, 0x44500403, + 0x81C, 0x43520403, + 0x81C, 0x42540403, + 0x81C, 0x41560403, + 0x81C, 0x40580403, + 0x81C, 0x055A0403, + 0x81C, 0x045C0403, + 0x81C, 0x035E0403, + 0x81C, 0x02600403, + 0x81C, 0x01620403, + 0x81C, 0x00640403, + 0x81C, 0x00660403, + 0x81C, 0x00680403, + 0x81C, 0x006A0403, + 0x81C, 0x006C0403, + 0x81C, 0x006E0403, + 0x81C, 0x00700403, + 0x81C, 0x00720403, + 0x81C, 0x00740403, + 0x81C, 0x00760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xFF000403, + 0x81C, 0xFF020403, + 0x81C, 0xFE040403, + 0x81C, 0xFD060403, + 0x81C, 0xFC080403, + 0x81C, 0xFB0A0403, + 0x81C, 0xFA0C0403, + 0x81C, 0xF90E0403, + 0x81C, 0xF8100403, + 0x81C, 0xF7120403, + 0x81C, 0xF6140403, + 0x81C, 0xF5160403, + 0x81C, 0xF4180403, + 0x81C, 0xF31A0403, + 0x81C, 0xF21C0403, + 0x81C, 0xD51E0403, + 0x81C, 0xD4200403, + 0x81C, 0xD3220403, + 0x81C, 0xD2240403, + 0x81C, 0xB6260403, + 0x81C, 0xB5280403, + 0x81C, 0xB42A0403, + 0x81C, 0xB32C0403, + 0x81C, 0xB22E0403, + 0x81C, 0xB1300403, + 0x81C, 0xB0320403, + 0x81C, 0xAF340403, + 0x81C, 0xAE360403, + 0x81C, 0xAD380403, + 0x81C, 0xAC3A0403, + 0x81C, 0xAB3C0403, + 0x81C, 0xAA3E0403, + 0x81C, 0xA9400403, + 0x81C, 0xA8420403, + 0x81C, 0xA7440403, + 0x81C, 0xA6460403, + 0x81C, 0xA5480403, + 0x81C, 0xA44A0403, + 0x81C, 0xA34C0403, + 0x81C, 0x854E0403, + 0x81C, 0x84500403, + 0x81C, 0x83520403, + 0x81C, 0x82540403, + 0x81C, 0x81560403, + 0x81C, 0x80580403, + 0x81C, 0x485A0403, + 0x81C, 0x475C0403, + 0x81C, 0x465E0403, + 0x81C, 0x45600403, + 0x81C, 0x44620403, + 0x81C, 0x0A640403, + 0x81C, 0x09660403, + 0x81C, 0x08680403, + 0x81C, 0x076A0403, + 0x81C, 0x066C0403, + 0x81C, 0x056E0403, + 0x81C, 0x04700403, + 0x81C, 0x03720403, + 0x81C, 0x02740403, + 0x81C, 0x01760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xFF000403, + 0x81C, 0xFF020403, + 0x81C, 0xFE040403, + 0x81C, 0xFD060403, + 0x81C, 0xFC080403, + 0x81C, 0xFB0A0403, + 0x81C, 0xFA0C0403, + 0x81C, 0xF90E0403, + 0x81C, 0xF8100403, + 0x81C, 0xF7120403, + 0x81C, 0xF6140403, + 0x81C, 0xF5160403, + 0x81C, 0xF4180403, + 0x81C, 0xF31A0403, + 0x81C, 0xF21C0403, + 0x81C, 0xD51E0403, + 0x81C, 0xD4200403, + 0x81C, 0xD3220403, + 0x81C, 0xD2240403, + 0x81C, 0xB6260403, + 0x81C, 0xB5280403, + 0x81C, 0xB42A0403, + 0x81C, 0xB32C0403, + 0x81C, 0xB22E0403, + 0x81C, 0xB1300403, + 0x81C, 0xB0320403, + 0x81C, 0xAF340403, + 0x81C, 0xAE360403, + 0x81C, 0xAD380403, + 0x81C, 0xAC3A0403, + 0x81C, 0xAB3C0403, + 0x81C, 0xAA3E0403, + 0x81C, 0xA9400403, + 0x81C, 0xA8420403, + 0x81C, 0xA7440403, + 0x81C, 0xA6460403, + 0x81C, 0xA5480403, + 0x81C, 0xA44A0403, + 0x81C, 0xA34C0403, + 0x81C, 0x854E0403, + 0x81C, 0x84500403, + 0x81C, 0x83520403, + 0x81C, 0x82540403, + 0x81C, 0x81560403, + 0x81C, 0x80580403, + 0x81C, 0x485A0403, + 0x81C, 0x475C0403, + 0x81C, 0x465E0403, + 0x81C, 0x45600403, + 0x81C, 0x44620403, + 0x81C, 0x0A640403, + 0x81C, 0x09660403, + 0x81C, 0x08680403, + 0x81C, 0x076A0403, + 0x81C, 0x066C0403, + 0x81C, 0x056E0403, + 0x81C, 0x04700403, + 0x81C, 0x03720403, + 0x81C, 0x02740403, + 0x81C, 0x01760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xF6000403, + 0x81C, 0xF5020403, + 0x81C, 0xF4040403, + 0x81C, 0xF3060403, + 0x81C, 0xF2080403, + 0x81C, 0xF10A0403, + 0x81C, 0xF00C0403, + 0x81C, 0xEF0E0403, + 0x81C, 0xD6100403, + 0x81C, 0xD5120403, + 0x81C, 0xD4140403, + 0x81C, 0xD3160403, + 0x81C, 0xD2180403, + 0x81C, 0xD11A0403, + 0x81C, 0xD01C0403, + 0x81C, 0xCF1E0403, + 0x81C, 0x95200403, + 0x81C, 0x94220403, + 0x81C, 0x93240403, + 0x81C, 0x92260403, + 0x81C, 0x91280403, + 0x81C, 0x902A0403, + 0x81C, 0x8F2C0403, + 0x81C, 0x8E2E0403, + 0x81C, 0x8D300403, + 0x81C, 0x8C320403, + 0x81C, 0x8B340403, + 0x81C, 0x8A360403, + 0x81C, 0x89380403, + 0x81C, 0x883A0403, + 0x81C, 0x873C0403, + 0x81C, 0x863E0403, + 0x81C, 0x68400403, + 0x81C, 0x67420403, + 0x81C, 0x66440403, + 0x81C, 0x65460403, + 0x81C, 0x64480403, + 0x81C, 0x634A0403, + 0x81C, 0x484C0403, + 0x81C, 0x474E0403, + 0x81C, 0x46500403, + 0x81C, 0x45520403, + 0x81C, 0x44540403, + 0x81C, 0x27560403, + 0x81C, 0x26580403, + 0x81C, 0x255A0403, + 0x81C, 0x245C0403, + 0x81C, 0x235E0403, + 0x81C, 0x04600403, + 0x81C, 0x03620403, + 0x81C, 0x02640403, + 0x81C, 0x01660403, + 0x81C, 0x00680403, + 0x81C, 0x006A0403, + 0x81C, 0x006C0403, + 0x81C, 0x006E0403, + 0x81C, 0x00700403, + 0x81C, 0x00720403, + 0x81C, 0x00740403, + 0x81C, 0x00760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xFF000403, + 0x81C, 0xFF020403, + 0x81C, 0xFE040403, + 0x81C, 0xFD060403, + 0x81C, 0xFC080403, + 0x81C, 0xFB0A0403, + 0x81C, 0xFA0C0403, + 0x81C, 0xF90E0403, + 0x81C, 0xF8100403, + 0x81C, 0xF7120403, + 0x81C, 0xF6140403, + 0x81C, 0xF5160403, + 0x81C, 0xF4180403, + 0x81C, 0xF31A0403, + 0x81C, 0xF21C0403, + 0x81C, 0xD51E0403, + 0x81C, 0xD4200403, + 0x81C, 0xD3220403, + 0x81C, 0xD2240403, + 0x81C, 0xB6260403, + 0x81C, 0xB5280403, + 0x81C, 0xB42A0403, + 0x81C, 0xB32C0403, + 0x81C, 0xB22E0403, + 0x81C, 0xB1300403, + 0x81C, 0xB0320403, + 0x81C, 0xAF340403, + 0x81C, 0xAE360403, + 0x81C, 0xAD380403, + 0x81C, 0xAC3A0403, + 0x81C, 0xAB3C0403, + 0x81C, 0xAA3E0403, + 0x81C, 0xA9400403, + 0x81C, 0xA8420403, + 0x81C, 0xA7440403, + 0x81C, 0xA6460403, + 0x81C, 0xA5480403, + 0x81C, 0xA44A0403, + 0x81C, 0xA34C0403, + 0x81C, 0x854E0403, + 0x81C, 0x84500403, + 0x81C, 0x83520403, + 0x81C, 0x82540403, + 0x81C, 0x81560403, + 0x81C, 0x80580403, + 0x81C, 0x485A0403, + 0x81C, 0x475C0403, + 0x81C, 0x465E0403, + 0x81C, 0x45600403, + 0x81C, 0x44620403, + 0x81C, 0x0A640403, + 0x81C, 0x09660403, + 0x81C, 0x08680403, + 0x81C, 0x076A0403, + 0x81C, 0x066C0403, + 0x81C, 0x056E0403, + 0x81C, 0x04700403, + 0x81C, 0x03720403, + 0x81C, 0x02740403, + 0x81C, 0x01760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xF5000403, + 0x81C, 0xF4020403, + 0x81C, 0xF3040403, + 0x81C, 0xF2060403, + 0x81C, 0xF1080403, + 0x81C, 0xF00A0403, + 0x81C, 0xEF0C0403, + 0x81C, 0xEE0E0403, + 0x81C, 0xED100403, + 0x81C, 0xEC120403, + 0x81C, 0xEB140403, + 0x81C, 0xEA160403, + 0x81C, 0xE9180403, + 0x81C, 0xE81A0403, + 0x81C, 0xE71C0403, + 0x81C, 0xE61E0403, + 0x81C, 0xE5200403, + 0x81C, 0xE4220403, + 0x81C, 0xE3240403, + 0x81C, 0xE2260403, + 0x81C, 0xE1280403, + 0x81C, 0xE02A0403, + 0x81C, 0xC32C0403, + 0x81C, 0xC22E0403, + 0x81C, 0xC1300403, + 0x81C, 0xC0320403, + 0x81C, 0xA4340403, + 0x81C, 0xA3360403, + 0x81C, 0xA2380403, + 0x81C, 0xA13A0403, + 0x81C, 0xA03C0403, + 0x81C, 0x823E0403, + 0x81C, 0x81400403, + 0x81C, 0x80420403, + 0x81C, 0x64440403, + 0x81C, 0x63460403, + 0x81C, 0x62480403, + 0x81C, 0x614A0403, + 0x81C, 0x604C0403, + 0x81C, 0x454E0403, + 0x81C, 0x44500403, + 0x81C, 0x43520403, + 0x81C, 0x42540403, + 0x81C, 0x41560403, + 0x81C, 0x40580403, + 0x81C, 0x055A0403, + 0x81C, 0x045C0403, + 0x81C, 0x035E0403, + 0x81C, 0x02600403, + 0x81C, 0x01620403, + 0x81C, 0x00640403, + 0x81C, 0x00660403, + 0x81C, 0x00680403, + 0x81C, 0x006A0403, + 0x81C, 0x006C0403, + 0x81C, 0x006E0403, + 0x81C, 0x00700403, + 0x81C, 0x00720403, + 0x81C, 0x00740403, + 0x81C, 0x00760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xF5000403, + 0x81C, 0xF4020403, + 0x81C, 0xF3040403, + 0x81C, 0xF2060403, + 0x81C, 0xF1080403, + 0x81C, 0xF00A0403, + 0x81C, 0xEF0C0403, + 0x81C, 0xEE0E0403, + 0x81C, 0xED100403, + 0x81C, 0xEC120403, + 0x81C, 0xEB140403, + 0x81C, 0xEA160403, + 0x81C, 0xE9180403, + 0x81C, 0xE81A0403, + 0x81C, 0xE71C0403, + 0x81C, 0xE61E0403, + 0x81C, 0xE5200403, + 0x81C, 0xE4220403, + 0x81C, 0xE3240403, + 0x81C, 0xE2260403, + 0x81C, 0xE1280403, + 0x81C, 0xE02A0403, + 0x81C, 0xC32C0403, + 0x81C, 0xC22E0403, + 0x81C, 0xC1300403, + 0x81C, 0xC0320403, + 0x81C, 0xA4340403, + 0x81C, 0xA3360403, + 0x81C, 0xA2380403, + 0x81C, 0xA13A0403, + 0x81C, 0xA03C0403, + 0x81C, 0x823E0403, + 0x81C, 0x81400403, + 0x81C, 0x80420403, + 0x81C, 0x64440403, + 0x81C, 0x63460403, + 0x81C, 0x62480403, + 0x81C, 0x614A0403, + 0x81C, 0x604C0403, + 0x81C, 0x454E0403, + 0x81C, 0x44500403, + 0x81C, 0x43520403, + 0x81C, 0x42540403, + 0x81C, 0x41560403, + 0x81C, 0x40580403, + 0x81C, 0x055A0403, + 0x81C, 0x045C0403, + 0x81C, 0x035E0403, + 0x81C, 0x02600403, + 0x81C, 0x01620403, + 0x81C, 0x00640403, + 0x81C, 0x00660403, + 0x81C, 0x00680403, + 0x81C, 0x006A0403, + 0x81C, 0x006C0403, + 0x81C, 0x006E0403, + 0x81C, 0x00700403, + 0x81C, 0x00720403, + 0x81C, 0x00740403, + 0x81C, 0x00760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x90000008, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xFF000403, + 0x81C, 0xFF020403, + 0x81C, 0xFE040403, + 0x81C, 0xFD060403, + 0x81C, 0xFC080403, + 0x81C, 0xFB0A0403, + 0x81C, 0xFA0C0403, + 0x81C, 0xF90E0403, + 0x81C, 0xF8100403, + 0x81C, 0xF7120403, + 0x81C, 0xF6140403, + 0x81C, 0xF5160403, + 0x81C, 0xF4180403, + 0x81C, 0xF31A0403, + 0x81C, 0xF21C0403, + 0x81C, 0xD51E0403, + 0x81C, 0xD4200403, + 0x81C, 0xD3220403, + 0x81C, 0xD2240403, + 0x81C, 0xB6260403, + 0x81C, 0xB5280403, + 0x81C, 0xB42A0403, + 0x81C, 0xB32C0403, + 0x81C, 0xB22E0403, + 0x81C, 0xB1300403, + 0x81C, 0xB0320403, + 0x81C, 0xAF340403, + 0x81C, 0xAE360403, + 0x81C, 0xAD380403, + 0x81C, 0xAC3A0403, + 0x81C, 0xAB3C0403, + 0x81C, 0xAA3E0403, + 0x81C, 0xA9400403, + 0x81C, 0xA8420403, + 0x81C, 0xA7440403, + 0x81C, 0xA6460403, + 0x81C, 0xA5480403, + 0x81C, 0xA44A0403, + 0x81C, 0xA34C0403, + 0x81C, 0x854E0403, + 0x81C, 0x84500403, + 0x81C, 0x83520403, + 0x81C, 0x82540403, + 0x81C, 0x81560403, + 0x81C, 0x80580403, + 0x81C, 0x485A0403, + 0x81C, 0x475C0403, + 0x81C, 0x465E0403, + 0x81C, 0x45600403, + 0x81C, 0x44620403, + 0x81C, 0x0A640403, + 0x81C, 0x09660403, + 0x81C, 0x08680403, + 0x81C, 0x076A0403, + 0x81C, 0x066C0403, + 0x81C, 0x056E0403, + 0x81C, 0x04700403, + 0x81C, 0x03720403, + 0x81C, 0x02740403, + 0x81C, 0x01760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x90000009, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xF5000403, + 0x81C, 0xF4020403, + 0x81C, 0xF3040403, + 0x81C, 0xF2060403, + 0x81C, 0xF1080403, + 0x81C, 0xF00A0403, + 0x81C, 0xEF0C0403, + 0x81C, 0xEE0E0403, + 0x81C, 0xED100403, + 0x81C, 0xEC120403, + 0x81C, 0xEB140403, + 0x81C, 0xEA160403, + 0x81C, 0xE9180403, + 0x81C, 0xE81A0403, + 0x81C, 0xE71C0403, + 0x81C, 0xE61E0403, + 0x81C, 0xE5200403, + 0x81C, 0xE4220403, + 0x81C, 0xE3240403, + 0x81C, 0xE2260403, + 0x81C, 0xE1280403, + 0x81C, 0xE02A0403, + 0x81C, 0xC32C0403, + 0x81C, 0xC22E0403, + 0x81C, 0xC1300403, + 0x81C, 0xC0320403, + 0x81C, 0xA4340403, + 0x81C, 0xA3360403, + 0x81C, 0xA2380403, + 0x81C, 0xA13A0403, + 0x81C, 0xA03C0403, + 0x81C, 0x823E0403, + 0x81C, 0x81400403, + 0x81C, 0x80420403, + 0x81C, 0x64440403, + 0x81C, 0x63460403, + 0x81C, 0x62480403, + 0x81C, 0x614A0403, + 0x81C, 0x604C0403, + 0x81C, 0x454E0403, + 0x81C, 0x44500403, + 0x81C, 0x43520403, + 0x81C, 0x42540403, + 0x81C, 0x41560403, + 0x81C, 0x40580403, + 0x81C, 0x055A0403, + 0x81C, 0x045C0403, + 0x81C, 0x035E0403, + 0x81C, 0x02600403, + 0x81C, 0x01620403, + 0x81C, 0x00640403, + 0x81C, 0x00660403, + 0x81C, 0x00680403, + 0x81C, 0x006A0403, + 0x81C, 0x006C0403, + 0x81C, 0x006E0403, + 0x81C, 0x00700403, + 0x81C, 0x00720403, + 0x81C, 0x00740403, + 0x81C, 0x00760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x9000000a, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xFF000403, + 0x81C, 0xFF020403, + 0x81C, 0xFE040403, + 0x81C, 0xFD060403, + 0x81C, 0xFC080403, + 0x81C, 0xFB0A0403, + 0x81C, 0xFA0C0403, + 0x81C, 0xF90E0403, + 0x81C, 0xF8100403, + 0x81C, 0xF7120403, + 0x81C, 0xF6140403, + 0x81C, 0xF5160403, + 0x81C, 0xF4180403, + 0x81C, 0xF31A0403, + 0x81C, 0xF21C0403, + 0x81C, 0xD51E0403, + 0x81C, 0xD4200403, + 0x81C, 0xD3220403, + 0x81C, 0xD2240403, + 0x81C, 0xB6260403, + 0x81C, 0xB5280403, + 0x81C, 0xB42A0403, + 0x81C, 0xB32C0403, + 0x81C, 0xB22E0403, + 0x81C, 0xB1300403, + 0x81C, 0xB0320403, + 0x81C, 0xAF340403, + 0x81C, 0xAE360403, + 0x81C, 0xAD380403, + 0x81C, 0xAC3A0403, + 0x81C, 0xAB3C0403, + 0x81C, 0xAA3E0403, + 0x81C, 0xA9400403, + 0x81C, 0xA8420403, + 0x81C, 0xA7440403, + 0x81C, 0xA6460403, + 0x81C, 0xA5480403, + 0x81C, 0xA44A0403, + 0x81C, 0xA34C0403, + 0x81C, 0x854E0403, + 0x81C, 0x84500403, + 0x81C, 0x83520403, + 0x81C, 0x82540403, + 0x81C, 0x81560403, + 0x81C, 0x80580403, + 0x81C, 0x485A0403, + 0x81C, 0x475C0403, + 0x81C, 0x465E0403, + 0x81C, 0x45600403, + 0x81C, 0x44620403, + 0x81C, 0x0A640403, + 0x81C, 0x09660403, + 0x81C, 0x08680403, + 0x81C, 0x076A0403, + 0x81C, 0x066C0403, + 0x81C, 0x056E0403, + 0x81C, 0x04700403, + 0x81C, 0x03720403, + 0x81C, 0x02740403, + 0x81C, 0x01760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x9000000b, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xF5000403, + 0x81C, 0xF4020403, + 0x81C, 0xF3040403, + 0x81C, 0xF2060403, + 0x81C, 0xF1080403, + 0x81C, 0xF00A0403, + 0x81C, 0xEF0C0403, + 0x81C, 0xEE0E0403, + 0x81C, 0xED100403, + 0x81C, 0xEC120403, + 0x81C, 0xEB140403, + 0x81C, 0xEA160403, + 0x81C, 0xE9180403, + 0x81C, 0xE81A0403, + 0x81C, 0xE71C0403, + 0x81C, 0xE61E0403, + 0x81C, 0xE5200403, + 0x81C, 0xE4220403, + 0x81C, 0xE3240403, + 0x81C, 0xE2260403, + 0x81C, 0xE1280403, + 0x81C, 0xE02A0403, + 0x81C, 0xC32C0403, + 0x81C, 0xC22E0403, + 0x81C, 0xC1300403, + 0x81C, 0xC0320403, + 0x81C, 0xA4340403, + 0x81C, 0xA3360403, + 0x81C, 0xA2380403, + 0x81C, 0xA13A0403, + 0x81C, 0xA03C0403, + 0x81C, 0x823E0403, + 0x81C, 0x81400403, + 0x81C, 0x80420403, + 0x81C, 0x64440403, + 0x81C, 0x63460403, + 0x81C, 0x62480403, + 0x81C, 0x614A0403, + 0x81C, 0x604C0403, + 0x81C, 0x454E0403, + 0x81C, 0x44500403, + 0x81C, 0x43520403, + 0x81C, 0x42540403, + 0x81C, 0x41560403, + 0x81C, 0x40580403, + 0x81C, 0x055A0403, + 0x81C, 0x045C0403, + 0x81C, 0x035E0403, + 0x81C, 0x02600403, + 0x81C, 0x01620403, + 0x81C, 0x00640403, + 0x81C, 0x00660403, + 0x81C, 0x00680403, + 0x81C, 0x006A0403, + 0x81C, 0x006C0403, + 0x81C, 0x006E0403, + 0x81C, 0x00700403, + 0x81C, 0x00720403, + 0x81C, 0x00740403, + 0x81C, 0x00760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x9000000c, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xFF000403, + 0x81C, 0xFF020403, + 0x81C, 0xFE040403, + 0x81C, 0xFD060403, + 0x81C, 0xFC080403, + 0x81C, 0xFB0A0403, + 0x81C, 0xFA0C0403, + 0x81C, 0xF90E0403, + 0x81C, 0xF8100403, + 0x81C, 0xF7120403, + 0x81C, 0xF6140403, + 0x81C, 0xF5160403, + 0x81C, 0xF4180403, + 0x81C, 0xF31A0403, + 0x81C, 0xF21C0403, + 0x81C, 0xD51E0403, + 0x81C, 0xD4200403, + 0x81C, 0xD3220403, + 0x81C, 0xD2240403, + 0x81C, 0xB6260403, + 0x81C, 0xB5280403, + 0x81C, 0xB42A0403, + 0x81C, 0xB32C0403, + 0x81C, 0xB22E0403, + 0x81C, 0xB1300403, + 0x81C, 0xB0320403, + 0x81C, 0xAF340403, + 0x81C, 0xAE360403, + 0x81C, 0xAD380403, + 0x81C, 0xAC3A0403, + 0x81C, 0xAB3C0403, + 0x81C, 0xAA3E0403, + 0x81C, 0xA9400403, + 0x81C, 0xA8420403, + 0x81C, 0xA7440403, + 0x81C, 0xA6460403, + 0x81C, 0xA5480403, + 0x81C, 0xA44A0403, + 0x81C, 0xA34C0403, + 0x81C, 0x854E0403, + 0x81C, 0x84500403, + 0x81C, 0x83520403, + 0x81C, 0x82540403, + 0x81C, 0x81560403, + 0x81C, 0x80580403, + 0x81C, 0x485A0403, + 0x81C, 0x475C0403, + 0x81C, 0x465E0403, + 0x81C, 0x45600403, + 0x81C, 0x44620403, + 0x81C, 0x0A640403, + 0x81C, 0x09660403, + 0x81C, 0x08680403, + 0x81C, 0x076A0403, + 0x81C, 0x066C0403, + 0x81C, 0x056E0403, + 0x81C, 0x04700403, + 0x81C, 0x03720403, + 0x81C, 0x02740403, + 0x81C, 0x01760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x9000000d, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xFF000403, + 0x81C, 0xFF020403, + 0x81C, 0xFE040403, + 0x81C, 0xFD060403, + 0x81C, 0xFC080403, + 0x81C, 0xFB0A0403, + 0x81C, 0xFA0C0403, + 0x81C, 0xF90E0403, + 0x81C, 0xF8100403, + 0x81C, 0xF7120403, + 0x81C, 0xF6140403, + 0x81C, 0xF5160403, + 0x81C, 0xF4180403, + 0x81C, 0xF31A0403, + 0x81C, 0xF21C0403, + 0x81C, 0xD51E0403, + 0x81C, 0xD4200403, + 0x81C, 0xD3220403, + 0x81C, 0xD2240403, + 0x81C, 0xB6260403, + 0x81C, 0xB5280403, + 0x81C, 0xB42A0403, + 0x81C, 0xB32C0403, + 0x81C, 0xB22E0403, + 0x81C, 0xB1300403, + 0x81C, 0xB0320403, + 0x81C, 0xAF340403, + 0x81C, 0xAE360403, + 0x81C, 0xAD380403, + 0x81C, 0xAC3A0403, + 0x81C, 0xAB3C0403, + 0x81C, 0xAA3E0403, + 0x81C, 0xA9400403, + 0x81C, 0xA8420403, + 0x81C, 0xA7440403, + 0x81C, 0xA6460403, + 0x81C, 0xA5480403, + 0x81C, 0xA44A0403, + 0x81C, 0xA34C0403, + 0x81C, 0x854E0403, + 0x81C, 0x84500403, + 0x81C, 0x83520403, + 0x81C, 0x82540403, + 0x81C, 0x81560403, + 0x81C, 0x80580403, + 0x81C, 0x485A0403, + 0x81C, 0x475C0403, + 0x81C, 0x465E0403, + 0x81C, 0x45600403, + 0x81C, 0x44620403, + 0x81C, 0x0A640403, + 0x81C, 0x09660403, + 0x81C, 0x08680403, + 0x81C, 0x076A0403, + 0x81C, 0x066C0403, + 0x81C, 0x056E0403, + 0x81C, 0x04700403, + 0x81C, 0x03720403, + 0x81C, 0x02740403, + 0x81C, 0x01760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x9000000e, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xFF000403, + 0x81C, 0xFF020403, + 0x81C, 0xFE040403, + 0x81C, 0xFD060403, + 0x81C, 0xFC080403, + 0x81C, 0xFB0A0403, + 0x81C, 0xFA0C0403, + 0x81C, 0xF90E0403, + 0x81C, 0xF8100403, + 0x81C, 0xF7120403, + 0x81C, 0xF6140403, + 0x81C, 0xF5160403, + 0x81C, 0xF4180403, + 0x81C, 0xF31A0403, + 0x81C, 0xF21C0403, + 0x81C, 0xD51E0403, + 0x81C, 0xD4200403, + 0x81C, 0xD3220403, + 0x81C, 0xD2240403, + 0x81C, 0xB6260403, + 0x81C, 0xB5280403, + 0x81C, 0xB42A0403, + 0x81C, 0xB32C0403, + 0x81C, 0xB22E0403, + 0x81C, 0xB1300403, + 0x81C, 0xB0320403, + 0x81C, 0xAF340403, + 0x81C, 0xAE360403, + 0x81C, 0xAD380403, + 0x81C, 0xAC3A0403, + 0x81C, 0xAB3C0403, + 0x81C, 0xAA3E0403, + 0x81C, 0xA9400403, + 0x81C, 0xA8420403, + 0x81C, 0xA7440403, + 0x81C, 0xA6460403, + 0x81C, 0xA5480403, + 0x81C, 0xA44A0403, + 0x81C, 0xA34C0403, + 0x81C, 0x854E0403, + 0x81C, 0x84500403, + 0x81C, 0x83520403, + 0x81C, 0x82540403, + 0x81C, 0x81560403, + 0x81C, 0x80580403, + 0x81C, 0x485A0403, + 0x81C, 0x475C0403, + 0x81C, 0x465E0403, + 0x81C, 0x45600403, + 0x81C, 0x44620403, + 0x81C, 0x0A640403, + 0x81C, 0x09660403, + 0x81C, 0x08680403, + 0x81C, 0x076A0403, + 0x81C, 0x066C0403, + 0x81C, 0x056E0403, + 0x81C, 0x04700403, + 0x81C, 0x03720403, + 0x81C, 0x02740403, + 0x81C, 0x01760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x9000000f, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xFF000403, + 0x81C, 0xFF020403, + 0x81C, 0xFE040403, + 0x81C, 0xFD060403, + 0x81C, 0xFC080403, + 0x81C, 0xFB0A0403, + 0x81C, 0xFA0C0403, + 0x81C, 0xF90E0403, + 0x81C, 0xF8100403, + 0x81C, 0xF7120403, + 0x81C, 0xF6140403, + 0x81C, 0xF5160403, + 0x81C, 0xF4180403, + 0x81C, 0xF31A0403, + 0x81C, 0xF21C0403, + 0x81C, 0xD51E0403, + 0x81C, 0xD4200403, + 0x81C, 0xD3220403, + 0x81C, 0xD2240403, + 0x81C, 0xB6260403, + 0x81C, 0xB5280403, + 0x81C, 0xB42A0403, + 0x81C, 0xB32C0403, + 0x81C, 0xB22E0403, + 0x81C, 0xB1300403, + 0x81C, 0xB0320403, + 0x81C, 0xAF340403, + 0x81C, 0xAE360403, + 0x81C, 0xAD380403, + 0x81C, 0xAC3A0403, + 0x81C, 0xAB3C0403, + 0x81C, 0xAA3E0403, + 0x81C, 0xA9400403, + 0x81C, 0xA8420403, + 0x81C, 0xA7440403, + 0x81C, 0xA6460403, + 0x81C, 0xA5480403, + 0x81C, 0xA44A0403, + 0x81C, 0xA34C0403, + 0x81C, 0x854E0403, + 0x81C, 0x84500403, + 0x81C, 0x83520403, + 0x81C, 0x82540403, + 0x81C, 0x81560403, + 0x81C, 0x80580403, + 0x81C, 0x485A0403, + 0x81C, 0x475C0403, + 0x81C, 0x465E0403, + 0x81C, 0x45600403, + 0x81C, 0x44620403, + 0x81C, 0x0A640403, + 0x81C, 0x09660403, + 0x81C, 0x08680403, + 0x81C, 0x076A0403, + 0x81C, 0x066C0403, + 0x81C, 0x056E0403, + 0x81C, 0x04700403, + 0x81C, 0x03720403, + 0x81C, 0x02740403, + 0x81C, 0x01760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x90000010, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xFF000403, + 0x81C, 0xFF020403, + 0x81C, 0xFE040403, + 0x81C, 0xFD060403, + 0x81C, 0xFC080403, + 0x81C, 0xFB0A0403, + 0x81C, 0xFA0C0403, + 0x81C, 0xF90E0403, + 0x81C, 0xF8100403, + 0x81C, 0xF7120403, + 0x81C, 0xF6140403, + 0x81C, 0xF5160403, + 0x81C, 0xF4180403, + 0x81C, 0xF31A0403, + 0x81C, 0xF21C0403, + 0x81C, 0xD51E0403, + 0x81C, 0xD4200403, + 0x81C, 0xD3220403, + 0x81C, 0xD2240403, + 0x81C, 0xB6260403, + 0x81C, 0xB5280403, + 0x81C, 0xB42A0403, + 0x81C, 0xB32C0403, + 0x81C, 0xB22E0403, + 0x81C, 0xB1300403, + 0x81C, 0xB0320403, + 0x81C, 0xAF340403, + 0x81C, 0xAE360403, + 0x81C, 0xAD380403, + 0x81C, 0xAC3A0403, + 0x81C, 0xAB3C0403, + 0x81C, 0xAA3E0403, + 0x81C, 0xA9400403, + 0x81C, 0xA8420403, + 0x81C, 0xA7440403, + 0x81C, 0xA6460403, + 0x81C, 0xA5480403, + 0x81C, 0xA44A0403, + 0x81C, 0xA34C0403, + 0x81C, 0x854E0403, + 0x81C, 0x84500403, + 0x81C, 0x83520403, + 0x81C, 0x82540403, + 0x81C, 0x81560403, + 0x81C, 0x80580403, + 0x81C, 0x485A0403, + 0x81C, 0x475C0403, + 0x81C, 0x465E0403, + 0x81C, 0x45600403, + 0x81C, 0x44620403, + 0x81C, 0x0A640403, + 0x81C, 0x09660403, + 0x81C, 0x08680403, + 0x81C, 0x076A0403, + 0x81C, 0x066C0403, + 0x81C, 0x056E0403, + 0x81C, 0x04700403, + 0x81C, 0x03720403, + 0x81C, 0x02740403, + 0x81C, 0x01760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0x90000012, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xF6000403, + 0x81C, 0xF5020403, + 0x81C, 0xF4040403, + 0x81C, 0xF3060403, + 0x81C, 0xF2080403, + 0x81C, 0xF10A0403, + 0x81C, 0xF00C0403, + 0x81C, 0xEF0E0403, + 0x81C, 0xD6100403, + 0x81C, 0xD5120403, + 0x81C, 0xD4140403, + 0x81C, 0xD3160403, + 0x81C, 0xD2180403, + 0x81C, 0xD11A0403, + 0x81C, 0xD01C0403, + 0x81C, 0xCF1E0403, + 0x81C, 0x95200403, + 0x81C, 0x94220403, + 0x81C, 0x93240403, + 0x81C, 0x92260403, + 0x81C, 0x91280403, + 0x81C, 0x902A0403, + 0x81C, 0x8F2C0403, + 0x81C, 0x8E2E0403, + 0x81C, 0x8D300403, + 0x81C, 0x8C320403, + 0x81C, 0x8B340403, + 0x81C, 0x8A360403, + 0x81C, 0x89380403, + 0x81C, 0x883A0403, + 0x81C, 0x873C0403, + 0x81C, 0x863E0403, + 0x81C, 0x68400403, + 0x81C, 0x67420403, + 0x81C, 0x66440403, + 0x81C, 0x65460403, + 0x81C, 0x64480403, + 0x81C, 0x634A0403, + 0x81C, 0x484C0403, + 0x81C, 0x474E0403, + 0x81C, 0x46500403, + 0x81C, 0x45520403, + 0x81C, 0x44540403, + 0x81C, 0x27560403, + 0x81C, 0x26580403, + 0x81C, 0x255A0403, + 0x81C, 0x245C0403, + 0x81C, 0x235E0403, + 0x81C, 0x04600403, + 0x81C, 0x03620403, + 0x81C, 0x02640403, + 0x81C, 0x01660403, + 0x81C, 0x00680403, + 0x81C, 0x006A0403, + 0x81C, 0x006C0403, + 0x81C, 0x006E0403, + 0x81C, 0x00700403, + 0x81C, 0x00720403, + 0x81C, 0x00740403, + 0x81C, 0x00760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0xA0000000, 0x00000000, + 0x81C, 0xFF000403, + 0x81C, 0xFF000403, + 0x81C, 0xFF020403, + 0x81C, 0xFE040403, + 0x81C, 0xFD060403, + 0x81C, 0xFC080403, + 0x81C, 0xFB0A0403, + 0x81C, 0xFA0C0403, + 0x81C, 0xF90E0403, + 0x81C, 0xF8100403, + 0x81C, 0xF7120403, + 0x81C, 0xF6140403, + 0x81C, 0xF5160403, + 0x81C, 0xF4180403, + 0x81C, 0xF31A0403, + 0x81C, 0xF21C0403, + 0x81C, 0xD51E0403, + 0x81C, 0xD4200403, + 0x81C, 0xD3220403, + 0x81C, 0xD2240403, + 0x81C, 0xB6260403, + 0x81C, 0xB5280403, + 0x81C, 0xB42A0403, + 0x81C, 0xB32C0403, + 0x81C, 0xB22E0403, + 0x81C, 0xB1300403, + 0x81C, 0xB0320403, + 0x81C, 0xAF340403, + 0x81C, 0xAE360403, + 0x81C, 0xAD380403, + 0x81C, 0xAC3A0403, + 0x81C, 0xAB3C0403, + 0x81C, 0xAA3E0403, + 0x81C, 0xA9400403, + 0x81C, 0xA8420403, + 0x81C, 0xA7440403, + 0x81C, 0xA6460403, + 0x81C, 0xA5480403, + 0x81C, 0xA44A0403, + 0x81C, 0xA34C0403, + 0x81C, 0x854E0403, + 0x81C, 0x84500403, + 0x81C, 0x83520403, + 0x81C, 0x82540403, + 0x81C, 0x81560403, + 0x81C, 0x80580403, + 0x81C, 0x485A0403, + 0x81C, 0x475C0403, + 0x81C, 0x465E0403, + 0x81C, 0x45600403, + 0x81C, 0x44620403, + 0x81C, 0x0A640403, + 0x81C, 0x09660403, + 0x81C, 0x08680403, + 0x81C, 0x076A0403, + 0x81C, 0x066C0403, + 0x81C, 0x056E0403, + 0x81C, 0x04700403, + 0x81C, 0x03720403, + 0x81C, 0x02740403, + 0x81C, 0x01760403, + 0x81C, 0x00780403, + 0x81C, 0x007A0403, + 0x81C, 0x007C0403, + 0x81C, 0x007E0403, + 0xB0000000, 0x00000000, + 0x80000000, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFD000503, + 0x81C, 0xFC020503, + 0x81C, 0xFB040503, + 0x81C, 0xFA060503, + 0x81C, 0xF9080503, + 0x81C, 0xF80A0503, + 0x81C, 0xF70C0503, + 0x81C, 0xF60E0503, + 0x81C, 0xF5100503, + 0x81C, 0xF4120503, + 0x81C, 0xF3140503, + 0x81C, 0xF2160503, + 0x81C, 0xF1180503, + 0x81C, 0xF01A0503, + 0x81C, 0xEE1C0503, + 0x81C, 0xED1E0503, + 0x81C, 0xEC200503, + 0x81C, 0xEB220503, + 0x81C, 0xEA240503, + 0x81C, 0xE9260503, + 0x81C, 0xE8280503, + 0x81C, 0xE72A0503, + 0x81C, 0xE62C0503, + 0x81C, 0xE52E0503, + 0x81C, 0xE4300503, + 0x81C, 0xE3320503, + 0x81C, 0xE2340503, + 0x81C, 0xC5360503, + 0x81C, 0xC4380503, + 0x81C, 0xC33A0503, + 0x81C, 0xC23C0503, + 0x81C, 0xA53E0503, + 0x81C, 0xA4400503, + 0x81C, 0xA3420503, + 0x81C, 0xA2440503, + 0x81C, 0xA1460503, + 0x81C, 0x83480503, + 0x81C, 0x824A0503, + 0x81C, 0x814C0503, + 0x81C, 0x804E0503, + 0x81C, 0x63500503, + 0x81C, 0x62520503, + 0x81C, 0x61540503, + 0x81C, 0x43560503, + 0x81C, 0x42580503, + 0x81C, 0x415A0503, + 0x81C, 0x405C0503, + 0x81C, 0x225E0503, + 0x81C, 0x21600503, + 0x81C, 0x20620503, + 0x81C, 0x03640503, + 0x81C, 0x02660503, + 0x81C, 0x01680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xBE000503, + 0x81C, 0xBD020503, + 0x81C, 0xBC040503, + 0x81C, 0xBB060503, + 0x81C, 0xBA080503, + 0x81C, 0xB90A0503, + 0x81C, 0xB80C0503, + 0x81C, 0xB70E0503, + 0x81C, 0xB6100503, + 0x81C, 0xB5120503, + 0x81C, 0xB4140503, + 0x81C, 0xB3160503, + 0x81C, 0xB2180503, + 0x81C, 0xB11A0503, + 0x81C, 0xB01C0503, + 0x81C, 0xAF1E0503, + 0x81C, 0xAE200503, + 0x81C, 0xAD220503, + 0x81C, 0xAC240503, + 0x81C, 0xAB260503, + 0x81C, 0x8D280503, + 0x81C, 0x8C2A0503, + 0x81C, 0x8B2C0503, + 0x81C, 0x8A2E0503, + 0x81C, 0x89300503, + 0x81C, 0x88320503, + 0x81C, 0x6A340503, + 0x81C, 0x69360503, + 0x81C, 0x68380503, + 0x81C, 0x673A0503, + 0x81C, 0x663C0503, + 0x81C, 0x653E0503, + 0x81C, 0x64400503, + 0x81C, 0x63420503, + 0x81C, 0x62440503, + 0x81C, 0x61460503, + 0x81C, 0x60480503, + 0x81C, 0x424A0503, + 0x81C, 0x414C0503, + 0x81C, 0x404E0503, + 0x81C, 0x06500503, + 0x81C, 0x05520503, + 0x81C, 0x04540503, + 0x81C, 0x03560503, + 0x81C, 0x02580503, + 0x81C, 0x015A0503, + 0x81C, 0x005C0503, + 0x81C, 0x005E0503, + 0x81C, 0x00600503, + 0x81C, 0x00620503, + 0x81C, 0x00640503, + 0x81C, 0x00660503, + 0x81C, 0x00680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007C0503, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000503, + 0x81C, 0xF7020503, + 0x81C, 0xF6040503, + 0x81C, 0xF5060503, + 0x81C, 0xF4080503, + 0x81C, 0xF30A0503, + 0x81C, 0xF20C0503, + 0x81C, 0xF10E0503, + 0x81C, 0xF0100503, + 0x81C, 0xEF120503, + 0x81C, 0xEE140503, + 0x81C, 0xED160503, + 0x81C, 0xEC180503, + 0x81C, 0xEB1A0503, + 0x81C, 0xEA1C0503, + 0x81C, 0xE91E0503, + 0x81C, 0xE8200503, + 0x81C, 0xE7220503, + 0x81C, 0xE6240503, + 0x81C, 0xE5260503, + 0x81C, 0xE4280503, + 0x81C, 0xE32A0503, + 0x81C, 0xC32C0503, + 0x81C, 0xC22E0503, + 0x81C, 0xC1300503, + 0x81C, 0xC0320503, + 0x81C, 0xA3340503, + 0x81C, 0xA2360503, + 0x81C, 0xA1380503, + 0x81C, 0xA03A0503, + 0x81C, 0x823C0503, + 0x81C, 0x813E0503, + 0x81C, 0x80400503, + 0x81C, 0x63420503, + 0x81C, 0x62440503, + 0x81C, 0x61460503, + 0x81C, 0x60480503, + 0x81C, 0x424A0503, + 0x81C, 0x414C0503, + 0x81C, 0x404E0503, + 0x81C, 0x22500503, + 0x81C, 0x21520503, + 0x81C, 0x20540503, + 0x81C, 0x03560503, + 0x81C, 0x02580503, + 0x81C, 0x015A0503, + 0x81C, 0x005C0503, + 0x81C, 0x005E0503, + 0x81C, 0x00600503, + 0x81C, 0x00620503, + 0x81C, 0x00640503, + 0x81C, 0x00660503, + 0x81C, 0x00680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFE000503, + 0x81C, 0xFD020503, + 0x81C, 0xFC040503, + 0x81C, 0xFB060503, + 0x81C, 0xFA080503, + 0x81C, 0xF90A0503, + 0x81C, 0xF80C0503, + 0x81C, 0xF70E0503, + 0x81C, 0xF6100503, + 0x81C, 0xF5120503, + 0x81C, 0xF4140503, + 0x81C, 0xF3160503, + 0x81C, 0xF2180503, + 0x81C, 0xF11A0503, + 0x81C, 0xF01C0503, + 0x81C, 0xEF1E0503, + 0x81C, 0xEE200503, + 0x81C, 0xED220503, + 0x81C, 0xEC240503, + 0x81C, 0xEB260503, + 0x81C, 0xEA280503, + 0x81C, 0xE92A0503, + 0x81C, 0xE82C0503, + 0x81C, 0xE72E0503, + 0x81C, 0xE6300503, + 0x81C, 0xE5320503, + 0x81C, 0xE4340503, + 0x81C, 0xE3360503, + 0x81C, 0xC6380503, + 0x81C, 0xC53A0503, + 0x81C, 0xC43C0503, + 0x81C, 0xC33E0503, + 0x81C, 0xA5400503, + 0x81C, 0xA4420503, + 0x81C, 0xA3440503, + 0x81C, 0xA2460503, + 0x81C, 0xA1480503, + 0x81C, 0xA04A0503, + 0x81C, 0x824C0503, + 0x81C, 0x814E0503, + 0x81C, 0x80500503, + 0x81C, 0x64520503, + 0x81C, 0x63540503, + 0x81C, 0x62560503, + 0x81C, 0x61580503, + 0x81C, 0x605A0503, + 0x81C, 0x235C0503, + 0x81C, 0x225E0503, + 0x81C, 0x21600503, + 0x81C, 0x20620503, + 0x81C, 0x03640503, + 0x81C, 0x02660503, + 0x81C, 0x01680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000503, + 0x81C, 0xF7020503, + 0x81C, 0xF6040503, + 0x81C, 0xF5060503, + 0x81C, 0xF4080503, + 0x81C, 0xF30A0503, + 0x81C, 0xF20C0503, + 0x81C, 0xF10E0503, + 0x81C, 0xF0100503, + 0x81C, 0xEF120503, + 0x81C, 0xEE140503, + 0x81C, 0xED160503, + 0x81C, 0xEC180503, + 0x81C, 0xEB1A0503, + 0x81C, 0xEA1C0503, + 0x81C, 0xE91E0503, + 0x81C, 0xE8200503, + 0x81C, 0xE7220503, + 0x81C, 0xE6240503, + 0x81C, 0xE5260503, + 0x81C, 0xE4280503, + 0x81C, 0xE32A0503, + 0x81C, 0xC32C0503, + 0x81C, 0xC22E0503, + 0x81C, 0xC1300503, + 0x81C, 0xC0320503, + 0x81C, 0xA3340503, + 0x81C, 0xA2360503, + 0x81C, 0xA1380503, + 0x81C, 0xA03A0503, + 0x81C, 0x823C0503, + 0x81C, 0x813E0503, + 0x81C, 0x80400503, + 0x81C, 0x63420503, + 0x81C, 0x62440503, + 0x81C, 0x61460503, + 0x81C, 0x60480503, + 0x81C, 0x424A0503, + 0x81C, 0x414C0503, + 0x81C, 0x404E0503, + 0x81C, 0x22500503, + 0x81C, 0x21520503, + 0x81C, 0x20540503, + 0x81C, 0x03560503, + 0x81C, 0x02580503, + 0x81C, 0x015A0503, + 0x81C, 0x005C0503, + 0x81C, 0x005E0503, + 0x81C, 0x00600503, + 0x81C, 0x00620503, + 0x81C, 0x00640503, + 0x81C, 0x00660503, + 0x81C, 0x00680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFD000503, + 0x81C, 0xFC020503, + 0x81C, 0xFB040503, + 0x81C, 0xFA060503, + 0x81C, 0xF9080503, + 0x81C, 0xF80A0503, + 0x81C, 0xF70C0503, + 0x81C, 0xF60E0503, + 0x81C, 0xF5100503, + 0x81C, 0xF4120503, + 0x81C, 0xF3140503, + 0x81C, 0xF2160503, + 0x81C, 0xF1180503, + 0x81C, 0xF01A0503, + 0x81C, 0xEF1C0503, + 0x81C, 0xEE1E0503, + 0x81C, 0xED200503, + 0x81C, 0xEC220503, + 0x81C, 0xEB240503, + 0x81C, 0xEA260503, + 0x81C, 0xE9280503, + 0x81C, 0xE82A0503, + 0x81C, 0xE72C0503, + 0x81C, 0xE62E0503, + 0x81C, 0xE5300503, + 0x81C, 0xE4320503, + 0x81C, 0xE3340503, + 0x81C, 0xE2360503, + 0x81C, 0xC5380503, + 0x81C, 0xC43A0503, + 0x81C, 0xC33C0503, + 0x81C, 0xC23E0503, + 0x81C, 0xA5400503, + 0x81C, 0xA4420503, + 0x81C, 0xA3440503, + 0x81C, 0xA2460503, + 0x81C, 0xA1480503, + 0x81C, 0x834A0503, + 0x81C, 0x824C0503, + 0x81C, 0x814E0503, + 0x81C, 0x64500503, + 0x81C, 0x63520503, + 0x81C, 0x62540503, + 0x81C, 0x61560503, + 0x81C, 0x42580503, + 0x81C, 0x415A0503, + 0x81C, 0x405C0503, + 0x81C, 0x065E0503, + 0x81C, 0x05600503, + 0x81C, 0x04620503, + 0x81C, 0x03640503, + 0x81C, 0x02660503, + 0x81C, 0x01680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFA000503, + 0x81C, 0xF9020503, + 0x81C, 0xF8040503, + 0x81C, 0xF7060503, + 0x81C, 0xF6080503, + 0x81C, 0xF50A0503, + 0x81C, 0xF40C0503, + 0x81C, 0xF30E0503, + 0x81C, 0xF2100503, + 0x81C, 0xF1120503, + 0x81C, 0xF0140503, + 0x81C, 0xEF160503, + 0x81C, 0xEE180503, + 0x81C, 0xED1A0503, + 0x81C, 0xEC1C0503, + 0x81C, 0xEB1E0503, + 0x81C, 0xEA200503, + 0x81C, 0xE9220503, + 0x81C, 0xE8240503, + 0x81C, 0xE7260503, + 0x81C, 0xE6280503, + 0x81C, 0xE52A0503, + 0x81C, 0xC42C0503, + 0x81C, 0xC32E0503, + 0x81C, 0xC2300503, + 0x81C, 0xC1320503, + 0x81C, 0xA4340503, + 0x81C, 0xA3360503, + 0x81C, 0xA2380503, + 0x81C, 0xA13A0503, + 0x81C, 0x833C0503, + 0x81C, 0x823E0503, + 0x81C, 0x81400503, + 0x81C, 0x63420503, + 0x81C, 0x62440503, + 0x81C, 0x61460503, + 0x81C, 0x60480503, + 0x81C, 0x424A0503, + 0x81C, 0x414C0503, + 0x81C, 0x404E0503, + 0x81C, 0x22500503, + 0x81C, 0x21520503, + 0x81C, 0x20540503, + 0x81C, 0x03560503, + 0x81C, 0x02580503, + 0x81C, 0x015A0503, + 0x81C, 0x005C0503, + 0x81C, 0x005E0503, + 0x81C, 0x00600503, + 0x81C, 0x00620503, + 0x81C, 0x00640503, + 0x81C, 0x00660503, + 0x81C, 0x00680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xBF000503, + 0x81C, 0xBE020503, + 0x81C, 0xBD040503, + 0x81C, 0xBC060503, + 0x81C, 0xBB080503, + 0x81C, 0xBA0A0503, + 0x81C, 0xB90C0503, + 0x81C, 0xB80E0503, + 0x81C, 0xB7100503, + 0x81C, 0xB6120503, + 0x81C, 0xB5140503, + 0x81C, 0xB4160503, + 0x81C, 0xB3180503, + 0x81C, 0xB21A0503, + 0x81C, 0xB11C0503, + 0x81C, 0x931E0503, + 0x81C, 0x92200503, + 0x81C, 0x91220503, + 0x81C, 0x90240503, + 0x81C, 0x8F260503, + 0x81C, 0x8E280503, + 0x81C, 0x8D2A0503, + 0x81C, 0x8C2C0503, + 0x81C, 0x8B2E0503, + 0x81C, 0x8A300503, + 0x81C, 0x89320503, + 0x81C, 0x88340503, + 0x81C, 0x6A360503, + 0x81C, 0x69380503, + 0x81C, 0x683A0503, + 0x81C, 0x673C0503, + 0x81C, 0x663E0503, + 0x81C, 0x65400503, + 0x81C, 0x64420503, + 0x81C, 0x63440503, + 0x81C, 0x62460503, + 0x81C, 0x61480503, + 0x81C, 0x604A0503, + 0x81C, 0x424C0503, + 0x81C, 0x414E0503, + 0x81C, 0x40500503, + 0x81C, 0x06520503, + 0x81C, 0x05540503, + 0x81C, 0x04560503, + 0x81C, 0x03580503, + 0x81C, 0x025A0503, + 0x81C, 0x015C0503, + 0x81C, 0x005E0503, + 0x81C, 0x00600503, + 0x81C, 0x00620503, + 0x81C, 0x00640503, + 0x81C, 0x00660503, + 0x81C, 0x00680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0x90000008, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFD000503, + 0x81C, 0xFC020503, + 0x81C, 0xFB040503, + 0x81C, 0xFA060503, + 0x81C, 0xF9080503, + 0x81C, 0xF80A0503, + 0x81C, 0xF70C0503, + 0x81C, 0xF60E0503, + 0x81C, 0xF5100503, + 0x81C, 0xF4120503, + 0x81C, 0xF3140503, + 0x81C, 0xF2160503, + 0x81C, 0xF1180503, + 0x81C, 0xF01A0503, + 0x81C, 0xEF1C0503, + 0x81C, 0xEE1E0503, + 0x81C, 0xED200503, + 0x81C, 0xEC220503, + 0x81C, 0xEB240503, + 0x81C, 0xEA260503, + 0x81C, 0xE9280503, + 0x81C, 0xE82A0503, + 0x81C, 0xE72C0503, + 0x81C, 0xE62E0503, + 0x81C, 0xE5300503, + 0x81C, 0xE4320503, + 0x81C, 0xE3340503, + 0x81C, 0xC6360503, + 0x81C, 0xC5380503, + 0x81C, 0xC43A0503, + 0x81C, 0xC33C0503, + 0x81C, 0xC23E0503, + 0x81C, 0xA5400503, + 0x81C, 0xA4420503, + 0x81C, 0xA3440503, + 0x81C, 0xA2460503, + 0x81C, 0xA1480503, + 0x81C, 0x834A0503, + 0x81C, 0x824C0503, + 0x81C, 0x814E0503, + 0x81C, 0x63500503, + 0x81C, 0x62520503, + 0x81C, 0x61540503, + 0x81C, 0x43560503, + 0x81C, 0x42580503, + 0x81C, 0x245A0503, + 0x81C, 0x235C0503, + 0x81C, 0x225E0503, + 0x81C, 0x21600503, + 0x81C, 0x04620503, + 0x81C, 0x03640503, + 0x81C, 0x02660503, + 0x81C, 0x01680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0x90000009, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000503, + 0x81C, 0xF7020503, + 0x81C, 0xF6040503, + 0x81C, 0xF5060503, + 0x81C, 0xF4080503, + 0x81C, 0xF30A0503, + 0x81C, 0xF20C0503, + 0x81C, 0xF10E0503, + 0x81C, 0xF0100503, + 0x81C, 0xEF120503, + 0x81C, 0xEE140503, + 0x81C, 0xED160503, + 0x81C, 0xEC180503, + 0x81C, 0xEB1A0503, + 0x81C, 0xEA1C0503, + 0x81C, 0xE91E0503, + 0x81C, 0xE8200503, + 0x81C, 0xE7220503, + 0x81C, 0xE6240503, + 0x81C, 0xE5260503, + 0x81C, 0xE4280503, + 0x81C, 0xE32A0503, + 0x81C, 0xE22C0503, + 0x81C, 0xC32E0503, + 0x81C, 0xC2300503, + 0x81C, 0xC1320503, + 0x81C, 0xA3340503, + 0x81C, 0xA2360503, + 0x81C, 0xA1380503, + 0x81C, 0xA03A0503, + 0x81C, 0x823C0503, + 0x81C, 0x813E0503, + 0x81C, 0x80400503, + 0x81C, 0x64420503, + 0x81C, 0x63440503, + 0x81C, 0x62460503, + 0x81C, 0x61480503, + 0x81C, 0x434A0503, + 0x81C, 0x424C0503, + 0x81C, 0x414E0503, + 0x81C, 0x40500503, + 0x81C, 0x22520503, + 0x81C, 0x21540503, + 0x81C, 0x20560503, + 0x81C, 0x04580503, + 0x81C, 0x035A0503, + 0x81C, 0x025C0503, + 0x81C, 0x015E0503, + 0x81C, 0x00600503, + 0x81C, 0x00620503, + 0x81C, 0x00640503, + 0x81C, 0x00660503, + 0x81C, 0x00680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0x9000000a, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFD000503, + 0x81C, 0xFC020503, + 0x81C, 0xFB040503, + 0x81C, 0xFA060503, + 0x81C, 0xF9080503, + 0x81C, 0xF80A0503, + 0x81C, 0xF70C0503, + 0x81C, 0xF60E0503, + 0x81C, 0xF5100503, + 0x81C, 0xF4120503, + 0x81C, 0xF3140503, + 0x81C, 0xF2160503, + 0x81C, 0xF1180503, + 0x81C, 0xF01A0503, + 0x81C, 0xEE1C0503, + 0x81C, 0xED1E0503, + 0x81C, 0xEC200503, + 0x81C, 0xEB220503, + 0x81C, 0xEA240503, + 0x81C, 0xE9260503, + 0x81C, 0xE8280503, + 0x81C, 0xE72A0503, + 0x81C, 0xE62C0503, + 0x81C, 0xE52E0503, + 0x81C, 0xE4300503, + 0x81C, 0xE3320503, + 0x81C, 0xE2340503, + 0x81C, 0xC5360503, + 0x81C, 0xC4380503, + 0x81C, 0xC33A0503, + 0x81C, 0xC23C0503, + 0x81C, 0xA53E0503, + 0x81C, 0xA4400503, + 0x81C, 0xA3420503, + 0x81C, 0xA2440503, + 0x81C, 0xA1460503, + 0x81C, 0x83480503, + 0x81C, 0x824A0503, + 0x81C, 0x814C0503, + 0x81C, 0x804E0503, + 0x81C, 0x63500503, + 0x81C, 0x62520503, + 0x81C, 0x61540503, + 0x81C, 0x43560503, + 0x81C, 0x42580503, + 0x81C, 0x415A0503, + 0x81C, 0x405C0503, + 0x81C, 0x225E0503, + 0x81C, 0x21600503, + 0x81C, 0x20620503, + 0x81C, 0x03640503, + 0x81C, 0x02660503, + 0x81C, 0x01680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0x9000000b, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF9000503, + 0x81C, 0xF8020503, + 0x81C, 0xF7040503, + 0x81C, 0xF6060503, + 0x81C, 0xF5080503, + 0x81C, 0xF40A0503, + 0x81C, 0xF30C0503, + 0x81C, 0xF20E0503, + 0x81C, 0xF1100503, + 0x81C, 0xF0120503, + 0x81C, 0xEF140503, + 0x81C, 0xEE160503, + 0x81C, 0xED180503, + 0x81C, 0xEC1A0503, + 0x81C, 0xEB1C0503, + 0x81C, 0xEA1E0503, + 0x81C, 0xE9200503, + 0x81C, 0xE8220503, + 0x81C, 0xE7240503, + 0x81C, 0xE6260503, + 0x81C, 0xE5280503, + 0x81C, 0xE42A0503, + 0x81C, 0xE32C0503, + 0x81C, 0xC32E0503, + 0x81C, 0xC2300503, + 0x81C, 0xC1320503, + 0x81C, 0xA4340503, + 0x81C, 0xA3360503, + 0x81C, 0xA2380503, + 0x81C, 0xA13A0503, + 0x81C, 0xA03C0503, + 0x81C, 0x823E0503, + 0x81C, 0x81400503, + 0x81C, 0x80420503, + 0x81C, 0x63440503, + 0x81C, 0x62460503, + 0x81C, 0x61480503, + 0x81C, 0x604A0503, + 0x81C, 0x244C0503, + 0x81C, 0x234E0503, + 0x81C, 0x22500503, + 0x81C, 0x21520503, + 0x81C, 0x20540503, + 0x81C, 0x05560503, + 0x81C, 0x04580503, + 0x81C, 0x035A0503, + 0x81C, 0x025C0503, + 0x81C, 0x015E0503, + 0x81C, 0x00600503, + 0x81C, 0x00620503, + 0x81C, 0x00640503, + 0x81C, 0x00660503, + 0x81C, 0x00680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0x9000000c, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFE000503, + 0x81C, 0xFD020503, + 0x81C, 0xFC040503, + 0x81C, 0xFB060503, + 0x81C, 0xFA080503, + 0x81C, 0xF90A0503, + 0x81C, 0xF80C0503, + 0x81C, 0xF70E0503, + 0x81C, 0xF6100503, + 0x81C, 0xF5120503, + 0x81C, 0xF4140503, + 0x81C, 0xF3160503, + 0x81C, 0xF2180503, + 0x81C, 0xF11A0503, + 0x81C, 0xF01C0503, + 0x81C, 0xEF1E0503, + 0x81C, 0xEE200503, + 0x81C, 0xED220503, + 0x81C, 0xEC240503, + 0x81C, 0xEB260503, + 0x81C, 0xEA280503, + 0x81C, 0xE92A0503, + 0x81C, 0xE82C0503, + 0x81C, 0xE72E0503, + 0x81C, 0xE6300503, + 0x81C, 0xE5320503, + 0x81C, 0xE4340503, + 0x81C, 0xE3360503, + 0x81C, 0xC6380503, + 0x81C, 0xC53A0503, + 0x81C, 0xC43C0503, + 0x81C, 0xC33E0503, + 0x81C, 0xA5400503, + 0x81C, 0xA4420503, + 0x81C, 0xA3440503, + 0x81C, 0xA2460503, + 0x81C, 0xA1480503, + 0x81C, 0xA04A0503, + 0x81C, 0x824C0503, + 0x81C, 0x814E0503, + 0x81C, 0x80500503, + 0x81C, 0x64520503, + 0x81C, 0x63540503, + 0x81C, 0x62560503, + 0x81C, 0x61580503, + 0x81C, 0x605A0503, + 0x81C, 0x235C0503, + 0x81C, 0x225E0503, + 0x81C, 0x21600503, + 0x81C, 0x20620503, + 0x81C, 0x03640503, + 0x81C, 0x02660503, + 0x81C, 0x01680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0x9000000d, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFD000503, + 0x81C, 0xFC020503, + 0x81C, 0xFB040503, + 0x81C, 0xFA060503, + 0x81C, 0xF9080503, + 0x81C, 0xF80A0503, + 0x81C, 0xF70C0503, + 0x81C, 0xF60E0503, + 0x81C, 0xF5100503, + 0x81C, 0xF4120503, + 0x81C, 0xF3140503, + 0x81C, 0xF2160503, + 0x81C, 0xF1180503, + 0x81C, 0xF01A0503, + 0x81C, 0xEE1C0503, + 0x81C, 0xED1E0503, + 0x81C, 0xEC200503, + 0x81C, 0xEB220503, + 0x81C, 0xEA240503, + 0x81C, 0xE9260503, + 0x81C, 0xE8280503, + 0x81C, 0xE72A0503, + 0x81C, 0xE62C0503, + 0x81C, 0xE52E0503, + 0x81C, 0xE4300503, + 0x81C, 0xE3320503, + 0x81C, 0xE2340503, + 0x81C, 0xC5360503, + 0x81C, 0xC4380503, + 0x81C, 0xC33A0503, + 0x81C, 0xC23C0503, + 0x81C, 0xA53E0503, + 0x81C, 0xA4400503, + 0x81C, 0xA3420503, + 0x81C, 0xA2440503, + 0x81C, 0xA1460503, + 0x81C, 0x83480503, + 0x81C, 0x824A0503, + 0x81C, 0x814C0503, + 0x81C, 0x804E0503, + 0x81C, 0x63500503, + 0x81C, 0x62520503, + 0x81C, 0x61540503, + 0x81C, 0x43560503, + 0x81C, 0x42580503, + 0x81C, 0x415A0503, + 0x81C, 0x405C0503, + 0x81C, 0x225E0503, + 0x81C, 0x21600503, + 0x81C, 0x20620503, + 0x81C, 0x03640503, + 0x81C, 0x02660503, + 0x81C, 0x01680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0x9000000e, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFD000503, + 0x81C, 0xFC020503, + 0x81C, 0xFB040503, + 0x81C, 0xFA060503, + 0x81C, 0xF9080503, + 0x81C, 0xF80A0503, + 0x81C, 0xF70C0503, + 0x81C, 0xF60E0503, + 0x81C, 0xF5100503, + 0x81C, 0xF4120503, + 0x81C, 0xF3140503, + 0x81C, 0xF2160503, + 0x81C, 0xF1180503, + 0x81C, 0xF01A0503, + 0x81C, 0xEE1C0503, + 0x81C, 0xED1E0503, + 0x81C, 0xEC200503, + 0x81C, 0xEB220503, + 0x81C, 0xEA240503, + 0x81C, 0xE9260503, + 0x81C, 0xE8280503, + 0x81C, 0xE72A0503, + 0x81C, 0xE62C0503, + 0x81C, 0xE52E0503, + 0x81C, 0xE4300503, + 0x81C, 0xE3320503, + 0x81C, 0xE2340503, + 0x81C, 0xC5360503, + 0x81C, 0xC4380503, + 0x81C, 0xC33A0503, + 0x81C, 0xC23C0503, + 0x81C, 0xA53E0503, + 0x81C, 0xA4400503, + 0x81C, 0xA3420503, + 0x81C, 0xA2440503, + 0x81C, 0xA1460503, + 0x81C, 0x83480503, + 0x81C, 0x824A0503, + 0x81C, 0x814C0503, + 0x81C, 0x804E0503, + 0x81C, 0x63500503, + 0x81C, 0x62520503, + 0x81C, 0x61540503, + 0x81C, 0x43560503, + 0x81C, 0x42580503, + 0x81C, 0x415A0503, + 0x81C, 0x405C0503, + 0x81C, 0x225E0503, + 0x81C, 0x21600503, + 0x81C, 0x20620503, + 0x81C, 0x03640503, + 0x81C, 0x02660503, + 0x81C, 0x01680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0x9000000f, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xBF000503, + 0x81C, 0xBF020503, + 0x81C, 0xBF040503, + 0x81C, 0xBF060503, + 0x81C, 0xBF080503, + 0x81C, 0xBF0A0503, + 0x81C, 0xBE0C0503, + 0x81C, 0xBD0E0503, + 0x81C, 0xBC100503, + 0x81C, 0xBB120503, + 0x81C, 0xBA140503, + 0x81C, 0xB9160503, + 0x81C, 0xB8180503, + 0x81C, 0xB71A0503, + 0x81C, 0xB61C0503, + 0x81C, 0xB51E0503, + 0x81C, 0xB2200503, + 0x81C, 0xB3220503, + 0x81C, 0xB2240503, + 0x81C, 0xB1260503, + 0x81C, 0xB0280503, + 0x81C, 0xAF2A0503, + 0x81C, 0xAE2C0503, + 0x81C, 0xAD2E0503, + 0x81C, 0xAC300503, + 0x81C, 0xAB320503, + 0x81C, 0xAA340503, + 0x81C, 0xC6360503, + 0x81C, 0xC5380503, + 0x81C, 0xC43A0503, + 0x81C, 0xC33C0503, + 0x81C, 0x883E0503, + 0x81C, 0x87400503, + 0x81C, 0x86420503, + 0x81C, 0x85440503, + 0x81C, 0x84460503, + 0x81C, 0x83480503, + 0x81C, 0x674A0503, + 0x81C, 0x664C0503, + 0x81C, 0x654E0503, + 0x81C, 0x64500503, + 0x81C, 0x27520503, + 0x81C, 0x26540503, + 0x81C, 0x25560503, + 0x81C, 0x24580503, + 0x81C, 0x235A0503, + 0x81C, 0x225C0503, + 0x81C, 0x215E0503, + 0x81C, 0x20600503, + 0x81C, 0x03620503, + 0x81C, 0x02640503, + 0x81C, 0x01660503, + 0x81C, 0x00680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0x90000010, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFE000403, + 0x81C, 0xFD000503, + 0x81C, 0xFC020503, + 0x81C, 0xFB040503, + 0x81C, 0xFA060503, + 0x81C, 0xF9080503, + 0x81C, 0xF80A0503, + 0x81C, 0xF70C0503, + 0x81C, 0xF60E0503, + 0x81C, 0xF5100503, + 0x81C, 0xF4120503, + 0x81C, 0xF3140503, + 0x81C, 0xF2160503, + 0x81C, 0xF1180503, + 0x81C, 0xF01A0503, + 0x81C, 0xEF1C0503, + 0x81C, 0xEE1E0503, + 0x81C, 0xED200503, + 0x81C, 0xEC220503, + 0x81C, 0xEB240503, + 0x81C, 0xEA260503, + 0x81C, 0xE9280503, + 0x81C, 0xE82A0503, + 0x81C, 0xE72C0503, + 0x81C, 0xE62E0503, + 0x81C, 0xE5300503, + 0x81C, 0xE4320503, + 0x81C, 0xE3340503, + 0x81C, 0xC6360503, + 0x81C, 0xC5380503, + 0x81C, 0xC43A0503, + 0x81C, 0xC33C0503, + 0x81C, 0xA53E0503, + 0x81C, 0xA4400503, + 0x81C, 0xA3420503, + 0x81C, 0xA2440503, + 0x81C, 0xA1460503, + 0x81C, 0xA0480503, + 0x81C, 0x824A0503, + 0x81C, 0x814C0503, + 0x81C, 0x804E0503, + 0x81C, 0x64500503, + 0x81C, 0x63520503, + 0x81C, 0x62540503, + 0x81C, 0x61560503, + 0x81C, 0x60580503, + 0x81C, 0x235A0503, + 0x81C, 0x225C0503, + 0x81C, 0x215E0503, + 0x81C, 0x20600503, + 0x81C, 0x03620503, + 0x81C, 0x02640503, + 0x81C, 0x01660503, + 0x81C, 0x00680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x90000012, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000503, + 0x81C, 0xF7020503, + 0x81C, 0xF6040503, + 0x81C, 0xF5060503, + 0x81C, 0xF4080503, + 0x81C, 0xF30A0503, + 0x81C, 0xF20C0503, + 0x81C, 0xF10E0503, + 0x81C, 0xF0100503, + 0x81C, 0xEF120503, + 0x81C, 0xEE140503, + 0x81C, 0xED160503, + 0x81C, 0xEC180503, + 0x81C, 0xEB1A0503, + 0x81C, 0xEA1C0503, + 0x81C, 0xE91E0503, + 0x81C, 0xE8200503, + 0x81C, 0xE7220503, + 0x81C, 0xE6240503, + 0x81C, 0xE5260503, + 0x81C, 0xE4280503, + 0x81C, 0xE32A0503, + 0x81C, 0xC32C0503, + 0x81C, 0xC22E0503, + 0x81C, 0xC1300503, + 0x81C, 0xC0320503, + 0x81C, 0xA3340503, + 0x81C, 0xA2360503, + 0x81C, 0xA1380503, + 0x81C, 0xA03A0503, + 0x81C, 0x823C0503, + 0x81C, 0x813E0503, + 0x81C, 0x80400503, + 0x81C, 0x63420503, + 0x81C, 0x62440503, + 0x81C, 0x61460503, + 0x81C, 0x60480503, + 0x81C, 0x424A0503, + 0x81C, 0x414C0503, + 0x81C, 0x404E0503, + 0x81C, 0x22500503, + 0x81C, 0x21520503, + 0x81C, 0x20540503, + 0x81C, 0x03560503, + 0x81C, 0x02580503, + 0x81C, 0x015A0503, + 0x81C, 0x005C0503, + 0x81C, 0x005E0503, + 0x81C, 0x00600503, + 0x81C, 0x00620503, + 0x81C, 0x00640503, + 0x81C, 0x00660503, + 0x81C, 0x00680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0xA0000000, 0x00000000, + 0x81C, 0xFE000503, + 0x81C, 0xFD020503, + 0x81C, 0xFC040503, + 0x81C, 0xFB060503, + 0x81C, 0xFA080503, + 0x81C, 0xF90A0503, + 0x81C, 0xF80C0503, + 0x81C, 0xF70E0503, + 0x81C, 0xF6100503, + 0x81C, 0xF5120503, + 0x81C, 0xF4140503, + 0x81C, 0xF3160503, + 0x81C, 0xF2180503, + 0x81C, 0xF11A0503, + 0x81C, 0xF01C0503, + 0x81C, 0xEF1E0503, + 0x81C, 0xEE200503, + 0x81C, 0xED220503, + 0x81C, 0xEC240503, + 0x81C, 0xEB260503, + 0x81C, 0xEA280503, + 0x81C, 0xE92A0503, + 0x81C, 0xE82C0503, + 0x81C, 0xE72E0503, + 0x81C, 0xE6300503, + 0x81C, 0xE5320503, + 0x81C, 0xE4340503, + 0x81C, 0xE3360503, + 0x81C, 0xC6380503, + 0x81C, 0xC53A0503, + 0x81C, 0xC43C0503, + 0x81C, 0xC33E0503, + 0x81C, 0xA5400503, + 0x81C, 0xA4420503, + 0x81C, 0xA3440503, + 0x81C, 0xA2460503, + 0x81C, 0xA1480503, + 0x81C, 0xA04A0503, + 0x81C, 0x824C0503, + 0x81C, 0x814E0503, + 0x81C, 0x80500503, + 0x81C, 0x64520503, + 0x81C, 0x63540503, + 0x81C, 0x62560503, + 0x81C, 0x61580503, + 0x81C, 0x605A0503, + 0x81C, 0x235C0503, + 0x81C, 0x225E0503, + 0x81C, 0x21600503, + 0x81C, 0x20620503, + 0x81C, 0x03640503, + 0x81C, 0x02660503, + 0x81C, 0x01680503, + 0x81C, 0x006A0503, + 0x81C, 0x006C0503, + 0x81C, 0x006E0503, + 0x81C, 0x00700503, + 0x81C, 0x00720503, + 0x81C, 0x00740503, + 0x81C, 0x00760503, + 0x81C, 0x00780503, + 0x81C, 0x007A0503, + 0x81C, 0x007C0503, + 0x81C, 0x007E0503, + 0x81C, 0x007E0503, + 0xB0000000, 0x00000000, + 0x80000000, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000603, + 0x81C, 0xFB020603, + 0x81C, 0xFA040603, + 0x81C, 0xF9060603, + 0x81C, 0xF8080603, + 0x81C, 0xF70A0603, + 0x81C, 0xF60C0603, + 0x81C, 0xF50E0603, + 0x81C, 0xF4100603, + 0x81C, 0xF3120603, + 0x81C, 0xF2140603, + 0x81C, 0xF1160603, + 0x81C, 0xF0180603, + 0x81C, 0xEE1A0603, + 0x81C, 0xED1C0603, + 0x81C, 0xEC1E0603, + 0x81C, 0xEB200603, + 0x81C, 0xEA220603, + 0x81C, 0xE9240603, + 0x81C, 0xE8260603, + 0x81C, 0xE7280603, + 0x81C, 0xE62A0603, + 0x81C, 0xE52C0603, + 0x81C, 0xE42E0603, + 0x81C, 0xE3300603, + 0x81C, 0xE2320603, + 0x81C, 0xC6340603, + 0x81C, 0xC5360603, + 0x81C, 0xC4380603, + 0x81C, 0xC33A0603, + 0x81C, 0xA63C0603, + 0x81C, 0xA53E0603, + 0x81C, 0xA4400603, + 0x81C, 0xA3420603, + 0x81C, 0xA2440603, + 0x81C, 0xA1460603, + 0x81C, 0x83480603, + 0x81C, 0x824A0603, + 0x81C, 0x814C0603, + 0x81C, 0x804E0603, + 0x81C, 0x63500603, + 0x81C, 0x62520603, + 0x81C, 0x61540603, + 0x81C, 0x42560603, + 0x81C, 0x41580603, + 0x81C, 0x405A0603, + 0x81C, 0x225C0603, + 0x81C, 0x215E0603, + 0x81C, 0x20600603, + 0x81C, 0x04620603, + 0x81C, 0x03640603, + 0x81C, 0x02660603, + 0x81C, 0x01680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xBD000603, + 0x81C, 0xBC020603, + 0x81C, 0xBB040603, + 0x81C, 0xBA060603, + 0x81C, 0xB9080603, + 0x81C, 0xB80A0603, + 0x81C, 0xB70C0603, + 0x81C, 0xB60E0603, + 0x81C, 0xB5100603, + 0x81C, 0xB4120603, + 0x81C, 0xB3140603, + 0x81C, 0xB2160603, + 0x81C, 0xB1180603, + 0x81C, 0xB01A0603, + 0x81C, 0xAF1C0603, + 0x81C, 0xAE1E0603, + 0x81C, 0xAD200603, + 0x81C, 0x8F220603, + 0x81C, 0x8E240603, + 0x81C, 0x8D260603, + 0x81C, 0x8C280603, + 0x81C, 0x8B2A0603, + 0x81C, 0x8A2C0603, + 0x81C, 0x892E0603, + 0x81C, 0x88300603, + 0x81C, 0x6B320603, + 0x81C, 0x6A340603, + 0x81C, 0x69360603, + 0x81C, 0x68380603, + 0x81C, 0x673A0603, + 0x81C, 0x663C0603, + 0x81C, 0x653E0603, + 0x81C, 0x64400603, + 0x81C, 0x63420603, + 0x81C, 0x62440603, + 0x81C, 0x61460603, + 0x81C, 0x60480603, + 0x81C, 0x424A0603, + 0x81C, 0x414C0603, + 0x81C, 0x404E0603, + 0x81C, 0x06500603, + 0x81C, 0x05520603, + 0x81C, 0x04540603, + 0x81C, 0x03560603, + 0x81C, 0x02580603, + 0x81C, 0x015A0603, + 0x81C, 0x005C0603, + 0x81C, 0x005E0603, + 0x81C, 0x00600603, + 0x81C, 0x00620603, + 0x81C, 0x00640603, + 0x81C, 0x00660603, + 0x81C, 0x00680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007C0603, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF7000603, + 0x81C, 0xF6020603, + 0x81C, 0xF5040603, + 0x81C, 0xF4060603, + 0x81C, 0xF3080603, + 0x81C, 0xF20A0603, + 0x81C, 0xF10C0603, + 0x81C, 0xF00E0603, + 0x81C, 0xEF100603, + 0x81C, 0xEE120603, + 0x81C, 0xED140603, + 0x81C, 0xEC160603, + 0x81C, 0xEB180603, + 0x81C, 0xEA1A0603, + 0x81C, 0xE91C0603, + 0x81C, 0xE81E0603, + 0x81C, 0xE7200603, + 0x81C, 0xE6220603, + 0x81C, 0xE5240603, + 0x81C, 0xE4260603, + 0x81C, 0xE3280603, + 0x81C, 0xC42A0603, + 0x81C, 0xC32C0603, + 0x81C, 0xC22E0603, + 0x81C, 0xC1300603, + 0x81C, 0xC0320603, + 0x81C, 0xA3340603, + 0x81C, 0xA2360603, + 0x81C, 0xA1380603, + 0x81C, 0xA03A0603, + 0x81C, 0x823C0603, + 0x81C, 0x813E0603, + 0x81C, 0x80400603, + 0x81C, 0x64420603, + 0x81C, 0x63440603, + 0x81C, 0x62460603, + 0x81C, 0x61480603, + 0x81C, 0x604A0603, + 0x81C, 0x414C0603, + 0x81C, 0x404E0603, + 0x81C, 0x22500603, + 0x81C, 0x21520603, + 0x81C, 0x20540603, + 0x81C, 0x03560603, + 0x81C, 0x02580603, + 0x81C, 0x015A0603, + 0x81C, 0x005C0603, + 0x81C, 0x005E0603, + 0x81C, 0x00600603, + 0x81C, 0x00620603, + 0x81C, 0x00640603, + 0x81C, 0x00660603, + 0x81C, 0x00680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000603, + 0x81C, 0xFB020603, + 0x81C, 0xFA040603, + 0x81C, 0xF9060603, + 0x81C, 0xF8080603, + 0x81C, 0xF70A0603, + 0x81C, 0xF60C0603, + 0x81C, 0xF50E0603, + 0x81C, 0xF4100603, + 0x81C, 0xF3120603, + 0x81C, 0xF2140603, + 0x81C, 0xF1160603, + 0x81C, 0xF0180603, + 0x81C, 0xEF1A0603, + 0x81C, 0xEE1C0603, + 0x81C, 0xED1E0603, + 0x81C, 0xEC200603, + 0x81C, 0xEB220603, + 0x81C, 0xEA240603, + 0x81C, 0xE9260603, + 0x81C, 0xE8280603, + 0x81C, 0xE72A0603, + 0x81C, 0xE62C0603, + 0x81C, 0xE52E0603, + 0x81C, 0xE4300603, + 0x81C, 0xE3320603, + 0x81C, 0xE2340603, + 0x81C, 0xC6360603, + 0x81C, 0xC5380603, + 0x81C, 0xC43A0603, + 0x81C, 0xC33C0603, + 0x81C, 0xA63E0603, + 0x81C, 0xA5400603, + 0x81C, 0xA4420603, + 0x81C, 0xA3440603, + 0x81C, 0xA2460603, + 0x81C, 0xA1480603, + 0x81C, 0x834A0603, + 0x81C, 0x824C0603, + 0x81C, 0x814E0603, + 0x81C, 0x64500603, + 0x81C, 0x63520603, + 0x81C, 0x62540603, + 0x81C, 0x61560603, + 0x81C, 0x60580603, + 0x81C, 0x405A0603, + 0x81C, 0x215C0603, + 0x81C, 0x205E0603, + 0x81C, 0x03600603, + 0x81C, 0x02620603, + 0x81C, 0x01640603, + 0x81C, 0x00660603, + 0x81C, 0x00680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF7000603, + 0x81C, 0xF6020603, + 0x81C, 0xF5040603, + 0x81C, 0xF4060603, + 0x81C, 0xF3080603, + 0x81C, 0xF20A0603, + 0x81C, 0xF10C0603, + 0x81C, 0xF00E0603, + 0x81C, 0xEF100603, + 0x81C, 0xEE120603, + 0x81C, 0xED140603, + 0x81C, 0xEC160603, + 0x81C, 0xEB180603, + 0x81C, 0xEA1A0603, + 0x81C, 0xE91C0603, + 0x81C, 0xE81E0603, + 0x81C, 0xE7200603, + 0x81C, 0xE6220603, + 0x81C, 0xE5240603, + 0x81C, 0xE4260603, + 0x81C, 0xE3280603, + 0x81C, 0xC42A0603, + 0x81C, 0xC32C0603, + 0x81C, 0xC22E0603, + 0x81C, 0xC1300603, + 0x81C, 0xC0320603, + 0x81C, 0xA3340603, + 0x81C, 0xA2360603, + 0x81C, 0xA1380603, + 0x81C, 0xA03A0603, + 0x81C, 0x823C0603, + 0x81C, 0x813E0603, + 0x81C, 0x80400603, + 0x81C, 0x64420603, + 0x81C, 0x63440603, + 0x81C, 0x62460603, + 0x81C, 0x61480603, + 0x81C, 0x604A0603, + 0x81C, 0x414C0603, + 0x81C, 0x404E0603, + 0x81C, 0x22500603, + 0x81C, 0x21520603, + 0x81C, 0x20540603, + 0x81C, 0x03560603, + 0x81C, 0x02580603, + 0x81C, 0x015A0603, + 0x81C, 0x005C0603, + 0x81C, 0x005E0603, + 0x81C, 0x00600603, + 0x81C, 0x00620603, + 0x81C, 0x00640603, + 0x81C, 0x00660603, + 0x81C, 0x00680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000603, + 0x81C, 0xFB020603, + 0x81C, 0xFA040603, + 0x81C, 0xF9060603, + 0x81C, 0xF8080603, + 0x81C, 0xF70A0603, + 0x81C, 0xF60C0603, + 0x81C, 0xF50E0603, + 0x81C, 0xF4100603, + 0x81C, 0xF3120603, + 0x81C, 0xF2140603, + 0x81C, 0xF1160603, + 0x81C, 0xF0180603, + 0x81C, 0xEF1A0603, + 0x81C, 0xEE1C0603, + 0x81C, 0xED1E0603, + 0x81C, 0xEC200603, + 0x81C, 0xEB220603, + 0x81C, 0xEA240603, + 0x81C, 0xE9260603, + 0x81C, 0xE8280603, + 0x81C, 0xE72A0603, + 0x81C, 0xE62C0603, + 0x81C, 0xE52E0603, + 0x81C, 0xE4300603, + 0x81C, 0xE3320603, + 0x81C, 0xE2340603, + 0x81C, 0xE1360603, + 0x81C, 0xC5380603, + 0x81C, 0xC43A0603, + 0x81C, 0xC33C0603, + 0x81C, 0xC23E0603, + 0x81C, 0xC1400603, + 0x81C, 0xA3420603, + 0x81C, 0xA2440603, + 0x81C, 0xA1460603, + 0x81C, 0xA0480603, + 0x81C, 0x834A0603, + 0x81C, 0x824C0603, + 0x81C, 0x814E0603, + 0x81C, 0x64500603, + 0x81C, 0x63520603, + 0x81C, 0x62540603, + 0x81C, 0x61560603, + 0x81C, 0x25580603, + 0x81C, 0x245A0603, + 0x81C, 0x235C0603, + 0x81C, 0x225E0603, + 0x81C, 0x21600603, + 0x81C, 0x04620603, + 0x81C, 0x03640603, + 0x81C, 0x02660603, + 0x81C, 0x01680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF9000603, + 0x81C, 0xF8020603, + 0x81C, 0xF7040603, + 0x81C, 0xF6060603, + 0x81C, 0xF5080603, + 0x81C, 0xF40A0603, + 0x81C, 0xF30C0603, + 0x81C, 0xF20E0603, + 0x81C, 0xF1100603, + 0x81C, 0xF0120603, + 0x81C, 0xEF140603, + 0x81C, 0xEE160603, + 0x81C, 0xED180603, + 0x81C, 0xEC1A0603, + 0x81C, 0xEB1C0603, + 0x81C, 0xEA1E0603, + 0x81C, 0xE9200603, + 0x81C, 0xE8220603, + 0x81C, 0xE7240603, + 0x81C, 0xE6260603, + 0x81C, 0xE5280603, + 0x81C, 0xC42A0603, + 0x81C, 0xC32C0603, + 0x81C, 0xC22E0603, + 0x81C, 0xC1300603, + 0x81C, 0xC0320603, + 0x81C, 0xA3340603, + 0x81C, 0xA2360603, + 0x81C, 0xA1380603, + 0x81C, 0xA03A0603, + 0x81C, 0x823C0603, + 0x81C, 0x813E0603, + 0x81C, 0x80400603, + 0x81C, 0x64420603, + 0x81C, 0x63440603, + 0x81C, 0x62460603, + 0x81C, 0x61480603, + 0x81C, 0x604A0603, + 0x81C, 0x414C0603, + 0x81C, 0x404E0603, + 0x81C, 0x22500603, + 0x81C, 0x21520603, + 0x81C, 0x20540603, + 0x81C, 0x03560603, + 0x81C, 0x02580603, + 0x81C, 0x015A0603, + 0x81C, 0x005C0603, + 0x81C, 0x005E0603, + 0x81C, 0x00600603, + 0x81C, 0x00620603, + 0x81C, 0x00640603, + 0x81C, 0x00660603, + 0x81C, 0x00680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xBE000603, + 0x81C, 0xBD020603, + 0x81C, 0xBC040603, + 0x81C, 0xBB060603, + 0x81C, 0xBA080603, + 0x81C, 0xB90A0603, + 0x81C, 0xB80C0603, + 0x81C, 0xB70E0603, + 0x81C, 0xB6100603, + 0x81C, 0xB5120603, + 0x81C, 0xB4140603, + 0x81C, 0xB3160603, + 0x81C, 0xB2180603, + 0x81C, 0xB11A0603, + 0x81C, 0xB01C0603, + 0x81C, 0x921E0603, + 0x81C, 0x91200603, + 0x81C, 0x90220603, + 0x81C, 0x8F240603, + 0x81C, 0x8E260603, + 0x81C, 0x8D280603, + 0x81C, 0x8C2A0603, + 0x81C, 0x8B2C0603, + 0x81C, 0x8A2E0603, + 0x81C, 0x89300603, + 0x81C, 0x88320603, + 0x81C, 0x6B340603, + 0x81C, 0x6A360603, + 0x81C, 0x69380603, + 0x81C, 0x683A0603, + 0x81C, 0x673C0603, + 0x81C, 0x663E0603, + 0x81C, 0x65400603, + 0x81C, 0x64420603, + 0x81C, 0x63440603, + 0x81C, 0x62460603, + 0x81C, 0x61480603, + 0x81C, 0x604A0603, + 0x81C, 0x424C0603, + 0x81C, 0x414E0603, + 0x81C, 0x40500603, + 0x81C, 0x06520603, + 0x81C, 0x05540603, + 0x81C, 0x04560603, + 0x81C, 0x03580603, + 0x81C, 0x025A0603, + 0x81C, 0x015C0603, + 0x81C, 0x005E0603, + 0x81C, 0x00600603, + 0x81C, 0x00620603, + 0x81C, 0x00640603, + 0x81C, 0x00660603, + 0x81C, 0x00680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0x90000008, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFB000603, + 0x81C, 0xFA020603, + 0x81C, 0xF9040603, + 0x81C, 0xF8060603, + 0x81C, 0xF7080603, + 0x81C, 0xF60A0603, + 0x81C, 0xF50C0603, + 0x81C, 0xF40E0603, + 0x81C, 0xF3100603, + 0x81C, 0xF2120603, + 0x81C, 0xF1140603, + 0x81C, 0xF0160603, + 0x81C, 0xEF180603, + 0x81C, 0xEE1A0603, + 0x81C, 0xED1C0603, + 0x81C, 0xEC1E0603, + 0x81C, 0xEB200603, + 0x81C, 0xEA220603, + 0x81C, 0xE9240603, + 0x81C, 0xE8260603, + 0x81C, 0xE7280603, + 0x81C, 0xE62A0603, + 0x81C, 0xE52C0603, + 0x81C, 0xE42E0603, + 0x81C, 0xE3300603, + 0x81C, 0xE2320603, + 0x81C, 0xC6340603, + 0x81C, 0xC5360603, + 0x81C, 0xC4380603, + 0x81C, 0xC33A0603, + 0x81C, 0xC23C0603, + 0x81C, 0xC13E0603, + 0x81C, 0xC0400603, + 0x81C, 0xA3420603, + 0x81C, 0xA2440603, + 0x81C, 0xA1460603, + 0x81C, 0xA0480603, + 0x81C, 0x824A0603, + 0x81C, 0x814C0603, + 0x81C, 0x804E0603, + 0x81C, 0x63500603, + 0x81C, 0x62520603, + 0x81C, 0x61540603, + 0x81C, 0x60560603, + 0x81C, 0x24580603, + 0x81C, 0x235A0603, + 0x81C, 0x225C0603, + 0x81C, 0x215E0603, + 0x81C, 0x20600603, + 0x81C, 0x03620603, + 0x81C, 0x02640603, + 0x81C, 0x01660603, + 0x81C, 0x00680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0x90000009, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000603, + 0x81C, 0xF7020603, + 0x81C, 0xF6040603, + 0x81C, 0xF5060603, + 0x81C, 0xF4080603, + 0x81C, 0xF30A0603, + 0x81C, 0xF20C0603, + 0x81C, 0xF10E0603, + 0x81C, 0xF0100603, + 0x81C, 0xEF120603, + 0x81C, 0xEE140603, + 0x81C, 0xED160603, + 0x81C, 0xEC180603, + 0x81C, 0xEB1A0603, + 0x81C, 0xEA1C0603, + 0x81C, 0xE91E0603, + 0x81C, 0xE8200603, + 0x81C, 0xE7220603, + 0x81C, 0xE6240603, + 0x81C, 0xE5260603, + 0x81C, 0xE4280603, + 0x81C, 0xE32A0603, + 0x81C, 0xC42C0603, + 0x81C, 0xC32E0603, + 0x81C, 0xC2300603, + 0x81C, 0xC1320603, + 0x81C, 0xA3340603, + 0x81C, 0xA2360603, + 0x81C, 0xA1380603, + 0x81C, 0xA03A0603, + 0x81C, 0x823C0603, + 0x81C, 0x813E0603, + 0x81C, 0x80400603, + 0x81C, 0x65420603, + 0x81C, 0x64440603, + 0x81C, 0x63460603, + 0x81C, 0x62480603, + 0x81C, 0x614A0603, + 0x81C, 0x424C0603, + 0x81C, 0x414E0603, + 0x81C, 0x40500603, + 0x81C, 0x22520603, + 0x81C, 0x21540603, + 0x81C, 0x20560603, + 0x81C, 0x04580603, + 0x81C, 0x035A0603, + 0x81C, 0x025C0603, + 0x81C, 0x015E0603, + 0x81C, 0x00600603, + 0x81C, 0x00620603, + 0x81C, 0x00640603, + 0x81C, 0x00660603, + 0x81C, 0x00680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0x9000000a, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000603, + 0x81C, 0xFB020603, + 0x81C, 0xFA040603, + 0x81C, 0xF9060603, + 0x81C, 0xF8080603, + 0x81C, 0xF70A0603, + 0x81C, 0xF60C0603, + 0x81C, 0xF50E0603, + 0x81C, 0xF4100603, + 0x81C, 0xF3120603, + 0x81C, 0xF2140603, + 0x81C, 0xF1160603, + 0x81C, 0xF0180603, + 0x81C, 0xEE1A0603, + 0x81C, 0xED1C0603, + 0x81C, 0xEC1E0603, + 0x81C, 0xEB200603, + 0x81C, 0xEA220603, + 0x81C, 0xE9240603, + 0x81C, 0xE8260603, + 0x81C, 0xE7280603, + 0x81C, 0xE62A0603, + 0x81C, 0xE52C0603, + 0x81C, 0xE42E0603, + 0x81C, 0xE3300603, + 0x81C, 0xE2320603, + 0x81C, 0xC6340603, + 0x81C, 0xC5360603, + 0x81C, 0xC4380603, + 0x81C, 0xC33A0603, + 0x81C, 0xA63C0603, + 0x81C, 0xA53E0603, + 0x81C, 0xA4400603, + 0x81C, 0xA3420603, + 0x81C, 0xA2440603, + 0x81C, 0xA1460603, + 0x81C, 0x83480603, + 0x81C, 0x824A0603, + 0x81C, 0x814C0603, + 0x81C, 0x804E0603, + 0x81C, 0x63500603, + 0x81C, 0x62520603, + 0x81C, 0x61540603, + 0x81C, 0x42560603, + 0x81C, 0x41580603, + 0x81C, 0x405A0603, + 0x81C, 0x225C0603, + 0x81C, 0x215E0603, + 0x81C, 0x20600603, + 0x81C, 0x04620603, + 0x81C, 0x03640603, + 0x81C, 0x02660603, + 0x81C, 0x01680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0x9000000b, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF9000603, + 0x81C, 0xF8020603, + 0x81C, 0xF7040603, + 0x81C, 0xF6060603, + 0x81C, 0xF5080603, + 0x81C, 0xF40A0603, + 0x81C, 0xF30C0603, + 0x81C, 0xF20E0603, + 0x81C, 0xF1100603, + 0x81C, 0xF0120603, + 0x81C, 0xEF140603, + 0x81C, 0xEE160603, + 0x81C, 0xED180603, + 0x81C, 0xEC1A0603, + 0x81C, 0xEB1C0603, + 0x81C, 0xEA1E0603, + 0x81C, 0xE9200603, + 0x81C, 0xE8220603, + 0x81C, 0xE7240603, + 0x81C, 0xE6260603, + 0x81C, 0xE5280603, + 0x81C, 0xE42A0603, + 0x81C, 0xC42C0603, + 0x81C, 0xC32E0603, + 0x81C, 0xC2300603, + 0x81C, 0xC1320603, + 0x81C, 0xA3340603, + 0x81C, 0xA2360603, + 0x81C, 0xA1380603, + 0x81C, 0xA03A0603, + 0x81C, 0x823C0603, + 0x81C, 0x813E0603, + 0x81C, 0x80400603, + 0x81C, 0x64420603, + 0x81C, 0x63440603, + 0x81C, 0x62460603, + 0x81C, 0x61480603, + 0x81C, 0x604A0603, + 0x81C, 0x244C0603, + 0x81C, 0x234E0603, + 0x81C, 0x22500603, + 0x81C, 0x21520603, + 0x81C, 0x20540603, + 0x81C, 0x05560603, + 0x81C, 0x04580603, + 0x81C, 0x035A0603, + 0x81C, 0x025C0603, + 0x81C, 0x015E0603, + 0x81C, 0x00600603, + 0x81C, 0x00620603, + 0x81C, 0x00640603, + 0x81C, 0x00660603, + 0x81C, 0x00680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0x9000000c, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000603, + 0x81C, 0xFB020603, + 0x81C, 0xFA040603, + 0x81C, 0xF9060603, + 0x81C, 0xF8080603, + 0x81C, 0xF70A0603, + 0x81C, 0xF60C0603, + 0x81C, 0xF50E0603, + 0x81C, 0xF4100603, + 0x81C, 0xF3120603, + 0x81C, 0xF2140603, + 0x81C, 0xF1160603, + 0x81C, 0xF0180603, + 0x81C, 0xEF1A0603, + 0x81C, 0xEE1C0603, + 0x81C, 0xED1E0603, + 0x81C, 0xEC200603, + 0x81C, 0xEB220603, + 0x81C, 0xEA240603, + 0x81C, 0xE9260603, + 0x81C, 0xE8280603, + 0x81C, 0xE72A0603, + 0x81C, 0xE62C0603, + 0x81C, 0xE52E0603, + 0x81C, 0xE4300603, + 0x81C, 0xE3320603, + 0x81C, 0xE2340603, + 0x81C, 0xC6360603, + 0x81C, 0xC5380603, + 0x81C, 0xC43A0603, + 0x81C, 0xC33C0603, + 0x81C, 0xA63E0603, + 0x81C, 0xA5400603, + 0x81C, 0xA4420603, + 0x81C, 0xA3440603, + 0x81C, 0xA2460603, + 0x81C, 0xA1480603, + 0x81C, 0x834A0603, + 0x81C, 0x824C0603, + 0x81C, 0x814E0603, + 0x81C, 0x64500603, + 0x81C, 0x63520603, + 0x81C, 0x62540603, + 0x81C, 0x61560603, + 0x81C, 0x60580603, + 0x81C, 0x405A0603, + 0x81C, 0x215C0603, + 0x81C, 0x205E0603, + 0x81C, 0x03600603, + 0x81C, 0x02620603, + 0x81C, 0x01640603, + 0x81C, 0x00660603, + 0x81C, 0x00680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0x9000000d, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000603, + 0x81C, 0xFB020603, + 0x81C, 0xFA040603, + 0x81C, 0xF9060603, + 0x81C, 0xF8080603, + 0x81C, 0xF70A0603, + 0x81C, 0xF60C0603, + 0x81C, 0xF50E0603, + 0x81C, 0xF4100603, + 0x81C, 0xF3120603, + 0x81C, 0xF2140603, + 0x81C, 0xF1160603, + 0x81C, 0xF0180603, + 0x81C, 0xEE1A0603, + 0x81C, 0xED1C0603, + 0x81C, 0xEC1E0603, + 0x81C, 0xEB200603, + 0x81C, 0xEA220603, + 0x81C, 0xE9240603, + 0x81C, 0xE8260603, + 0x81C, 0xE7280603, + 0x81C, 0xE62A0603, + 0x81C, 0xE52C0603, + 0x81C, 0xE42E0603, + 0x81C, 0xE3300603, + 0x81C, 0xE2320603, + 0x81C, 0xC6340603, + 0x81C, 0xC5360603, + 0x81C, 0xC4380603, + 0x81C, 0xC33A0603, + 0x81C, 0xA63C0603, + 0x81C, 0xA53E0603, + 0x81C, 0xA4400603, + 0x81C, 0xA3420603, + 0x81C, 0xA2440603, + 0x81C, 0xA1460603, + 0x81C, 0x83480603, + 0x81C, 0x824A0603, + 0x81C, 0x814C0603, + 0x81C, 0x804E0603, + 0x81C, 0x63500603, + 0x81C, 0x62520603, + 0x81C, 0x61540603, + 0x81C, 0x42560603, + 0x81C, 0x41580603, + 0x81C, 0x405A0603, + 0x81C, 0x225C0603, + 0x81C, 0x215E0603, + 0x81C, 0x20600603, + 0x81C, 0x04620603, + 0x81C, 0x03640603, + 0x81C, 0x02660603, + 0x81C, 0x01680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0x9000000e, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000603, + 0x81C, 0xFB020603, + 0x81C, 0xFA040603, + 0x81C, 0xF9060603, + 0x81C, 0xF8080603, + 0x81C, 0xF70A0603, + 0x81C, 0xF60C0603, + 0x81C, 0xF50E0603, + 0x81C, 0xF4100603, + 0x81C, 0xF3120603, + 0x81C, 0xF2140603, + 0x81C, 0xF1160603, + 0x81C, 0xF0180603, + 0x81C, 0xEE1A0603, + 0x81C, 0xED1C0603, + 0x81C, 0xEC1E0603, + 0x81C, 0xEB200603, + 0x81C, 0xEA220603, + 0x81C, 0xE9240603, + 0x81C, 0xE8260603, + 0x81C, 0xE7280603, + 0x81C, 0xE62A0603, + 0x81C, 0xE52C0603, + 0x81C, 0xE42E0603, + 0x81C, 0xE3300603, + 0x81C, 0xE2320603, + 0x81C, 0xC6340603, + 0x81C, 0xC5360603, + 0x81C, 0xC4380603, + 0x81C, 0xC33A0603, + 0x81C, 0xA63C0603, + 0x81C, 0xA53E0603, + 0x81C, 0xA4400603, + 0x81C, 0xA3420603, + 0x81C, 0xA2440603, + 0x81C, 0xA1460603, + 0x81C, 0x83480603, + 0x81C, 0x824A0603, + 0x81C, 0x814C0603, + 0x81C, 0x804E0603, + 0x81C, 0x63500603, + 0x81C, 0x62520603, + 0x81C, 0x61540603, + 0x81C, 0x42560603, + 0x81C, 0x41580603, + 0x81C, 0x405A0603, + 0x81C, 0x225C0603, + 0x81C, 0x215E0603, + 0x81C, 0x20600603, + 0x81C, 0x04620603, + 0x81C, 0x03640603, + 0x81C, 0x02660603, + 0x81C, 0x01680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0x9000000f, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xBF000603, + 0x81C, 0xBF020603, + 0x81C, 0xBF040603, + 0x81C, 0xBF060603, + 0x81C, 0xBF080603, + 0x81C, 0xBE0A0603, + 0x81C, 0xBD0C0603, + 0x81C, 0xBC0E0603, + 0x81C, 0xBB100603, + 0x81C, 0xBA120603, + 0x81C, 0xB9140603, + 0x81C, 0xB8160603, + 0x81C, 0xB7180603, + 0x81C, 0xB61A0603, + 0x81C, 0xB51C0603, + 0x81C, 0xB41E0603, + 0x81C, 0xB1200603, + 0x81C, 0xB2220603, + 0x81C, 0xB1240603, + 0x81C, 0xB0260603, + 0x81C, 0xAF280603, + 0x81C, 0xAE2A0603, + 0x81C, 0xAD2C0603, + 0x81C, 0xAC2E0603, + 0x81C, 0xAB300603, + 0x81C, 0xAA320603, + 0x81C, 0xC6340603, + 0x81C, 0xC5360603, + 0x81C, 0xC4380603, + 0x81C, 0xC33A0603, + 0x81C, 0x883C0603, + 0x81C, 0x873E0603, + 0x81C, 0x86400603, + 0x81C, 0x85420603, + 0x81C, 0x84440603, + 0x81C, 0x83460603, + 0x81C, 0x67480603, + 0x81C, 0x664A0603, + 0x81C, 0x654C0603, + 0x81C, 0x644E0603, + 0x81C, 0x27500603, + 0x81C, 0x26520603, + 0x81C, 0x25540603, + 0x81C, 0x24560603, + 0x81C, 0x23580603, + 0x81C, 0x225A0603, + 0x81C, 0x215C0603, + 0x81C, 0x205E0603, + 0x81C, 0x03600603, + 0x81C, 0x02620603, + 0x81C, 0x01640603, + 0x81C, 0x00660603, + 0x81C, 0x00680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0x90000010, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000403, + 0x81C, 0xFB000603, + 0x81C, 0xFA020603, + 0x81C, 0xF9040603, + 0x81C, 0xF8060603, + 0x81C, 0xF7080603, + 0x81C, 0xF60A0603, + 0x81C, 0xF50C0603, + 0x81C, 0xF40E0603, + 0x81C, 0xF3100603, + 0x81C, 0xF2120603, + 0x81C, 0xF1140603, + 0x81C, 0xF0160603, + 0x81C, 0xEF180603, + 0x81C, 0xEE1A0603, + 0x81C, 0xED1C0603, + 0x81C, 0xEC1E0603, + 0x81C, 0xEB200603, + 0x81C, 0xEA220603, + 0x81C, 0xE9240603, + 0x81C, 0xE8260603, + 0x81C, 0xE7280603, + 0x81C, 0xE62A0603, + 0x81C, 0xE52C0603, + 0x81C, 0xE42E0603, + 0x81C, 0xE3300603, + 0x81C, 0xE2320603, + 0x81C, 0xC6340603, + 0x81C, 0xC5360603, + 0x81C, 0xC4380603, + 0x81C, 0xC33A0603, + 0x81C, 0xA63C0603, + 0x81C, 0xA53E0603, + 0x81C, 0xA4400603, + 0x81C, 0xA3420603, + 0x81C, 0xA2440603, + 0x81C, 0xA1460603, + 0x81C, 0x83480603, + 0x81C, 0x824A0603, + 0x81C, 0x814C0603, + 0x81C, 0x644E0603, + 0x81C, 0x63500603, + 0x81C, 0x62520603, + 0x81C, 0x61540603, + 0x81C, 0x60560603, + 0x81C, 0x40580603, + 0x81C, 0x215A0603, + 0x81C, 0x205C0603, + 0x81C, 0x035E0603, + 0x81C, 0x02600603, + 0x81C, 0x01620603, + 0x81C, 0x00640603, + 0x81C, 0x00660603, + 0x81C, 0x00680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x90000012, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF7000603, + 0x81C, 0xF6020603, + 0x81C, 0xF5040603, + 0x81C, 0xF4060603, + 0x81C, 0xF3080603, + 0x81C, 0xF20A0603, + 0x81C, 0xF10C0603, + 0x81C, 0xF00E0603, + 0x81C, 0xEF100603, + 0x81C, 0xEE120603, + 0x81C, 0xED140603, + 0x81C, 0xEC160603, + 0x81C, 0xEB180603, + 0x81C, 0xEA1A0603, + 0x81C, 0xE91C0603, + 0x81C, 0xE81E0603, + 0x81C, 0xE7200603, + 0x81C, 0xE6220603, + 0x81C, 0xE5240603, + 0x81C, 0xE4260603, + 0x81C, 0xE3280603, + 0x81C, 0xC42A0603, + 0x81C, 0xC32C0603, + 0x81C, 0xC22E0603, + 0x81C, 0xC1300603, + 0x81C, 0xC0320603, + 0x81C, 0xA3340603, + 0x81C, 0xA2360603, + 0x81C, 0xA1380603, + 0x81C, 0xA03A0603, + 0x81C, 0x823C0603, + 0x81C, 0x813E0603, + 0x81C, 0x80400603, + 0x81C, 0x64420603, + 0x81C, 0x63440603, + 0x81C, 0x62460603, + 0x81C, 0x61480603, + 0x81C, 0x604A0603, + 0x81C, 0x414C0603, + 0x81C, 0x404E0603, + 0x81C, 0x22500603, + 0x81C, 0x21520603, + 0x81C, 0x20540603, + 0x81C, 0x03560603, + 0x81C, 0x02580603, + 0x81C, 0x015A0603, + 0x81C, 0x005C0603, + 0x81C, 0x005E0603, + 0x81C, 0x00600603, + 0x81C, 0x00620603, + 0x81C, 0x00640603, + 0x81C, 0x00660603, + 0x81C, 0x00680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0xA0000000, 0x00000000, + 0x81C, 0xFD000603, + 0x81C, 0xFC020603, + 0x81C, 0xFB040603, + 0x81C, 0xFA060603, + 0x81C, 0xF9080603, + 0x81C, 0xF80A0603, + 0x81C, 0xF70C0603, + 0x81C, 0xF60E0603, + 0x81C, 0xF5100603, + 0x81C, 0xF4120603, + 0x81C, 0xF3140603, + 0x81C, 0xF2160603, + 0x81C, 0xF1180603, + 0x81C, 0xF01A0603, + 0x81C, 0xEF1C0603, + 0x81C, 0xEE1E0603, + 0x81C, 0xED200603, + 0x81C, 0xEC220603, + 0x81C, 0xEB240603, + 0x81C, 0xEA260603, + 0x81C, 0xE9280603, + 0x81C, 0xE82A0603, + 0x81C, 0xE72C0603, + 0x81C, 0xE62E0603, + 0x81C, 0xE5300603, + 0x81C, 0xE4320603, + 0x81C, 0xE3340603, + 0x81C, 0xC6360603, + 0x81C, 0xC5380603, + 0x81C, 0xC43A0603, + 0x81C, 0xC33C0603, + 0x81C, 0xA63E0603, + 0x81C, 0xA5400603, + 0x81C, 0xA4420603, + 0x81C, 0xA3440603, + 0x81C, 0xA2460603, + 0x81C, 0xA1480603, + 0x81C, 0x834A0603, + 0x81C, 0x824C0603, + 0x81C, 0x814E0603, + 0x81C, 0x64500603, + 0x81C, 0x63520603, + 0x81C, 0x62540603, + 0x81C, 0x61560603, + 0x81C, 0x60580603, + 0x81C, 0x235A0603, + 0x81C, 0x225C0603, + 0x81C, 0x215E0603, + 0x81C, 0x20600603, + 0x81C, 0x03620603, + 0x81C, 0x02640603, + 0x81C, 0x01660603, + 0x81C, 0x00680603, + 0x81C, 0x006A0603, + 0x81C, 0x006C0603, + 0x81C, 0x006E0603, + 0x81C, 0x00700603, + 0x81C, 0x00720603, + 0x81C, 0x00740603, + 0x81C, 0x00760603, + 0x81C, 0x00780603, + 0x81C, 0x007A0603, + 0x81C, 0x007C0603, + 0x81C, 0x007E0603, + 0x81C, 0x007E0603, + 0xB0000000, 0x00000000, + 0x80000000, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000703, + 0x81C, 0xFB020703, + 0x81C, 0xFA040703, + 0x81C, 0xF9060703, + 0x81C, 0xF8080703, + 0x81C, 0xF70A0703, + 0x81C, 0xF60C0703, + 0x81C, 0xF50E0703, + 0x81C, 0xF4100703, + 0x81C, 0xF3120703, + 0x81C, 0xF2140703, + 0x81C, 0xF1160703, + 0x81C, 0xEF180703, + 0x81C, 0xEE1A0703, + 0x81C, 0xED1C0703, + 0x81C, 0xEC1E0703, + 0x81C, 0xEB200703, + 0x81C, 0xEA220703, + 0x81C, 0xE9240703, + 0x81C, 0xE8260703, + 0x81C, 0xE7280703, + 0x81C, 0xE62A0703, + 0x81C, 0xE52C0703, + 0x81C, 0xE42E0703, + 0x81C, 0xE3300703, + 0x81C, 0xE2320703, + 0x81C, 0xC6340703, + 0x81C, 0xC5360703, + 0x81C, 0xC4380703, + 0x81C, 0xC33A0703, + 0x81C, 0xA63C0703, + 0x81C, 0xA53E0703, + 0x81C, 0xA4400703, + 0x81C, 0xA3420703, + 0x81C, 0xA2440703, + 0x81C, 0xA1460703, + 0x81C, 0x83480703, + 0x81C, 0x824A0703, + 0x81C, 0x814C0703, + 0x81C, 0x804E0703, + 0x81C, 0x63500703, + 0x81C, 0x62520703, + 0x81C, 0x61540703, + 0x81C, 0x42560703, + 0x81C, 0x41580703, + 0x81C, 0x405A0703, + 0x81C, 0x225C0703, + 0x81C, 0x215E0703, + 0x81C, 0x20600703, + 0x81C, 0x04620703, + 0x81C, 0x03640703, + 0x81C, 0x02660703, + 0x81C, 0x01680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xBD000703, + 0x81C, 0xBC020703, + 0x81C, 0xBB040703, + 0x81C, 0xBA060703, + 0x81C, 0xB9080703, + 0x81C, 0xB80A0703, + 0x81C, 0xB70C0703, + 0x81C, 0xB60E0703, + 0x81C, 0xB5100703, + 0x81C, 0xB4120703, + 0x81C, 0xB3140703, + 0x81C, 0xB2160703, + 0x81C, 0xB1180703, + 0x81C, 0xB01A0703, + 0x81C, 0xAF1C0703, + 0x81C, 0xAE1E0703, + 0x81C, 0xAD200703, + 0x81C, 0xAC220703, + 0x81C, 0x8E240703, + 0x81C, 0x8D260703, + 0x81C, 0x8C280703, + 0x81C, 0x6F2A0703, + 0x81C, 0x6E2C0703, + 0x81C, 0x6D2E0703, + 0x81C, 0x6C300703, + 0x81C, 0x6B320703, + 0x81C, 0x6A340703, + 0x81C, 0x69360703, + 0x81C, 0x68380703, + 0x81C, 0x673A0703, + 0x81C, 0x663C0703, + 0x81C, 0x653E0703, + 0x81C, 0x64400703, + 0x81C, 0x63420703, + 0x81C, 0x62440703, + 0x81C, 0x61460703, + 0x81C, 0x60480703, + 0x81C, 0x424A0703, + 0x81C, 0x414C0703, + 0x81C, 0x404E0703, + 0x81C, 0x06500703, + 0x81C, 0x05520703, + 0x81C, 0x04540703, + 0x81C, 0x03560703, + 0x81C, 0x02580703, + 0x81C, 0x015A0703, + 0x81C, 0x005C0703, + 0x81C, 0x005E0703, + 0x81C, 0x00600703, + 0x81C, 0x00620703, + 0x81C, 0x00640703, + 0x81C, 0x00660703, + 0x81C, 0x00680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007C0703, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF7000703, + 0x81C, 0xF6020703, + 0x81C, 0xF5040703, + 0x81C, 0xF4060703, + 0x81C, 0xF3080703, + 0x81C, 0xF20A0703, + 0x81C, 0xF10C0703, + 0x81C, 0xF00E0703, + 0x81C, 0xEF100703, + 0x81C, 0xEE120703, + 0x81C, 0xED140703, + 0x81C, 0xEC160703, + 0x81C, 0xEB180703, + 0x81C, 0xEA1A0703, + 0x81C, 0xE91C0703, + 0x81C, 0xCA1E0703, + 0x81C, 0xC9200703, + 0x81C, 0xC8220703, + 0x81C, 0xC7240703, + 0x81C, 0xC6260703, + 0x81C, 0xC5280703, + 0x81C, 0xC42A0703, + 0x81C, 0xC32C0703, + 0x81C, 0xC22E0703, + 0x81C, 0xC1300703, + 0x81C, 0xA4320703, + 0x81C, 0xA3340703, + 0x81C, 0xA2360703, + 0x81C, 0xA1380703, + 0x81C, 0xA03A0703, + 0x81C, 0x823C0703, + 0x81C, 0x813E0703, + 0x81C, 0x80400703, + 0x81C, 0x64420703, + 0x81C, 0x63440703, + 0x81C, 0x62460703, + 0x81C, 0x61480703, + 0x81C, 0x604A0703, + 0x81C, 0x414C0703, + 0x81C, 0x404E0703, + 0x81C, 0x22500703, + 0x81C, 0x21520703, + 0x81C, 0x20540703, + 0x81C, 0x03560703, + 0x81C, 0x02580703, + 0x81C, 0x015A0703, + 0x81C, 0x005C0703, + 0x81C, 0x005E0703, + 0x81C, 0x00600703, + 0x81C, 0x00620703, + 0x81C, 0x00640703, + 0x81C, 0x00660703, + 0x81C, 0x00680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000703, + 0x81C, 0xFB020703, + 0x81C, 0xFA040703, + 0x81C, 0xF9060703, + 0x81C, 0xF8080703, + 0x81C, 0xF70A0703, + 0x81C, 0xF60C0703, + 0x81C, 0xF50E0703, + 0x81C, 0xF4100703, + 0x81C, 0xF3120703, + 0x81C, 0xF2140703, + 0x81C, 0xF1160703, + 0x81C, 0xF0180703, + 0x81C, 0xEF1A0703, + 0x81C, 0xEE1C0703, + 0x81C, 0xED1E0703, + 0x81C, 0xEC200703, + 0x81C, 0xEB220703, + 0x81C, 0xEA240703, + 0x81C, 0xE9260703, + 0x81C, 0xE8280703, + 0x81C, 0xE72A0703, + 0x81C, 0xE62C0703, + 0x81C, 0xE52E0703, + 0x81C, 0xE4300703, + 0x81C, 0xE3320703, + 0x81C, 0xE2340703, + 0x81C, 0xC6360703, + 0x81C, 0xC5380703, + 0x81C, 0xC43A0703, + 0x81C, 0xC33C0703, + 0x81C, 0xA63E0703, + 0x81C, 0xA5400703, + 0x81C, 0xA4420703, + 0x81C, 0xA3440703, + 0x81C, 0xA2460703, + 0x81C, 0x84480703, + 0x81C, 0x834A0703, + 0x81C, 0x824C0703, + 0x81C, 0x814E0703, + 0x81C, 0x80500703, + 0x81C, 0x63520703, + 0x81C, 0x62540703, + 0x81C, 0x61560703, + 0x81C, 0x60580703, + 0x81C, 0x225A0703, + 0x81C, 0x055C0703, + 0x81C, 0x045E0703, + 0x81C, 0x03600703, + 0x81C, 0x02620703, + 0x81C, 0x01640703, + 0x81C, 0x00660703, + 0x81C, 0x00680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF7000703, + 0x81C, 0xF6020703, + 0x81C, 0xF5040703, + 0x81C, 0xF4060703, + 0x81C, 0xF3080703, + 0x81C, 0xF20A0703, + 0x81C, 0xF10C0703, + 0x81C, 0xF00E0703, + 0x81C, 0xEF100703, + 0x81C, 0xEE120703, + 0x81C, 0xED140703, + 0x81C, 0xEC160703, + 0x81C, 0xEB180703, + 0x81C, 0xEA1A0703, + 0x81C, 0xE91C0703, + 0x81C, 0xCA1E0703, + 0x81C, 0xC9200703, + 0x81C, 0xC8220703, + 0x81C, 0xC7240703, + 0x81C, 0xC6260703, + 0x81C, 0xC5280703, + 0x81C, 0xC42A0703, + 0x81C, 0xC32C0703, + 0x81C, 0xC22E0703, + 0x81C, 0xC1300703, + 0x81C, 0xA4320703, + 0x81C, 0xA3340703, + 0x81C, 0xA2360703, + 0x81C, 0xA1380703, + 0x81C, 0xA03A0703, + 0x81C, 0x823C0703, + 0x81C, 0x813E0703, + 0x81C, 0x80400703, + 0x81C, 0x64420703, + 0x81C, 0x63440703, + 0x81C, 0x62460703, + 0x81C, 0x61480703, + 0x81C, 0x604A0703, + 0x81C, 0x414C0703, + 0x81C, 0x404E0703, + 0x81C, 0x22500703, + 0x81C, 0x21520703, + 0x81C, 0x20540703, + 0x81C, 0x03560703, + 0x81C, 0x02580703, + 0x81C, 0x015A0703, + 0x81C, 0x005C0703, + 0x81C, 0x005E0703, + 0x81C, 0x00600703, + 0x81C, 0x00620703, + 0x81C, 0x00640703, + 0x81C, 0x00660703, + 0x81C, 0x00680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFB000703, + 0x81C, 0xFA020703, + 0x81C, 0xF9040703, + 0x81C, 0xF8060703, + 0x81C, 0xF7080703, + 0x81C, 0xF60A0703, + 0x81C, 0xF50C0703, + 0x81C, 0xF40E0703, + 0x81C, 0xF3100703, + 0x81C, 0xF2120703, + 0x81C, 0xF1140703, + 0x81C, 0xF0160703, + 0x81C, 0xEF180703, + 0x81C, 0xEE1A0703, + 0x81C, 0xED1C0703, + 0x81C, 0xEC1E0703, + 0x81C, 0xEB200703, + 0x81C, 0xEA220703, + 0x81C, 0xE9240703, + 0x81C, 0xE8260703, + 0x81C, 0xE7280703, + 0x81C, 0xE62A0703, + 0x81C, 0xE52C0703, + 0x81C, 0xE42E0703, + 0x81C, 0xE3300703, + 0x81C, 0xE2320703, + 0x81C, 0xE1340703, + 0x81C, 0xC5360703, + 0x81C, 0xC4380703, + 0x81C, 0xC33A0703, + 0x81C, 0xC23C0703, + 0x81C, 0xC13E0703, + 0x81C, 0xA4400703, + 0x81C, 0xA3420703, + 0x81C, 0xA2440703, + 0x81C, 0xA1460703, + 0x81C, 0x83480703, + 0x81C, 0x824A0703, + 0x81C, 0x814C0703, + 0x81C, 0x804E0703, + 0x81C, 0x64500703, + 0x81C, 0x63520703, + 0x81C, 0x62540703, + 0x81C, 0x61560703, + 0x81C, 0x60580703, + 0x81C, 0x235A0703, + 0x81C, 0x225C0703, + 0x81C, 0x215E0703, + 0x81C, 0x20600703, + 0x81C, 0x04620703, + 0x81C, 0x03640703, + 0x81C, 0x02660703, + 0x81C, 0x01680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF9000703, + 0x81C, 0xF8020703, + 0x81C, 0xF7040703, + 0x81C, 0xF6060703, + 0x81C, 0xF5080703, + 0x81C, 0xF40A0703, + 0x81C, 0xF30C0703, + 0x81C, 0xF20E0703, + 0x81C, 0xF1100703, + 0x81C, 0xF0120703, + 0x81C, 0xEF140703, + 0x81C, 0xEE160703, + 0x81C, 0xED180703, + 0x81C, 0xEC1A0703, + 0x81C, 0xEB1C0703, + 0x81C, 0xEA1E0703, + 0x81C, 0xC9200703, + 0x81C, 0xC8220703, + 0x81C, 0xC7240703, + 0x81C, 0xC6260703, + 0x81C, 0xC5280703, + 0x81C, 0xC42A0703, + 0x81C, 0xC32C0703, + 0x81C, 0xC22E0703, + 0x81C, 0xC1300703, + 0x81C, 0xC0320703, + 0x81C, 0xA3340703, + 0x81C, 0xA2360703, + 0x81C, 0xA1380703, + 0x81C, 0xA03A0703, + 0x81C, 0x823C0703, + 0x81C, 0x813E0703, + 0x81C, 0x80400703, + 0x81C, 0x64420703, + 0x81C, 0x63440703, + 0x81C, 0x62460703, + 0x81C, 0x61480703, + 0x81C, 0x604A0703, + 0x81C, 0x414C0703, + 0x81C, 0x404E0703, + 0x81C, 0x22500703, + 0x81C, 0x21520703, + 0x81C, 0x20540703, + 0x81C, 0x03560703, + 0x81C, 0x02580703, + 0x81C, 0x015A0703, + 0x81C, 0x005C0703, + 0x81C, 0x005E0703, + 0x81C, 0x00600703, + 0x81C, 0x00620703, + 0x81C, 0x00640703, + 0x81C, 0x00660703, + 0x81C, 0x00680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xBE000703, + 0x81C, 0xBD020703, + 0x81C, 0xBC040703, + 0x81C, 0xBB060703, + 0x81C, 0xBA080703, + 0x81C, 0xB90A0703, + 0x81C, 0xB80C0703, + 0x81C, 0xB70E0703, + 0x81C, 0xB6100703, + 0x81C, 0xB5120703, + 0x81C, 0xB4140703, + 0x81C, 0xB3160703, + 0x81C, 0xB2180703, + 0x81C, 0xB11A0703, + 0x81C, 0xB01C0703, + 0x81C, 0x921E0703, + 0x81C, 0x91200703, + 0x81C, 0x90220703, + 0x81C, 0x8F240703, + 0x81C, 0x8E260703, + 0x81C, 0x8D280703, + 0x81C, 0x8C2A0703, + 0x81C, 0x6F2C0703, + 0x81C, 0x6E2E0703, + 0x81C, 0x6D300703, + 0x81C, 0x6C320703, + 0x81C, 0x6B340703, + 0x81C, 0x6A360703, + 0x81C, 0x69380703, + 0x81C, 0x683A0703, + 0x81C, 0x673C0703, + 0x81C, 0x663E0703, + 0x81C, 0x65400703, + 0x81C, 0x64420703, + 0x81C, 0x63440703, + 0x81C, 0x62460703, + 0x81C, 0x61480703, + 0x81C, 0x604A0703, + 0x81C, 0x424C0703, + 0x81C, 0x414E0703, + 0x81C, 0x40500703, + 0x81C, 0x06520703, + 0x81C, 0x05540703, + 0x81C, 0x04560703, + 0x81C, 0x03580703, + 0x81C, 0x025A0703, + 0x81C, 0x015C0703, + 0x81C, 0x005E0703, + 0x81C, 0x00600703, + 0x81C, 0x00620703, + 0x81C, 0x00640703, + 0x81C, 0x00660703, + 0x81C, 0x00680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0x90000008, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFB000703, + 0x81C, 0xFA020703, + 0x81C, 0xF9040703, + 0x81C, 0xF8060703, + 0x81C, 0xF7080703, + 0x81C, 0xF60A0703, + 0x81C, 0xF50C0703, + 0x81C, 0xF40E0703, + 0x81C, 0xF3100703, + 0x81C, 0xF2120703, + 0x81C, 0xF1140703, + 0x81C, 0xF0160703, + 0x81C, 0xEF180703, + 0x81C, 0xEE1A0703, + 0x81C, 0xED1C0703, + 0x81C, 0xEC1E0703, + 0x81C, 0xEB200703, + 0x81C, 0xEA220703, + 0x81C, 0xE9240703, + 0x81C, 0xE8260703, + 0x81C, 0xE7280703, + 0x81C, 0xE62A0703, + 0x81C, 0xE52C0703, + 0x81C, 0xE42E0703, + 0x81C, 0xE3300703, + 0x81C, 0xE2320703, + 0x81C, 0xC6340703, + 0x81C, 0xC5360703, + 0x81C, 0xC4380703, + 0x81C, 0xC33A0703, + 0x81C, 0xC23C0703, + 0x81C, 0xC13E0703, + 0x81C, 0xA4400703, + 0x81C, 0xA3420703, + 0x81C, 0xA2440703, + 0x81C, 0xA1460703, + 0x81C, 0x83480703, + 0x81C, 0x824A0703, + 0x81C, 0x814C0703, + 0x81C, 0x804E0703, + 0x81C, 0x63500703, + 0x81C, 0x62520703, + 0x81C, 0x43540703, + 0x81C, 0x42560703, + 0x81C, 0x41580703, + 0x81C, 0x235A0703, + 0x81C, 0x225C0703, + 0x81C, 0x215E0703, + 0x81C, 0x20600703, + 0x81C, 0x04620703, + 0x81C, 0x03640703, + 0x81C, 0x02660703, + 0x81C, 0x01680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0x90000009, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000703, + 0x81C, 0xF7020703, + 0x81C, 0xF6040703, + 0x81C, 0xF5060703, + 0x81C, 0xF4080703, + 0x81C, 0xF30A0703, + 0x81C, 0xF20C0703, + 0x81C, 0xF10E0703, + 0x81C, 0xF0100703, + 0x81C, 0xEF120703, + 0x81C, 0xEE140703, + 0x81C, 0xED160703, + 0x81C, 0xEC180703, + 0x81C, 0xEB1A0703, + 0x81C, 0xEA1C0703, + 0x81C, 0xE91E0703, + 0x81C, 0xCA200703, + 0x81C, 0xC9220703, + 0x81C, 0xC8240703, + 0x81C, 0xC7260703, + 0x81C, 0xC6280703, + 0x81C, 0xC52A0703, + 0x81C, 0xC42C0703, + 0x81C, 0xC32E0703, + 0x81C, 0xC2300703, + 0x81C, 0xC1320703, + 0x81C, 0xA3340703, + 0x81C, 0xA2360703, + 0x81C, 0xA1380703, + 0x81C, 0xA03A0703, + 0x81C, 0x823C0703, + 0x81C, 0x813E0703, + 0x81C, 0x80400703, + 0x81C, 0x65420703, + 0x81C, 0x64440703, + 0x81C, 0x63460703, + 0x81C, 0x62480703, + 0x81C, 0x614A0703, + 0x81C, 0x424C0703, + 0x81C, 0x414E0703, + 0x81C, 0x40500703, + 0x81C, 0x22520703, + 0x81C, 0x21540703, + 0x81C, 0x20560703, + 0x81C, 0x04580703, + 0x81C, 0x035A0703, + 0x81C, 0x025C0703, + 0x81C, 0x015E0703, + 0x81C, 0x00600703, + 0x81C, 0x00620703, + 0x81C, 0x00640703, + 0x81C, 0x00660703, + 0x81C, 0x00680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0x9000000a, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000703, + 0x81C, 0xFB020703, + 0x81C, 0xFA040703, + 0x81C, 0xF9060703, + 0x81C, 0xF8080703, + 0x81C, 0xF70A0703, + 0x81C, 0xF60C0703, + 0x81C, 0xF50E0703, + 0x81C, 0xF4100703, + 0x81C, 0xF3120703, + 0x81C, 0xF2140703, + 0x81C, 0xF1160703, + 0x81C, 0xEF180703, + 0x81C, 0xEE1A0703, + 0x81C, 0xED1C0703, + 0x81C, 0xEC1E0703, + 0x81C, 0xEB200703, + 0x81C, 0xEA220703, + 0x81C, 0xE9240703, + 0x81C, 0xE8260703, + 0x81C, 0xE7280703, + 0x81C, 0xE62A0703, + 0x81C, 0xE52C0703, + 0x81C, 0xE42E0703, + 0x81C, 0xE3300703, + 0x81C, 0xE2320703, + 0x81C, 0xC6340703, + 0x81C, 0xC5360703, + 0x81C, 0xC4380703, + 0x81C, 0xC33A0703, + 0x81C, 0xA63C0703, + 0x81C, 0xA53E0703, + 0x81C, 0xA4400703, + 0x81C, 0xA3420703, + 0x81C, 0xA2440703, + 0x81C, 0xA1460703, + 0x81C, 0x83480703, + 0x81C, 0x824A0703, + 0x81C, 0x814C0703, + 0x81C, 0x804E0703, + 0x81C, 0x63500703, + 0x81C, 0x62520703, + 0x81C, 0x61540703, + 0x81C, 0x42560703, + 0x81C, 0x41580703, + 0x81C, 0x405A0703, + 0x81C, 0x225C0703, + 0x81C, 0x215E0703, + 0x81C, 0x20600703, + 0x81C, 0x04620703, + 0x81C, 0x03640703, + 0x81C, 0x02660703, + 0x81C, 0x01680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0x9000000b, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF8000703, + 0x81C, 0xF7020703, + 0x81C, 0xF6040703, + 0x81C, 0xF5060703, + 0x81C, 0xF4080703, + 0x81C, 0xF30A0703, + 0x81C, 0xF20C0703, + 0x81C, 0xF10E0703, + 0x81C, 0xF0100703, + 0x81C, 0xEF120703, + 0x81C, 0xEE140703, + 0x81C, 0xED160703, + 0x81C, 0xEC180703, + 0x81C, 0xEB1A0703, + 0x81C, 0xEA1C0703, + 0x81C, 0xE91E0703, + 0x81C, 0xCA200703, + 0x81C, 0xC9220703, + 0x81C, 0xC8240703, + 0x81C, 0xC7260703, + 0x81C, 0xC6280703, + 0x81C, 0xC52A0703, + 0x81C, 0xC42C0703, + 0x81C, 0xC32E0703, + 0x81C, 0xC2300703, + 0x81C, 0xC1320703, + 0x81C, 0xA3340703, + 0x81C, 0xA2360703, + 0x81C, 0xA1380703, + 0x81C, 0xA03A0703, + 0x81C, 0x823C0703, + 0x81C, 0x813E0703, + 0x81C, 0x80400703, + 0x81C, 0x64420703, + 0x81C, 0x63440703, + 0x81C, 0x62460703, + 0x81C, 0x61480703, + 0x81C, 0x604A0703, + 0x81C, 0x234C0703, + 0x81C, 0x224E0703, + 0x81C, 0x21500703, + 0x81C, 0x20520703, + 0x81C, 0x06540703, + 0x81C, 0x05560703, + 0x81C, 0x04580703, + 0x81C, 0x035A0703, + 0x81C, 0x025C0703, + 0x81C, 0x015E0703, + 0x81C, 0x00600703, + 0x81C, 0x00620703, + 0x81C, 0x00640703, + 0x81C, 0x00660703, + 0x81C, 0x00680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0x9000000c, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000703, + 0x81C, 0xFB020703, + 0x81C, 0xFA040703, + 0x81C, 0xF9060703, + 0x81C, 0xF8080703, + 0x81C, 0xF70A0703, + 0x81C, 0xF60C0703, + 0x81C, 0xF50E0703, + 0x81C, 0xF4100703, + 0x81C, 0xF3120703, + 0x81C, 0xF2140703, + 0x81C, 0xF1160703, + 0x81C, 0xF0180703, + 0x81C, 0xEF1A0703, + 0x81C, 0xEE1C0703, + 0x81C, 0xED1E0703, + 0x81C, 0xEC200703, + 0x81C, 0xEB220703, + 0x81C, 0xEA240703, + 0x81C, 0xE9260703, + 0x81C, 0xE8280703, + 0x81C, 0xE72A0703, + 0x81C, 0xE62C0703, + 0x81C, 0xE52E0703, + 0x81C, 0xE4300703, + 0x81C, 0xE3320703, + 0x81C, 0xE2340703, + 0x81C, 0xC6360703, + 0x81C, 0xC5380703, + 0x81C, 0xC43A0703, + 0x81C, 0xC33C0703, + 0x81C, 0xA63E0703, + 0x81C, 0xA5400703, + 0x81C, 0xA4420703, + 0x81C, 0xA3440703, + 0x81C, 0xA2460703, + 0x81C, 0x84480703, + 0x81C, 0x834A0703, + 0x81C, 0x824C0703, + 0x81C, 0x814E0703, + 0x81C, 0x80500703, + 0x81C, 0x63520703, + 0x81C, 0x62540703, + 0x81C, 0x61560703, + 0x81C, 0x60580703, + 0x81C, 0x225A0703, + 0x81C, 0x055C0703, + 0x81C, 0x045E0703, + 0x81C, 0x03600703, + 0x81C, 0x02620703, + 0x81C, 0x01640703, + 0x81C, 0x00660703, + 0x81C, 0x00680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0x9000000d, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFB000703, + 0x81C, 0xFA020703, + 0x81C, 0xF9040703, + 0x81C, 0xF8060703, + 0x81C, 0xF7080703, + 0x81C, 0xF60A0703, + 0x81C, 0xF50C0703, + 0x81C, 0xF40E0703, + 0x81C, 0xF3100703, + 0x81C, 0xF2120703, + 0x81C, 0xF1140703, + 0x81C, 0xEF160703, + 0x81C, 0xEE180703, + 0x81C, 0xED1A0703, + 0x81C, 0xEC1C0703, + 0x81C, 0xEB1E0703, + 0x81C, 0xEA200703, + 0x81C, 0xE9220703, + 0x81C, 0xE8240703, + 0x81C, 0xE7260703, + 0x81C, 0xE6280703, + 0x81C, 0xE52A0703, + 0x81C, 0xE42C0703, + 0x81C, 0xE32E0703, + 0x81C, 0xE2300703, + 0x81C, 0xE1320703, + 0x81C, 0xC6340703, + 0x81C, 0xC5360703, + 0x81C, 0xC4380703, + 0x81C, 0xC33A0703, + 0x81C, 0xA63C0703, + 0x81C, 0xA53E0703, + 0x81C, 0xA4400703, + 0x81C, 0xA3420703, + 0x81C, 0xA2440703, + 0x81C, 0xA1460703, + 0x81C, 0x83480703, + 0x81C, 0x824A0703, + 0x81C, 0x814C0703, + 0x81C, 0x804E0703, + 0x81C, 0x63500703, + 0x81C, 0x62520703, + 0x81C, 0x61540703, + 0x81C, 0x42560703, + 0x81C, 0x41580703, + 0x81C, 0x405A0703, + 0x81C, 0x225C0703, + 0x81C, 0x215E0703, + 0x81C, 0x20600703, + 0x81C, 0x04620703, + 0x81C, 0x03640703, + 0x81C, 0x02660703, + 0x81C, 0x01680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0x9000000e, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFB000703, + 0x81C, 0xFA020703, + 0x81C, 0xF9040703, + 0x81C, 0xF8060703, + 0x81C, 0xF7080703, + 0x81C, 0xF60A0703, + 0x81C, 0xF50C0703, + 0x81C, 0xF40E0703, + 0x81C, 0xF3100703, + 0x81C, 0xF2120703, + 0x81C, 0xF1140703, + 0x81C, 0xEF160703, + 0x81C, 0xEE180703, + 0x81C, 0xED1A0703, + 0x81C, 0xEC1C0703, + 0x81C, 0xEB1E0703, + 0x81C, 0xEA200703, + 0x81C, 0xE9220703, + 0x81C, 0xE8240703, + 0x81C, 0xE7260703, + 0x81C, 0xE6280703, + 0x81C, 0xE52A0703, + 0x81C, 0xE42C0703, + 0x81C, 0xE32E0703, + 0x81C, 0xE2300703, + 0x81C, 0xE1320703, + 0x81C, 0xC6340703, + 0x81C, 0xC5360703, + 0x81C, 0xC4380703, + 0x81C, 0xC33A0703, + 0x81C, 0xA63C0703, + 0x81C, 0xA53E0703, + 0x81C, 0xA4400703, + 0x81C, 0xA3420703, + 0x81C, 0xA2440703, + 0x81C, 0xA1460703, + 0x81C, 0x83480703, + 0x81C, 0x824A0703, + 0x81C, 0x814C0703, + 0x81C, 0x804E0703, + 0x81C, 0x63500703, + 0x81C, 0x62520703, + 0x81C, 0x61540703, + 0x81C, 0x42560703, + 0x81C, 0x41580703, + 0x81C, 0x405A0703, + 0x81C, 0x225C0703, + 0x81C, 0x215E0703, + 0x81C, 0x20600703, + 0x81C, 0x04620703, + 0x81C, 0x03640703, + 0x81C, 0x02660703, + 0x81C, 0x01680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0x9000000f, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xBF000703, + 0x81C, 0xBF020703, + 0x81C, 0xBF040703, + 0x81C, 0xBF060703, + 0x81C, 0xBF080703, + 0x81C, 0xBE0A0703, + 0x81C, 0xBD0C0703, + 0x81C, 0xBC0E0703, + 0x81C, 0xBB100703, + 0x81C, 0xBA120703, + 0x81C, 0xB9140703, + 0x81C, 0xB8160703, + 0x81C, 0xB7180703, + 0x81C, 0xB61A0703, + 0x81C, 0xB51C0703, + 0x81C, 0xB41E0703, + 0x81C, 0xB1200703, + 0x81C, 0xB2220703, + 0x81C, 0xB1240703, + 0x81C, 0xB0260703, + 0x81C, 0xAF280703, + 0x81C, 0xAE2A0703, + 0x81C, 0xAD2C0703, + 0x81C, 0xAC2E0703, + 0x81C, 0xAB300703, + 0x81C, 0xAA320703, + 0x81C, 0xC6340703, + 0x81C, 0xC5360703, + 0x81C, 0xC4380703, + 0x81C, 0xC33A0703, + 0x81C, 0x883C0703, + 0x81C, 0x873E0703, + 0x81C, 0x86400703, + 0x81C, 0x85420703, + 0x81C, 0x84440703, + 0x81C, 0x83460703, + 0x81C, 0x67480703, + 0x81C, 0x664A0703, + 0x81C, 0x654C0703, + 0x81C, 0x644E0703, + 0x81C, 0x27500703, + 0x81C, 0x26520703, + 0x81C, 0x25540703, + 0x81C, 0x24560703, + 0x81C, 0x23580703, + 0x81C, 0x225A0703, + 0x81C, 0x215C0703, + 0x81C, 0x205E0703, + 0x81C, 0x03600703, + 0x81C, 0x02620703, + 0x81C, 0x01640703, + 0x81C, 0x00660703, + 0x81C, 0x00680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0x90000010, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xFC000403, + 0x81C, 0xFB000703, + 0x81C, 0xFA020703, + 0x81C, 0xF9040703, + 0x81C, 0xF8060703, + 0x81C, 0xF7080703, + 0x81C, 0xF60A0703, + 0x81C, 0xF50C0703, + 0x81C, 0xF40E0703, + 0x81C, 0xF3100703, + 0x81C, 0xF2120703, + 0x81C, 0xF1140703, + 0x81C, 0xF0160703, + 0x81C, 0xEF180703, + 0x81C, 0xEE1A0703, + 0x81C, 0xED1C0703, + 0x81C, 0xEC1E0703, + 0x81C, 0xEB200703, + 0x81C, 0xEA220703, + 0x81C, 0xE9240703, + 0x81C, 0xE8260703, + 0x81C, 0xE7280703, + 0x81C, 0xE62A0703, + 0x81C, 0xE52C0703, + 0x81C, 0xE42E0703, + 0x81C, 0xE3300703, + 0x81C, 0xE2320703, + 0x81C, 0xC6340703, + 0x81C, 0xC5360703, + 0x81C, 0xC4380703, + 0x81C, 0xC33A0703, + 0x81C, 0xA63C0703, + 0x81C, 0xA53E0703, + 0x81C, 0xA4400703, + 0x81C, 0xA3420703, + 0x81C, 0xA2440703, + 0x81C, 0x84460703, + 0x81C, 0x83480703, + 0x81C, 0x824A0703, + 0x81C, 0x814C0703, + 0x81C, 0x804E0703, + 0x81C, 0x63500703, + 0x81C, 0x62520703, + 0x81C, 0x61540703, + 0x81C, 0x60560703, + 0x81C, 0x22580703, + 0x81C, 0x055A0703, + 0x81C, 0x045C0703, + 0x81C, 0x035E0703, + 0x81C, 0x02600703, + 0x81C, 0x01620703, + 0x81C, 0x00640703, + 0x81C, 0x00660703, + 0x81C, 0x00680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x90000012, 0x00000000, 0x40000000, 0x00000000, + 0x81C, 0xF7000703, + 0x81C, 0xF6020703, + 0x81C, 0xF5040703, + 0x81C, 0xF4060703, + 0x81C, 0xF3080703, + 0x81C, 0xF20A0703, + 0x81C, 0xF10C0703, + 0x81C, 0xF00E0703, + 0x81C, 0xEF100703, + 0x81C, 0xEE120703, + 0x81C, 0xED140703, + 0x81C, 0xEC160703, + 0x81C, 0xEB180703, + 0x81C, 0xEA1A0703, + 0x81C, 0xE91C0703, + 0x81C, 0xCA1E0703, + 0x81C, 0xC9200703, + 0x81C, 0xC8220703, + 0x81C, 0xC7240703, + 0x81C, 0xC6260703, + 0x81C, 0xC5280703, + 0x81C, 0xC42A0703, + 0x81C, 0xC32C0703, + 0x81C, 0xC22E0703, + 0x81C, 0xC1300703, + 0x81C, 0xA4320703, + 0x81C, 0xA3340703, + 0x81C, 0xA2360703, + 0x81C, 0xA1380703, + 0x81C, 0xA03A0703, + 0x81C, 0x823C0703, + 0x81C, 0x813E0703, + 0x81C, 0x80400703, + 0x81C, 0x64420703, + 0x81C, 0x63440703, + 0x81C, 0x62460703, + 0x81C, 0x61480703, + 0x81C, 0x604A0703, + 0x81C, 0x414C0703, + 0x81C, 0x404E0703, + 0x81C, 0x22500703, + 0x81C, 0x21520703, + 0x81C, 0x20540703, + 0x81C, 0x03560703, + 0x81C, 0x02580703, + 0x81C, 0x015A0703, + 0x81C, 0x005C0703, + 0x81C, 0x005E0703, + 0x81C, 0x00600703, + 0x81C, 0x00620703, + 0x81C, 0x00640703, + 0x81C, 0x00660703, + 0x81C, 0x00680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0xA0000000, 0x00000000, + 0x81C, 0xFC000703, + 0x81C, 0xFB020703, + 0x81C, 0xFA040703, + 0x81C, 0xF9060703, + 0x81C, 0xF8080703, + 0x81C, 0xF70A0703, + 0x81C, 0xF60C0703, + 0x81C, 0xF50E0703, + 0x81C, 0xF4100703, + 0x81C, 0xF3120703, + 0x81C, 0xF2140703, + 0x81C, 0xF1160703, + 0x81C, 0xF0180703, + 0x81C, 0xEF1A0703, + 0x81C, 0xEE1C0703, + 0x81C, 0xED1E0703, + 0x81C, 0xEC200703, + 0x81C, 0xEB220703, + 0x81C, 0xEA240703, + 0x81C, 0xE9260703, + 0x81C, 0xE8280703, + 0x81C, 0xE72A0703, + 0x81C, 0xE62C0703, + 0x81C, 0xE52E0703, + 0x81C, 0xE4300703, + 0x81C, 0xE3320703, + 0x81C, 0xE2340703, + 0x81C, 0xC6360703, + 0x81C, 0xC5380703, + 0x81C, 0xC43A0703, + 0x81C, 0xC33C0703, + 0x81C, 0xA63E0703, + 0x81C, 0xA5400703, + 0x81C, 0xA4420703, + 0x81C, 0xA3440703, + 0x81C, 0xA2460703, + 0x81C, 0x84480703, + 0x81C, 0x834A0703, + 0x81C, 0x824C0703, + 0x81C, 0x814E0703, + 0x81C, 0x80500703, + 0x81C, 0x63520703, + 0x81C, 0x62540703, + 0x81C, 0x61560703, + 0x81C, 0x60580703, + 0x81C, 0x235A0703, + 0x81C, 0x225C0703, + 0x81C, 0x215E0703, + 0x81C, 0x20600703, + 0x81C, 0x03620703, + 0x81C, 0x02640703, + 0x81C, 0x01660703, + 0x81C, 0x00680703, + 0x81C, 0x006A0703, + 0x81C, 0x006C0703, + 0x81C, 0x006E0703, + 0x81C, 0x00700703, + 0x81C, 0x00720703, + 0x81C, 0x00740703, + 0x81C, 0x00760703, + 0x81C, 0x00780703, + 0x81C, 0x007A0703, + 0x81C, 0x007C0703, + 0x81C, 0x007E0703, + 0x81C, 0x007E0703, + 0xB0000000, 0x00000000, + 0x80000000, 0x00000000, 0x40000000, 0x00000000, + 0xC50, 0x00000022, + 0xC50, 0x00000020, + 0xE50, 0x00000022, + 0xE50, 0x00000020, + 0x9000000d, 0x00000000, 0x40000000, 0x00000000, + 0xC50, 0x00000022, + 0xC50, 0x00000020, + 0xE50, 0x00000022, + 0xE50, 0x00000020, + 0x9000000e, 0x00000000, 0x40000000, 0x00000000, + 0xC50, 0x00000022, + 0xC50, 0x00000020, + 0xE50, 0x00000022, + 0xE50, 0x00000020, + 0xA0000000, 0x00000000, + 0xC50, 0x00000022, + 0xC50, 0x00000020, + 0xE50, 0x00000022, + 0xE50, 0x00000020, + 0xB0000000, 0x00000000, + +}; + +RTW_DECL_TABLE_PHY_COND(rtw8822b_agc, rtw_phy_cfg_agc); + +static const u32 rtw8822b_bb[] = { + 0x800, 0x9020D010, + 0x804, 0x800181A0, + 0x808, 0x0E028233, + 0x80C, 0x10000013, + 0x810, 0x22101243, + 0x814, 0x020C3D11, + 0x818, 0x84A10385, + 0x81C, 0x1E1E081F, + 0x820, 0x0001AAAA, + 0x824, 0x00030FE0, + 0x828, 0x0000CCCC, + 0x82C, 0x75CB7010, + 0x830, 0x79A0EAAA, + 0x834, 0x072E6986, + 0x838, 0x87766441, + 0x83C, 0x9194B2B7, + 0x840, 0x171750E0, + 0x844, 0x4D3D7CDB, + 0x848, 0x4AD0408B, + 0x84C, 0x6AFBF7A5, + 0x850, 0x28A74706, + 0x854, 0x0001520C, + 0x858, 0x4060C000, + 0x85C, 0x74010160, + 0x860, 0x68A7C321, + 0x864, 0x79F27032, + 0x868, 0x8CA7A314, + 0x86C, 0x778C2878, + 0x870, 0x77777777, + 0x874, 0x27612C2E, + 0x878, 0xC0003152, + 0x87C, 0x5C8FC000, + 0x880, 0x00000000, + 0x884, 0x00000000, + 0x888, 0x00000000, + 0x88C, 0x00000000, + 0x890, 0x00000000, + 0x894, 0x00000000, + 0x898, 0x00000000, + 0x89C, 0x00000000, + 0x8A0, 0x00000013, + 0x8A4, 0x7F7F7F7F, + 0x8A8, 0x2202033E, + 0x8AC, 0xF00F000A, + 0x8B0, 0x00000600, + 0x8B4, 0x000FC080, + 0x8B8, 0xEC0057F7, + 0x8BC, 0xACB520A3, + 0x8C0, 0xFFE04020, + 0x8C4, 0x47C00000, + 0x8C8, 0x000251A5, + 0x8CC, 0x08108492, + 0x8D0, 0x0000B800, + 0x8D4, 0x860308A0, + 0x8D8, 0x29095612, + 0x8DC, 0x00000000, + 0x8E0, 0x32D16777, + 0x8E4, 0x4C098935, + 0x8E8, 0xFFFFC42C, + 0x8EC, 0x99999999, + 0x8F0, 0x00009999, + 0x8F4, 0x00D80FA1, + 0x8F8, 0x40000080, + 0x8FC, 0x00000130, + 0x900, 0x00800000, + 0x904, 0x00000000, + 0x908, 0x00000000, + 0x90C, 0xD3000000, + 0x910, 0x0000FC00, + 0x914, 0xC6380000, + 0x918, 0x1C1028C0, + 0x91C, 0x64B11A1C, + 0x920, 0xE0767233, + 0x924, 0x855A2500, + 0x928, 0x4AB0E4E4, + 0x92C, 0xFFFEB200, + 0x930, 0xFFFFFFFE, + 0x934, 0x001FFFFF, + 0x938, 0x00008480, + 0x93C, 0xE41C0642, + 0x940, 0x0E470430, + 0x944, 0x00000000, + 0x948, 0xAC000000, + 0x94C, 0x10000083, + 0x950, 0x32010080, + 0x954, 0x84510080, + 0x958, 0x00000001, + 0x95C, 0x04248000, + 0x960, 0x00000000, + 0x964, 0x00000000, + 0x968, 0x00000000, + 0x96C, 0x00000000, + 0x970, 0x00001FFF, + 0x974, 0x44000FFF, + 0x978, 0x00000000, + 0x97C, 0x00000000, + 0x980, 0x00000000, + 0x984, 0x00000000, + 0x988, 0x00000000, + 0x98C, 0x43440000, + 0x990, 0x27100000, + 0x994, 0xFFFF0100, + 0x998, 0xFFFFFF5C, + 0x99C, 0xFFFFFFFF, + 0x9A0, 0x000000FF, + 0x9A4, 0x80000088, + 0x9A8, 0x0C2F0000, + 0x9AC, 0x01560000, + 0x9B0, 0x70000000, + 0x9B4, 0x00000000, + 0x9B8, 0x00000000, + 0x9BC, 0x00000000, + 0x9C0, 0x00000000, + 0x9C4, 0x00000000, + 0x9C8, 0x00000000, + 0x9CC, 0x00000000, + 0x9D0, 0x00000000, + 0x9D4, 0x00000000, + 0x9D8, 0x00000000, + 0x9DC, 0x00000000, + 0x9E0, 0x00000000, + 0x9E4, 0x02000402, + 0x9E8, 0x000022D4, + 0x9EC, 0x00000000, + 0x9F0, 0x00010080, + 0x9F4, 0x00000000, + 0x9F8, 0x00000000, + 0x9FC, 0xEFFFF7F7, + 0xA00, 0x00D047C8, + 0xA04, 0x81FF800C, + 0xA08, 0x8C838300, + 0xA0C, 0x2E20100F, + 0xA10, 0x9500BB78, + 0xA14, 0x1114D028, + 0xA18, 0x00881117, + 0xA1C, 0x89140F00, + 0xA20, 0x84880000, + 0xA24, 0x384F6577, + 0xA28, 0x00001525, + 0xA2C, 0x00920000, + 0xA70, 0x101FFF00, + 0xA74, 0x00000148, + 0xA78, 0x00000900, + 0xA7C, 0x225B0606, + 0xA80, 0x218675B2, + 0xA84, 0x80208C00, + 0xA88, 0x040C0000, + 0xA8C, 0x12345678, + 0xA90, 0xABCDEF00, + 0xA94, 0x001B1B89, + 0xA98, 0x030A0000, + 0xA9C, 0x00060000, + 0xAA0, 0x00000000, + 0xAA4, 0x0004000F, + 0xAA8, 0x00000200, + 0xB00, 0xE1000440, + 0xB04, 0x00800000, + 0xB08, 0xFF02030B, + 0xB0C, 0x01EAA406, + 0xB10, 0x00030690, + 0xB14, 0x006000FA, + 0xB18, 0x00000002, + 0xB1C, 0x00000002, + 0xB20, 0x4B00001F, + 0xB24, 0x4E8E3E40, + 0xB28, 0x03020100, + 0xB2C, 0x07060504, + 0xB30, 0x0B0A0908, + 0xB34, 0x0F0E0D0C, + 0xB38, 0x13121110, + 0xB3C, 0x0000003A, + 0xB40, 0x00000000, + 0xB44, 0x80000000, + 0xB48, 0x3F0000FA, + 0xB4C, 0x88C80020, + 0xB50, 0x00000000, + 0xB54, 0x00004241, + 0xB58, 0xE0008208, + 0xB5C, 0x41EFFFF9, + 0xB60, 0x00000000, + 0xB64, 0x00200063, + 0xB68, 0x0000003A, + 0xB6C, 0x00000102, + 0xB70, 0x4E6D1870, + 0xB74, 0x03020100, + 0xB78, 0x07060504, + 0xB7C, 0x0B0A0908, + 0xB80, 0x0F0E0D0C, + 0xB84, 0x13121110, + 0xB88, 0x00000000, + 0xB8C, 0x00000000, + 0xC00, 0x00000007, + 0xC04, 0x00000020, + 0xC08, 0x60403231, + 0xC0C, 0x00012345, + 0xC10, 0x00000100, + 0xC14, 0x01000000, + 0xC18, 0x00000000, + 0xC1C, 0x40040053, + 0xC20, 0x40020103, + 0xC24, 0x00000000, + 0xC28, 0x00000000, + 0xC2C, 0x00000000, + 0xC30, 0x00000000, + 0xC34, 0x00000000, + 0xC38, 0x00000000, + 0xC3C, 0x00000000, + 0xC40, 0x00000000, + 0xC44, 0x00000000, + 0xC48, 0x00000000, + 0xC4C, 0x00000000, + 0xC50, 0x00000020, + 0xC54, 0x00000000, + 0xC58, 0xD8020402, + 0xC5C, 0xDE000120, + 0xC68, 0x5979993F, + 0xC6C, 0x0000122A, + 0xC70, 0x99795979, + 0xC74, 0x99795979, + 0xC78, 0x99799979, + 0xC7C, 0x99791979, + 0xC80, 0x19791979, + 0xC84, 0x19791979, + 0xC88, 0x00000000, + 0xC8C, 0x07000000, + 0xC94, 0x01000100, + 0xC98, 0x201C8000, + 0xC9C, 0x00000000, + 0xCA0, 0x0000A555, + 0xCA4, 0x08040201, + 0xCA8, 0x80402010, + 0xCAC, 0x00000000, + 0xCB0, 0x77777777, + 0xCB4, 0x00007777, + 0xCB8, 0x00000000, + 0xCBC, 0x00000000, + 0xCC0, 0x00000000, + 0xCC4, 0x00000000, + 0xCC8, 0x00000000, + 0xCCC, 0x00000000, + 0xCD0, 0x00000000, + 0xCD4, 0x00000000, + 0xCD8, 0x00000000, + 0xCDC, 0x00000000, + 0xCE0, 0x00000000, + 0xCE4, 0x00000000, + 0xCE8, 0x00000000, + 0xCEC, 0x00000000, + 0xE00, 0x00000007, + 0xE04, 0x00000020, + 0xE08, 0x60403231, + 0xE0C, 0x00012345, + 0xE10, 0x00000100, + 0xE14, 0x01000000, + 0xE18, 0x00000000, + 0xE1C, 0x40040053, + 0xE20, 0x40020103, + 0xE24, 0x00000000, + 0xE28, 0x00000000, + 0xE2C, 0x00000000, + 0xE30, 0x00000000, + 0xE34, 0x00000000, + 0xE38, 0x00000000, + 0xE3C, 0x00000000, + 0xE40, 0x00000000, + 0xE44, 0x00000000, + 0xE48, 0x00000000, + 0xE4C, 0x00000000, + 0xE50, 0x00000020, + 0xE54, 0x00000000, + 0xE58, 0xD8120402, + 0xE5C, 0xDE000120, + 0xE68, 0x5979993F, + 0xE6C, 0x0000122A, + 0xE70, 0x99795979, + 0xE74, 0x99795979, + 0xE78, 0x99799979, + 0xE7C, 0x99791979, + 0xE80, 0x19791979, + 0xE84, 0x19791979, + 0xE88, 0x00000000, + 0xE8C, 0x07000000, + 0xE94, 0x01000100, + 0xE98, 0x201C8000, + 0xE9C, 0x00000000, + 0xEA0, 0x0000A555, + 0xEA4, 0x08040201, + 0xEA8, 0x80402010, + 0xEAC, 0x00000000, + 0xEB0, 0x77777777, + 0xEB4, 0x00007777, + 0xEB8, 0x00000000, + 0xEBC, 0x00000000, + 0xEC0, 0x00000000, + 0xEC4, 0x00000000, + 0xEC8, 0x00000000, + 0xECC, 0x00000000, + 0xED0, 0x00000000, + 0xED4, 0x00000000, + 0xED8, 0x00000000, + 0xEDC, 0x00000000, + 0xEE0, 0x00000000, + 0xEE4, 0x00000000, + 0xEE8, 0x00000000, + 0xEEC, 0x00000000, + 0x1900, 0x00000000, + 0x1904, 0x00238000, + 0x1908, 0x00000000, + 0x190C, 0x00000000, + 0x1910, 0x00000000, + 0x1914, 0x00000000, + 0x1918, 0x00000000, + 0x191C, 0x00000000, + 0x1920, 0x00000000, + 0x1924, 0x00000000, + 0x1928, 0x00000000, + 0x192C, 0x00000000, + 0x1930, 0x00000000, + 0x1934, 0x00000000, + 0x1938, 0x00000000, + 0x193C, 0x00000000, + 0x1940, 0x00000000, + 0x1944, 0x00000000, + 0x1948, 0x00000000, + 0x194C, 0x00000000, + 0x1950, 0x00000000, + 0x1954, 0x00000000, + 0x1958, 0x00000000, + 0x195C, 0x00000000, + 0x1960, 0x00000000, + 0x1964, 0x00000000, + 0x1968, 0x00000000, + 0x196C, 0x00000000, + 0x1970, 0x00000000, + 0x1974, 0x00000000, + 0x1978, 0x00000000, + 0x197C, 0x00000000, + 0x1980, 0x00000000, + 0x1984, 0x03000000, + 0x1988, 0x21401E88, + 0x198C, 0x00004000, + 0x1990, 0x00000000, + 0x1994, 0x00000000, + 0x1998, 0x00000053, + 0x199C, 0x00000000, + 0x19A0, 0x00000000, + 0x19A4, 0x00000000, + 0x19A8, 0x00000000, + 0x19AC, 0x0E47E47F, + 0x19B0, 0x00000000, + 0x19B4, 0x0E47E47F, + 0x19B8, 0x00000000, + 0x19BC, 0x00000000, + 0x19C0, 0x00000000, + 0x19C4, 0x00000000, + 0x19C8, 0x00000000, + 0x19CC, 0x00000000, + 0x19D0, 0x00000000, + 0x19D4, 0xAAAAAAAA, + 0x19D8, 0x00000AAA, + 0x19DC, 0x133E0F37, + 0x19E0, 0x00000000, + 0x19E4, 0x00000000, + 0x19E8, 0x00000000, + 0x19EC, 0x00000000, + 0x19F0, 0x00000000, + 0x19F4, 0x00000000, + 0x19F8, 0x01A00000, + 0x19FC, 0x00000000, + 0x1C00, 0x00000100, + 0x1C04, 0x01000000, + 0x1C08, 0x00000100, + 0x1C0C, 0x01000000, + 0x1C10, 0x00000100, + 0x1C14, 0x01000000, + 0x1C18, 0x00000100, + 0x1C1C, 0x01000000, + 0x1C20, 0x00000100, + 0x1C24, 0x01000000, + 0x1C28, 0x00000100, + 0x1C2C, 0x01000000, + 0x1C30, 0x00000100, + 0x1C34, 0x01000000, + 0x1C38, 0x00000000, + 0x1C3C, 0x00000000, + 0x1C40, 0x000C0100, + 0x1C44, 0x000000F3, + 0x1C48, 0x1A8249A8, + 0x1C4C, 0x1461C826, + 0x1C50, 0x0001469E, + 0x1C54, 0x58D158D1, + 0x1C58, 0x04490088, + 0x1C5C, 0x04004400, + 0x1C60, 0x00000000, + 0x1C64, 0x04004400, + 0x1C68, 0x00000100, + 0x1C6C, 0x01000000, + 0x1C70, 0x00000100, + 0x1C74, 0x01000000, + 0x1C78, 0x00000000, + 0x1C7C, 0x00000010, + 0x1C80, 0x5FFF5FFF, + 0x1C84, 0x5FFF5FFF, + 0x1C88, 0x5FFF5FFF, + 0x1C8C, 0x5FFF5FFF, + 0x1C90, 0x5FFF5FFF, + 0x1C94, 0x5FFF5FFF, + 0x1C98, 0x5FFF5FFF, + 0x1C9C, 0x5FFF5FFF, + 0x1CA0, 0x00000100, + 0x1CA4, 0x01000000, + 0x1CA8, 0x00000100, + 0x1CAC, 0x5FFF5FFF, + 0x1CB0, 0x00000100, + 0x1CB4, 0x01000000, + 0x1CB8, 0x00000000, + 0x1CBC, 0x00000000, + 0x1CC0, 0x00000100, + 0x1CC4, 0x01000000, + 0x1CC8, 0x00000100, + 0x1CCC, 0x01000000, + 0x1CD0, 0x00000100, + 0x1CD4, 0x01000000, + 0x1CD8, 0x00000100, + 0x1CDC, 0x01000000, + 0x1CE0, 0x00000100, + 0x1CE4, 0x01000000, + 0x1CE8, 0x00000100, + 0x1CEC, 0x01000000, + 0x1CF0, 0x00000100, + 0x1CF4, 0x01000000, + 0x1CF8, 0x00000000, + 0x1CFC, 0x00000000, + 0xC60, 0x70038040, + 0xC60, 0x70038040, + 0xC60, 0x70146040, + 0xC60, 0x70246040, + 0xC60, 0x70346040, + 0xC60, 0x70446040, + 0xC60, 0x70532040, + 0xC60, 0x70646040, + 0xC60, 0x70738040, + 0xC60, 0x70838040, + 0xC60, 0x70938040, + 0xC60, 0x70A38040, + 0xC60, 0x70B36040, + 0xC60, 0x70C06040, + 0xC60, 0x70D06040, + 0xC60, 0x70E76040, + 0xC60, 0x70F06040, + 0xE60, 0x70038040, + 0xE60, 0x70038040, + 0xE60, 0x70146040, + 0xE60, 0x70246040, + 0xE60, 0x70346040, + 0xE60, 0x70446040, + 0xE60, 0x70532040, + 0xE60, 0x70646040, + 0xE60, 0x70738040, + 0xE60, 0x70838040, + 0xE60, 0x70938040, + 0xE60, 0x70A38040, + 0xE60, 0x70B36040, + 0xE60, 0x70C06040, + 0xE60, 0x70D06040, + 0xE60, 0x70E76040, + 0xE60, 0x70F06040, + 0xC64, 0x00800000, + 0xC64, 0x08800001, + 0xC64, 0x00800002, + 0xC64, 0x00800003, + 0xC64, 0x00800004, + 0xC64, 0x00800005, + 0xC64, 0x00800006, + 0xC64, 0x08800007, + 0xC64, 0x00004000, + 0xE64, 0x00800000, + 0xE64, 0x08800001, + 0xE64, 0x00800002, + 0xE64, 0x00800003, + 0xE64, 0x00800004, + 0xE64, 0x00800005, + 0xE64, 0x00800006, + 0xE64, 0x08800007, + 0xE64, 0x00004000, + 0x1B00, 0xF8000008, + 0x1B00, 0xF80A7008, + 0x1B00, 0xF8015008, + 0x1B00, 0xF8000008, + 0x1B04, 0xE24629D2, + 0x1B08, 0x00000080, + 0x1B0C, 0x00000000, + 0x1B10, 0x00011C00, + 0x1B14, 0x00000000, + 0x1B18, 0x00292903, + 0x1B1C, 0xA2193C32, + 0x1B20, 0x01840008, + 0x1B24, 0x01860008, + 0x1B28, 0x80060300, + 0x1B2C, 0x00000003, + 0x1B30, 0x20000000, + 0x1B34, 0x00000800, + 0x1B3C, 0x20000000, + 0x1BC0, 0x01000000, + 0x1BCC, 0x00000000, + 0x1B00, 0xF800000A, + 0x1B1C, 0xA2193C32, + 0x1B20, 0x01840008, + 0x1B24, 0x01860008, + 0x1B28, 0x80060300, + 0x1B2C, 0x00000003, + 0x1B30, 0x20000000, + 0x1B34, 0x00000800, + 0x1B3C, 0x20000000, + 0x1BC0, 0x01000000, + 0x1BCC, 0x00000000, + 0x1B00, 0xF8000000, + 0x1B80, 0x00000007, + 0x1B80, 0x090A0005, + 0x1B80, 0x090A0007, + 0x1B80, 0x0FFE0015, + 0x1B80, 0x0FFE0017, + 0x1B80, 0x00220025, + 0x1B80, 0x00220027, + 0x1B80, 0x00040035, + 0x1B80, 0x00040037, + 0x1B80, 0x05C00045, + 0x1B80, 0x05C00047, + 0x1B80, 0x00070055, + 0x1B80, 0x00070057, + 0x1B80, 0x64000065, + 0x1B80, 0x64000067, + 0x1B80, 0x00020075, + 0x1B80, 0x00020077, + 0x1B80, 0x00080085, + 0x1B80, 0x00080087, + 0x1B80, 0x80000095, + 0x1B80, 0x80000097, + 0x1B80, 0x090800A5, + 0x1B80, 0x090800A7, + 0x1B80, 0x0F0200B5, + 0x1B80, 0x0F0200B7, + 0x1B80, 0x002200C5, + 0x1B80, 0x002200C7, + 0x1B80, 0x000400D5, + 0x1B80, 0x000400D7, + 0x1B80, 0x05C000E5, + 0x1B80, 0x05C000E7, + 0x1B80, 0x000700F5, + 0x1B80, 0x000700F7, + 0x1B80, 0x64020105, + 0x1B80, 0x64020107, + 0x1B80, 0x00020115, + 0x1B80, 0x00020117, + 0x1B80, 0x00040125, + 0x1B80, 0x00040127, + 0x1B80, 0x4A000135, + 0x1B80, 0x4A000137, + 0x1B80, 0x4B040145, + 0x1B80, 0x4B040147, + 0x1B80, 0x85030155, + 0x1B80, 0x85030157, + 0x1B80, 0x40090165, + 0x1B80, 0x40090167, + 0x1B80, 0xE0280175, + 0x1B80, 0xE0280177, + 0x1B80, 0x4B050185, + 0x1B80, 0x4B050187, + 0x1B80, 0x86030195, + 0x1B80, 0x86030197, + 0x1B80, 0x400B01A5, + 0x1B80, 0x400B01A7, + 0x1B80, 0xE02801B5, + 0x1B80, 0xE02801B7, + 0x1B80, 0x4B0001C5, + 0x1B80, 0x4B0001C7, + 0x1B80, 0x000701D5, + 0x1B80, 0x000701D7, + 0x1B80, 0x4C0001E5, + 0x1B80, 0x4C0001E7, + 0x1B80, 0x000401F5, + 0x1B80, 0x000401F7, + 0x1B80, 0x4D040205, + 0x1B80, 0x4D040207, + 0x1B80, 0x2EF00215, + 0x1B80, 0x2EF00217, + 0x1B80, 0x00000225, + 0x1B80, 0x00000227, + 0x1B80, 0x20810235, + 0x1B80, 0x20810237, + 0x1B80, 0x23450245, + 0x1B80, 0x23450247, + 0x1B80, 0x4D000255, + 0x1B80, 0x4D000257, + 0x1B80, 0x00040265, + 0x1B80, 0x00040267, + 0x1B80, 0x30000275, + 0x1B80, 0x30000277, + 0x1B80, 0xE1D80285, + 0x1B80, 0xE1D80287, + 0x1B80, 0xF0110295, + 0x1B80, 0xF0110297, + 0x1B80, 0xF11102A5, + 0x1B80, 0xF11102A7, + 0x1B80, 0xF21102B5, + 0x1B80, 0xF21102B7, + 0x1B80, 0xF31102C5, + 0x1B80, 0xF31102C7, + 0x1B80, 0xF41102D5, + 0x1B80, 0xF41102D7, + 0x1B80, 0xF51102E5, + 0x1B80, 0xF51102E7, + 0x1B80, 0xF61102F5, + 0x1B80, 0xF61102F7, + 0x1B80, 0xF7110305, + 0x1B80, 0xF7110307, + 0x1B80, 0xF8110315, + 0x1B80, 0xF8110317, + 0x1B80, 0xF9110325, + 0x1B80, 0xF9110327, + 0x1B80, 0xFA110335, + 0x1B80, 0xFA110337, + 0x1B80, 0xFB110345, + 0x1B80, 0xFB110347, + 0x1B80, 0xFC110355, + 0x1B80, 0xFC110357, + 0x1B80, 0xFD110365, + 0x1B80, 0xFD110367, + 0x1B80, 0xFE110375, + 0x1B80, 0xFE110377, + 0x1B80, 0xFF110385, + 0x1B80, 0xFF110387, + 0x1B80, 0x00010395, + 0x1B80, 0x00010397, + 0x1B80, 0x305103A5, + 0x1B80, 0x305103A7, + 0x1B80, 0x306903B5, + 0x1B80, 0x306903B7, + 0x1B80, 0x30B403C5, + 0x1B80, 0x30B403C7, + 0x1B80, 0x30B703D5, + 0x1B80, 0x30B703D7, + 0x1B80, 0x306B03E5, + 0x1B80, 0x306B03E7, + 0x1B80, 0x307603F5, + 0x1B80, 0x307603F7, + 0x1B80, 0x30810405, + 0x1B80, 0x30810407, + 0x1B80, 0x30C10415, + 0x1B80, 0x30C10417, + 0x1B80, 0x30BB0425, + 0x1B80, 0x30BB0427, + 0x1B80, 0x30CF0435, + 0x1B80, 0x30CF0437, + 0x1B80, 0x30DA0445, + 0x1B80, 0x30DA0447, + 0x1B80, 0x30E50455, + 0x1B80, 0x30E50457, + 0x1B80, 0x304A0465, + 0x1B80, 0x304A0467, + 0x1B80, 0x31140475, + 0x1B80, 0x31140477, + 0x1B80, 0x31250485, + 0x1B80, 0x31250487, + 0x1B80, 0x313A0495, + 0x1B80, 0x313A0497, + 0x1B80, 0x4D0404A5, + 0x1B80, 0x4D0404A7, + 0x1B80, 0x2EF004B5, + 0x1B80, 0x2EF004B7, + 0x1B80, 0x000004C5, + 0x1B80, 0x000004C7, + 0x1B80, 0x208104D5, + 0x1B80, 0x208104D7, + 0x1B80, 0xA3B504E5, + 0x1B80, 0xA3B504E7, + 0x1B80, 0x4D0004F5, + 0x1B80, 0x4D0004F7, + 0x1B80, 0x30000505, + 0x1B80, 0x30000507, + 0x1B80, 0xE1650515, + 0x1B80, 0xE1650517, + 0x1B80, 0x4D040525, + 0x1B80, 0x4D040527, + 0x1B80, 0x20800535, + 0x1B80, 0x20800537, + 0x1B80, 0x00000545, + 0x1B80, 0x00000547, + 0x1B80, 0x4D000555, + 0x1B80, 0x4D000557, + 0x1B80, 0x55070565, + 0x1B80, 0x55070567, + 0x1B80, 0xE15D0575, + 0x1B80, 0xE15D0577, + 0x1B80, 0xE15D0585, + 0x1B80, 0xE15D0587, + 0x1B80, 0x4D040595, + 0x1B80, 0x4D040597, + 0x1B80, 0x208805A5, + 0x1B80, 0x208805A7, + 0x1B80, 0x020005B5, + 0x1B80, 0x020005B7, + 0x1B80, 0x4D0005C5, + 0x1B80, 0x4D0005C7, + 0x1B80, 0x550F05D5, + 0x1B80, 0x550F05D7, + 0x1B80, 0xE15D05E5, + 0x1B80, 0xE15D05E7, + 0x1B80, 0x4F0205F5, + 0x1B80, 0x4F0205F7, + 0x1B80, 0x4E000605, + 0x1B80, 0x4E000607, + 0x1B80, 0x53020615, + 0x1B80, 0x53020617, + 0x1B80, 0x52010625, + 0x1B80, 0x52010627, + 0x1B80, 0xE1610635, + 0x1B80, 0xE1610637, + 0x1B80, 0x4D080645, + 0x1B80, 0x4D080647, + 0x1B80, 0x57100655, + 0x1B80, 0x57100657, + 0x1B80, 0x57000665, + 0x1B80, 0x57000667, + 0x1B80, 0x4D000675, + 0x1B80, 0x4D000677, + 0x1B80, 0x00010685, + 0x1B80, 0x00010687, + 0x1B80, 0xE1650695, + 0x1B80, 0xE1650697, + 0x1B80, 0x000106A5, + 0x1B80, 0x000106A7, + 0x1B80, 0x308B06B5, + 0x1B80, 0x308B06B7, + 0x1B80, 0x002306C5, + 0x1B80, 0x002306C7, + 0x1B80, 0xE1CB06D5, + 0x1B80, 0xE1CB06D7, + 0x1B80, 0x000206E5, + 0x1B80, 0x000206E7, + 0x1B80, 0x54E906F5, + 0x1B80, 0x54E906F7, + 0x1B80, 0x0BA60705, + 0x1B80, 0x0BA60707, + 0x1B80, 0x00230715, + 0x1B80, 0x00230717, + 0x1B80, 0xE1CB0725, + 0x1B80, 0xE1CB0727, + 0x1B80, 0x00020735, + 0x1B80, 0x00020737, + 0x1B80, 0x4D300745, + 0x1B80, 0x4D300747, + 0x1B80, 0x30A40755, + 0x1B80, 0x30A40757, + 0x1B80, 0x30870765, + 0x1B80, 0x30870767, + 0x1B80, 0x00220775, + 0x1B80, 0x00220777, + 0x1B80, 0xE1CB0785, + 0x1B80, 0xE1CB0787, + 0x1B80, 0x00020795, + 0x1B80, 0x00020797, + 0x1B80, 0x54E807A5, + 0x1B80, 0x54E807A7, + 0x1B80, 0x0BA607B5, + 0x1B80, 0x0BA607B7, + 0x1B80, 0x002207C5, + 0x1B80, 0x002207C7, + 0x1B80, 0xE1CB07D5, + 0x1B80, 0xE1CB07D7, + 0x1B80, 0x000207E5, + 0x1B80, 0x000207E7, + 0x1B80, 0x4D3007F5, + 0x1B80, 0x4D3007F7, + 0x1B80, 0x30A40805, + 0x1B80, 0x30A40807, + 0x1B80, 0x63F10815, + 0x1B80, 0x63F10817, + 0x1B80, 0xE1650825, + 0x1B80, 0xE1650827, + 0x1B80, 0xE1CB0835, + 0x1B80, 0xE1CB0837, + 0x1B80, 0x63F40845, + 0x1B80, 0x63F40847, + 0x1B80, 0xE1650855, + 0x1B80, 0xE1650857, + 0x1B80, 0xE1CB0865, + 0x1B80, 0xE1CB0867, + 0x1B80, 0x0BA80875, + 0x1B80, 0x0BA80877, + 0x1B80, 0x63F80885, + 0x1B80, 0x63F80887, + 0x1B80, 0xE1650895, + 0x1B80, 0xE1650897, + 0x1B80, 0xE1CB08A5, + 0x1B80, 0xE1CB08A7, + 0x1B80, 0x0BA908B5, + 0x1B80, 0x0BA908B7, + 0x1B80, 0x63FC08C5, + 0x1B80, 0x63FC08C7, + 0x1B80, 0xE16508D5, + 0x1B80, 0xE16508D7, + 0x1B80, 0xE1CB08E5, + 0x1B80, 0xE1CB08E7, + 0x1B80, 0x63FF08F5, + 0x1B80, 0x63FF08F7, + 0x1B80, 0xE1650905, + 0x1B80, 0xE1650907, + 0x1B80, 0xE1CB0915, + 0x1B80, 0xE1CB0917, + 0x1B80, 0x63000925, + 0x1B80, 0x63000927, + 0x1B80, 0xE1650935, + 0x1B80, 0xE1650937, + 0x1B80, 0xE1CB0945, + 0x1B80, 0xE1CB0947, + 0x1B80, 0x63030955, + 0x1B80, 0x63030957, + 0x1B80, 0xE1650965, + 0x1B80, 0xE1650967, + 0x1B80, 0xE1CB0975, + 0x1B80, 0xE1CB0977, + 0x1B80, 0xF4D40985, + 0x1B80, 0xF4D40987, + 0x1B80, 0x63070995, + 0x1B80, 0x63070997, + 0x1B80, 0xE16509A5, + 0x1B80, 0xE16509A7, + 0x1B80, 0xE1CB09B5, + 0x1B80, 0xE1CB09B7, + 0x1B80, 0xF5DB09C5, + 0x1B80, 0xF5DB09C7, + 0x1B80, 0x630B09D5, + 0x1B80, 0x630B09D7, + 0x1B80, 0xE16509E5, + 0x1B80, 0xE16509E7, + 0x1B80, 0xE1CB09F5, + 0x1B80, 0xE1CB09F7, + 0x1B80, 0x630E0A05, + 0x1B80, 0x630E0A07, + 0x1B80, 0xE1650A15, + 0x1B80, 0xE1650A17, + 0x1B80, 0xE1CB0A25, + 0x1B80, 0xE1CB0A27, + 0x1B80, 0x4D300A35, + 0x1B80, 0x4D300A37, + 0x1B80, 0x55010A45, + 0x1B80, 0x55010A47, + 0x1B80, 0x57040A55, + 0x1B80, 0x57040A57, + 0x1B80, 0x57000A65, + 0x1B80, 0x57000A67, + 0x1B80, 0x96000A75, + 0x1B80, 0x96000A77, + 0x1B80, 0x57080A85, + 0x1B80, 0x57080A87, + 0x1B80, 0x57000A95, + 0x1B80, 0x57000A97, + 0x1B80, 0x95000AA5, + 0x1B80, 0x95000AA7, + 0x1B80, 0x4D000AB5, + 0x1B80, 0x4D000AB7, + 0x1B80, 0x6C070AC5, + 0x1B80, 0x6C070AC7, + 0x1B80, 0x7B200AD5, + 0x1B80, 0x7B200AD7, + 0x1B80, 0x7A000AE5, + 0x1B80, 0x7A000AE7, + 0x1B80, 0x79000AF5, + 0x1B80, 0x79000AF7, + 0x1B80, 0x7F200B05, + 0x1B80, 0x7F200B07, + 0x1B80, 0x7E000B15, + 0x1B80, 0x7E000B17, + 0x1B80, 0x7D000B25, + 0x1B80, 0x7D000B27, + 0x1B80, 0x00010B35, + 0x1B80, 0x00010B37, + 0x1B80, 0x62850B45, + 0x1B80, 0x62850B47, + 0x1B80, 0xE1650B55, + 0x1B80, 0xE1650B57, + 0x1B80, 0x00010B65, + 0x1B80, 0x00010B67, + 0x1B80, 0x5C320B75, + 0x1B80, 0x5C320B77, + 0x1B80, 0xE1C70B85, + 0x1B80, 0xE1C70B87, + 0x1B80, 0xE1930B95, + 0x1B80, 0xE1930B97, + 0x1B80, 0x00010BA5, + 0x1B80, 0x00010BA7, + 0x1B80, 0x5C320BB5, + 0x1B80, 0x5C320BB7, + 0x1B80, 0x63F40BC5, + 0x1B80, 0x63F40BC7, + 0x1B80, 0x62850BD5, + 0x1B80, 0x62850BD7, + 0x1B80, 0x0BB00BE5, + 0x1B80, 0x0BB00BE7, + 0x1B80, 0xE1650BF5, + 0x1B80, 0xE1650BF7, + 0x1B80, 0xE1CB0C05, + 0x1B80, 0xE1CB0C07, + 0x1B80, 0x5C320C15, + 0x1B80, 0x5C320C17, + 0x1B80, 0x63FC0C25, + 0x1B80, 0x63FC0C27, + 0x1B80, 0x62850C35, + 0x1B80, 0x62850C37, + 0x1B80, 0x0BB10C45, + 0x1B80, 0x0BB10C47, + 0x1B80, 0xE1650C55, + 0x1B80, 0xE1650C57, + 0x1B80, 0xE1CB0C65, + 0x1B80, 0xE1CB0C67, + 0x1B80, 0x63030C75, + 0x1B80, 0x63030C77, + 0x1B80, 0xE1650C85, + 0x1B80, 0xE1650C87, + 0x1B80, 0xE1CB0C95, + 0x1B80, 0xE1CB0C97, + 0x1B80, 0xF7040CA5, + 0x1B80, 0xF7040CA7, + 0x1B80, 0x630B0CB5, + 0x1B80, 0x630B0CB7, + 0x1B80, 0xE1650CC5, + 0x1B80, 0xE1650CC7, + 0x1B80, 0xE1CB0CD5, + 0x1B80, 0xE1CB0CD7, + 0x1B80, 0x00010CE5, + 0x1B80, 0x00010CE7, + 0x1B80, 0x30F30CF5, + 0x1B80, 0x30F30CF7, + 0x1B80, 0x00230D05, + 0x1B80, 0x00230D07, + 0x1B80, 0xE1D00D15, + 0x1B80, 0xE1D00D17, + 0x1B80, 0x00020D25, + 0x1B80, 0x00020D27, + 0x1B80, 0x54E90D35, + 0x1B80, 0x54E90D37, + 0x1B80, 0x0BA60D45, + 0x1B80, 0x0BA60D47, + 0x1B80, 0x00230D55, + 0x1B80, 0x00230D57, + 0x1B80, 0xE1D00D65, + 0x1B80, 0xE1D00D67, + 0x1B80, 0x00020D75, + 0x1B80, 0x00020D77, + 0x1B80, 0x4D100D85, + 0x1B80, 0x4D100D87, + 0x1B80, 0x30A40D95, + 0x1B80, 0x30A40D97, + 0x1B80, 0x30ED0DA5, + 0x1B80, 0x30ED0DA7, + 0x1B80, 0x00220DB5, + 0x1B80, 0x00220DB7, + 0x1B80, 0xE1D00DC5, + 0x1B80, 0xE1D00DC7, + 0x1B80, 0x00020DD5, + 0x1B80, 0x00020DD7, + 0x1B80, 0x54E80DE5, + 0x1B80, 0x54E80DE7, + 0x1B80, 0x0BA60DF5, + 0x1B80, 0x0BA60DF7, + 0x1B80, 0x00220E05, + 0x1B80, 0x00220E07, + 0x1B80, 0xE1D00E15, + 0x1B80, 0xE1D00E17, + 0x1B80, 0x00020E25, + 0x1B80, 0x00020E27, + 0x1B80, 0x4D100E35, + 0x1B80, 0x4D100E37, + 0x1B80, 0x30A40E45, + 0x1B80, 0x30A40E47, + 0x1B80, 0x5C320E55, + 0x1B80, 0x5C320E57, + 0x1B80, 0x54F00E65, + 0x1B80, 0x54F00E67, + 0x1B80, 0x67F10E75, + 0x1B80, 0x67F10E77, + 0x1B80, 0xE1930E85, + 0x1B80, 0xE1930E87, + 0x1B80, 0xE1D00E95, + 0x1B80, 0xE1D00E97, + 0x1B80, 0x67F40EA5, + 0x1B80, 0x67F40EA7, + 0x1B80, 0xE1930EB5, + 0x1B80, 0xE1930EB7, + 0x1B80, 0xE1D00EC5, + 0x1B80, 0xE1D00EC7, + 0x1B80, 0x5C320ED5, + 0x1B80, 0x5C320ED7, + 0x1B80, 0x54F10EE5, + 0x1B80, 0x54F10EE7, + 0x1B80, 0x0BA80EF5, + 0x1B80, 0x0BA80EF7, + 0x1B80, 0x67F80F05, + 0x1B80, 0x67F80F07, + 0x1B80, 0xE1930F15, + 0x1B80, 0xE1930F17, + 0x1B80, 0xE1D00F25, + 0x1B80, 0xE1D00F27, + 0x1B80, 0x5C320F35, + 0x1B80, 0x5C320F37, + 0x1B80, 0x54F10F45, + 0x1B80, 0x54F10F47, + 0x1B80, 0x0BA90F55, + 0x1B80, 0x0BA90F57, + 0x1B80, 0x67FC0F65, + 0x1B80, 0x67FC0F67, + 0x1B80, 0xE1930F75, + 0x1B80, 0xE1930F77, + 0x1B80, 0xE1D00F85, + 0x1B80, 0xE1D00F87, + 0x1B80, 0x67FF0F95, + 0x1B80, 0x67FF0F97, + 0x1B80, 0xE1930FA5, + 0x1B80, 0xE1930FA7, + 0x1B80, 0xE1D00FB5, + 0x1B80, 0xE1D00FB7, + 0x1B80, 0x5C320FC5, + 0x1B80, 0x5C320FC7, + 0x1B80, 0x54F20FD5, + 0x1B80, 0x54F20FD7, + 0x1B80, 0x67000FE5, + 0x1B80, 0x67000FE7, + 0x1B80, 0xE1930FF5, + 0x1B80, 0xE1930FF7, + 0x1B80, 0xE1D01005, + 0x1B80, 0xE1D01007, + 0x1B80, 0x67031015, + 0x1B80, 0x67031017, + 0x1B80, 0xE1931025, + 0x1B80, 0xE1931027, + 0x1B80, 0xE1D01035, + 0x1B80, 0xE1D01037, + 0x1B80, 0xF9CC1045, + 0x1B80, 0xF9CC1047, + 0x1B80, 0x67071055, + 0x1B80, 0x67071057, + 0x1B80, 0xE1931065, + 0x1B80, 0xE1931067, + 0x1B80, 0xE1D01075, + 0x1B80, 0xE1D01077, + 0x1B80, 0xFAD31085, + 0x1B80, 0xFAD31087, + 0x1B80, 0x5C321095, + 0x1B80, 0x5C321097, + 0x1B80, 0x54F310A5, + 0x1B80, 0x54F310A7, + 0x1B80, 0x670B10B5, + 0x1B80, 0x670B10B7, + 0x1B80, 0xE19310C5, + 0x1B80, 0xE19310C7, + 0x1B80, 0xE1D010D5, + 0x1B80, 0xE1D010D7, + 0x1B80, 0x670E10E5, + 0x1B80, 0x670E10E7, + 0x1B80, 0xE19310F5, + 0x1B80, 0xE19310F7, + 0x1B80, 0xE1D01105, + 0x1B80, 0xE1D01107, + 0x1B80, 0x4D101115, + 0x1B80, 0x4D101117, + 0x1B80, 0x30A41125, + 0x1B80, 0x30A41127, + 0x1B80, 0x00011135, + 0x1B80, 0x00011137, + 0x1B80, 0x6C001145, + 0x1B80, 0x6C001147, + 0x1B80, 0x00061155, + 0x1B80, 0x00061157, + 0x1B80, 0x53001165, + 0x1B80, 0x53001167, + 0x1B80, 0x57F71175, + 0x1B80, 0x57F71177, + 0x1B80, 0x58211185, + 0x1B80, 0x58211187, + 0x1B80, 0x592E1195, + 0x1B80, 0x592E1197, + 0x1B80, 0x5A3811A5, + 0x1B80, 0x5A3811A7, + 0x1B80, 0x5B4111B5, + 0x1B80, 0x5B4111B7, + 0x1B80, 0x000711C5, + 0x1B80, 0x000711C7, + 0x1B80, 0x5C0011D5, + 0x1B80, 0x5C0011D7, + 0x1B80, 0x4B0011E5, + 0x1B80, 0x4B0011E7, + 0x1B80, 0x4E8F11F5, + 0x1B80, 0x4E8F11F7, + 0x1B80, 0x4F151205, + 0x1B80, 0x4F151207, + 0x1B80, 0x00041215, + 0x1B80, 0x00041217, + 0x1B80, 0xE1B51225, + 0x1B80, 0xE1B51227, + 0x1B80, 0xAB001235, + 0x1B80, 0xAB001237, + 0x1B80, 0x00011245, + 0x1B80, 0x00011247, + 0x1B80, 0x6C001255, + 0x1B80, 0x6C001257, + 0x1B80, 0x00061265, + 0x1B80, 0x00061267, + 0x1B80, 0x53001275, + 0x1B80, 0x53001277, + 0x1B80, 0x57F71285, + 0x1B80, 0x57F71287, + 0x1B80, 0x58211295, + 0x1B80, 0x58211297, + 0x1B80, 0x592E12A5, + 0x1B80, 0x592E12A7, + 0x1B80, 0x5A3812B5, + 0x1B80, 0x5A3812B7, + 0x1B80, 0x5B4112C5, + 0x1B80, 0x5B4112C7, + 0x1B80, 0x000712D5, + 0x1B80, 0x000712D7, + 0x1B80, 0x5C0012E5, + 0x1B80, 0x5C0012E7, + 0x1B80, 0x4B4012F5, + 0x1B80, 0x4B4012F7, + 0x1B80, 0x4E971305, + 0x1B80, 0x4E971307, + 0x1B80, 0x4F111315, + 0x1B80, 0x4F111317, + 0x1B80, 0x00041325, + 0x1B80, 0x00041327, + 0x1B80, 0xE1B51335, + 0x1B80, 0xE1B51337, + 0x1B80, 0xAB001345, + 0x1B80, 0xAB001347, + 0x1B80, 0x8B001355, + 0x1B80, 0x8B001357, + 0x1B80, 0xAB001365, + 0x1B80, 0xAB001367, + 0x1B80, 0x8A191375, + 0x1B80, 0x8A191377, + 0x1B80, 0x301D1385, + 0x1B80, 0x301D1387, + 0x1B80, 0x00011395, + 0x1B80, 0x00011397, + 0x1B80, 0x6C0113A5, + 0x1B80, 0x6C0113A7, + 0x1B80, 0x000613B5, + 0x1B80, 0x000613B7, + 0x1B80, 0x530113C5, + 0x1B80, 0x530113C7, + 0x1B80, 0x57F713D5, + 0x1B80, 0x57F713D7, + 0x1B80, 0x582113E5, + 0x1B80, 0x582113E7, + 0x1B80, 0x592E13F5, + 0x1B80, 0x592E13F7, + 0x1B80, 0x5A381405, + 0x1B80, 0x5A381407, + 0x1B80, 0x5B411415, + 0x1B80, 0x5B411417, + 0x1B80, 0x00071425, + 0x1B80, 0x00071427, + 0x1B80, 0x5C001435, + 0x1B80, 0x5C001437, + 0x1B80, 0x4B001445, + 0x1B80, 0x4B001447, + 0x1B80, 0x4E871455, + 0x1B80, 0x4E871457, + 0x1B80, 0x4F111465, + 0x1B80, 0x4F111467, + 0x1B80, 0x00041475, + 0x1B80, 0x00041477, + 0x1B80, 0xE1B51485, + 0x1B80, 0xE1B51487, + 0x1B80, 0xAB001495, + 0x1B80, 0xAB001497, + 0x1B80, 0x000614A5, + 0x1B80, 0x000614A7, + 0x1B80, 0x577714B5, + 0x1B80, 0x577714B7, + 0x1B80, 0x000714C5, + 0x1B80, 0x000714C7, + 0x1B80, 0x4E8614D5, + 0x1B80, 0x4E8614D7, + 0x1B80, 0x000414E5, + 0x1B80, 0x000414E7, + 0x1B80, 0x000114F5, + 0x1B80, 0x000114F7, + 0x1B80, 0x00011505, + 0x1B80, 0x00011507, + 0x1B80, 0x7B241515, + 0x1B80, 0x7B241517, + 0x1B80, 0x7A401525, + 0x1B80, 0x7A401527, + 0x1B80, 0x79001535, + 0x1B80, 0x79001537, + 0x1B80, 0x55031545, + 0x1B80, 0x55031547, + 0x1B80, 0x315D1555, + 0x1B80, 0x315D1557, + 0x1B80, 0x7B1C1565, + 0x1B80, 0x7B1C1567, + 0x1B80, 0x7A401575, + 0x1B80, 0x7A401577, + 0x1B80, 0x550B1585, + 0x1B80, 0x550B1587, + 0x1B80, 0x315D1595, + 0x1B80, 0x315D1597, + 0x1B80, 0x7B2015A5, + 0x1B80, 0x7B2015A7, + 0x1B80, 0x7A0015B5, + 0x1B80, 0x7A0015B7, + 0x1B80, 0x551315C5, + 0x1B80, 0x551315C7, + 0x1B80, 0x740115D5, + 0x1B80, 0x740115D7, + 0x1B80, 0x740015E5, + 0x1B80, 0x740015E7, + 0x1B80, 0x8E0015F5, + 0x1B80, 0x8E0015F7, + 0x1B80, 0x00011605, + 0x1B80, 0x00011607, + 0x1B80, 0x57021615, + 0x1B80, 0x57021617, + 0x1B80, 0x57001625, + 0x1B80, 0x57001627, + 0x1B80, 0x97001635, + 0x1B80, 0x97001637, + 0x1B80, 0x00011645, + 0x1B80, 0x00011647, + 0x1B80, 0x4F781655, + 0x1B80, 0x4F781657, + 0x1B80, 0x53881665, + 0x1B80, 0x53881667, + 0x1B80, 0xE1731675, + 0x1B80, 0xE1731677, + 0x1B80, 0x54801685, + 0x1B80, 0x54801687, + 0x1B80, 0x54001695, + 0x1B80, 0x54001697, + 0x1B80, 0xE17316A5, + 0x1B80, 0xE17316A7, + 0x1B80, 0x548116B5, + 0x1B80, 0x548116B7, + 0x1B80, 0x540016C5, + 0x1B80, 0x540016C7, + 0x1B80, 0xE17316D5, + 0x1B80, 0xE17316D7, + 0x1B80, 0x548216E5, + 0x1B80, 0x548216E7, + 0x1B80, 0x540016F5, + 0x1B80, 0x540016F7, + 0x1B80, 0xE17E1705, + 0x1B80, 0xE17E1707, + 0x1B80, 0xBF1D1715, + 0x1B80, 0xBF1D1717, + 0x1B80, 0x301D1725, + 0x1B80, 0x301D1727, + 0x1B80, 0xE1511735, + 0x1B80, 0xE1511737, + 0x1B80, 0xE1561745, + 0x1B80, 0xE1561747, + 0x1B80, 0xE15A1755, + 0x1B80, 0xE15A1757, + 0x1B80, 0xE1611765, + 0x1B80, 0xE1611767, + 0x1B80, 0xE1C71775, + 0x1B80, 0xE1C71777, + 0x1B80, 0x55131785, + 0x1B80, 0x55131787, + 0x1B80, 0xE15D1795, + 0x1B80, 0xE15D1797, + 0x1B80, 0x551517A5, + 0x1B80, 0x551517A7, + 0x1B80, 0xE16117B5, + 0x1B80, 0xE16117B7, + 0x1B80, 0xE1C717C5, + 0x1B80, 0xE1C717C7, + 0x1B80, 0x000117D5, + 0x1B80, 0x000117D7, + 0x1B80, 0x54BF17E5, + 0x1B80, 0x54BF17E7, + 0x1B80, 0x54C017F5, + 0x1B80, 0x54C017F7, + 0x1B80, 0x54A31805, + 0x1B80, 0x54A31807, + 0x1B80, 0x54C11815, + 0x1B80, 0x54C11817, + 0x1B80, 0x54A41825, + 0x1B80, 0x54A41827, + 0x1B80, 0x4C181835, + 0x1B80, 0x4C181837, + 0x1B80, 0xBF071845, + 0x1B80, 0xBF071847, + 0x1B80, 0x54C21855, + 0x1B80, 0x54C21857, + 0x1B80, 0x54A41865, + 0x1B80, 0x54A41867, + 0x1B80, 0xBF041875, + 0x1B80, 0xBF041877, + 0x1B80, 0x54C11885, + 0x1B80, 0x54C11887, + 0x1B80, 0x54A31895, + 0x1B80, 0x54A31897, + 0x1B80, 0xBF0118A5, + 0x1B80, 0xBF0118A7, + 0x1B80, 0xE1D518B5, + 0x1B80, 0xE1D518B7, + 0x1B80, 0x54DF18C5, + 0x1B80, 0x54DF18C7, + 0x1B80, 0x000118D5, + 0x1B80, 0x000118D7, + 0x1B80, 0x54BF18E5, + 0x1B80, 0x54BF18E7, + 0x1B80, 0x54E518F5, + 0x1B80, 0x54E518F7, + 0x1B80, 0x050A1905, + 0x1B80, 0x050A1907, + 0x1B80, 0x54DF1915, + 0x1B80, 0x54DF1917, + 0x1B80, 0x00011925, + 0x1B80, 0x00011927, + 0x1B80, 0x7F201935, + 0x1B80, 0x7F201937, + 0x1B80, 0x7E001945, + 0x1B80, 0x7E001947, + 0x1B80, 0x7D001955, + 0x1B80, 0x7D001957, + 0x1B80, 0x55011965, + 0x1B80, 0x55011967, + 0x1B80, 0x5C311975, + 0x1B80, 0x5C311977, + 0x1B80, 0xE15D1985, + 0x1B80, 0xE15D1987, + 0x1B80, 0xE1611995, + 0x1B80, 0xE1611997, + 0x1B80, 0x548019A5, + 0x1B80, 0x548019A7, + 0x1B80, 0x540019B5, + 0x1B80, 0x540019B7, + 0x1B80, 0xE15D19C5, + 0x1B80, 0xE15D19C7, + 0x1B80, 0xE16119D5, + 0x1B80, 0xE16119D7, + 0x1B80, 0x548119E5, + 0x1B80, 0x548119E7, + 0x1B80, 0x540019F5, + 0x1B80, 0x540019F7, + 0x1B80, 0xE15D1A05, + 0x1B80, 0xE15D1A07, + 0x1B80, 0xE1611A15, + 0x1B80, 0xE1611A17, + 0x1B80, 0x54821A25, + 0x1B80, 0x54821A27, + 0x1B80, 0x54001A35, + 0x1B80, 0x54001A37, + 0x1B80, 0xE17E1A45, + 0x1B80, 0xE17E1A47, + 0x1B80, 0xBFE91A55, + 0x1B80, 0xBFE91A57, + 0x1B80, 0x301D1A65, + 0x1B80, 0x301D1A67, + 0x1B80, 0x00231A75, + 0x1B80, 0x00231A77, + 0x1B80, 0x7B201A85, + 0x1B80, 0x7B201A87, + 0x1B80, 0x7A001A95, + 0x1B80, 0x7A001A97, + 0x1B80, 0x79001AA5, + 0x1B80, 0x79001AA7, + 0x1B80, 0xE1CB1AB5, + 0x1B80, 0xE1CB1AB7, + 0x1B80, 0x00021AC5, + 0x1B80, 0x00021AC7, + 0x1B80, 0x00011AD5, + 0x1B80, 0x00011AD7, + 0x1B80, 0x00221AE5, + 0x1B80, 0x00221AE7, + 0x1B80, 0x7B201AF5, + 0x1B80, 0x7B201AF7, + 0x1B80, 0x7A001B05, + 0x1B80, 0x7A001B07, + 0x1B80, 0x79001B15, + 0x1B80, 0x79001B17, + 0x1B80, 0xE1CB1B25, + 0x1B80, 0xE1CB1B27, + 0x1B80, 0x00021B35, + 0x1B80, 0x00021B37, + 0x1B80, 0x00011B45, + 0x1B80, 0x00011B47, + 0x1B80, 0x74021B55, + 0x1B80, 0x74021B57, + 0x1B80, 0x003F1B65, + 0x1B80, 0x003F1B67, + 0x1B80, 0x74001B75, + 0x1B80, 0x74001B77, + 0x1B80, 0x00021B85, + 0x1B80, 0x00021B87, + 0x1B80, 0x00011B95, + 0x1B80, 0x00011B97, + 0x1B80, 0x4D041BA5, + 0x1B80, 0x4D041BA7, + 0x1B80, 0x2EF81BB5, + 0x1B80, 0x2EF81BB7, + 0x1B80, 0x00001BC5, + 0x1B80, 0x00001BC7, + 0x1B80, 0x23301BD5, + 0x1B80, 0x23301BD7, + 0x1B80, 0x00241BE5, + 0x1B80, 0x00241BE7, + 0x1B80, 0x23E01BF5, + 0x1B80, 0x23E01BF7, + 0x1B80, 0x003F1C05, + 0x1B80, 0x003F1C07, + 0x1B80, 0x23FC1C15, + 0x1B80, 0x23FC1C17, + 0x1B80, 0xBFCE1C25, + 0x1B80, 0xBFCE1C27, + 0x1B80, 0x2EF01C35, + 0x1B80, 0x2EF01C37, + 0x1B80, 0x00001C45, + 0x1B80, 0x00001C47, + 0x1B80, 0x4D001C55, + 0x1B80, 0x4D001C57, + 0x1B80, 0x00011C65, + 0x1B80, 0x00011C67, + 0x1B80, 0x549F1C75, + 0x1B80, 0x549F1C77, + 0x1B80, 0x54FF1C85, + 0x1B80, 0x54FF1C87, + 0x1B80, 0x54001C95, + 0x1B80, 0x54001C97, + 0x1B80, 0x00011CA5, + 0x1B80, 0x00011CA7, + 0x1B80, 0x5C311CB5, + 0x1B80, 0x5C311CB7, + 0x1B80, 0x07141CC5, + 0x1B80, 0x07141CC7, + 0x1B80, 0x54001CD5, + 0x1B80, 0x54001CD7, + 0x1B80, 0x5C321CE5, + 0x1B80, 0x5C321CE7, + 0x1B80, 0x00011CF5, + 0x1B80, 0x00011CF7, + 0x1B80, 0x5C321D05, + 0x1B80, 0x5C321D07, + 0x1B80, 0x07141D15, + 0x1B80, 0x07141D17, + 0x1B80, 0x54001D25, + 0x1B80, 0x54001D27, + 0x1B80, 0x5C311D35, + 0x1B80, 0x5C311D37, + 0x1B80, 0x00011D45, + 0x1B80, 0x00011D47, + 0x1B80, 0x4C981D55, + 0x1B80, 0x4C981D57, + 0x1B80, 0x4C181D65, + 0x1B80, 0x4C181D67, + 0x1B80, 0x00011D75, + 0x1B80, 0x00011D77, + 0x1B80, 0x5C321D85, + 0x1B80, 0x5C321D87, + 0x1B80, 0x62841D95, + 0x1B80, 0x62841D97, + 0x1B80, 0x66861DA5, + 0x1B80, 0x66861DA7, + 0x1B80, 0x6C031DB5, + 0x1B80, 0x6C031DB7, + 0x1B80, 0x7B201DC5, + 0x1B80, 0x7B201DC7, + 0x1B80, 0x7A001DD5, + 0x1B80, 0x7A001DD7, + 0x1B80, 0x79001DE5, + 0x1B80, 0x79001DE7, + 0x1B80, 0x7F201DF5, + 0x1B80, 0x7F201DF7, + 0x1B80, 0x7E001E05, + 0x1B80, 0x7E001E07, + 0x1B80, 0x7D001E15, + 0x1B80, 0x7D001E17, + 0x1B80, 0x09011E25, + 0x1B80, 0x09011E27, + 0x1B80, 0x0C011E35, + 0x1B80, 0x0C011E37, + 0x1B80, 0x0BA61E45, + 0x1B80, 0x0BA61E47, + 0x1B80, 0x00011E55, + 0x1B80, 0x00011E57, + 0x1B80, 0x00000006, + 0x1B80, 0x00000002, +}; + +RTW_DECL_TABLE_PHY_COND(rtw8822b_bb, rtw_phy_cfg_bb); + +static const u32 rtw8822b_bb_pg_type2[] = { + 0, 0, 0, 0x00000c20, 0xffffffff, 0x32343638, + 0, 0, 0, 0x00000c24, 0xffffffff, 0x36384042, + 0, 0, 0, 0x00000c28, 0xffffffff, 0x28303234, + 0, 0, 0, 0x00000c2c, 0xffffffff, 0x34363840, + 0, 0, 0, 0x00000c30, 0xffffffff, 0x26283032, + 0, 0, 1, 0x00000c34, 0xffffffff, 0x34363840, + 0, 0, 1, 0x00000c38, 0xffffffff, 0x26283032, + 0, 0, 0, 0x00000c3c, 0xffffffff, 0x34363840, + 0, 0, 0, 0x00000c40, 0xffffffff, 0x26283032, + 0, 0, 0, 0x00000c44, 0xffffffff, 0x38402224, + 0, 0, 1, 0x00000c48, 0xffffffff, 0x30323436, + 0, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628, + 0, 1, 0, 0x00000e20, 0xffffffff, 0x32343638, + 0, 1, 0, 0x00000e24, 0xffffffff, 0x36384042, + 0, 1, 0, 0x00000e28, 0xffffffff, 0x28303234, + 0, 1, 0, 0x00000e2c, 0xffffffff, 0x34363840, + 0, 1, 0, 0x00000e30, 0xffffffff, 0x26283032, + 0, 1, 1, 0x00000e34, 0xffffffff, 0x34363840, + 0, 1, 1, 0x00000e38, 0xffffffff, 0x26283032, + 0, 1, 0, 0x00000e3c, 0xffffffff, 0x34363840, + 0, 1, 0, 0x00000e40, 0xffffffff, 0x26283032, + 0, 1, 0, 0x00000e44, 0xffffffff, 0x38402224, + 0, 1, 1, 0x00000e48, 0xffffffff, 0x30323436, + 0, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628, + 1, 0, 0, 0x00000c24, 0xffffffff, 0x40424446, + 1, 0, 0, 0x00000c28, 0xffffffff, 0x32343638, + 1, 0, 0, 0x00000c2c, 0xffffffff, 0x38404244, + 1, 0, 0, 0x00000c30, 0xffffffff, 0x30323436, + 1, 0, 1, 0x00000c34, 0xffffffff, 0x38404244, + 1, 0, 1, 0x00000c38, 0xffffffff, 0x30323436, + 1, 0, 0, 0x00000c3c, 0xffffffff, 0x38404244, + 1, 0, 0, 0x00000c40, 0xffffffff, 0x30323436, + 1, 0, 0, 0x00000c44, 0xffffffff, 0x42442628, + 1, 0, 1, 0x00000c48, 0xffffffff, 0x34363840, + 1, 0, 1, 0x00000c4c, 0xffffffff, 0x26283032, + 1, 1, 0, 0x00000e24, 0xffffffff, 0x40424446, + 1, 1, 0, 0x00000e28, 0xffffffff, 0x32343638, + 1, 1, 0, 0x00000e2c, 0xffffffff, 0x38404244, + 1, 1, 0, 0x00000e30, 0xffffffff, 0x30323436, + 1, 1, 1, 0x00000e34, 0xffffffff, 0x38404244, + 1, 1, 1, 0x00000e38, 0xffffffff, 0x30323436, + 1, 1, 0, 0x00000e3c, 0xffffffff, 0x38404244, + 1, 1, 0, 0x00000e40, 0xffffffff, 0x30323436, + 1, 1, 0, 0x00000e44, 0xffffffff, 0x42442628, + 1, 1, 1, 0x00000e48, 0xffffffff, 0x34363840, + 1, 1, 1, 0x00000e4c, 0xffffffff, 0x26283032 +}; + +RTW_DECL_TABLE_BB_PG(rtw8822b_bb_pg_type2); + +static const u32 rtw8822b_bb_pg_type5[] = { + 0, 0, 0, 0x00000c20, 0xffffffff, 0x32343638, + 0, 0, 0, 0x00000c24, 0xffffffff, 0x36384042, + 0, 0, 0, 0x00000c28, 0xffffffff, 0x28303234, + 0, 0, 0, 0x00000c2c, 0xffffffff, 0x34363840, + 0, 0, 0, 0x00000c30, 0xffffffff, 0x26283032, + 0, 0, 1, 0x00000c34, 0xffffffff, 0x34363840, + 0, 0, 1, 0x00000c38, 0xffffffff, 0x26283032, + 0, 0, 0, 0x00000c3c, 0xffffffff, 0x34363840, + 0, 0, 0, 0x00000c40, 0xffffffff, 0x26283032, + 0, 0, 0, 0x00000c44, 0xffffffff, 0x38402224, + 0, 0, 1, 0x00000c48, 0xffffffff, 0x30323436, + 0, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628, + 0, 1, 0, 0x00000e20, 0xffffffff, 0x32343638, + 0, 1, 0, 0x00000e24, 0xffffffff, 0x36384042, + 0, 1, 0, 0x00000e28, 0xffffffff, 0x28303234, + 0, 1, 0, 0x00000e2c, 0xffffffff, 0x34363840, + 0, 1, 0, 0x00000e30, 0xffffffff, 0x26283032, + 0, 1, 1, 0x00000e34, 0xffffffff, 0x34363840, + 0, 1, 1, 0x00000e38, 0xffffffff, 0x26283032, + 0, 1, 0, 0x00000e3c, 0xffffffff, 0x34363840, + 0, 1, 0, 0x00000e40, 0xffffffff, 0x26283032, + 0, 1, 0, 0x00000e44, 0xffffffff, 0x38402224, + 0, 1, 1, 0x00000e48, 0xffffffff, 0x30323436, + 0, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628, + 1, 0, 0, 0x00000c24, 0xffffffff, 0x34363840, + 1, 0, 0, 0x00000c28, 0xffffffff, 0x26283032, + 1, 0, 0, 0x00000c2c, 0xffffffff, 0x32343638, + 1, 0, 0, 0x00000c30, 0xffffffff, 0x24262830, + 1, 0, 1, 0x00000c34, 0xffffffff, 0x32343638, + 1, 0, 1, 0x00000c38, 0xffffffff, 0x24262830, + 1, 0, 0, 0x00000c3c, 0xffffffff, 0x32343638, + 1, 0, 0, 0x00000c40, 0xffffffff, 0x24262830, + 1, 0, 0, 0x00000c44, 0xffffffff, 0x36382022, + 1, 0, 1, 0x00000c48, 0xffffffff, 0x28303234, + 1, 0, 1, 0x00000c4c, 0xffffffff, 0x20222426, + 1, 1, 0, 0x00000e24, 0xffffffff, 0x34363840, + 1, 1, 0, 0x00000e28, 0xffffffff, 0x26283032, + 1, 1, 0, 0x00000e2c, 0xffffffff, 0x32343638, + 1, 1, 0, 0x00000e30, 0xffffffff, 0x24262830, + 1, 1, 1, 0x00000e34, 0xffffffff, 0x32343638, + 1, 1, 1, 0x00000e38, 0xffffffff, 0x24262830, + 1, 1, 0, 0x00000e3c, 0xffffffff, 0x32343638, + 1, 1, 0, 0x00000e40, 0xffffffff, 0x24262830, + 1, 1, 0, 0x00000e44, 0xffffffff, 0x36382022, + 1, 1, 1, 0x00000e48, 0xffffffff, 0x28303234, + 1, 1, 1, 0x00000e4c, 0xffffffff, 0x20222426 +}; + +RTW_DECL_TABLE_BB_PG(rtw8822b_bb_pg_type5); + +static const u32 rtw8822b_rf_a[] = { + 0x000, 0x00030000, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0xA0000000, 0x00000000, + 0x001, 0x00040029, + 0xB0000000, 0x00000000, + 0x018, 0x00010D24, + 0x0EF, 0x00080000, + 0x033, 0x00000002, + 0x03E, 0x0000003F, + 0x8300000c, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000D0F4E, + 0xA0000000, 0x00000000, + 0x03F, 0x000C0F4E, + 0xB0000000, 0x00000000, + 0x033, 0x00000001, + 0x03E, 0x00000034, + 0x03F, 0x0004080E, + 0x0EF, 0x00080000, + 0x0DF, 0x00002449, + 0x033, 0x00000024, + 0x03E, 0x0000003F, + 0x03F, 0x00060FDE, + 0x0EF, 0x00000000, + 0x0EF, 0x00080000, + 0x033, 0x00000025, + 0x03E, 0x00000037, + 0x03F, 0x0007EFCE, + 0x0EF, 0x00000000, + 0x0EF, 0x00080000, + 0x033, 0x00000026, + 0x03E, 0x00000037, + 0x03F, 0x000DEFCE, + 0x0EF, 0x00000000, + 0x07F, 0x00000000, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FF0F8, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FF0F8, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FB0F8, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FB0F8, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FB0F8, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FB0F8, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FF0F8, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FF0F8, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FB0F8, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FF0F8, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FF0F8, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FB0F8, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FB0F8, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FF0F8, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FF0F8, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FB0F8, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FB0F8, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FB0F8, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FB0F8, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FF0F8, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FB0F8, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FB0F8, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FB0F8, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FB0F8, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FF0F8, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x0B0, 0x000FF0F8, + 0xA0000000, 0x00000000, + 0x0B0, 0x000FF0F8, + 0xB0000000, 0x00000000, + 0x0B1, 0x0007DBE4, + 0x0B2, 0x000225D1, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C330, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0003C360, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x000FC760, + 0xA0000000, 0x00000000, + 0x0B3, 0x000FC760, + 0xB0000000, 0x00000000, + 0x0B4, 0x00099DD0, + 0x0B5, 0x000400FC, + 0x0B6, 0x000187F0, + 0x0B7, 0x00030018, + 0x0B8, 0x00080800, + 0x0B9, 0x00000000, + 0x0BA, 0x00008000, + 0x0BB, 0x00000000, + 0x0BC, 0x00040030, + 0x0BD, 0x00000000, + 0x0BE, 0x00000000, + 0x0BF, 0x00000000, + 0x0C0, 0x00000000, + 0x0C1, 0x00000000, + 0x0C2, 0x00000000, + 0x0C3, 0x00000000, + 0x0C4, 0x00002402, + 0x0C5, 0x00000009, + 0x0C6, 0x00040299, + 0x0C7, 0x00055555, + 0x0C8, 0x0000C16C, + 0x0C9, 0x0001C146, + 0x0CA, 0x00000000, + 0x0CB, 0x00000000, + 0x0CC, 0x00000000, + 0x0CD, 0x00000000, + 0x0CE, 0x00090C00, + 0x0CF, 0x0006D200, + 0x0DF, 0x00000009, + 0x018, 0x00010524, + 0x089, 0x00000207, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FF186, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FF186, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FF186, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FE186, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FE186, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FF186, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FF186, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FF186, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FF186, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FF186, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FF186, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FE186, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FF186, + 0xA0000000, 0x00000000, + 0x08A, 0x000FF186, + 0xB0000000, 0x00000000, + 0x08B, 0x00061E3C, + 0x08C, 0x000112C7, + 0x08D, 0x000F4988, + 0x08E, 0x00064D40, + 0x0EF, 0x00020000, + 0x033, 0x00000007, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0xA0000000, 0x00000000, + 0x03E, 0x00004000, + 0xB0000000, 0x00000000, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0006, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000DFF86, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0006, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000DFF86, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0006, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0006, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0006, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0xA0000000, 0x00000000, + 0x03F, 0x000C3186, + 0xB0000000, 0x00000000, + 0x033, 0x00000006, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0xA0000000, 0x00000000, + 0x03E, 0x00004080, + 0xB0000000, 0x00000000, + 0x03F, 0x000C3186, + 0x033, 0x00000005, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x000040C8, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x000040C8, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x000040C8, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x000040C8, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x000040C8, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x000040C8, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004084, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x000040C8, + 0xA0000000, 0x00000000, + 0x03E, 0x000040C8, + 0xB0000000, 0x00000000, + 0x03F, 0x000C3186, + 0x033, 0x00000004, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004190, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004190, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004190, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004190, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004190, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004190, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004108, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004190, + 0xA0000000, 0x00000000, + 0x03E, 0x00004190, + 0xB0000000, 0x00000000, + 0x03F, 0x000C3186, + 0x033, 0x00000003, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004998, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004998, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004998, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004998, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004998, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004998, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x0000490C, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004998, + 0xA0000000, 0x00000000, + 0x03E, 0x00004998, + 0xB0000000, 0x00000000, + 0x03F, 0x000C3186, + 0x033, 0x00000002, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005840, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005840, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005840, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005840, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005840, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005840, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005E00, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005840, + 0xA0000000, 0x00000000, + 0x03E, 0x00005840, + 0xB0000000, 0x00000000, + 0x03F, 0x000C3186, + 0x033, 0x00000001, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x000058C2, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x000058C2, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x000058C2, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x000058C2, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x000058C2, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x000058C2, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005862, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x000058C2, + 0xA0000000, 0x00000000, + 0x03E, 0x000058C2, + 0xB0000000, 0x00000000, + 0x03F, 0x000C3186, + 0x033, 0x00000000, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005930, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005930, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005930, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005930, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005930, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005930, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005948, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00005930, + 0xA0000000, 0x00000000, + 0x03E, 0x00005930, + 0xB0000000, 0x00000000, + 0x03F, 0x000C3186, + 0x033, 0x0000000F, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0xA0000000, 0x00000000, + 0x03E, 0x00004000, + 0xB0000000, 0x00000000, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0006, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000DFF86, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000DFF86, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0006, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0006, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0006, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0006, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0xA0000000, 0x00000000, + 0x03F, 0x000C3186, + 0xB0000000, 0x00000000, + 0x033, 0x0000000E, + 0x03E, 0x00004080, + 0x03F, 0x000C3186, + 0x033, 0x0000000D, + 0x03E, 0x000040C8, + 0x03F, 0x000C3186, + 0x033, 0x0000000C, + 0x03E, 0x00004190, + 0x03F, 0x000C3186, + 0x033, 0x0000000B, + 0x03E, 0x00004998, + 0x03F, 0x000C3186, + 0x033, 0x0000000A, + 0x03E, 0x00005840, + 0x03F, 0x000C3186, + 0x033, 0x00000009, + 0x03E, 0x000058C2, + 0x03F, 0x000C3186, + 0x033, 0x00000008, + 0x03E, 0x00005930, + 0x03F, 0x000C3186, + 0x033, 0x00000017, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0xA0000000, 0x00000000, + 0x03E, 0x00004000, + 0xB0000000, 0x00000000, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0006, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0006, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000DFF86, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0006, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0006, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0006, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C3186, + 0xA0000000, 0x00000000, + 0x03F, 0x000C3186, + 0xB0000000, 0x00000000, + 0x033, 0x00000016, + 0x03E, 0x00004080, + 0x03F, 0x000C3186, + 0x033, 0x00000015, + 0x03E, 0x000040C8, + 0x03F, 0x000C3186, + 0x033, 0x00000014, + 0x03E, 0x00004190, + 0x03F, 0x000C3186, + 0x033, 0x00000013, + 0x03E, 0x00004998, + 0x03F, 0x000C3186, + 0x033, 0x00000012, + 0x03E, 0x00005840, + 0x03F, 0x000C3186, + 0x033, 0x00000011, + 0x03E, 0x000058C2, + 0x03F, 0x000C3186, + 0x033, 0x00000010, + 0x03E, 0x00005930, + 0x03F, 0x000C3186, + 0x0EF, 0x00000000, + 0x0EF, 0x00004000, + 0x033, 0x00000000, + 0x03F, 0x0000000A, + 0x033, 0x00000001, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000005, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000006, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000005, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000005, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000005, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000005, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0xA0000000, 0x00000000, + 0x03F, 0x00000005, + 0xB0000000, 0x00000000, + 0x033, 0x00000002, + 0x03F, 0x00000000, + 0x0EF, 0x00000000, + 0x018, 0x00000401, + 0x084, 0x00001209, + 0x086, 0x000001A0, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0xA0000000, 0x00000000, + 0x087, 0x000E8180, + 0xB0000000, 0x00000000, + 0x088, 0x00070020, + 0x0DE, 0x00000010, + 0x0EF, 0x00008000, + 0x033, 0x0000000F, + 0x03F, 0x0000003C, + 0x033, 0x0000000E, + 0x03F, 0x00000038, + 0x033, 0x0000000D, + 0x03F, 0x00000030, + 0x033, 0x0000000C, + 0x03F, 0x00000028, + 0x033, 0x0000000B, + 0x03F, 0x00000020, + 0x033, 0x0000000A, + 0x03F, 0x00000018, + 0x033, 0x00000009, + 0x03F, 0x00000010, + 0x033, 0x00000008, + 0x03F, 0x00000008, + 0x033, 0x00000007, + 0x03F, 0x0000003C, + 0x033, 0x00000006, + 0x03F, 0x00000038, + 0x033, 0x00000005, + 0x03F, 0x00000030, + 0x033, 0x00000004, + 0x03F, 0x00000028, + 0x033, 0x00000003, + 0x03F, 0x00000020, + 0x033, 0x00000002, + 0x03F, 0x00000018, + 0x033, 0x00000001, + 0x03F, 0x00000010, + 0x033, 0x00000000, + 0x03F, 0x00000008, + 0x0EF, 0x00000000, + 0x0B8, 0x00080A00, + 0x0FE, 0x00000000, + 0x0B0, 0x000FF0FA, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0CA, 0x00080000, + 0x0FE, 0x00000000, + 0x0C9, 0x0001C141, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0B0, 0x000FF0F8, + 0x018, 0x00018D24, + 0xFFE, 0x00000000, + 0xFFE, 0x00000000, + 0xFFE, 0x00000000, + 0xFFE, 0x00000000, + 0x018, 0x00010D24, + 0x01B, 0x00075A40, + 0x0EE, 0x00000002, + 0x033, 0x00000000, + 0x03F, 0x00000004, + 0x033, 0x00000001, + 0x03F, 0x00000004, + 0x033, 0x00000002, + 0x03F, 0x00000004, + 0x033, 0x00000003, + 0x03F, 0x00000004, + 0x033, 0x00000004, + 0x03F, 0x00000004, + 0x033, 0x00000005, + 0x03F, 0x00000006, + 0x033, 0x00000006, + 0x03F, 0x00000004, + 0x033, 0x00000007, + 0x03F, 0x00000000, + 0x0EE, 0x00000000, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D3D1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D4A0, + 0x062, 0x0000D203, + 0x063, 0x00000062, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000062, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D301, + 0x062, 0x0000D303, + 0x063, 0x00000002, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000062, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D301, + 0x062, 0x0000D303, + 0x063, 0x00000002, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D4A0, + 0x062, 0x0000D203, + 0x063, 0x00000062, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D4A0, + 0x062, 0x0000D203, + 0x063, 0x00000062, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D301, + 0x062, 0x0000D303, + 0x063, 0x00000002, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D3D1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D3D1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D4A0, + 0x062, 0x0000D203, + 0x063, 0x00000062, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D301, + 0x062, 0x0000D303, + 0x063, 0x00000002, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D3D1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D3D1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D301, + 0x062, 0x0000D303, + 0x063, 0x00000002, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D301, + 0x062, 0x0000D303, + 0x063, 0x00000002, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D301, + 0x062, 0x0000D303, + 0x063, 0x00000002, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000062, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D4A0, + 0x062, 0x0000D203, + 0x063, 0x00000062, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000062, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D301, + 0x062, 0x0000D303, + 0x063, 0x00000002, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000062, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D301, + 0x062, 0x0000D303, + 0x063, 0x00000002, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D4A0, + 0x062, 0x0000D203, + 0x063, 0x00000062, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D4A0, + 0x062, 0x0000D203, + 0x063, 0x00000062, + 0xA0000000, 0x00000000, + 0x061, 0x0005D3D0, + 0x062, 0x0000D303, + 0x063, 0x00000002, + 0xB0000000, 0x00000000, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A3, + 0x030, 0x000093A3, + 0x030, 0x0000A3A3, + 0x030, 0x0000B3A3, + 0x0EF, 0x00000000, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000004A3, + 0x030, 0x000014A3, + 0x030, 0x000024A3, + 0x030, 0x000034A3, + 0x030, 0x000044A3, + 0x030, 0x000054A3, + 0x030, 0x000064A3, + 0x030, 0x000074A3, + 0x030, 0x000084A3, + 0x030, 0x000094A3, + 0x030, 0x0000A4A3, + 0x030, 0x0000B4A3, + 0x0EF, 0x00000000, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000002A6, + 0x030, 0x000012A6, + 0x030, 0x000022A6, + 0x030, 0x000032A6, + 0x030, 0x000042A6, + 0x030, 0x000052A6, + 0x030, 0x000062A6, + 0x030, 0x000072A6, + 0x030, 0x000082A6, + 0x030, 0x000092A6, + 0x030, 0x0000A2A6, + 0x030, 0x0000B2A6, + 0x0EF, 0x00000000, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x00000303, + 0x030, 0x00001303, + 0x030, 0x00002303, + 0x030, 0x00003303, + 0x030, 0x000043A4, + 0x030, 0x000053A4, + 0x030, 0x000063A4, + 0x030, 0x000073A4, + 0x030, 0x00008365, + 0x030, 0x00009365, + 0x030, 0x0000A365, + 0x030, 0x0000B365, + 0x0EF, 0x00000000, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000002A6, + 0x030, 0x000012A6, + 0x030, 0x000022A6, + 0x030, 0x000032A6, + 0x030, 0x000042A6, + 0x030, 0x000052A6, + 0x030, 0x000062A6, + 0x030, 0x000072A6, + 0x030, 0x000082A6, + 0x030, 0x000092A6, + 0x030, 0x0000A2A6, + 0x030, 0x0000B2A6, + 0x0EF, 0x00000000, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000003A3, + 0x030, 0x000013A3, + 0x030, 0x000023A3, + 0x030, 0x000033A3, + 0x030, 0x00004355, + 0x030, 0x00005355, + 0x030, 0x00006355, + 0x030, 0x00007355, + 0x030, 0x00008315, + 0x030, 0x00009315, + 0x030, 0x0000A315, + 0x030, 0x0000B315, + 0x0EF, 0x00000000, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000004A3, + 0x030, 0x000014A3, + 0x030, 0x000024A3, + 0x030, 0x000034A3, + 0x030, 0x000044A3, + 0x030, 0x000054A3, + 0x030, 0x000064A3, + 0x030, 0x000074A3, + 0x030, 0x000084A3, + 0x030, 0x000094A3, + 0x030, 0x0000A4A3, + 0x030, 0x0000B4A3, + 0x0EF, 0x00000000, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000004A3, + 0x030, 0x000014A3, + 0x030, 0x000024A3, + 0x030, 0x000034A3, + 0x030, 0x000044A3, + 0x030, 0x000054A3, + 0x030, 0x000064A3, + 0x030, 0x000074A3, + 0x030, 0x000084A3, + 0x030, 0x000094A3, + 0x030, 0x0000A4A3, + 0x030, 0x0000B4A3, + 0x0EF, 0x00000000, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x00000384, + 0x030, 0x00001384, + 0x030, 0x00002384, + 0x030, 0x00003384, + 0x030, 0x00004425, + 0x030, 0x00005425, + 0x030, 0x00006425, + 0x030, 0x00007425, + 0x030, 0x000084A6, + 0x030, 0x000094A6, + 0x030, 0x0000A4A6, + 0x030, 0x0000B4A6, + 0x0EF, 0x00000000, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x00000463, + 0x030, 0x00001463, + 0x030, 0x00002463, + 0x030, 0x00003463, + 0x030, 0x00004545, + 0x030, 0x00005545, + 0x030, 0x00006545, + 0x030, 0x00007545, + 0x030, 0x00008565, + 0x030, 0x00009565, + 0x030, 0x0000A565, + 0x030, 0x0000B565, + 0x0EF, 0x00000000, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A3, + 0x030, 0x000093A3, + 0x030, 0x0000A3A3, + 0x030, 0x0000B3A3, + 0x0EF, 0x00000000, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000004A3, + 0x030, 0x000014A3, + 0x030, 0x000024A3, + 0x030, 0x000034A3, + 0x030, 0x000044A3, + 0x030, 0x000054A3, + 0x030, 0x000064A3, + 0x030, 0x000074A3, + 0x030, 0x000084A3, + 0x030, 0x000094A3, + 0x030, 0x0000A4A3, + 0x030, 0x0000B4A3, + 0x0EF, 0x00000000, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x00000443, + 0x030, 0x00001443, + 0x030, 0x00002443, + 0x030, 0x00003443, + 0x030, 0x000043A4, + 0x030, 0x000053A4, + 0x030, 0x000063A4, + 0x030, 0x000073A4, + 0x030, 0x00008365, + 0x030, 0x00009365, + 0x030, 0x0000A365, + 0x030, 0x0000B365, + 0x0EF, 0x00000000, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x00000443, + 0x030, 0x00001443, + 0x030, 0x00002443, + 0x030, 0x00003443, + 0x030, 0x00004483, + 0x030, 0x00005483, + 0x030, 0x00006483, + 0x030, 0x00007483, + 0x030, 0x000084A4, + 0x030, 0x000094A4, + 0x030, 0x0000A4A4, + 0x030, 0x0000B4A4, + 0x0EF, 0x00000000, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x00000361, + 0x030, 0x00001361, + 0x030, 0x00002361, + 0x030, 0x00003361, + 0x030, 0x00004443, + 0x030, 0x00005443, + 0x030, 0x00006443, + 0x030, 0x00007443, + 0x030, 0x00008424, + 0x030, 0x00009424, + 0x030, 0x0000A424, + 0x030, 0x0000B424, + 0x0EF, 0x00000000, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x00000334, + 0x030, 0x00001334, + 0x030, 0x00002334, + 0x030, 0x00003334, + 0x030, 0x000043A4, + 0x030, 0x000053A4, + 0x030, 0x000063A4, + 0x030, 0x000073A4, + 0x030, 0x00008365, + 0x030, 0x00009365, + 0x030, 0x0000A365, + 0x030, 0x0000B365, + 0x0EF, 0x00000000, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x00000403, + 0x030, 0x00001403, + 0x030, 0x00002403, + 0x030, 0x00003403, + 0x030, 0x000044A2, + 0x030, 0x000054A2, + 0x030, 0x000064A2, + 0x030, 0x000074A2, + 0x030, 0x000083A3, + 0x030, 0x000093A3, + 0x030, 0x0000A3A3, + 0x030, 0x0000B3A3, + 0x0EF, 0x00000000, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000003A3, + 0x030, 0x000013A3, + 0x030, 0x000023A3, + 0x030, 0x000033A3, + 0x030, 0x000043A4, + 0x030, 0x000053A4, + 0x030, 0x000063A4, + 0x030, 0x000073A4, + 0x030, 0x00008365, + 0x030, 0x00009365, + 0x030, 0x0000A365, + 0x030, 0x0000B365, + 0x0EF, 0x00000000, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000002A6, + 0x030, 0x000012A6, + 0x030, 0x000022A6, + 0x030, 0x000032A6, + 0x030, 0x000042A6, + 0x030, 0x000052A6, + 0x030, 0x000062A6, + 0x030, 0x000072A6, + 0x030, 0x000082A6, + 0x030, 0x000092A6, + 0x030, 0x0000A2A6, + 0x030, 0x0000B2A6, + 0x0EF, 0x00000000, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000004A0, + 0x030, 0x000014A0, + 0x030, 0x000024A0, + 0x030, 0x000034A0, + 0x030, 0x000044A0, + 0x030, 0x000054A0, + 0x030, 0x000064A0, + 0x030, 0x000074A0, + 0x030, 0x000084A0, + 0x030, 0x000094A0, + 0x030, 0x0000A4A0, + 0x030, 0x0000B4A0, + 0x0EF, 0x00000000, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000002A1, + 0x030, 0x000012A1, + 0x030, 0x000022A1, + 0x030, 0x000032A1, + 0x030, 0x000042A1, + 0x030, 0x000052A1, + 0x030, 0x000062A1, + 0x030, 0x000072A1, + 0x030, 0x000082A1, + 0x030, 0x000092A1, + 0x030, 0x0000A2A1, + 0x030, 0x0000B2A1, + 0x0EF, 0x00000000, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000003A0, + 0x030, 0x000013A0, + 0x030, 0x000023A0, + 0x030, 0x000033A0, + 0x030, 0x000043A1, + 0x030, 0x000053A1, + 0x030, 0x000063A1, + 0x030, 0x000073A1, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x0EF, 0x00000000, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000002A1, + 0x030, 0x000012A1, + 0x030, 0x000022A1, + 0x030, 0x000032A1, + 0x030, 0x000042A1, + 0x030, 0x000052A1, + 0x030, 0x000062A1, + 0x030, 0x000072A1, + 0x030, 0x000082A1, + 0x030, 0x000092A1, + 0x030, 0x0000A2A1, + 0x030, 0x0000B2A1, + 0x0EF, 0x00000000, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000003A0, + 0x030, 0x000013A0, + 0x030, 0x000023A0, + 0x030, 0x000033A0, + 0x030, 0x00004430, + 0x030, 0x00005430, + 0x030, 0x00006430, + 0x030, 0x00007430, + 0x030, 0x00008372, + 0x030, 0x00009372, + 0x030, 0x0000A372, + 0x030, 0x0000B372, + 0x0EF, 0x00000000, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000004A0, + 0x030, 0x000014A0, + 0x030, 0x000024A0, + 0x030, 0x000034A0, + 0x030, 0x000044A0, + 0x030, 0x000054A0, + 0x030, 0x000064A0, + 0x030, 0x000074A0, + 0x030, 0x000084A0, + 0x030, 0x000094A0, + 0x030, 0x0000A4A0, + 0x030, 0x0000B4A0, + 0x0EF, 0x00000000, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000004A0, + 0x030, 0x000014A0, + 0x030, 0x000024A0, + 0x030, 0x000034A0, + 0x030, 0x000044A0, + 0x030, 0x000054A0, + 0x030, 0x000064A0, + 0x030, 0x000074A0, + 0x030, 0x000084A0, + 0x030, 0x000094A0, + 0x030, 0x0000A4A0, + 0x030, 0x0000B4A0, + 0x0EF, 0x00000000, + 0xA0000000, 0x00000000, + 0x0EF, 0x00000200, + 0x030, 0x000003D0, + 0x030, 0x000013D0, + 0x030, 0x000023D0, + 0x030, 0x000033D0, + 0x030, 0x000043D0, + 0x030, 0x000053D0, + 0x030, 0x000063D0, + 0x030, 0x000073D0, + 0x030, 0x000083D0, + 0x030, 0x000093D0, + 0x030, 0x0000A3D0, + 0x030, 0x0000B3D0, + 0x0EF, 0x00000000, + 0xB0000000, 0x00000000, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x00000203, + 0x030, 0x00001203, + 0x030, 0x00002203, + 0x030, 0x00003203, + 0x030, 0x00004203, + 0x030, 0x00005203, + 0x030, 0x00006203, + 0x030, 0x00007203, + 0x030, 0x00008203, + 0x030, 0x00009203, + 0x030, 0x0000A203, + 0x030, 0x0000B203, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x00000203, + 0x030, 0x00001203, + 0x030, 0x00002203, + 0x030, 0x00003203, + 0x030, 0x00004203, + 0x030, 0x00005203, + 0x030, 0x00006203, + 0x030, 0x00007203, + 0x030, 0x00008203, + 0x030, 0x00009203, + 0x030, 0x0000A203, + 0x030, 0x0000B203, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x00000203, + 0x030, 0x00001203, + 0x030, 0x00002203, + 0x030, 0x00003203, + 0x030, 0x00004203, + 0x030, 0x00005203, + 0x030, 0x00006203, + 0x030, 0x00007203, + 0x030, 0x00008203, + 0x030, 0x00009203, + 0x030, 0x0000A203, + 0x030, 0x0000B203, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A3, + 0x030, 0x000013A3, + 0x030, 0x000023A3, + 0x030, 0x000033A3, + 0x030, 0x000043A3, + 0x030, 0x000053A3, + 0x030, 0x000063A3, + 0x030, 0x000073A3, + 0x030, 0x000083A3, + 0x030, 0x000093A3, + 0x030, 0x0000A3A3, + 0x030, 0x0000B3A3, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x00000203, + 0x030, 0x00001203, + 0x030, 0x00002203, + 0x030, 0x00003203, + 0x030, 0x00004203, + 0x030, 0x00005203, + 0x030, 0x00006203, + 0x030, 0x00007203, + 0x030, 0x00008203, + 0x030, 0x00009203, + 0x030, 0x0000A203, + 0x030, 0x0000B203, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x00000203, + 0x030, 0x00001203, + 0x030, 0x00002203, + 0x030, 0x00003203, + 0x030, 0x00004203, + 0x030, 0x00005203, + 0x030, 0x00006203, + 0x030, 0x00007203, + 0x030, 0x00008203, + 0x030, 0x00009203, + 0x030, 0x0000A203, + 0x030, 0x0000B203, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x00000203, + 0x030, 0x00001203, + 0x030, 0x00002203, + 0x030, 0x00003203, + 0x030, 0x00004203, + 0x030, 0x00005203, + 0x030, 0x00006203, + 0x030, 0x00007203, + 0x030, 0x00008203, + 0x030, 0x00009203, + 0x030, 0x0000A203, + 0x030, 0x0000B203, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x00000203, + 0x030, 0x00001203, + 0x030, 0x00002203, + 0x030, 0x00003203, + 0x030, 0x00004203, + 0x030, 0x00005203, + 0x030, 0x00006203, + 0x030, 0x00007203, + 0x030, 0x00008203, + 0x030, 0x00009203, + 0x030, 0x0000A203, + 0x030, 0x0000B203, + 0xA0000000, 0x00000000, + 0x0EF, 0x00000080, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000764, + 0x030, 0x00001632, + 0x030, 0x00002421, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000777, + 0x030, 0x00001442, + 0x030, 0x00002222, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000776, + 0x030, 0x00001455, + 0x030, 0x00002335, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000660, + 0x030, 0x00001443, + 0x030, 0x00002221, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000764, + 0x030, 0x00001632, + 0x030, 0x00002421, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000764, + 0x030, 0x00001632, + 0x030, 0x00002421, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000767, + 0x030, 0x00001442, + 0x030, 0x00002222, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000765, + 0x030, 0x00001632, + 0x030, 0x00002451, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000764, + 0x030, 0x00001632, + 0x030, 0x00002421, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000777, + 0x030, 0x00001454, + 0x030, 0x00002224, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000777, + 0x030, 0x00001442, + 0x030, 0x00002222, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000777, + 0x030, 0x00001442, + 0x030, 0x00002222, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000775, + 0x030, 0x00001422, + 0x030, 0x00002210, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000775, + 0x030, 0x00001343, + 0x030, 0x00002210, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0xA0000000, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000764, + 0x030, 0x00001632, + 0x030, 0x00002421, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x0EF, 0x00000800, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000C09, + 0x033, 0x00000021, + 0x03F, 0x00000C0C, + 0x033, 0x00000022, + 0x03F, 0x00000C0F, + 0x033, 0x00000023, + 0x03F, 0x00000C2C, + 0x033, 0x00000024, + 0x03F, 0x00000C2F, + 0x033, 0x00000025, + 0x03F, 0x00000C8A, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000C90, + 0x033, 0x00000028, + 0x03F, 0x00000CD0, + 0x033, 0x00000029, + 0x03F, 0x00000CF2, + 0x033, 0x0000002A, + 0x03F, 0x00000CF5, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000007, + 0x033, 0x00000021, + 0x03F, 0x0000000A, + 0x033, 0x00000022, + 0x03F, 0x0000000D, + 0x033, 0x00000023, + 0x03F, 0x0000002A, + 0x033, 0x00000024, + 0x03F, 0x0000002D, + 0x033, 0x00000025, + 0x03F, 0x00000030, + 0x033, 0x00000026, + 0x03F, 0x0000006D, + 0x033, 0x00000027, + 0x03F, 0x00000070, + 0x033, 0x00000028, + 0x03F, 0x000000ED, + 0x033, 0x00000029, + 0x03F, 0x000000F0, + 0x033, 0x0000002A, + 0x03F, 0x000000F3, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000005, + 0x033, 0x00000021, + 0x03F, 0x00000008, + 0x033, 0x00000022, + 0x03F, 0x0000000B, + 0x033, 0x00000023, + 0x03F, 0x0000000E, + 0x033, 0x00000024, + 0x03F, 0x0000002B, + 0x033, 0x00000025, + 0x03F, 0x0000002E, + 0x033, 0x00000026, + 0x03F, 0x0000006B, + 0x033, 0x00000027, + 0x03F, 0x0000006E, + 0x033, 0x00000028, + 0x03F, 0x00000071, + 0x033, 0x00000029, + 0x03F, 0x00000074, + 0x033, 0x0000002A, + 0x03F, 0x00000077, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000429, + 0x033, 0x00000021, + 0x03F, 0x00000828, + 0x033, 0x00000022, + 0x03F, 0x00000847, + 0x033, 0x00000023, + 0x03F, 0x0000084A, + 0x033, 0x00000024, + 0x03F, 0x00000C4B, + 0x033, 0x00000025, + 0x03F, 0x00000C6C, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000CAF, + 0x033, 0x00000028, + 0x03F, 0x00000CD1, + 0x033, 0x00000029, + 0x03F, 0x00000CF3, + 0x033, 0x0000002A, + 0x03F, 0x00000CF6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000005, + 0x033, 0x00000021, + 0x03F, 0x00000008, + 0x033, 0x00000022, + 0x03F, 0x0000000B, + 0x033, 0x00000023, + 0x03F, 0x0000000E, + 0x033, 0x00000024, + 0x03F, 0x0000002B, + 0x033, 0x00000025, + 0x03F, 0x0000002E, + 0x033, 0x00000026, + 0x03F, 0x0000006B, + 0x033, 0x00000027, + 0x03F, 0x0000006E, + 0x033, 0x00000028, + 0x03F, 0x00000071, + 0x033, 0x00000029, + 0x03F, 0x00000074, + 0x033, 0x0000002A, + 0x03F, 0x00000077, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x0000042B, + 0x033, 0x00000021, + 0x03F, 0x0000082A, + 0x033, 0x00000022, + 0x03F, 0x00000849, + 0x033, 0x00000023, + 0x03F, 0x0000084C, + 0x033, 0x00000024, + 0x03F, 0x00000C4C, + 0x033, 0x00000025, + 0x03F, 0x00000C6C, + 0x033, 0x00000026, + 0x03F, 0x00000CAC, + 0x033, 0x00000027, + 0x03F, 0x00000CED, + 0x033, 0x00000028, + 0x03F, 0x00000CF0, + 0x033, 0x00000029, + 0x03F, 0x00000CF3, + 0x033, 0x0000002A, + 0x03F, 0x00000CF6, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000007, + 0x033, 0x00000021, + 0x03F, 0x0000000A, + 0x033, 0x00000022, + 0x03F, 0x0000000D, + 0x033, 0x00000023, + 0x03F, 0x0000002A, + 0x033, 0x00000024, + 0x03F, 0x0000002D, + 0x033, 0x00000025, + 0x03F, 0x00000030, + 0x033, 0x00000026, + 0x03F, 0x0000006D, + 0x033, 0x00000027, + 0x03F, 0x00000070, + 0x033, 0x00000028, + 0x03F, 0x000000ED, + 0x033, 0x00000029, + 0x03F, 0x000000F0, + 0x033, 0x0000002A, + 0x03F, 0x000000F3, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000007, + 0x033, 0x00000021, + 0x03F, 0x0000000A, + 0x033, 0x00000022, + 0x03F, 0x0000000D, + 0x033, 0x00000023, + 0x03F, 0x0000002A, + 0x033, 0x00000024, + 0x03F, 0x0000002D, + 0x033, 0x00000025, + 0x03F, 0x00000030, + 0x033, 0x00000026, + 0x03F, 0x0000006D, + 0x033, 0x00000027, + 0x03F, 0x00000070, + 0x033, 0x00000028, + 0x03F, 0x000000ED, + 0x033, 0x00000029, + 0x03F, 0x000000F0, + 0x033, 0x0000002A, + 0x03F, 0x000000F3, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000C0C, + 0x033, 0x00000021, + 0x03F, 0x00000C29, + 0x033, 0x00000022, + 0x03F, 0x00000C2C, + 0x033, 0x00000023, + 0x03F, 0x00000C69, + 0x033, 0x00000024, + 0x03F, 0x00000CA8, + 0x033, 0x00000025, + 0x03F, 0x00000CE8, + 0x033, 0x00000026, + 0x03F, 0x00000CEB, + 0x033, 0x00000027, + 0x03F, 0x00000CEE, + 0x033, 0x00000028, + 0x03F, 0x00000CF1, + 0x033, 0x00000029, + 0x03F, 0x00000CF4, + 0x033, 0x0000002A, + 0x03F, 0x00000CF7, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000C09, + 0x033, 0x00000021, + 0x03F, 0x00000C0C, + 0x033, 0x00000022, + 0x03F, 0x00000C0F, + 0x033, 0x00000023, + 0x03F, 0x00000C2C, + 0x033, 0x00000024, + 0x03F, 0x00000C2F, + 0x033, 0x00000025, + 0x03F, 0x00000C8A, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000C90, + 0x033, 0x00000028, + 0x03F, 0x00000CD0, + 0x033, 0x00000029, + 0x03F, 0x00000CF2, + 0x033, 0x0000002A, + 0x03F, 0x00000CF5, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000C09, + 0x033, 0x00000021, + 0x03F, 0x00000C0C, + 0x033, 0x00000022, + 0x03F, 0x00000C0F, + 0x033, 0x00000023, + 0x03F, 0x00000C2C, + 0x033, 0x00000024, + 0x03F, 0x00000C2F, + 0x033, 0x00000025, + 0x03F, 0x00000C8A, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000C90, + 0x033, 0x00000028, + 0x03F, 0x00000CD0, + 0x033, 0x00000029, + 0x03F, 0x00000CF2, + 0x033, 0x0000002A, + 0x03F, 0x00000CF5, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000007, + 0x033, 0x00000021, + 0x03F, 0x0000000A, + 0x033, 0x00000022, + 0x03F, 0x0000000D, + 0x033, 0x00000023, + 0x03F, 0x0000002A, + 0x033, 0x00000024, + 0x03F, 0x0000002D, + 0x033, 0x00000025, + 0x03F, 0x00000030, + 0x033, 0x00000026, + 0x03F, 0x0000006D, + 0x033, 0x00000027, + 0x03F, 0x00000070, + 0x033, 0x00000028, + 0x03F, 0x000000ED, + 0x033, 0x00000029, + 0x03F, 0x000000F0, + 0x033, 0x0000002A, + 0x03F, 0x000000F3, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000429, + 0x033, 0x00000021, + 0x03F, 0x00000828, + 0x033, 0x00000022, + 0x03F, 0x00000847, + 0x033, 0x00000023, + 0x03F, 0x0000084A, + 0x033, 0x00000024, + 0x03F, 0x00000C4B, + 0x033, 0x00000025, + 0x03F, 0x00000CE5, + 0x033, 0x00000026, + 0x03F, 0x00000CE8, + 0x033, 0x00000027, + 0x03F, 0x00000CEB, + 0x033, 0x00000028, + 0x03F, 0x00000CEE, + 0x033, 0x00000029, + 0x03F, 0x00000CF1, + 0x033, 0x0000002A, + 0x03F, 0x00000CF4, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000C0B, + 0x033, 0x00000021, + 0x03F, 0x00000C0E, + 0x033, 0x00000022, + 0x03F, 0x00000C2B, + 0x033, 0x00000023, + 0x03F, 0x00000C2E, + 0x033, 0x00000024, + 0x03F, 0x00000C89, + 0x033, 0x00000025, + 0x03F, 0x00000CE8, + 0x033, 0x00000026, + 0x03F, 0x00000CEB, + 0x033, 0x00000027, + 0x03F, 0x00000CEE, + 0x033, 0x00000028, + 0x03F, 0x00000CF1, + 0x033, 0x00000029, + 0x03F, 0x00000CF4, + 0x033, 0x0000002A, + 0x03F, 0x00000CF7, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000C09, + 0x033, 0x00000021, + 0x03F, 0x00000C0C, + 0x033, 0x00000022, + 0x03F, 0x00000C0F, + 0x033, 0x00000023, + 0x03F, 0x00000C2C, + 0x033, 0x00000024, + 0x03F, 0x00000C2F, + 0x033, 0x00000025, + 0x03F, 0x00000C8A, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000C90, + 0x033, 0x00000028, + 0x03F, 0x00000CD0, + 0x033, 0x00000029, + 0x03F, 0x00000CF2, + 0x033, 0x0000002A, + 0x03F, 0x00000CF5, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000429, + 0x033, 0x00000021, + 0x03F, 0x00000828, + 0x033, 0x00000022, + 0x03F, 0x00000847, + 0x033, 0x00000023, + 0x03F, 0x0000084A, + 0x033, 0x00000024, + 0x03F, 0x0000086A, + 0x033, 0x00000025, + 0x03F, 0x0000086D, + 0x033, 0x00000026, + 0x03F, 0x00000870, + 0x033, 0x00000027, + 0x03F, 0x00000891, + 0x033, 0x00000028, + 0x03F, 0x00000894, + 0x033, 0x00000029, + 0x03F, 0x000008B5, + 0x033, 0x0000002A, + 0x03F, 0x000008F5, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000429, + 0x033, 0x00000021, + 0x03F, 0x00000828, + 0x033, 0x00000022, + 0x03F, 0x00000847, + 0x033, 0x00000023, + 0x03F, 0x0000084A, + 0x033, 0x00000024, + 0x03F, 0x00000C4B, + 0x033, 0x00000025, + 0x03F, 0x00000C6C, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000CAF, + 0x033, 0x00000028, + 0x03F, 0x00000CD1, + 0x033, 0x00000029, + 0x03F, 0x00000CF3, + 0x033, 0x0000002A, + 0x03F, 0x00000CF6, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000429, + 0x033, 0x00000021, + 0x03F, 0x00000828, + 0x033, 0x00000022, + 0x03F, 0x00000847, + 0x033, 0x00000023, + 0x03F, 0x0000084A, + 0x033, 0x00000024, + 0x03F, 0x00000C4B, + 0x033, 0x00000025, + 0x03F, 0x00000C6C, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000CAF, + 0x033, 0x00000028, + 0x03F, 0x00000CD1, + 0x033, 0x00000029, + 0x03F, 0x00000CF3, + 0x033, 0x0000002A, + 0x03F, 0x00000CF6, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000005, + 0x033, 0x00000021, + 0x03F, 0x00000008, + 0x033, 0x00000022, + 0x03F, 0x0000000B, + 0x033, 0x00000023, + 0x03F, 0x0000000E, + 0x033, 0x00000024, + 0x03F, 0x0000002B, + 0x033, 0x00000025, + 0x03F, 0x0000002E, + 0x033, 0x00000026, + 0x03F, 0x0000006B, + 0x033, 0x00000027, + 0x03F, 0x0000006E, + 0x033, 0x00000028, + 0x03F, 0x00000071, + 0x033, 0x00000029, + 0x03F, 0x00000074, + 0x033, 0x0000002A, + 0x03F, 0x00000077, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000007, + 0x033, 0x00000021, + 0x03F, 0x0000000A, + 0x033, 0x00000022, + 0x03F, 0x0000000D, + 0x033, 0x00000023, + 0x03F, 0x0000002A, + 0x033, 0x00000024, + 0x03F, 0x0000002D, + 0x033, 0x00000025, + 0x03F, 0x00000030, + 0x033, 0x00000026, + 0x03F, 0x0000006D, + 0x033, 0x00000027, + 0x03F, 0x00000070, + 0x033, 0x00000028, + 0x03F, 0x000000ED, + 0x033, 0x00000029, + 0x03F, 0x000000F0, + 0x033, 0x0000002A, + 0x03F, 0x000000F3, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000005, + 0x033, 0x00000021, + 0x03F, 0x00000008, + 0x033, 0x00000022, + 0x03F, 0x0000000B, + 0x033, 0x00000023, + 0x03F, 0x0000000E, + 0x033, 0x00000024, + 0x03F, 0x0000002B, + 0x033, 0x00000025, + 0x03F, 0x00000068, + 0x033, 0x00000026, + 0x03F, 0x0000006B, + 0x033, 0x00000027, + 0x03F, 0x0000006E, + 0x033, 0x00000028, + 0x03F, 0x00000071, + 0x033, 0x00000029, + 0x03F, 0x00000074, + 0x033, 0x0000002A, + 0x03F, 0x00000077, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x0000042B, + 0x033, 0x00000021, + 0x03F, 0x0000082A, + 0x033, 0x00000022, + 0x03F, 0x00000849, + 0x033, 0x00000023, + 0x03F, 0x0000084C, + 0x033, 0x00000024, + 0x03F, 0x00000C4C, + 0x033, 0x00000025, + 0x03F, 0x00000C8A, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000CEB, + 0x033, 0x00000028, + 0x03F, 0x00000CEE, + 0x033, 0x00000029, + 0x03F, 0x00000CF1, + 0x033, 0x0000002A, + 0x03F, 0x00000CF4, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000005, + 0x033, 0x00000021, + 0x03F, 0x00000008, + 0x033, 0x00000022, + 0x03F, 0x0000000B, + 0x033, 0x00000023, + 0x03F, 0x0000000E, + 0x033, 0x00000024, + 0x03F, 0x0000002B, + 0x033, 0x00000025, + 0x03F, 0x00000068, + 0x033, 0x00000026, + 0x03F, 0x0000006B, + 0x033, 0x00000027, + 0x03F, 0x0000006E, + 0x033, 0x00000028, + 0x03F, 0x00000071, + 0x033, 0x00000029, + 0x03F, 0x00000074, + 0x033, 0x0000002A, + 0x03F, 0x00000077, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x0000042B, + 0x033, 0x00000021, + 0x03F, 0x0000082A, + 0x033, 0x00000022, + 0x03F, 0x00000849, + 0x033, 0x00000023, + 0x03F, 0x0000084C, + 0x033, 0x00000024, + 0x03F, 0x00000C4C, + 0x033, 0x00000025, + 0x03F, 0x00000C8A, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000CEB, + 0x033, 0x00000028, + 0x03F, 0x00000CEE, + 0x033, 0x00000029, + 0x03F, 0x00000CF1, + 0x033, 0x0000002A, + 0x03F, 0x00000CF4, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000007, + 0x033, 0x00000021, + 0x03F, 0x0000000A, + 0x033, 0x00000022, + 0x03F, 0x0000000D, + 0x033, 0x00000023, + 0x03F, 0x0000002A, + 0x033, 0x00000024, + 0x03F, 0x0000002D, + 0x033, 0x00000025, + 0x03F, 0x00000030, + 0x033, 0x00000026, + 0x03F, 0x0000006D, + 0x033, 0x00000027, + 0x03F, 0x00000070, + 0x033, 0x00000028, + 0x03F, 0x000000ED, + 0x033, 0x00000029, + 0x03F, 0x000000F0, + 0x033, 0x0000002A, + 0x03F, 0x000000F3, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000007, + 0x033, 0x00000021, + 0x03F, 0x0000000A, + 0x033, 0x00000022, + 0x03F, 0x0000000D, + 0x033, 0x00000023, + 0x03F, 0x0000002A, + 0x033, 0x00000024, + 0x03F, 0x0000002D, + 0x033, 0x00000025, + 0x03F, 0x00000030, + 0x033, 0x00000026, + 0x03F, 0x0000006D, + 0x033, 0x00000027, + 0x03F, 0x00000070, + 0x033, 0x00000028, + 0x03F, 0x000000ED, + 0x033, 0x00000029, + 0x03F, 0x000000F0, + 0x033, 0x0000002A, + 0x03F, 0x000000F3, + 0xA0000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000C09, + 0x033, 0x00000021, + 0x03F, 0x00000C0C, + 0x033, 0x00000022, + 0x03F, 0x00000C0F, + 0x033, 0x00000023, + 0x03F, 0x00000C2C, + 0x033, 0x00000024, + 0x03F, 0x00000C2F, + 0x033, 0x00000025, + 0x03F, 0x00000C8A, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000C90, + 0x033, 0x00000028, + 0x03F, 0x00000CD0, + 0x033, 0x00000029, + 0x03F, 0x00000CF2, + 0x033, 0x0000002A, + 0x03F, 0x00000CF5, + 0xB0000000, 0x00000000, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000C0A, + 0x033, 0x00000061, + 0x03F, 0x00000C0D, + 0x033, 0x00000062, + 0x03F, 0x00000C2A, + 0x033, 0x00000063, + 0x03F, 0x00000C2D, + 0x033, 0x00000064, + 0x03F, 0x00000C6A, + 0x033, 0x00000065, + 0x03F, 0x00000CAA, + 0x033, 0x00000066, + 0x03F, 0x00000CAD, + 0x033, 0x00000067, + 0x03F, 0x00000CB0, + 0x033, 0x00000068, + 0x03F, 0x00000CF1, + 0x033, 0x00000069, + 0x03F, 0x00000CF4, + 0x033, 0x0000006A, + 0x03F, 0x00000CF7, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000007, + 0x033, 0x00000061, + 0x03F, 0x0000000A, + 0x033, 0x00000062, + 0x03F, 0x0000000D, + 0x033, 0x00000063, + 0x03F, 0x0000002A, + 0x033, 0x00000064, + 0x03F, 0x0000002D, + 0x033, 0x00000065, + 0x03F, 0x00000030, + 0x033, 0x00000066, + 0x03F, 0x0000006D, + 0x033, 0x00000067, + 0x03F, 0x00000070, + 0x033, 0x00000068, + 0x03F, 0x000000ED, + 0x033, 0x00000069, + 0x03F, 0x000000F0, + 0x033, 0x0000006A, + 0x03F, 0x000000F3, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000005, + 0x033, 0x00000061, + 0x03F, 0x00000008, + 0x033, 0x00000062, + 0x03F, 0x0000000B, + 0x033, 0x00000063, + 0x03F, 0x0000000E, + 0x033, 0x00000064, + 0x03F, 0x0000002B, + 0x033, 0x00000065, + 0x03F, 0x0000002E, + 0x033, 0x00000066, + 0x03F, 0x0000006B, + 0x033, 0x00000067, + 0x03F, 0x0000006E, + 0x033, 0x00000068, + 0x03F, 0x00000071, + 0x033, 0x00000069, + 0x03F, 0x00000074, + 0x033, 0x0000006A, + 0x03F, 0x00000077, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000429, + 0x033, 0x00000061, + 0x03F, 0x00000828, + 0x033, 0x00000062, + 0x03F, 0x00000847, + 0x033, 0x00000063, + 0x03F, 0x0000084A, + 0x033, 0x00000064, + 0x03F, 0x00000C4B, + 0x033, 0x00000065, + 0x03F, 0x00000C6C, + 0x033, 0x00000066, + 0x03F, 0x00000C8D, + 0x033, 0x00000067, + 0x03F, 0x00000CAF, + 0x033, 0x00000068, + 0x03F, 0x00000CD1, + 0x033, 0x00000069, + 0x03F, 0x00000CF3, + 0x033, 0x0000006A, + 0x03F, 0x00000CF6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000005, + 0x033, 0x00000061, + 0x03F, 0x00000008, + 0x033, 0x00000062, + 0x03F, 0x0000000B, + 0x033, 0x00000063, + 0x03F, 0x0000000E, + 0x033, 0x00000064, + 0x03F, 0x0000002B, + 0x033, 0x00000065, + 0x03F, 0x0000002E, + 0x033, 0x00000066, + 0x03F, 0x0000006B, + 0x033, 0x00000067, + 0x03F, 0x0000006E, + 0x033, 0x00000068, + 0x03F, 0x00000071, + 0x033, 0x00000069, + 0x03F, 0x00000074, + 0x033, 0x0000006A, + 0x03F, 0x00000077, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x0000042A, + 0x033, 0x00000061, + 0x03F, 0x00000829, + 0x033, 0x00000062, + 0x03F, 0x00000848, + 0x033, 0x00000063, + 0x03F, 0x0000084B, + 0x033, 0x00000064, + 0x03F, 0x00000C4B, + 0x033, 0x00000065, + 0x03F, 0x00000C6C, + 0x033, 0x00000066, + 0x03F, 0x00000CAC, + 0x033, 0x00000067, + 0x03F, 0x00000CED, + 0x033, 0x00000068, + 0x03F, 0x00000CF0, + 0x033, 0x00000069, + 0x03F, 0x00000CF3, + 0x033, 0x0000006A, + 0x03F, 0x00000CF6, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000007, + 0x033, 0x00000061, + 0x03F, 0x0000000A, + 0x033, 0x00000062, + 0x03F, 0x0000000D, + 0x033, 0x00000063, + 0x03F, 0x0000002A, + 0x033, 0x00000064, + 0x03F, 0x0000002D, + 0x033, 0x00000065, + 0x03F, 0x00000030, + 0x033, 0x00000066, + 0x03F, 0x0000006D, + 0x033, 0x00000067, + 0x03F, 0x00000070, + 0x033, 0x00000068, + 0x03F, 0x000000ED, + 0x033, 0x00000069, + 0x03F, 0x000000F0, + 0x033, 0x0000006A, + 0x03F, 0x000000F3, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000007, + 0x033, 0x00000061, + 0x03F, 0x0000000A, + 0x033, 0x00000062, + 0x03F, 0x0000000D, + 0x033, 0x00000063, + 0x03F, 0x0000002A, + 0x033, 0x00000064, + 0x03F, 0x0000002D, + 0x033, 0x00000065, + 0x03F, 0x00000030, + 0x033, 0x00000066, + 0x03F, 0x0000006D, + 0x033, 0x00000067, + 0x03F, 0x00000070, + 0x033, 0x00000068, + 0x03F, 0x000000ED, + 0x033, 0x00000069, + 0x03F, 0x000000F0, + 0x033, 0x0000006A, + 0x03F, 0x000000F3, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x0000080B, + 0x033, 0x00000061, + 0x03F, 0x0000080E, + 0x033, 0x00000062, + 0x03F, 0x00000848, + 0x033, 0x00000063, + 0x03F, 0x00000869, + 0x033, 0x00000064, + 0x03F, 0x000008A9, + 0x033, 0x00000065, + 0x03F, 0x00000CE8, + 0x033, 0x00000066, + 0x03F, 0x00000CEB, + 0x033, 0x00000067, + 0x03F, 0x00000CEE, + 0x033, 0x00000068, + 0x03F, 0x00000CF1, + 0x033, 0x00000069, + 0x03F, 0x00000CF4, + 0x033, 0x0000006A, + 0x03F, 0x00000CF7, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000C0A, + 0x033, 0x00000061, + 0x03F, 0x00000C0D, + 0x033, 0x00000062, + 0x03F, 0x00000C2A, + 0x033, 0x00000063, + 0x03F, 0x00000C2D, + 0x033, 0x00000064, + 0x03F, 0x00000C6A, + 0x033, 0x00000065, + 0x03F, 0x00000CAA, + 0x033, 0x00000066, + 0x03F, 0x00000CAD, + 0x033, 0x00000067, + 0x03F, 0x00000CB0, + 0x033, 0x00000068, + 0x03F, 0x00000CF1, + 0x033, 0x00000069, + 0x03F, 0x00000CF4, + 0x033, 0x0000006A, + 0x03F, 0x00000CF7, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000C0A, + 0x033, 0x00000061, + 0x03F, 0x00000C0D, + 0x033, 0x00000062, + 0x03F, 0x00000C2A, + 0x033, 0x00000063, + 0x03F, 0x00000C2D, + 0x033, 0x00000064, + 0x03F, 0x00000C6A, + 0x033, 0x00000065, + 0x03F, 0x00000CAA, + 0x033, 0x00000066, + 0x03F, 0x00000CAD, + 0x033, 0x00000067, + 0x03F, 0x00000CB0, + 0x033, 0x00000068, + 0x03F, 0x00000CF1, + 0x033, 0x00000069, + 0x03F, 0x00000CF4, + 0x033, 0x0000006A, + 0x03F, 0x00000CF7, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000005, + 0x033, 0x00000061, + 0x03F, 0x00000008, + 0x033, 0x00000062, + 0x03F, 0x0000000B, + 0x033, 0x00000063, + 0x03F, 0x0000000E, + 0x033, 0x00000064, + 0x03F, 0x0000002B, + 0x033, 0x00000065, + 0x03F, 0x00000068, + 0x033, 0x00000066, + 0x03F, 0x0000006B, + 0x033, 0x00000067, + 0x03F, 0x0000006E, + 0x033, 0x00000068, + 0x03F, 0x00000071, + 0x033, 0x00000069, + 0x03F, 0x00000074, + 0x033, 0x0000006A, + 0x03F, 0x00000077, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000429, + 0x033, 0x00000061, + 0x03F, 0x00000828, + 0x033, 0x00000062, + 0x03F, 0x00000847, + 0x033, 0x00000063, + 0x03F, 0x0000084A, + 0x033, 0x00000064, + 0x03F, 0x00000C4B, + 0x033, 0x00000065, + 0x03F, 0x00000CE5, + 0x033, 0x00000066, + 0x03F, 0x00000CE8, + 0x033, 0x00000067, + 0x03F, 0x00000CEB, + 0x033, 0x00000068, + 0x03F, 0x00000CEE, + 0x033, 0x00000069, + 0x03F, 0x00000CF1, + 0x033, 0x0000006A, + 0x03F, 0x00000CF4, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000C0A, + 0x033, 0x00000061, + 0x03F, 0x00000C0D, + 0x033, 0x00000062, + 0x03F, 0x00000C10, + 0x033, 0x00000063, + 0x03F, 0x00000C4A, + 0x033, 0x00000064, + 0x03F, 0x00000C4D, + 0x033, 0x00000065, + 0x03F, 0x00000CC9, + 0x033, 0x00000066, + 0x03F, 0x00000CEB, + 0x033, 0x00000067, + 0x03F, 0x00000CEE, + 0x033, 0x00000068, + 0x03F, 0x00000CF1, + 0x033, 0x00000069, + 0x03F, 0x00000CF4, + 0x033, 0x0000006A, + 0x03F, 0x00000CF7, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000C0A, + 0x033, 0x00000061, + 0x03F, 0x00000C0D, + 0x033, 0x00000062, + 0x03F, 0x00000C2A, + 0x033, 0x00000063, + 0x03F, 0x00000C2D, + 0x033, 0x00000064, + 0x03F, 0x00000C6A, + 0x033, 0x00000065, + 0x03F, 0x00000CAA, + 0x033, 0x00000066, + 0x03F, 0x00000CAD, + 0x033, 0x00000067, + 0x03F, 0x00000CB0, + 0x033, 0x00000068, + 0x03F, 0x00000CF1, + 0x033, 0x00000069, + 0x03F, 0x00000CF4, + 0x033, 0x0000006A, + 0x03F, 0x00000CF7, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000429, + 0x033, 0x00000061, + 0x03F, 0x00000828, + 0x033, 0x00000062, + 0x03F, 0x00000847, + 0x033, 0x00000063, + 0x03F, 0x0000084A, + 0x033, 0x00000064, + 0x03F, 0x0000086A, + 0x033, 0x00000065, + 0x03F, 0x0000086D, + 0x033, 0x00000066, + 0x03F, 0x00000870, + 0x033, 0x00000067, + 0x03F, 0x00000891, + 0x033, 0x00000068, + 0x03F, 0x00000894, + 0x033, 0x00000069, + 0x03F, 0x000008B5, + 0x033, 0x0000006A, + 0x03F, 0x000008F5, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000429, + 0x033, 0x00000061, + 0x03F, 0x00000828, + 0x033, 0x00000062, + 0x03F, 0x00000847, + 0x033, 0x00000063, + 0x03F, 0x0000084A, + 0x033, 0x00000064, + 0x03F, 0x00000C4B, + 0x033, 0x00000065, + 0x03F, 0x00000C6C, + 0x033, 0x00000066, + 0x03F, 0x00000C8D, + 0x033, 0x00000067, + 0x03F, 0x00000CAF, + 0x033, 0x00000068, + 0x03F, 0x00000CD1, + 0x033, 0x00000069, + 0x03F, 0x00000CF3, + 0x033, 0x0000006A, + 0x03F, 0x00000CF6, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000429, + 0x033, 0x00000061, + 0x03F, 0x00000828, + 0x033, 0x00000062, + 0x03F, 0x00000847, + 0x033, 0x00000063, + 0x03F, 0x0000084A, + 0x033, 0x00000064, + 0x03F, 0x00000C4B, + 0x033, 0x00000065, + 0x03F, 0x00000C6C, + 0x033, 0x00000066, + 0x03F, 0x00000C8D, + 0x033, 0x00000067, + 0x03F, 0x00000CAF, + 0x033, 0x00000068, + 0x03F, 0x00000CD1, + 0x033, 0x00000069, + 0x03F, 0x00000CF3, + 0x033, 0x0000006A, + 0x03F, 0x00000CF6, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000005, + 0x033, 0x00000061, + 0x03F, 0x00000008, + 0x033, 0x00000062, + 0x03F, 0x0000000B, + 0x033, 0x00000063, + 0x03F, 0x0000000E, + 0x033, 0x00000064, + 0x03F, 0x0000002B, + 0x033, 0x00000065, + 0x03F, 0x0000002E, + 0x033, 0x00000066, + 0x03F, 0x0000006B, + 0x033, 0x00000067, + 0x03F, 0x0000006E, + 0x033, 0x00000068, + 0x03F, 0x00000071, + 0x033, 0x00000069, + 0x03F, 0x00000074, + 0x033, 0x0000006A, + 0x03F, 0x00000077, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000007, + 0x033, 0x00000061, + 0x03F, 0x0000000A, + 0x033, 0x00000062, + 0x03F, 0x0000000D, + 0x033, 0x00000063, + 0x03F, 0x0000002A, + 0x033, 0x00000064, + 0x03F, 0x0000002D, + 0x033, 0x00000065, + 0x03F, 0x00000030, + 0x033, 0x00000066, + 0x03F, 0x0000006D, + 0x033, 0x00000067, + 0x03F, 0x00000070, + 0x033, 0x00000068, + 0x03F, 0x000000ED, + 0x033, 0x00000069, + 0x03F, 0x000000F0, + 0x033, 0x0000006A, + 0x03F, 0x000000F3, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000005, + 0x033, 0x00000061, + 0x03F, 0x00000008, + 0x033, 0x00000062, + 0x03F, 0x0000000B, + 0x033, 0x00000063, + 0x03F, 0x0000000E, + 0x033, 0x00000064, + 0x03F, 0x0000002B, + 0x033, 0x00000065, + 0x03F, 0x00000068, + 0x033, 0x00000066, + 0x03F, 0x0000006B, + 0x033, 0x00000067, + 0x03F, 0x0000006E, + 0x033, 0x00000068, + 0x03F, 0x00000071, + 0x033, 0x00000069, + 0x03F, 0x00000074, + 0x033, 0x0000006A, + 0x03F, 0x00000077, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x0000042C, + 0x033, 0x00000061, + 0x03F, 0x0000082B, + 0x033, 0x00000062, + 0x03F, 0x0000084A, + 0x033, 0x00000063, + 0x03F, 0x0000084D, + 0x033, 0x00000064, + 0x03F, 0x00000C4D, + 0x033, 0x00000065, + 0x03F, 0x00000C8B, + 0x033, 0x00000066, + 0x03F, 0x00000C8E, + 0x033, 0x00000067, + 0x03F, 0x00000CEC, + 0x033, 0x00000068, + 0x03F, 0x00000CEF, + 0x033, 0x00000069, + 0x03F, 0x00000CF2, + 0x033, 0x0000006A, + 0x03F, 0x00000CF5, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000005, + 0x033, 0x00000061, + 0x03F, 0x00000008, + 0x033, 0x00000062, + 0x03F, 0x0000000B, + 0x033, 0x00000063, + 0x03F, 0x0000000E, + 0x033, 0x00000064, + 0x03F, 0x0000002B, + 0x033, 0x00000065, + 0x03F, 0x00000068, + 0x033, 0x00000066, + 0x03F, 0x0000006B, + 0x033, 0x00000067, + 0x03F, 0x0000006E, + 0x033, 0x00000068, + 0x03F, 0x00000071, + 0x033, 0x00000069, + 0x03F, 0x00000074, + 0x033, 0x0000006A, + 0x03F, 0x00000077, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x0000042C, + 0x033, 0x00000061, + 0x03F, 0x0000082B, + 0x033, 0x00000062, + 0x03F, 0x0000084A, + 0x033, 0x00000063, + 0x03F, 0x0000084D, + 0x033, 0x00000064, + 0x03F, 0x00000C4D, + 0x033, 0x00000065, + 0x03F, 0x00000C8B, + 0x033, 0x00000066, + 0x03F, 0x00000C8E, + 0x033, 0x00000067, + 0x03F, 0x00000CEC, + 0x033, 0x00000068, + 0x03F, 0x00000CEF, + 0x033, 0x00000069, + 0x03F, 0x00000CF2, + 0x033, 0x0000006A, + 0x03F, 0x00000CF5, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000007, + 0x033, 0x00000061, + 0x03F, 0x0000000A, + 0x033, 0x00000062, + 0x03F, 0x0000000D, + 0x033, 0x00000063, + 0x03F, 0x0000002A, + 0x033, 0x00000064, + 0x03F, 0x0000002D, + 0x033, 0x00000065, + 0x03F, 0x00000030, + 0x033, 0x00000066, + 0x03F, 0x0000006D, + 0x033, 0x00000067, + 0x03F, 0x00000070, + 0x033, 0x00000068, + 0x03F, 0x000000ED, + 0x033, 0x00000069, + 0x03F, 0x000000F0, + 0x033, 0x0000006A, + 0x03F, 0x000000F3, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000007, + 0x033, 0x00000061, + 0x03F, 0x0000000A, + 0x033, 0x00000062, + 0x03F, 0x0000000D, + 0x033, 0x00000063, + 0x03F, 0x0000002A, + 0x033, 0x00000064, + 0x03F, 0x0000002D, + 0x033, 0x00000065, + 0x03F, 0x00000030, + 0x033, 0x00000066, + 0x03F, 0x0000006D, + 0x033, 0x00000067, + 0x03F, 0x00000070, + 0x033, 0x00000068, + 0x03F, 0x000000ED, + 0x033, 0x00000069, + 0x03F, 0x000000F0, + 0x033, 0x0000006A, + 0x03F, 0x000000F3, + 0xA0000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000C0A, + 0x033, 0x00000061, + 0x03F, 0x00000C0D, + 0x033, 0x00000062, + 0x03F, 0x00000C2A, + 0x033, 0x00000063, + 0x03F, 0x00000C2D, + 0x033, 0x00000064, + 0x03F, 0x00000C6A, + 0x033, 0x00000065, + 0x03F, 0x00000CAA, + 0x033, 0x00000066, + 0x03F, 0x00000CAD, + 0x033, 0x00000067, + 0x03F, 0x00000CB0, + 0x033, 0x00000068, + 0x03F, 0x00000CF1, + 0x033, 0x00000069, + 0x03F, 0x00000CF4, + 0x033, 0x0000006A, + 0x03F, 0x00000CF7, + 0xB0000000, 0x00000000, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000C09, + 0x033, 0x000000A1, + 0x03F, 0x00000C0C, + 0x033, 0x000000A2, + 0x03F, 0x00000C0F, + 0x033, 0x000000A3, + 0x03F, 0x00000C2C, + 0x033, 0x000000A4, + 0x03F, 0x00000C2F, + 0x033, 0x000000A5, + 0x03F, 0x00000C8A, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000C90, + 0x033, 0x000000A8, + 0x03F, 0x00000CEF, + 0x033, 0x000000A9, + 0x03F, 0x00000CF2, + 0x033, 0x000000AA, + 0x03F, 0x00000CF5, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000007, + 0x033, 0x000000A1, + 0x03F, 0x0000000A, + 0x033, 0x000000A2, + 0x03F, 0x0000000D, + 0x033, 0x000000A3, + 0x03F, 0x0000002A, + 0x033, 0x000000A4, + 0x03F, 0x0000002D, + 0x033, 0x000000A5, + 0x03F, 0x00000030, + 0x033, 0x000000A6, + 0x03F, 0x0000006D, + 0x033, 0x000000A7, + 0x03F, 0x00000070, + 0x033, 0x000000A8, + 0x03F, 0x000000ED, + 0x033, 0x000000A9, + 0x03F, 0x000000F0, + 0x033, 0x000000AA, + 0x03F, 0x000000F3, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000005, + 0x033, 0x000000A1, + 0x03F, 0x00000008, + 0x033, 0x000000A2, + 0x03F, 0x0000000B, + 0x033, 0x000000A3, + 0x03F, 0x0000000E, + 0x033, 0x000000A4, + 0x03F, 0x0000002B, + 0x033, 0x000000A5, + 0x03F, 0x0000002E, + 0x033, 0x000000A6, + 0x03F, 0x00000031, + 0x033, 0x000000A7, + 0x03F, 0x00000034, + 0x033, 0x000000A8, + 0x03F, 0x00000053, + 0x033, 0x000000A9, + 0x03F, 0x00000056, + 0x033, 0x000000AA, + 0x03F, 0x000000D1, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000429, + 0x033, 0x000000A1, + 0x03F, 0x00000828, + 0x033, 0x000000A2, + 0x03F, 0x00000847, + 0x033, 0x000000A3, + 0x03F, 0x0000084A, + 0x033, 0x000000A4, + 0x03F, 0x00000C4B, + 0x033, 0x000000A5, + 0x03F, 0x00000C6C, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000CAF, + 0x033, 0x000000A8, + 0x03F, 0x00000CD1, + 0x033, 0x000000A9, + 0x03F, 0x00000CF3, + 0x033, 0x000000AA, + 0x03F, 0x00000CF6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000005, + 0x033, 0x000000A1, + 0x03F, 0x00000008, + 0x033, 0x000000A2, + 0x03F, 0x0000000B, + 0x033, 0x000000A3, + 0x03F, 0x0000000E, + 0x033, 0x000000A4, + 0x03F, 0x0000002B, + 0x033, 0x000000A5, + 0x03F, 0x0000002E, + 0x033, 0x000000A6, + 0x03F, 0x00000031, + 0x033, 0x000000A7, + 0x03F, 0x00000034, + 0x033, 0x000000A8, + 0x03F, 0x00000053, + 0x033, 0x000000A9, + 0x03F, 0x00000056, + 0x033, 0x000000AA, + 0x03F, 0x000000D1, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000429, + 0x033, 0x000000A1, + 0x03F, 0x00000828, + 0x033, 0x000000A2, + 0x03F, 0x00000847, + 0x033, 0x000000A3, + 0x03F, 0x0000084A, + 0x033, 0x000000A4, + 0x03F, 0x00000C4B, + 0x033, 0x000000A5, + 0x03F, 0x00000C6C, + 0x033, 0x000000A6, + 0x03F, 0x00000CAC, + 0x033, 0x000000A7, + 0x03F, 0x00000CED, + 0x033, 0x000000A8, + 0x03F, 0x00000CF0, + 0x033, 0x000000A9, + 0x03F, 0x00000CF3, + 0x033, 0x000000AA, + 0x03F, 0x00000CF6, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000007, + 0x033, 0x000000A1, + 0x03F, 0x0000000A, + 0x033, 0x000000A2, + 0x03F, 0x0000000D, + 0x033, 0x000000A3, + 0x03F, 0x0000002A, + 0x033, 0x000000A4, + 0x03F, 0x0000002D, + 0x033, 0x000000A5, + 0x03F, 0x00000030, + 0x033, 0x000000A6, + 0x03F, 0x0000006D, + 0x033, 0x000000A7, + 0x03F, 0x00000070, + 0x033, 0x000000A8, + 0x03F, 0x000000ED, + 0x033, 0x000000A9, + 0x03F, 0x000000F0, + 0x033, 0x000000AA, + 0x03F, 0x000000F3, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000007, + 0x033, 0x000000A1, + 0x03F, 0x0000000A, + 0x033, 0x000000A2, + 0x03F, 0x0000000D, + 0x033, 0x000000A3, + 0x03F, 0x0000002A, + 0x033, 0x000000A4, + 0x03F, 0x0000002D, + 0x033, 0x000000A5, + 0x03F, 0x00000030, + 0x033, 0x000000A6, + 0x03F, 0x0000006D, + 0x033, 0x000000A7, + 0x03F, 0x00000070, + 0x033, 0x000000A8, + 0x03F, 0x000000ED, + 0x033, 0x000000A9, + 0x03F, 0x000000F0, + 0x033, 0x000000AA, + 0x03F, 0x000000F3, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000C0A, + 0x033, 0x000000A1, + 0x03F, 0x00000C0D, + 0x033, 0x000000A2, + 0x03F, 0x00000C2A, + 0x033, 0x000000A3, + 0x03F, 0x00000C2D, + 0x033, 0x000000A4, + 0x03F, 0x00000C6A, + 0x033, 0x000000A5, + 0x03F, 0x00000CE8, + 0x033, 0x000000A6, + 0x03F, 0x00000CEB, + 0x033, 0x000000A7, + 0x03F, 0x00000CEE, + 0x033, 0x000000A8, + 0x03F, 0x00000CF1, + 0x033, 0x000000A9, + 0x03F, 0x00000CF4, + 0x033, 0x000000AA, + 0x03F, 0x00000CF7, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000C09, + 0x033, 0x000000A1, + 0x03F, 0x00000C0C, + 0x033, 0x000000A2, + 0x03F, 0x00000C0F, + 0x033, 0x000000A3, + 0x03F, 0x00000C2C, + 0x033, 0x000000A4, + 0x03F, 0x00000C2F, + 0x033, 0x000000A5, + 0x03F, 0x00000C8A, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000C90, + 0x033, 0x000000A8, + 0x03F, 0x00000CEF, + 0x033, 0x000000A9, + 0x03F, 0x00000CF2, + 0x033, 0x000000AA, + 0x03F, 0x00000CF5, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000C09, + 0x033, 0x000000A1, + 0x03F, 0x00000C0C, + 0x033, 0x000000A2, + 0x03F, 0x00000C0F, + 0x033, 0x000000A3, + 0x03F, 0x00000C2C, + 0x033, 0x000000A4, + 0x03F, 0x00000C2F, + 0x033, 0x000000A5, + 0x03F, 0x00000C8A, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000C90, + 0x033, 0x000000A8, + 0x03F, 0x00000CEF, + 0x033, 0x000000A9, + 0x03F, 0x00000CF2, + 0x033, 0x000000AA, + 0x03F, 0x00000CF5, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000007, + 0x033, 0x000000A1, + 0x03F, 0x0000000A, + 0x033, 0x000000A2, + 0x03F, 0x0000000D, + 0x033, 0x000000A3, + 0x03F, 0x0000002A, + 0x033, 0x000000A4, + 0x03F, 0x0000002D, + 0x033, 0x000000A5, + 0x03F, 0x00000030, + 0x033, 0x000000A6, + 0x03F, 0x0000006D, + 0x033, 0x000000A7, + 0x03F, 0x00000070, + 0x033, 0x000000A8, + 0x03F, 0x000000ED, + 0x033, 0x000000A9, + 0x03F, 0x000000F0, + 0x033, 0x000000AA, + 0x03F, 0x000000F3, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000429, + 0x033, 0x000000A1, + 0x03F, 0x00000828, + 0x033, 0x000000A2, + 0x03F, 0x00000847, + 0x033, 0x000000A3, + 0x03F, 0x0000084A, + 0x033, 0x000000A4, + 0x03F, 0x00000C4B, + 0x033, 0x000000A5, + 0x03F, 0x00000CE5, + 0x033, 0x000000A6, + 0x03F, 0x00000CE8, + 0x033, 0x000000A7, + 0x03F, 0x00000CEB, + 0x033, 0x000000A8, + 0x03F, 0x00000CEE, + 0x033, 0x000000A9, + 0x03F, 0x00000CF1, + 0x033, 0x000000AA, + 0x03F, 0x00000CF4, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000824, + 0x033, 0x000000A1, + 0x03F, 0x00000827, + 0x033, 0x000000A2, + 0x03F, 0x0000082A, + 0x033, 0x000000A3, + 0x03F, 0x0000082D, + 0x033, 0x000000A4, + 0x03F, 0x00000C68, + 0x033, 0x000000A5, + 0x03F, 0x00000C6B, + 0x033, 0x000000A6, + 0x03F, 0x00000CCA, + 0x033, 0x000000A7, + 0x03F, 0x00000CCD, + 0x033, 0x000000A8, + 0x03F, 0x00000CEF, + 0x033, 0x000000A9, + 0x03F, 0x00000CF2, + 0x033, 0x000000AA, + 0x03F, 0x00000CF5, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000C08, + 0x033, 0x000000A1, + 0x03F, 0x00000C0B, + 0x033, 0x000000A2, + 0x03F, 0x00000C0E, + 0x033, 0x000000A3, + 0x03F, 0x00000C2B, + 0x033, 0x000000A4, + 0x03F, 0x00000C2E, + 0x033, 0x000000A5, + 0x03F, 0x00000C31, + 0x033, 0x000000A6, + 0x03F, 0x00000CCA, + 0x033, 0x000000A7, + 0x03F, 0x00000CCD, + 0x033, 0x000000A8, + 0x03F, 0x00000CEF, + 0x033, 0x000000A9, + 0x03F, 0x00000CF2, + 0x033, 0x000000AA, + 0x03F, 0x00000CF5, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000429, + 0x033, 0x000000A1, + 0x03F, 0x00000828, + 0x033, 0x000000A2, + 0x03F, 0x00000847, + 0x033, 0x000000A3, + 0x03F, 0x0000084A, + 0x033, 0x000000A4, + 0x03F, 0x0000086A, + 0x033, 0x000000A5, + 0x03F, 0x0000086D, + 0x033, 0x000000A6, + 0x03F, 0x00000870, + 0x033, 0x000000A7, + 0x03F, 0x00000891, + 0x033, 0x000000A8, + 0x03F, 0x00000894, + 0x033, 0x000000A9, + 0x03F, 0x000008B5, + 0x033, 0x000000AA, + 0x03F, 0x000008F5, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000429, + 0x033, 0x000000A1, + 0x03F, 0x00000828, + 0x033, 0x000000A2, + 0x03F, 0x00000847, + 0x033, 0x000000A3, + 0x03F, 0x0000084A, + 0x033, 0x000000A4, + 0x03F, 0x00000C4B, + 0x033, 0x000000A5, + 0x03F, 0x00000C6C, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000CAF, + 0x033, 0x000000A8, + 0x03F, 0x00000CD1, + 0x033, 0x000000A9, + 0x03F, 0x00000CF3, + 0x033, 0x000000AA, + 0x03F, 0x00000CF6, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000429, + 0x033, 0x000000A1, + 0x03F, 0x00000828, + 0x033, 0x000000A2, + 0x03F, 0x00000847, + 0x033, 0x000000A3, + 0x03F, 0x0000084A, + 0x033, 0x000000A4, + 0x03F, 0x00000C4B, + 0x033, 0x000000A5, + 0x03F, 0x00000C6C, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000CAF, + 0x033, 0x000000A8, + 0x03F, 0x00000CD1, + 0x033, 0x000000A9, + 0x03F, 0x00000CF3, + 0x033, 0x000000AA, + 0x03F, 0x00000CF6, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000005, + 0x033, 0x000000A1, + 0x03F, 0x00000008, + 0x033, 0x000000A2, + 0x03F, 0x0000000B, + 0x033, 0x000000A3, + 0x03F, 0x0000000E, + 0x033, 0x000000A4, + 0x03F, 0x0000002B, + 0x033, 0x000000A5, + 0x03F, 0x0000002E, + 0x033, 0x000000A6, + 0x03F, 0x00000031, + 0x033, 0x000000A7, + 0x03F, 0x00000034, + 0x033, 0x000000A8, + 0x03F, 0x00000053, + 0x033, 0x000000A9, + 0x03F, 0x00000056, + 0x033, 0x000000AA, + 0x03F, 0x000000D1, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000007, + 0x033, 0x000000A1, + 0x03F, 0x0000000A, + 0x033, 0x000000A2, + 0x03F, 0x0000000D, + 0x033, 0x000000A3, + 0x03F, 0x0000002A, + 0x033, 0x000000A4, + 0x03F, 0x0000002D, + 0x033, 0x000000A5, + 0x03F, 0x00000030, + 0x033, 0x000000A6, + 0x03F, 0x0000006D, + 0x033, 0x000000A7, + 0x03F, 0x00000070, + 0x033, 0x000000A8, + 0x03F, 0x000000ED, + 0x033, 0x000000A9, + 0x03F, 0x000000F0, + 0x033, 0x000000AA, + 0x03F, 0x000000F3, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000005, + 0x033, 0x000000A1, + 0x03F, 0x00000008, + 0x033, 0x000000A2, + 0x03F, 0x0000000B, + 0x033, 0x000000A3, + 0x03F, 0x0000000E, + 0x033, 0x000000A4, + 0x03F, 0x00000047, + 0x033, 0x000000A5, + 0x03F, 0x0000004A, + 0x033, 0x000000A6, + 0x03F, 0x0000004D, + 0x033, 0x000000A7, + 0x03F, 0x00000050, + 0x033, 0x000000A8, + 0x03F, 0x00000053, + 0x033, 0x000000A9, + 0x03F, 0x00000056, + 0x033, 0x000000AA, + 0x03F, 0x00000094, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x0000042A, + 0x033, 0x000000A1, + 0x03F, 0x00000829, + 0x033, 0x000000A2, + 0x03F, 0x00000848, + 0x033, 0x000000A3, + 0x03F, 0x0000084B, + 0x033, 0x000000A4, + 0x03F, 0x00000C4C, + 0x033, 0x000000A5, + 0x03F, 0x00000C8A, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000CEB, + 0x033, 0x000000A8, + 0x03F, 0x00000CEE, + 0x033, 0x000000A9, + 0x03F, 0x00000CF1, + 0x033, 0x000000AA, + 0x03F, 0x00000CF4, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000005, + 0x033, 0x000000A1, + 0x03F, 0x00000008, + 0x033, 0x000000A2, + 0x03F, 0x0000000B, + 0x033, 0x000000A3, + 0x03F, 0x0000000E, + 0x033, 0x000000A4, + 0x03F, 0x00000047, + 0x033, 0x000000A5, + 0x03F, 0x0000004A, + 0x033, 0x000000A6, + 0x03F, 0x0000004D, + 0x033, 0x000000A7, + 0x03F, 0x00000050, + 0x033, 0x000000A8, + 0x03F, 0x00000053, + 0x033, 0x000000A9, + 0x03F, 0x00000056, + 0x033, 0x000000AA, + 0x03F, 0x00000094, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x0000042A, + 0x033, 0x000000A1, + 0x03F, 0x00000829, + 0x033, 0x000000A2, + 0x03F, 0x00000848, + 0x033, 0x000000A3, + 0x03F, 0x0000084B, + 0x033, 0x000000A4, + 0x03F, 0x00000C4C, + 0x033, 0x000000A5, + 0x03F, 0x00000C8A, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000CEB, + 0x033, 0x000000A8, + 0x03F, 0x00000CEE, + 0x033, 0x000000A9, + 0x03F, 0x00000CF1, + 0x033, 0x000000AA, + 0x03F, 0x00000CF4, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000007, + 0x033, 0x000000A1, + 0x03F, 0x0000000A, + 0x033, 0x000000A2, + 0x03F, 0x0000000D, + 0x033, 0x000000A3, + 0x03F, 0x0000002A, + 0x033, 0x000000A4, + 0x03F, 0x0000002D, + 0x033, 0x000000A5, + 0x03F, 0x00000030, + 0x033, 0x000000A6, + 0x03F, 0x0000006D, + 0x033, 0x000000A7, + 0x03F, 0x00000070, + 0x033, 0x000000A8, + 0x03F, 0x000000ED, + 0x033, 0x000000A9, + 0x03F, 0x000000F0, + 0x033, 0x000000AA, + 0x03F, 0x000000F3, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000007, + 0x033, 0x000000A1, + 0x03F, 0x0000000A, + 0x033, 0x000000A2, + 0x03F, 0x0000000D, + 0x033, 0x000000A3, + 0x03F, 0x0000002A, + 0x033, 0x000000A4, + 0x03F, 0x0000002D, + 0x033, 0x000000A5, + 0x03F, 0x00000030, + 0x033, 0x000000A6, + 0x03F, 0x0000006D, + 0x033, 0x000000A7, + 0x03F, 0x00000070, + 0x033, 0x000000A8, + 0x03F, 0x000000ED, + 0x033, 0x000000A9, + 0x03F, 0x000000F0, + 0x033, 0x000000AA, + 0x03F, 0x000000F3, + 0xA0000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000C09, + 0x033, 0x000000A1, + 0x03F, 0x00000C0C, + 0x033, 0x000000A2, + 0x03F, 0x00000C0F, + 0x033, 0x000000A3, + 0x03F, 0x00000C2C, + 0x033, 0x000000A4, + 0x03F, 0x00000C2F, + 0x033, 0x000000A5, + 0x03F, 0x00000C8A, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000C90, + 0x033, 0x000000A8, + 0x03F, 0x00000CEF, + 0x033, 0x000000A9, + 0x03F, 0x00000CF2, + 0x033, 0x000000AA, + 0x03F, 0x00000CF5, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x0EF, 0x00000400, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000047C, + 0x033, 0x00000001, + 0x03F, 0x0000047C, + 0x033, 0x00000002, + 0x03F, 0x0000047C, + 0x033, 0x00000003, + 0x03F, 0x0000047C, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000047C, + 0x033, 0x00000001, + 0x03F, 0x0000047C, + 0x033, 0x00000002, + 0x03F, 0x0000047C, + 0x033, 0x00000003, + 0x03F, 0x0000047C, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000047C, + 0x033, 0x00000001, + 0x03F, 0x0000047C, + 0x033, 0x00000002, + 0x03F, 0x0000047C, + 0x033, 0x00000003, + 0x03F, 0x0000047C, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000047C, + 0x033, 0x00000001, + 0x03F, 0x0000047C, + 0x033, 0x00000002, + 0x03F, 0x0000047C, + 0x033, 0x00000003, + 0x03F, 0x0000047C, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000047C, + 0x033, 0x00000001, + 0x03F, 0x0000047C, + 0x033, 0x00000002, + 0x03F, 0x0000047C, + 0x033, 0x00000003, + 0x03F, 0x0000047C, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x000008BB, + 0x033, 0x00000001, + 0x03F, 0x000008BB, + 0x033, 0x00000002, + 0x03F, 0x000008BB, + 0x033, 0x00000003, + 0x03F, 0x000008BB, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000047C, + 0x033, 0x00000001, + 0x03F, 0x0000047C, + 0x033, 0x00000002, + 0x03F, 0x0000047C, + 0x033, 0x00000003, + 0x03F, 0x0000047C, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000047C, + 0x033, 0x00000001, + 0x03F, 0x0000047C, + 0x033, 0x00000002, + 0x03F, 0x0000047C, + 0x033, 0x00000003, + 0x03F, 0x0000047C, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000047C, + 0x033, 0x00000001, + 0x03F, 0x0000047C, + 0x033, 0x00000002, + 0x03F, 0x0000047C, + 0x033, 0x00000003, + 0x03F, 0x0000047C, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000047C, + 0x033, 0x00000001, + 0x03F, 0x0000047C, + 0x033, 0x00000002, + 0x03F, 0x0000047C, + 0x033, 0x00000003, + 0x03F, 0x0000047C, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000047C, + 0x033, 0x00000001, + 0x03F, 0x0000047C, + 0x033, 0x00000002, + 0x03F, 0x0000047C, + 0x033, 0x00000003, + 0x03F, 0x0000047C, + 0xA0000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x000004BB, + 0x033, 0x00000001, + 0x03F, 0x000004BB, + 0x033, 0x00000002, + 0x03F, 0x000004BB, + 0x033, 0x00000003, + 0x03F, 0x000004BB, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x0EF, 0x00000100, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00001726, + 0x033, 0x00000001, + 0x03F, 0x00001726, + 0x033, 0x00000002, + 0x03F, 0x00001726, + 0x033, 0x00000003, + 0x03F, 0x00001726, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00001726, + 0x033, 0x00000001, + 0x03F, 0x00001726, + 0x033, 0x00000002, + 0x03F, 0x00001726, + 0x033, 0x00000003, + 0x03F, 0x00001726, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00001726, + 0x033, 0x00000001, + 0x03F, 0x00001726, + 0x033, 0x00000002, + 0x03F, 0x00001726, + 0x033, 0x00000003, + 0x03F, 0x00001726, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00001726, + 0x033, 0x00000001, + 0x03F, 0x00001726, + 0x033, 0x00000002, + 0x03F, 0x00001726, + 0x033, 0x00000003, + 0x03F, 0x00001726, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00001726, + 0x033, 0x00000001, + 0x03F, 0x00001726, + 0x033, 0x00000002, + 0x03F, 0x00001726, + 0x033, 0x00000003, + 0x03F, 0x00001726, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00001726, + 0x033, 0x00000001, + 0x03F, 0x00001726, + 0x033, 0x00000002, + 0x03F, 0x00001726, + 0x033, 0x00000003, + 0x03F, 0x00001726, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00001726, + 0x033, 0x00000001, + 0x03F, 0x00001726, + 0x033, 0x00000002, + 0x03F, 0x00001726, + 0x033, 0x00000003, + 0x03F, 0x00001726, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00001726, + 0x033, 0x00000001, + 0x03F, 0x00001726, + 0x033, 0x00000002, + 0x03F, 0x00001726, + 0x033, 0x00000003, + 0x03F, 0x00001726, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00001726, + 0x033, 0x00000001, + 0x03F, 0x00001726, + 0x033, 0x00000002, + 0x03F, 0x00001726, + 0x033, 0x00000003, + 0x03F, 0x00001726, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00001726, + 0x033, 0x00000001, + 0x03F, 0x00001726, + 0x033, 0x00000002, + 0x03F, 0x00001726, + 0x033, 0x00000003, + 0x03F, 0x00001726, + 0xA0000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000F34, + 0x033, 0x00000001, + 0x03F, 0x00000F34, + 0x033, 0x00000002, + 0x03F, 0x00000F34, + 0x033, 0x00000003, + 0x03F, 0x00000F34, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0xA0000000, 0x00000000, + 0x081, 0x0000F000, + 0x087, 0x00016040, + 0x051, 0x00000C00, + 0x052, 0x0007C241, + 0x053, 0x0001C069, + 0x054, 0x00078032, + 0x057, 0x0000CE0A, + 0x058, 0x00058750, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000800, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000003, + 0x033, 0x00000001, + 0x03F, 0x00000006, + 0x033, 0x00000002, + 0x03F, 0x00000009, + 0x033, 0x00000003, + 0x03F, 0x00000026, + 0x033, 0x00000004, + 0x03F, 0x00000029, + 0x033, 0x00000005, + 0x03F, 0x0000002C, + 0x033, 0x00000006, + 0x03F, 0x0000002F, + 0x033, 0x00000007, + 0x03F, 0x00000033, + 0x033, 0x00000008, + 0x03F, 0x00000036, + 0x033, 0x00000009, + 0x03F, 0x00000039, + 0x033, 0x0000000A, + 0x03F, 0x0000003C, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000002, + 0x033, 0x00000001, + 0x03F, 0x00000005, + 0x033, 0x00000002, + 0x03F, 0x00000008, + 0x033, 0x00000003, + 0x03F, 0x0000000B, + 0x033, 0x00000004, + 0x03F, 0x0000000E, + 0x033, 0x00000005, + 0x03F, 0x0000002B, + 0x033, 0x00000006, + 0x03F, 0x0000002E, + 0x033, 0x00000007, + 0x03F, 0x00000031, + 0x033, 0x00000008, + 0x03F, 0x0000006E, + 0x033, 0x00000009, + 0x03F, 0x00000071, + 0x033, 0x0000000A, + 0x03F, 0x00000074, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000003, + 0x033, 0x00000001, + 0x03F, 0x00000006, + 0x033, 0x00000002, + 0x03F, 0x00000009, + 0x033, 0x00000003, + 0x03F, 0x00000026, + 0x033, 0x00000004, + 0x03F, 0x00000029, + 0x033, 0x00000005, + 0x03F, 0x0000002C, + 0x033, 0x00000006, + 0x03F, 0x0000002F, + 0x033, 0x00000007, + 0x03F, 0x00000033, + 0x033, 0x00000008, + 0x03F, 0x00000036, + 0x033, 0x00000009, + 0x03F, 0x00000039, + 0x033, 0x0000000A, + 0x03F, 0x0000003C, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000003, + 0x033, 0x00000001, + 0x03F, 0x00000006, + 0x033, 0x00000002, + 0x03F, 0x00000009, + 0x033, 0x00000003, + 0x03F, 0x00000026, + 0x033, 0x00000004, + 0x03F, 0x00000029, + 0x033, 0x00000005, + 0x03F, 0x0000002C, + 0x033, 0x00000006, + 0x03F, 0x0000002F, + 0x033, 0x00000007, + 0x03F, 0x00000033, + 0x033, 0x00000008, + 0x03F, 0x00000036, + 0x033, 0x00000009, + 0x03F, 0x00000039, + 0x033, 0x0000000A, + 0x03F, 0x0000003C, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000003, + 0x033, 0x00000001, + 0x03F, 0x00000006, + 0x033, 0x00000002, + 0x03F, 0x00000009, + 0x033, 0x00000003, + 0x03F, 0x00000026, + 0x033, 0x00000004, + 0x03F, 0x00000029, + 0x033, 0x00000005, + 0x03F, 0x0000002C, + 0x033, 0x00000006, + 0x03F, 0x0000002F, + 0x033, 0x00000007, + 0x03F, 0x00000033, + 0x033, 0x00000008, + 0x03F, 0x00000036, + 0x033, 0x00000009, + 0x03F, 0x00000039, + 0x033, 0x0000000A, + 0x03F, 0x0000003C, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000002, + 0x033, 0x00000001, + 0x03F, 0x00000005, + 0x033, 0x00000002, + 0x03F, 0x00000008, + 0x033, 0x00000003, + 0x03F, 0x0000000B, + 0x033, 0x00000004, + 0x03F, 0x0000000E, + 0x033, 0x00000005, + 0x03F, 0x0000002B, + 0x033, 0x00000006, + 0x03F, 0x0000002E, + 0x033, 0x00000007, + 0x03F, 0x00000031, + 0x033, 0x00000008, + 0x03F, 0x0000006E, + 0x033, 0x00000009, + 0x03F, 0x00000071, + 0x033, 0x0000000A, + 0x03F, 0x00000074, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000003, + 0x033, 0x00000001, + 0x03F, 0x00000006, + 0x033, 0x00000002, + 0x03F, 0x00000009, + 0x033, 0x00000003, + 0x03F, 0x00000026, + 0x033, 0x00000004, + 0x03F, 0x00000029, + 0x033, 0x00000005, + 0x03F, 0x0000002C, + 0x033, 0x00000006, + 0x03F, 0x0000002F, + 0x033, 0x00000007, + 0x03F, 0x00000033, + 0x033, 0x00000008, + 0x03F, 0x00000036, + 0x033, 0x00000009, + 0x03F, 0x00000039, + 0x033, 0x0000000A, + 0x03F, 0x0000003C, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000003, + 0x033, 0x00000001, + 0x03F, 0x00000006, + 0x033, 0x00000002, + 0x03F, 0x00000009, + 0x033, 0x00000003, + 0x03F, 0x00000026, + 0x033, 0x00000004, + 0x03F, 0x00000029, + 0x033, 0x00000005, + 0x03F, 0x0000002C, + 0x033, 0x00000006, + 0x03F, 0x0000002F, + 0x033, 0x00000007, + 0x03F, 0x00000033, + 0x033, 0x00000008, + 0x03F, 0x00000036, + 0x033, 0x00000009, + 0x03F, 0x00000039, + 0x033, 0x0000000A, + 0x03F, 0x0000003C, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000003, + 0x033, 0x00000001, + 0x03F, 0x00000006, + 0x033, 0x00000002, + 0x03F, 0x00000009, + 0x033, 0x00000003, + 0x03F, 0x00000026, + 0x033, 0x00000004, + 0x03F, 0x00000029, + 0x033, 0x00000005, + 0x03F, 0x0000002C, + 0x033, 0x00000006, + 0x03F, 0x0000002F, + 0x033, 0x00000007, + 0x03F, 0x00000033, + 0x033, 0x00000008, + 0x03F, 0x00000036, + 0x033, 0x00000009, + 0x03F, 0x00000039, + 0x033, 0x0000000A, + 0x03F, 0x0000003C, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000003, + 0x033, 0x00000001, + 0x03F, 0x00000006, + 0x033, 0x00000002, + 0x03F, 0x00000009, + 0x033, 0x00000003, + 0x03F, 0x00000026, + 0x033, 0x00000004, + 0x03F, 0x00000029, + 0x033, 0x00000005, + 0x03F, 0x0000002C, + 0x033, 0x00000006, + 0x03F, 0x0000002F, + 0x033, 0x00000007, + 0x03F, 0x00000033, + 0x033, 0x00000008, + 0x03F, 0x00000036, + 0x033, 0x00000009, + 0x03F, 0x00000039, + 0x033, 0x0000000A, + 0x03F, 0x0000003C, + 0xA0000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0005142C, + 0x033, 0x00000001, + 0x03F, 0x0005144B, + 0x033, 0x00000002, + 0x03F, 0x0005144E, + 0x033, 0x00000003, + 0x03F, 0x00051C69, + 0x033, 0x00000004, + 0x03F, 0x00051C6C, + 0x033, 0x00000005, + 0x03F, 0x00051C6F, + 0x033, 0x00000006, + 0x03F, 0x00051CEB, + 0x033, 0x00000007, + 0x03F, 0x00051CEE, + 0x033, 0x00000008, + 0x03F, 0x00051CF1, + 0x033, 0x00000009, + 0x03F, 0x00051CF4, + 0x033, 0x0000000A, + 0x03F, 0x00051CF7, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x0EF, 0x00000010, + 0x033, 0x00000000, + 0x008, 0x0009C060, + 0x033, 0x00000001, + 0x008, 0x0009C060, + 0x0EF, 0x00000000, + 0x033, 0x000000A2, + 0x0EF, 0x00080000, + 0x03E, 0x0000593F, + 0x8300000c, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000D0F4F, + 0xA0000000, 0x00000000, + 0x03F, 0x000C0F4F, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x033, 0x000000A3, + 0x0EF, 0x00080000, + 0x03E, 0x00005934, + 0x03F, 0x0005AFCF, + 0x0EF, 0x00000000, + 0x83000002, 0x00000000, 0x40000000, 0x00000000, + 0x0CE, 0x00094400, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x0CE, 0x00094400, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x0CE, 0x00094400, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x0CE, 0x00094400, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x0CE, 0x00094400, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x0CE, 0x00094400, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x0CE, 0x00094400, + 0xA0000000, 0x00000000, + 0x0CE, 0x00094C00, + 0xB0000000, 0x00000000, + 0x83000002, 0x00000000, 0x40000000, 0x00000000, + 0x0CF, 0x00072F00, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x0CF, 0x00072F00, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x0CF, 0x00072F00, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x0CF, 0x00072F00, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x0CF, 0x00064700, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x0CF, 0x00072F00, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x0CF, 0x00072F00, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x0CF, 0x00072F00, + 0xA0000000, 0x00000000, + 0x0CF, 0x00064700, + 0xB0000000, 0x00000000, + 0x83000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000004, + 0x033, 0x00000000, + 0x03F, 0x00000056, + 0x033, 0x00000001, + 0x03F, 0x000000D6, + 0x0EF, 0x00000000, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000004, + 0x033, 0x00000000, + 0x03F, 0x00000056, + 0x033, 0x00000001, + 0x03F, 0x000000D6, + 0x0EF, 0x00000000, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000004, + 0x033, 0x00000000, + 0x03F, 0x00000056, + 0x033, 0x00000001, + 0x03F, 0x000000D6, + 0x0EF, 0x00000000, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000004, + 0x033, 0x00000000, + 0x03F, 0x00000056, + 0x033, 0x00000001, + 0x03F, 0x000000D6, + 0x0EF, 0x00000000, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000004, + 0x033, 0x00000000, + 0x03F, 0x00000096, + 0x033, 0x00000001, + 0x03F, 0x000000D6, + 0x0EF, 0x00000000, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000004, + 0x033, 0x00000000, + 0x03F, 0x00000056, + 0x033, 0x00000001, + 0x03F, 0x00000056, + 0x0EF, 0x00000000, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000004, + 0x033, 0x00000000, + 0x03F, 0x00000056, + 0x033, 0x00000001, + 0x03F, 0x000000D6, + 0x0EF, 0x00000000, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000004, + 0x033, 0x00000000, + 0x03F, 0x00000056, + 0x033, 0x00000001, + 0x03F, 0x000000D6, + 0x0EF, 0x00000000, + 0xA0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000096, + 0x033, 0x00000001, + 0x03F, 0x000000D6, + 0x0EF, 0x00000000, + 0xB0000000, 0x00000000, + 0x0B0, 0x000FF0FC, + 0x0C4, 0x00081402, + 0x0CC, 0x00082000, +}; + +RTW_DECL_TABLE_RF_RADIO(rtw8822b_rf_a, A); + +static const u32 rtw8822b_rf_b[] = { + 0x000, 0x00030000, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x00040029, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x001, 0x0004002D, + 0xA0000000, 0x00000000, + 0x001, 0x00040029, + 0xB0000000, 0x00000000, + 0x018, 0x00010D24, + 0x0EF, 0x00080000, + 0x033, 0x00000002, + 0x03E, 0x0000003F, + 0x8300000c, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000D0F4E, + 0xA0000000, 0x00000000, + 0x03F, 0x000C0F4E, + 0xB0000000, 0x00000000, + 0x033, 0x00000001, + 0x03E, 0x00000034, + 0x03F, 0x0004080E, + 0x0EF, 0x00080000, + 0x0DF, 0x00002449, + 0x033, 0x00000024, + 0x03E, 0x0000003F, + 0x03F, 0x00060FDE, + 0x0EF, 0x00000000, + 0x0EF, 0x00080000, + 0x033, 0x00000025, + 0x03E, 0x00000037, + 0x03F, 0x0007EFCE, + 0x0EF, 0x00000000, + 0x0EF, 0x00080000, + 0x033, 0x00000026, + 0x03E, 0x00000037, + 0x03F, 0x000DEFCE, + 0x0EF, 0x00000000, + 0x0DF, 0x00000009, + 0x018, 0x00010524, + 0x089, 0x00000207, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FF186, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FF186, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FE186, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FF186, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FF186, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FF186, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FE186, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x08A, 0x000FF186, + 0xA0000000, 0x00000000, + 0x08A, 0x000FF186, + 0xB0000000, 0x00000000, + 0x08B, 0x00061E3C, + 0x08C, 0x000112C7, + 0x08D, 0x000F4988, + 0x08E, 0x00064D40, + 0x0EF, 0x00020000, + 0x033, 0x00000007, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C3186, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x03F, 0x000C3186, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C3186, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C3186, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C3186, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x03F, 0x000C3186, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0xA0000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C3186, + 0xB0000000, 0x00000000, + 0x033, 0x00000006, + 0x03E, 0x00004080, + 0x03F, 0x000C3186, + 0x033, 0x00000005, + 0x03E, 0x000040C8, + 0x03F, 0x000C3186, + 0x033, 0x00000004, + 0x03E, 0x00004190, + 0x03F, 0x000C3186, + 0x033, 0x00000003, + 0x03E, 0x00004998, + 0x03F, 0x000C3186, + 0x033, 0x00000002, + 0x03E, 0x00005840, + 0x03F, 0x000C3186, + 0x033, 0x00000001, + 0x03E, 0x000058C2, + 0x03F, 0x000C3186, + 0x033, 0x00000000, + 0x03E, 0x00005930, + 0x03F, 0x000C3186, + 0x033, 0x0000000F, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C3186, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C3186, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x03F, 0x000C3186, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C3186, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C3186, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C3186, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x03F, 0x000C3186, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0xA0000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C3186, + 0xB0000000, 0x00000000, + 0x033, 0x0000000E, + 0x03E, 0x00004080, + 0x03F, 0x000C3186, + 0x033, 0x0000000D, + 0x8300000f, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x000040D0, + 0xA0000000, 0x00000000, + 0x03E, 0x000040C8, + 0xB0000000, 0x00000000, + 0x03F, 0x000C3186, + 0x033, 0x0000000C, + 0x03E, 0x00004190, + 0x03F, 0x000C3186, + 0x033, 0x0000000B, + 0x03E, 0x00004998, + 0x03F, 0x000C3186, + 0x033, 0x0000000A, + 0x03E, 0x00005840, + 0x03F, 0x000C3186, + 0x033, 0x00000009, + 0x03E, 0x000058C2, + 0x03F, 0x000C3186, + 0x033, 0x00000008, + 0x03E, 0x00005930, + 0x03F, 0x000C3186, + 0x033, 0x00000017, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C3186, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000DFF86, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x03F, 0x000C3186, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C3186, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C3186, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000DFF86, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C3186, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C0006, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004080, + 0x03F, 0x000C3186, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x00004040, + 0x03F, 0x000C3186, + 0xA0000000, 0x00000000, + 0x03E, 0x00004000, + 0x03F, 0x000C3186, + 0xB0000000, 0x00000000, + 0x033, 0x00000016, + 0x03E, 0x00004080, + 0x03F, 0x000C3186, + 0x033, 0x00000015, + 0x8300000f, 0x00000000, 0x40000000, 0x00000000, + 0x03E, 0x000040D0, + 0xA0000000, 0x00000000, + 0x03E, 0x000040C8, + 0xB0000000, 0x00000000, + 0x03F, 0x000C3186, + 0x033, 0x00000014, + 0x03E, 0x00004190, + 0x03F, 0x000C3186, + 0x033, 0x00000013, + 0x03E, 0x00004998, + 0x03F, 0x000C3186, + 0x033, 0x00000012, + 0x03E, 0x00005840, + 0x03F, 0x000C3186, + 0x033, 0x00000011, + 0x03E, 0x000058C2, + 0x03F, 0x000C3186, + 0x033, 0x00000010, + 0x03E, 0x00005930, + 0x03F, 0x000C3186, + 0x0EF, 0x00000000, + 0x0EF, 0x00004000, + 0x033, 0x00000000, + 0x03F, 0x0000000A, + 0x033, 0x00000001, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000005, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000002, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000005, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000005, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000005, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0xA0000000, 0x00000000, + 0x03F, 0x00000005, + 0xB0000000, 0x00000000, + 0x033, 0x00000002, + 0x03F, 0x00000000, + 0x0EF, 0x00000000, + 0x018, 0x00000401, + 0x084, 0x00001209, + 0x086, 0x000001A0, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x087, 0x00068080, + 0xA0000000, 0x00000000, + 0x087, 0x000E8180, + 0xB0000000, 0x00000000, + 0x088, 0x00070020, + 0x0DE, 0x00000010, + 0x0EF, 0x00008000, + 0x033, 0x0000000F, + 0x03F, 0x0000003C, + 0x033, 0x0000000E, + 0x03F, 0x00000038, + 0x033, 0x0000000D, + 0x03F, 0x00000030, + 0x033, 0x0000000C, + 0x03F, 0x00000028, + 0x033, 0x0000000B, + 0x03F, 0x00000020, + 0x033, 0x0000000A, + 0x03F, 0x00000018, + 0x033, 0x00000009, + 0x03F, 0x00000010, + 0x033, 0x00000008, + 0x03F, 0x00000008, + 0x033, 0x00000007, + 0x03F, 0x0000003C, + 0x033, 0x00000006, + 0x03F, 0x00000038, + 0x033, 0x00000005, + 0x03F, 0x00000030, + 0x033, 0x00000004, + 0x03F, 0x00000028, + 0x033, 0x00000003, + 0x03F, 0x00000020, + 0x033, 0x00000002, + 0x03F, 0x00000018, + 0x033, 0x00000001, + 0x03F, 0x00000010, + 0x033, 0x00000000, + 0x03F, 0x00000008, + 0x0EF, 0x00000000, + 0x018, 0x00018D24, + 0xFFE, 0x00000000, + 0xFFE, 0x00000000, + 0xFFE, 0x00000000, + 0xFFE, 0x00000000, + 0x018, 0x00010D24, + 0x01B, 0x00075A40, + 0x0EE, 0x00000002, + 0x033, 0x00000000, + 0x03F, 0x00000004, + 0x033, 0x00000001, + 0x03F, 0x00000004, + 0x033, 0x00000002, + 0x03F, 0x00000004, + 0x033, 0x00000003, + 0x03F, 0x00000004, + 0x033, 0x00000004, + 0x03F, 0x00000004, + 0x033, 0x00000005, + 0x03F, 0x00000006, + 0x033, 0x00000006, + 0x03F, 0x00000004, + 0x033, 0x00000007, + 0x03F, 0x00000000, + 0x0EE, 0x00000000, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D3D1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D4A0, + 0x062, 0x0000D203, + 0x063, 0x00000062, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000062, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000062, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D4A0, + 0x062, 0x0000D203, + 0x063, 0x00000062, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D4A0, + 0x062, 0x0000D203, + 0x063, 0x00000062, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D3D1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D3D1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D4A0, + 0x062, 0x0000D203, + 0x063, 0x00000062, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D3D1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D3D1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000062, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D4A0, + 0x062, 0x0000D203, + 0x063, 0x00000062, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000062, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000062, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D2A1, + 0x062, 0x0000D3A2, + 0x063, 0x00000002, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D4A0, + 0x062, 0x0000D203, + 0x063, 0x00000062, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x061, 0x0005D4A0, + 0x062, 0x0000D203, + 0x063, 0x00000062, + 0xA0000000, 0x00000000, + 0x061, 0x0005D3D0, + 0x062, 0x0000D303, + 0x063, 0x00000002, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000200, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A3, + 0x030, 0x000053A3, + 0x030, 0x000063A3, + 0x030, 0x000073A3, + 0x030, 0x000083A3, + 0x030, 0x000093A3, + 0x030, 0x0000A3A3, + 0x030, 0x0000B3A3, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000004A3, + 0x030, 0x000014A3, + 0x030, 0x000024A3, + 0x030, 0x000034A3, + 0x030, 0x000044A3, + 0x030, 0x000054A3, + 0x030, 0x000064A3, + 0x030, 0x000074A3, + 0x030, 0x000084A3, + 0x030, 0x000094A3, + 0x030, 0x0000A4A3, + 0x030, 0x0000B4A3, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000002A6, + 0x030, 0x000012A6, + 0x030, 0x000022A6, + 0x030, 0x000032A6, + 0x030, 0x000042A6, + 0x030, 0x000052A6, + 0x030, 0x000062A6, + 0x030, 0x000072A6, + 0x030, 0x000082A6, + 0x030, 0x000092A6, + 0x030, 0x0000A2A6, + 0x030, 0x0000B2A6, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000303, + 0x030, 0x00001303, + 0x030, 0x00002303, + 0x030, 0x00003303, + 0x030, 0x000043A4, + 0x030, 0x000053A4, + 0x030, 0x000063A4, + 0x030, 0x000073A4, + 0x030, 0x00008365, + 0x030, 0x00009365, + 0x030, 0x0000A365, + 0x030, 0x0000B365, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000002A6, + 0x030, 0x000012A6, + 0x030, 0x000022A6, + 0x030, 0x000032A6, + 0x030, 0x000042A6, + 0x030, 0x000052A6, + 0x030, 0x000062A6, + 0x030, 0x000072A6, + 0x030, 0x000082A6, + 0x030, 0x000092A6, + 0x030, 0x0000A2A6, + 0x030, 0x0000B2A6, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000004A4, + 0x030, 0x000014A4, + 0x030, 0x000024A4, + 0x030, 0x000034A4, + 0x030, 0x000043A4, + 0x030, 0x000053A4, + 0x030, 0x000063A4, + 0x030, 0x000073A4, + 0x030, 0x000083A5, + 0x030, 0x000093A5, + 0x030, 0x0000A3A5, + 0x030, 0x0000B3A5, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000004A3, + 0x030, 0x000014A3, + 0x030, 0x000024A3, + 0x030, 0x000034A3, + 0x030, 0x000044A3, + 0x030, 0x000054A3, + 0x030, 0x000064A3, + 0x030, 0x000074A3, + 0x030, 0x000084A3, + 0x030, 0x000094A3, + 0x030, 0x0000A4A3, + 0x030, 0x0000B4A3, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000004A3, + 0x030, 0x000014A3, + 0x030, 0x000024A3, + 0x030, 0x000034A3, + 0x030, 0x000044A3, + 0x030, 0x000054A3, + 0x030, 0x000064A3, + 0x030, 0x000074A3, + 0x030, 0x000084A3, + 0x030, 0x000094A3, + 0x030, 0x0000A4A3, + 0x030, 0x0000B4A3, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000002F4, + 0x030, 0x000012F4, + 0x030, 0x000022F4, + 0x030, 0x000032F4, + 0x030, 0x00004365, + 0x030, 0x00005365, + 0x030, 0x00006365, + 0x030, 0x00007365, + 0x030, 0x000082A4, + 0x030, 0x000092A4, + 0x030, 0x0000A2A4, + 0x030, 0x0000B2A4, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000382, + 0x030, 0x00001382, + 0x030, 0x00002382, + 0x030, 0x00003382, + 0x030, 0x00004445, + 0x030, 0x00005445, + 0x030, 0x00006445, + 0x030, 0x00007445, + 0x030, 0x00008425, + 0x030, 0x00009425, + 0x030, 0x0000A425, + 0x030, 0x0000B425, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A3, + 0x030, 0x000053A3, + 0x030, 0x000063A3, + 0x030, 0x000073A3, + 0x030, 0x000083A3, + 0x030, 0x000093A3, + 0x030, 0x0000A3A3, + 0x030, 0x0000B3A3, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000004A3, + 0x030, 0x000014A3, + 0x030, 0x000024A3, + 0x030, 0x000034A3, + 0x030, 0x000044A3, + 0x030, 0x000054A3, + 0x030, 0x000064A3, + 0x030, 0x000074A3, + 0x030, 0x000084A3, + 0x030, 0x000094A3, + 0x030, 0x0000A4A3, + 0x030, 0x0000B4A3, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000443, + 0x030, 0x00001443, + 0x030, 0x00002443, + 0x030, 0x00003443, + 0x030, 0x000043A4, + 0x030, 0x000053A4, + 0x030, 0x000063A4, + 0x030, 0x000073A4, + 0x030, 0x00008365, + 0x030, 0x00009365, + 0x030, 0x0000A365, + 0x030, 0x0000B365, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000343, + 0x030, 0x00001343, + 0x030, 0x00002343, + 0x030, 0x00003343, + 0x030, 0x00004483, + 0x030, 0x00005483, + 0x030, 0x00006483, + 0x030, 0x00007483, + 0x030, 0x000083A4, + 0x030, 0x000093A4, + 0x030, 0x0000A3A4, + 0x030, 0x0000B3A4, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x00004423, + 0x030, 0x00005423, + 0x030, 0x00006423, + 0x030, 0x00007423, + 0x030, 0x00008324, + 0x030, 0x00009324, + 0x030, 0x0000A324, + 0x030, 0x0000B324, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000303, + 0x030, 0x00001303, + 0x030, 0x00002303, + 0x030, 0x00003303, + 0x030, 0x000043A4, + 0x030, 0x000053A4, + 0x030, 0x000063A4, + 0x030, 0x000073A4, + 0x030, 0x00008365, + 0x030, 0x00009365, + 0x030, 0x0000A365, + 0x030, 0x0000B365, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000403, + 0x030, 0x00001403, + 0x030, 0x00002403, + 0x030, 0x00003403, + 0x030, 0x000043A4, + 0x030, 0x000053A4, + 0x030, 0x000063A4, + 0x030, 0x000073A4, + 0x030, 0x000083A3, + 0x030, 0x000093A3, + 0x030, 0x0000A3A3, + 0x030, 0x0000B3A3, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A3, + 0x030, 0x000013A3, + 0x030, 0x000023A3, + 0x030, 0x000033A3, + 0x030, 0x000043A4, + 0x030, 0x000053A4, + 0x030, 0x000063A4, + 0x030, 0x000073A4, + 0x030, 0x00008365, + 0x030, 0x00009365, + 0x030, 0x0000A365, + 0x030, 0x0000B365, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000002A6, + 0x030, 0x000012A6, + 0x030, 0x000022A6, + 0x030, 0x000032A6, + 0x030, 0x000042A6, + 0x030, 0x000052A6, + 0x030, 0x000062A6, + 0x030, 0x000072A6, + 0x030, 0x000082A6, + 0x030, 0x000092A6, + 0x030, 0x0000A2A6, + 0x030, 0x0000B2A6, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000004A0, + 0x030, 0x000014A0, + 0x030, 0x000024A0, + 0x030, 0x000034A0, + 0x030, 0x000044A0, + 0x030, 0x000054A0, + 0x030, 0x000064A0, + 0x030, 0x000074A0, + 0x030, 0x000084A0, + 0x030, 0x000094A0, + 0x030, 0x0000A4A0, + 0x030, 0x0000B4A0, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000002A1, + 0x030, 0x000012A1, + 0x030, 0x000022A1, + 0x030, 0x000032A1, + 0x030, 0x000042A1, + 0x030, 0x000052A1, + 0x030, 0x000062A1, + 0x030, 0x000072A1, + 0x030, 0x000082A1, + 0x030, 0x000092A1, + 0x030, 0x0000A2A1, + 0x030, 0x0000B2A1, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000004A0, + 0x030, 0x000014A0, + 0x030, 0x000024A0, + 0x030, 0x000034A0, + 0x030, 0x000043A1, + 0x030, 0x000053A1, + 0x030, 0x000063A1, + 0x030, 0x000073A1, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000002A1, + 0x030, 0x000012A1, + 0x030, 0x000022A1, + 0x030, 0x000032A1, + 0x030, 0x000042A1, + 0x030, 0x000052A1, + 0x030, 0x000062A1, + 0x030, 0x000072A1, + 0x030, 0x000082A1, + 0x030, 0x000092A1, + 0x030, 0x0000A2A1, + 0x030, 0x0000B2A1, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000004A1, + 0x030, 0x000014A1, + 0x030, 0x000024A1, + 0x030, 0x000034A1, + 0x030, 0x000043A1, + 0x030, 0x000053A1, + 0x030, 0x000063A1, + 0x030, 0x000073A1, + 0x030, 0x000083A1, + 0x030, 0x000093A1, + 0x030, 0x0000A3A1, + 0x030, 0x0000B3A1, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000004A0, + 0x030, 0x000014A0, + 0x030, 0x000024A0, + 0x030, 0x000034A0, + 0x030, 0x000044A0, + 0x030, 0x000054A0, + 0x030, 0x000064A0, + 0x030, 0x000074A0, + 0x030, 0x000084A0, + 0x030, 0x000094A0, + 0x030, 0x0000A4A0, + 0x030, 0x0000B4A0, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000004A0, + 0x030, 0x000014A0, + 0x030, 0x000024A0, + 0x030, 0x000034A0, + 0x030, 0x000044A0, + 0x030, 0x000054A0, + 0x030, 0x000064A0, + 0x030, 0x000074A0, + 0x030, 0x000084A0, + 0x030, 0x000094A0, + 0x030, 0x0000A4A0, + 0x030, 0x0000B4A0, + 0xA0000000, 0x00000000, + 0x030, 0x000002D0, + 0x030, 0x000012D0, + 0x030, 0x000022D0, + 0x030, 0x000032D0, + 0x030, 0x000042D0, + 0x030, 0x000052D0, + 0x030, 0x000062D0, + 0x030, 0x000072D0, + 0x030, 0x000082D0, + 0x030, 0x000092D0, + 0x030, 0x0000A2D0, + 0x030, 0x0000B2D0, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x0EF, 0x00000080, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000203, + 0x030, 0x00001203, + 0x030, 0x00002203, + 0x030, 0x00003203, + 0x030, 0x00004203, + 0x030, 0x00005203, + 0x030, 0x00006203, + 0x030, 0x00007203, + 0x030, 0x00008203, + 0x030, 0x00009203, + 0x030, 0x0000A203, + 0x030, 0x0000B203, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000203, + 0x030, 0x00001203, + 0x030, 0x00002203, + 0x030, 0x00003203, + 0x030, 0x00004203, + 0x030, 0x00005203, + 0x030, 0x00006203, + 0x030, 0x00007203, + 0x030, 0x00008203, + 0x030, 0x00009203, + 0x030, 0x0000A203, + 0x030, 0x0000B203, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000203, + 0x030, 0x00001203, + 0x030, 0x00002203, + 0x030, 0x00003203, + 0x030, 0x00004203, + 0x030, 0x00005203, + 0x030, 0x00006203, + 0x030, 0x00007203, + 0x030, 0x00008203, + 0x030, 0x00009203, + 0x030, 0x0000A203, + 0x030, 0x0000B203, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A3, + 0x030, 0x000013A3, + 0x030, 0x000023A3, + 0x030, 0x000033A3, + 0x030, 0x000043A4, + 0x030, 0x000053A4, + 0x030, 0x000063A4, + 0x030, 0x000073A4, + 0x030, 0x000083A3, + 0x030, 0x000093A3, + 0x030, 0x0000A3A3, + 0x030, 0x0000B3A3, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000203, + 0x030, 0x00001203, + 0x030, 0x00002203, + 0x030, 0x00003203, + 0x030, 0x00004203, + 0x030, 0x00005203, + 0x030, 0x00006203, + 0x030, 0x00007203, + 0x030, 0x00008203, + 0x030, 0x00009203, + 0x030, 0x0000A203, + 0x030, 0x0000B203, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000203, + 0x030, 0x00001203, + 0x030, 0x00002203, + 0x030, 0x00003203, + 0x030, 0x00004203, + 0x030, 0x00005203, + 0x030, 0x00006203, + 0x030, 0x00007203, + 0x030, 0x00008203, + 0x030, 0x00009203, + 0x030, 0x0000A203, + 0x030, 0x0000B203, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000203, + 0x030, 0x00001203, + 0x030, 0x00002203, + 0x030, 0x00003203, + 0x030, 0x00004203, + 0x030, 0x00005203, + 0x030, 0x00006203, + 0x030, 0x00007203, + 0x030, 0x00008203, + 0x030, 0x00009203, + 0x030, 0x0000A203, + 0x030, 0x0000B203, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000203, + 0x030, 0x00001203, + 0x030, 0x00002203, + 0x030, 0x00003203, + 0x030, 0x00004203, + 0x030, 0x00005203, + 0x030, 0x00006203, + 0x030, 0x00007203, + 0x030, 0x00008203, + 0x030, 0x00009203, + 0x030, 0x0000A203, + 0x030, 0x0000B203, + 0xA0000000, 0x00000000, + 0x030, 0x000003A2, + 0x030, 0x000013A2, + 0x030, 0x000023A2, + 0x030, 0x000033A2, + 0x030, 0x000043A2, + 0x030, 0x000053A2, + 0x030, 0x000063A2, + 0x030, 0x000073A2, + 0x030, 0x000083A2, + 0x030, 0x000093A2, + 0x030, 0x0000A3A2, + 0x030, 0x0000B3A2, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x0EF, 0x00000040, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000764, + 0x030, 0x00001632, + 0x030, 0x00002421, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000777, + 0x030, 0x00001442, + 0x030, 0x00002222, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000764, + 0x030, 0x00001452, + 0x030, 0x00002220, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000660, + 0x030, 0x00001341, + 0x030, 0x00002220, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000764, + 0x030, 0x00001632, + 0x030, 0x00002421, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000764, + 0x030, 0x00001632, + 0x030, 0x00002421, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000767, + 0x030, 0x00001442, + 0x030, 0x00002222, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000765, + 0x030, 0x00001632, + 0x030, 0x00002451, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000764, + 0x030, 0x00001632, + 0x030, 0x00002421, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000777, + 0x030, 0x00001442, + 0x030, 0x00002222, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000776, + 0x030, 0x00001442, + 0x030, 0x00002222, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000777, + 0x030, 0x00001442, + 0x030, 0x00002222, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004777, + 0x030, 0x00005777, + 0x030, 0x00006777, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000775, + 0x030, 0x00001422, + 0x030, 0x00002210, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000775, + 0x030, 0x00001222, + 0x030, 0x00002210, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000645, + 0x030, 0x00001333, + 0x030, 0x00002011, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0xA0000000, 0x00000000, + 0x030, 0x00000764, + 0x030, 0x00001632, + 0x030, 0x00002421, + 0x030, 0x00004000, + 0x030, 0x00005000, + 0x030, 0x00006000, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x0EF, 0x00000800, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000C09, + 0x033, 0x00000021, + 0x03F, 0x00000C0C, + 0x033, 0x00000022, + 0x03F, 0x00000C0F, + 0x033, 0x00000023, + 0x03F, 0x00000C2C, + 0x033, 0x00000024, + 0x03F, 0x00000C2F, + 0x033, 0x00000025, + 0x03F, 0x00000C8A, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000C90, + 0x033, 0x00000028, + 0x03F, 0x00000CD0, + 0x033, 0x00000029, + 0x03F, 0x00000CF2, + 0x033, 0x0000002A, + 0x03F, 0x00000CF5, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000007, + 0x033, 0x00000021, + 0x03F, 0x0000000A, + 0x033, 0x00000022, + 0x03F, 0x0000000D, + 0x033, 0x00000023, + 0x03F, 0x0000002A, + 0x033, 0x00000024, + 0x03F, 0x0000002D, + 0x033, 0x00000025, + 0x03F, 0x00000030, + 0x033, 0x00000026, + 0x03F, 0x0000006D, + 0x033, 0x00000027, + 0x03F, 0x00000070, + 0x033, 0x00000028, + 0x03F, 0x000000ED, + 0x033, 0x00000029, + 0x03F, 0x000000F0, + 0x033, 0x0000002A, + 0x03F, 0x000000F3, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000005, + 0x033, 0x00000021, + 0x03F, 0x00000008, + 0x033, 0x00000022, + 0x03F, 0x0000000B, + 0x033, 0x00000023, + 0x03F, 0x0000000E, + 0x033, 0x00000024, + 0x03F, 0x0000002B, + 0x033, 0x00000025, + 0x03F, 0x0000002E, + 0x033, 0x00000026, + 0x03F, 0x0000006B, + 0x033, 0x00000027, + 0x03F, 0x0000006E, + 0x033, 0x00000028, + 0x03F, 0x00000071, + 0x033, 0x00000029, + 0x03F, 0x00000074, + 0x033, 0x0000002A, + 0x03F, 0x00000077, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000429, + 0x033, 0x00000021, + 0x03F, 0x00000828, + 0x033, 0x00000022, + 0x03F, 0x00000847, + 0x033, 0x00000023, + 0x03F, 0x0000084A, + 0x033, 0x00000024, + 0x03F, 0x00000C4B, + 0x033, 0x00000025, + 0x03F, 0x00000C6C, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000CAF, + 0x033, 0x00000028, + 0x03F, 0x00000CD1, + 0x033, 0x00000029, + 0x03F, 0x00000CF3, + 0x033, 0x0000002A, + 0x03F, 0x00000CF6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000005, + 0x033, 0x00000021, + 0x03F, 0x00000008, + 0x033, 0x00000022, + 0x03F, 0x0000000B, + 0x033, 0x00000023, + 0x03F, 0x0000000E, + 0x033, 0x00000024, + 0x03F, 0x0000002B, + 0x033, 0x00000025, + 0x03F, 0x0000002E, + 0x033, 0x00000026, + 0x03F, 0x0000006B, + 0x033, 0x00000027, + 0x03F, 0x0000006E, + 0x033, 0x00000028, + 0x03F, 0x00000071, + 0x033, 0x00000029, + 0x03F, 0x00000074, + 0x033, 0x0000002A, + 0x03F, 0x00000077, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x0000042C, + 0x033, 0x00000021, + 0x03F, 0x0000082B, + 0x033, 0x00000022, + 0x03F, 0x0000084A, + 0x033, 0x00000023, + 0x03F, 0x0000084D, + 0x033, 0x00000024, + 0x03F, 0x00000C4E, + 0x033, 0x00000025, + 0x03F, 0x00000C6E, + 0x033, 0x00000026, + 0x03F, 0x00000CAD, + 0x033, 0x00000027, + 0x03F, 0x00000CED, + 0x033, 0x00000028, + 0x03F, 0x00000CF0, + 0x033, 0x00000029, + 0x03F, 0x00000CF3, + 0x033, 0x0000002A, + 0x03F, 0x00000CF6, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000007, + 0x033, 0x00000021, + 0x03F, 0x0000000A, + 0x033, 0x00000022, + 0x03F, 0x0000000D, + 0x033, 0x00000023, + 0x03F, 0x0000002A, + 0x033, 0x00000024, + 0x03F, 0x0000002D, + 0x033, 0x00000025, + 0x03F, 0x00000030, + 0x033, 0x00000026, + 0x03F, 0x0000006D, + 0x033, 0x00000027, + 0x03F, 0x00000070, + 0x033, 0x00000028, + 0x03F, 0x000000ED, + 0x033, 0x00000029, + 0x03F, 0x000000F0, + 0x033, 0x0000002A, + 0x03F, 0x000000F3, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000007, + 0x033, 0x00000021, + 0x03F, 0x0000000A, + 0x033, 0x00000022, + 0x03F, 0x0000000D, + 0x033, 0x00000023, + 0x03F, 0x0000002A, + 0x033, 0x00000024, + 0x03F, 0x0000002D, + 0x033, 0x00000025, + 0x03F, 0x00000030, + 0x033, 0x00000026, + 0x03F, 0x0000006D, + 0x033, 0x00000027, + 0x03F, 0x00000070, + 0x033, 0x00000028, + 0x03F, 0x000000ED, + 0x033, 0x00000029, + 0x03F, 0x000000F0, + 0x033, 0x0000002A, + 0x03F, 0x000000F3, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000828, + 0x033, 0x00000021, + 0x03F, 0x0000082B, + 0x033, 0x00000022, + 0x03F, 0x00000868, + 0x033, 0x00000023, + 0x03F, 0x00000889, + 0x033, 0x00000024, + 0x03F, 0x000008AA, + 0x033, 0x00000025, + 0x03F, 0x00000CE8, + 0x033, 0x00000026, + 0x03F, 0x00000CEB, + 0x033, 0x00000027, + 0x03F, 0x00000CEE, + 0x033, 0x00000028, + 0x03F, 0x00000CF1, + 0x033, 0x00000029, + 0x03F, 0x00000CF4, + 0x033, 0x0000002A, + 0x03F, 0x00000CF7, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000C09, + 0x033, 0x00000021, + 0x03F, 0x00000C0C, + 0x033, 0x00000022, + 0x03F, 0x00000C0F, + 0x033, 0x00000023, + 0x03F, 0x00000C2C, + 0x033, 0x00000024, + 0x03F, 0x00000C2F, + 0x033, 0x00000025, + 0x03F, 0x00000C8A, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000C90, + 0x033, 0x00000028, + 0x03F, 0x00000CD0, + 0x033, 0x00000029, + 0x03F, 0x00000CF2, + 0x033, 0x0000002A, + 0x03F, 0x00000CF5, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000C09, + 0x033, 0x00000021, + 0x03F, 0x00000C0C, + 0x033, 0x00000022, + 0x03F, 0x00000C0F, + 0x033, 0x00000023, + 0x03F, 0x00000C2C, + 0x033, 0x00000024, + 0x03F, 0x00000C2F, + 0x033, 0x00000025, + 0x03F, 0x00000C8A, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000C90, + 0x033, 0x00000028, + 0x03F, 0x00000CD0, + 0x033, 0x00000029, + 0x03F, 0x00000CF2, + 0x033, 0x0000002A, + 0x03F, 0x00000CF5, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000007, + 0x033, 0x00000021, + 0x03F, 0x0000000A, + 0x033, 0x00000022, + 0x03F, 0x0000000D, + 0x033, 0x00000023, + 0x03F, 0x0000002A, + 0x033, 0x00000024, + 0x03F, 0x0000002D, + 0x033, 0x00000025, + 0x03F, 0x00000030, + 0x033, 0x00000026, + 0x03F, 0x0000006D, + 0x033, 0x00000027, + 0x03F, 0x00000070, + 0x033, 0x00000028, + 0x03F, 0x000000ED, + 0x033, 0x00000029, + 0x03F, 0x000000F0, + 0x033, 0x0000002A, + 0x03F, 0x000000F3, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000429, + 0x033, 0x00000021, + 0x03F, 0x00000828, + 0x033, 0x00000022, + 0x03F, 0x00000847, + 0x033, 0x00000023, + 0x03F, 0x0000084A, + 0x033, 0x00000024, + 0x03F, 0x00000C4B, + 0x033, 0x00000025, + 0x03F, 0x00000CE5, + 0x033, 0x00000026, + 0x03F, 0x00000CE8, + 0x033, 0x00000027, + 0x03F, 0x00000CEB, + 0x033, 0x00000028, + 0x03F, 0x00000CEE, + 0x033, 0x00000029, + 0x03F, 0x00000CF1, + 0x033, 0x0000002A, + 0x03F, 0x00000CF4, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000C25, + 0x033, 0x00000021, + 0x03F, 0x00000C28, + 0x033, 0x00000022, + 0x03F, 0x00000C2B, + 0x033, 0x00000023, + 0x03F, 0x00000C68, + 0x033, 0x00000024, + 0x03F, 0x00000C6B, + 0x033, 0x00000025, + 0x03F, 0x00000C6E, + 0x033, 0x00000026, + 0x03F, 0x00000CEB, + 0x033, 0x00000027, + 0x03F, 0x00000CEE, + 0x033, 0x00000028, + 0x03F, 0x00000CF1, + 0x033, 0x00000029, + 0x03F, 0x00000CF4, + 0x033, 0x0000002A, + 0x03F, 0x00000CF7, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000C09, + 0x033, 0x00000021, + 0x03F, 0x00000C0C, + 0x033, 0x00000022, + 0x03F, 0x00000C0F, + 0x033, 0x00000023, + 0x03F, 0x00000C2C, + 0x033, 0x00000024, + 0x03F, 0x00000C2F, + 0x033, 0x00000025, + 0x03F, 0x00000C8A, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000C90, + 0x033, 0x00000028, + 0x03F, 0x00000CD0, + 0x033, 0x00000029, + 0x03F, 0x00000CF2, + 0x033, 0x0000002A, + 0x03F, 0x00000CF5, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000429, + 0x033, 0x00000021, + 0x03F, 0x00000828, + 0x033, 0x00000022, + 0x03F, 0x00000847, + 0x033, 0x00000023, + 0x03F, 0x0000084A, + 0x033, 0x00000024, + 0x03F, 0x00000C4B, + 0x033, 0x00000025, + 0x03F, 0x00000C8A, + 0x033, 0x00000026, + 0x03F, 0x00000CEA, + 0x033, 0x00000027, + 0x03F, 0x00000CED, + 0x033, 0x00000028, + 0x03F, 0x00000CF0, + 0x033, 0x00000029, + 0x03F, 0x00000CF3, + 0x033, 0x0000002A, + 0x03F, 0x00000CF6, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000429, + 0x033, 0x00000021, + 0x03F, 0x00000828, + 0x033, 0x00000022, + 0x03F, 0x00000847, + 0x033, 0x00000023, + 0x03F, 0x0000084A, + 0x033, 0x00000024, + 0x03F, 0x00000C4B, + 0x033, 0x00000025, + 0x03F, 0x00000C6C, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000CAF, + 0x033, 0x00000028, + 0x03F, 0x00000CD1, + 0x033, 0x00000029, + 0x03F, 0x00000CF3, + 0x033, 0x0000002A, + 0x03F, 0x00000CF6, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000429, + 0x033, 0x00000021, + 0x03F, 0x00000828, + 0x033, 0x00000022, + 0x03F, 0x00000847, + 0x033, 0x00000023, + 0x03F, 0x0000084A, + 0x033, 0x00000024, + 0x03F, 0x00000C4B, + 0x033, 0x00000025, + 0x03F, 0x00000C6C, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000CAF, + 0x033, 0x00000028, + 0x03F, 0x00000CD1, + 0x033, 0x00000029, + 0x03F, 0x00000CF3, + 0x033, 0x0000002A, + 0x03F, 0x00000CF6, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000005, + 0x033, 0x00000021, + 0x03F, 0x00000008, + 0x033, 0x00000022, + 0x03F, 0x0000000B, + 0x033, 0x00000023, + 0x03F, 0x0000000E, + 0x033, 0x00000024, + 0x03F, 0x0000002B, + 0x033, 0x00000025, + 0x03F, 0x0000002E, + 0x033, 0x00000026, + 0x03F, 0x0000006B, + 0x033, 0x00000027, + 0x03F, 0x0000006E, + 0x033, 0x00000028, + 0x03F, 0x00000071, + 0x033, 0x00000029, + 0x03F, 0x00000074, + 0x033, 0x0000002A, + 0x03F, 0x00000077, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000007, + 0x033, 0x00000021, + 0x03F, 0x0000000A, + 0x033, 0x00000022, + 0x03F, 0x0000000D, + 0x033, 0x00000023, + 0x03F, 0x0000002A, + 0x033, 0x00000024, + 0x03F, 0x0000002D, + 0x033, 0x00000025, + 0x03F, 0x00000030, + 0x033, 0x00000026, + 0x03F, 0x0000006D, + 0x033, 0x00000027, + 0x03F, 0x00000070, + 0x033, 0x00000028, + 0x03F, 0x000000ED, + 0x033, 0x00000029, + 0x03F, 0x000000F0, + 0x033, 0x0000002A, + 0x03F, 0x000000F3, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000005, + 0x033, 0x00000021, + 0x03F, 0x00000008, + 0x033, 0x00000022, + 0x03F, 0x0000000B, + 0x033, 0x00000023, + 0x03F, 0x0000000E, + 0x033, 0x00000024, + 0x03F, 0x0000002B, + 0x033, 0x00000025, + 0x03F, 0x00000068, + 0x033, 0x00000026, + 0x03F, 0x0000006B, + 0x033, 0x00000027, + 0x03F, 0x0000006E, + 0x033, 0x00000028, + 0x03F, 0x00000071, + 0x033, 0x00000029, + 0x03F, 0x00000074, + 0x033, 0x0000002A, + 0x03F, 0x00000077, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x0000042B, + 0x033, 0x00000021, + 0x03F, 0x0000082A, + 0x033, 0x00000022, + 0x03F, 0x00000849, + 0x033, 0x00000023, + 0x03F, 0x0000084C, + 0x033, 0x00000024, + 0x03F, 0x00000C4C, + 0x033, 0x00000025, + 0x03F, 0x00000C8A, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000CEB, + 0x033, 0x00000028, + 0x03F, 0x00000CEE, + 0x033, 0x00000029, + 0x03F, 0x00000CF1, + 0x033, 0x0000002A, + 0x03F, 0x00000CF4, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000005, + 0x033, 0x00000021, + 0x03F, 0x00000008, + 0x033, 0x00000022, + 0x03F, 0x0000000B, + 0x033, 0x00000023, + 0x03F, 0x0000000E, + 0x033, 0x00000024, + 0x03F, 0x0000002B, + 0x033, 0x00000025, + 0x03F, 0x00000068, + 0x033, 0x00000026, + 0x03F, 0x0000006B, + 0x033, 0x00000027, + 0x03F, 0x0000006E, + 0x033, 0x00000028, + 0x03F, 0x00000071, + 0x033, 0x00000029, + 0x03F, 0x00000074, + 0x033, 0x0000002A, + 0x03F, 0x00000077, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x0000042B, + 0x033, 0x00000021, + 0x03F, 0x0000082A, + 0x033, 0x00000022, + 0x03F, 0x00000849, + 0x033, 0x00000023, + 0x03F, 0x0000084C, + 0x033, 0x00000024, + 0x03F, 0x00000C4C, + 0x033, 0x00000025, + 0x03F, 0x00000C8A, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000CEB, + 0x033, 0x00000028, + 0x03F, 0x00000CEE, + 0x033, 0x00000029, + 0x03F, 0x00000CF1, + 0x033, 0x0000002A, + 0x03F, 0x00000CF4, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000007, + 0x033, 0x00000021, + 0x03F, 0x0000000A, + 0x033, 0x00000022, + 0x03F, 0x0000000D, + 0x033, 0x00000023, + 0x03F, 0x0000002A, + 0x033, 0x00000024, + 0x03F, 0x0000002D, + 0x033, 0x00000025, + 0x03F, 0x00000030, + 0x033, 0x00000026, + 0x03F, 0x0000006D, + 0x033, 0x00000027, + 0x03F, 0x00000070, + 0x033, 0x00000028, + 0x03F, 0x000000ED, + 0x033, 0x00000029, + 0x03F, 0x000000F0, + 0x033, 0x0000002A, + 0x03F, 0x000000F3, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000007, + 0x033, 0x00000021, + 0x03F, 0x0000000A, + 0x033, 0x00000022, + 0x03F, 0x0000000D, + 0x033, 0x00000023, + 0x03F, 0x0000002A, + 0x033, 0x00000024, + 0x03F, 0x0000002D, + 0x033, 0x00000025, + 0x03F, 0x00000030, + 0x033, 0x00000026, + 0x03F, 0x0000006D, + 0x033, 0x00000027, + 0x03F, 0x00000070, + 0x033, 0x00000028, + 0x03F, 0x000000ED, + 0x033, 0x00000029, + 0x03F, 0x000000F0, + 0x033, 0x0000002A, + 0x03F, 0x000000F3, + 0xA0000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000C09, + 0x033, 0x00000021, + 0x03F, 0x00000C0C, + 0x033, 0x00000022, + 0x03F, 0x00000C0F, + 0x033, 0x00000023, + 0x03F, 0x00000C2C, + 0x033, 0x00000024, + 0x03F, 0x00000C2F, + 0x033, 0x00000025, + 0x03F, 0x00000C8A, + 0x033, 0x00000026, + 0x03F, 0x00000C8D, + 0x033, 0x00000027, + 0x03F, 0x00000C90, + 0x033, 0x00000028, + 0x03F, 0x00000CD0, + 0x033, 0x00000029, + 0x03F, 0x00000CF2, + 0x033, 0x0000002A, + 0x03F, 0x00000CF5, + 0xB0000000, 0x00000000, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000C0A, + 0x033, 0x00000061, + 0x03F, 0x00000C0D, + 0x033, 0x00000062, + 0x03F, 0x00000C2A, + 0x033, 0x00000063, + 0x03F, 0x00000C2D, + 0x033, 0x00000064, + 0x03F, 0x00000C6A, + 0x033, 0x00000065, + 0x03F, 0x00000CAA, + 0x033, 0x00000066, + 0x03F, 0x00000CAD, + 0x033, 0x00000067, + 0x03F, 0x00000CB0, + 0x033, 0x00000068, + 0x03F, 0x00000CF1, + 0x033, 0x00000069, + 0x03F, 0x00000CF4, + 0x033, 0x0000006A, + 0x03F, 0x00000CF7, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000007, + 0x033, 0x00000061, + 0x03F, 0x0000000A, + 0x033, 0x00000062, + 0x03F, 0x0000000D, + 0x033, 0x00000063, + 0x03F, 0x0000002A, + 0x033, 0x00000064, + 0x03F, 0x0000002D, + 0x033, 0x00000065, + 0x03F, 0x00000030, + 0x033, 0x00000066, + 0x03F, 0x0000006D, + 0x033, 0x00000067, + 0x03F, 0x00000070, + 0x033, 0x00000068, + 0x03F, 0x000000ED, + 0x033, 0x00000069, + 0x03F, 0x000000F0, + 0x033, 0x0000006A, + 0x03F, 0x000000F3, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000005, + 0x033, 0x00000061, + 0x03F, 0x00000008, + 0x033, 0x00000062, + 0x03F, 0x0000000B, + 0x033, 0x00000063, + 0x03F, 0x0000000E, + 0x033, 0x00000064, + 0x03F, 0x0000002B, + 0x033, 0x00000065, + 0x03F, 0x0000002E, + 0x033, 0x00000066, + 0x03F, 0x0000006B, + 0x033, 0x00000067, + 0x03F, 0x0000006E, + 0x033, 0x00000068, + 0x03F, 0x00000071, + 0x033, 0x00000069, + 0x03F, 0x00000074, + 0x033, 0x0000006A, + 0x03F, 0x00000077, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000429, + 0x033, 0x00000061, + 0x03F, 0x00000828, + 0x033, 0x00000062, + 0x03F, 0x00000847, + 0x033, 0x00000063, + 0x03F, 0x0000084A, + 0x033, 0x00000064, + 0x03F, 0x00000C4B, + 0x033, 0x00000065, + 0x03F, 0x00000C6C, + 0x033, 0x00000066, + 0x03F, 0x00000C8D, + 0x033, 0x00000067, + 0x03F, 0x00000CAF, + 0x033, 0x00000068, + 0x03F, 0x00000CD1, + 0x033, 0x00000069, + 0x03F, 0x00000CF3, + 0x033, 0x0000006A, + 0x03F, 0x00000CF6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000005, + 0x033, 0x00000061, + 0x03F, 0x00000008, + 0x033, 0x00000062, + 0x03F, 0x0000000B, + 0x033, 0x00000063, + 0x03F, 0x0000000E, + 0x033, 0x00000064, + 0x03F, 0x0000002B, + 0x033, 0x00000065, + 0x03F, 0x0000002E, + 0x033, 0x00000066, + 0x03F, 0x0000006B, + 0x033, 0x00000067, + 0x03F, 0x0000006E, + 0x033, 0x00000068, + 0x03F, 0x00000071, + 0x033, 0x00000069, + 0x03F, 0x00000074, + 0x033, 0x0000006A, + 0x03F, 0x00000077, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x0000042A, + 0x033, 0x00000061, + 0x03F, 0x00000829, + 0x033, 0x00000062, + 0x03F, 0x00000848, + 0x033, 0x00000063, + 0x03F, 0x0000084B, + 0x033, 0x00000064, + 0x03F, 0x00000C4B, + 0x033, 0x00000065, + 0x03F, 0x00000C6C, + 0x033, 0x00000066, + 0x03F, 0x00000CAC, + 0x033, 0x00000067, + 0x03F, 0x00000CED, + 0x033, 0x00000068, + 0x03F, 0x00000CF0, + 0x033, 0x00000069, + 0x03F, 0x00000CF3, + 0x033, 0x0000006A, + 0x03F, 0x00000CF6, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000007, + 0x033, 0x00000061, + 0x03F, 0x0000000A, + 0x033, 0x00000062, + 0x03F, 0x0000000D, + 0x033, 0x00000063, + 0x03F, 0x0000002A, + 0x033, 0x00000064, + 0x03F, 0x0000002D, + 0x033, 0x00000065, + 0x03F, 0x00000030, + 0x033, 0x00000066, + 0x03F, 0x0000006D, + 0x033, 0x00000067, + 0x03F, 0x00000070, + 0x033, 0x00000068, + 0x03F, 0x000000ED, + 0x033, 0x00000069, + 0x03F, 0x000000F0, + 0x033, 0x0000006A, + 0x03F, 0x000000F3, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000007, + 0x033, 0x00000061, + 0x03F, 0x0000000A, + 0x033, 0x00000062, + 0x03F, 0x0000000D, + 0x033, 0x00000063, + 0x03F, 0x0000002A, + 0x033, 0x00000064, + 0x03F, 0x0000002D, + 0x033, 0x00000065, + 0x03F, 0x00000030, + 0x033, 0x00000066, + 0x03F, 0x0000006D, + 0x033, 0x00000067, + 0x03F, 0x00000070, + 0x033, 0x00000068, + 0x03F, 0x000000ED, + 0x033, 0x00000069, + 0x03F, 0x000000F0, + 0x033, 0x0000006A, + 0x03F, 0x000000F3, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000842, + 0x033, 0x00000061, + 0x03F, 0x00000845, + 0x033, 0x00000062, + 0x03F, 0x00000866, + 0x033, 0x00000063, + 0x03F, 0x000008A6, + 0x033, 0x00000064, + 0x03F, 0x000008C8, + 0x033, 0x00000065, + 0x03F, 0x00000CE8, + 0x033, 0x00000066, + 0x03F, 0x00000CEB, + 0x033, 0x00000067, + 0x03F, 0x00000CEE, + 0x033, 0x00000068, + 0x03F, 0x00000CF1, + 0x033, 0x00000069, + 0x03F, 0x00000CF4, + 0x033, 0x0000006A, + 0x03F, 0x00000CF7, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000C0A, + 0x033, 0x00000061, + 0x03F, 0x00000C0D, + 0x033, 0x00000062, + 0x03F, 0x00000C2A, + 0x033, 0x00000063, + 0x03F, 0x00000C2D, + 0x033, 0x00000064, + 0x03F, 0x00000C6A, + 0x033, 0x00000065, + 0x03F, 0x00000CAA, + 0x033, 0x00000066, + 0x03F, 0x00000CAD, + 0x033, 0x00000067, + 0x03F, 0x00000CB0, + 0x033, 0x00000068, + 0x03F, 0x00000CF1, + 0x033, 0x00000069, + 0x03F, 0x00000CF4, + 0x033, 0x0000006A, + 0x03F, 0x00000CF7, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000C0A, + 0x033, 0x00000061, + 0x03F, 0x00000C0D, + 0x033, 0x00000062, + 0x03F, 0x00000C2A, + 0x033, 0x00000063, + 0x03F, 0x00000C2D, + 0x033, 0x00000064, + 0x03F, 0x00000C6A, + 0x033, 0x00000065, + 0x03F, 0x00000CAA, + 0x033, 0x00000066, + 0x03F, 0x00000CAD, + 0x033, 0x00000067, + 0x03F, 0x00000CB0, + 0x033, 0x00000068, + 0x03F, 0x00000CF1, + 0x033, 0x00000069, + 0x03F, 0x00000CF4, + 0x033, 0x0000006A, + 0x03F, 0x00000CF7, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000005, + 0x033, 0x00000061, + 0x03F, 0x00000008, + 0x033, 0x00000062, + 0x03F, 0x0000000B, + 0x033, 0x00000063, + 0x03F, 0x0000000E, + 0x033, 0x00000064, + 0x03F, 0x0000002B, + 0x033, 0x00000065, + 0x03F, 0x00000068, + 0x033, 0x00000066, + 0x03F, 0x0000006B, + 0x033, 0x00000067, + 0x03F, 0x0000006E, + 0x033, 0x00000068, + 0x03F, 0x00000071, + 0x033, 0x00000069, + 0x03F, 0x00000074, + 0x033, 0x0000006A, + 0x03F, 0x00000077, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000429, + 0x033, 0x00000061, + 0x03F, 0x00000828, + 0x033, 0x00000062, + 0x03F, 0x00000847, + 0x033, 0x00000063, + 0x03F, 0x0000084A, + 0x033, 0x00000064, + 0x03F, 0x00000C4B, + 0x033, 0x00000065, + 0x03F, 0x00000CE5, + 0x033, 0x00000066, + 0x03F, 0x00000CE8, + 0x033, 0x00000067, + 0x03F, 0x00000CEB, + 0x033, 0x00000068, + 0x03F, 0x00000CEE, + 0x033, 0x00000069, + 0x03F, 0x00000CF1, + 0x033, 0x0000006A, + 0x03F, 0x00000CF4, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000C0A, + 0x033, 0x00000061, + 0x03F, 0x00000C0D, + 0x033, 0x00000062, + 0x03F, 0x00000C10, + 0x033, 0x00000063, + 0x03F, 0x00000C4A, + 0x033, 0x00000064, + 0x03F, 0x00000C4D, + 0x033, 0x00000065, + 0x03F, 0x00000CC9, + 0x033, 0x00000066, + 0x03F, 0x00000CEB, + 0x033, 0x00000067, + 0x03F, 0x00000CEE, + 0x033, 0x00000068, + 0x03F, 0x00000CF1, + 0x033, 0x00000069, + 0x03F, 0x00000CF4, + 0x033, 0x0000006A, + 0x03F, 0x00000CF7, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000C0A, + 0x033, 0x00000061, + 0x03F, 0x00000C0D, + 0x033, 0x00000062, + 0x03F, 0x00000C2A, + 0x033, 0x00000063, + 0x03F, 0x00000C2D, + 0x033, 0x00000064, + 0x03F, 0x00000C6A, + 0x033, 0x00000065, + 0x03F, 0x00000CAA, + 0x033, 0x00000066, + 0x03F, 0x00000CAD, + 0x033, 0x00000067, + 0x03F, 0x00000CB0, + 0x033, 0x00000068, + 0x03F, 0x00000CF1, + 0x033, 0x00000069, + 0x03F, 0x00000CF4, + 0x033, 0x0000006A, + 0x03F, 0x00000CF7, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000429, + 0x033, 0x00000061, + 0x03F, 0x00000828, + 0x033, 0x00000062, + 0x03F, 0x00000847, + 0x033, 0x00000063, + 0x03F, 0x0000084A, + 0x033, 0x00000064, + 0x03F, 0x00000C4B, + 0x033, 0x00000065, + 0x03F, 0x00000C8A, + 0x033, 0x00000066, + 0x03F, 0x00000CEA, + 0x033, 0x00000067, + 0x03F, 0x00000CED, + 0x033, 0x00000068, + 0x03F, 0x00000CF0, + 0x033, 0x00000069, + 0x03F, 0x00000CF3, + 0x033, 0x0000006A, + 0x03F, 0x00000CF6, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000429, + 0x033, 0x00000061, + 0x03F, 0x00000828, + 0x033, 0x00000062, + 0x03F, 0x00000847, + 0x033, 0x00000063, + 0x03F, 0x0000084A, + 0x033, 0x00000064, + 0x03F, 0x00000C4B, + 0x033, 0x00000065, + 0x03F, 0x00000C6C, + 0x033, 0x00000066, + 0x03F, 0x00000C8D, + 0x033, 0x00000067, + 0x03F, 0x00000CAF, + 0x033, 0x00000068, + 0x03F, 0x00000CD1, + 0x033, 0x00000069, + 0x03F, 0x00000CF3, + 0x033, 0x0000006A, + 0x03F, 0x00000CF6, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000429, + 0x033, 0x00000061, + 0x03F, 0x00000828, + 0x033, 0x00000062, + 0x03F, 0x00000847, + 0x033, 0x00000063, + 0x03F, 0x0000084A, + 0x033, 0x00000064, + 0x03F, 0x00000C4B, + 0x033, 0x00000065, + 0x03F, 0x00000C6C, + 0x033, 0x00000066, + 0x03F, 0x00000C8D, + 0x033, 0x00000067, + 0x03F, 0x00000CAF, + 0x033, 0x00000068, + 0x03F, 0x00000CD1, + 0x033, 0x00000069, + 0x03F, 0x00000CF3, + 0x033, 0x0000006A, + 0x03F, 0x00000CF6, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000005, + 0x033, 0x00000061, + 0x03F, 0x00000008, + 0x033, 0x00000062, + 0x03F, 0x0000000B, + 0x033, 0x00000063, + 0x03F, 0x0000000E, + 0x033, 0x00000064, + 0x03F, 0x0000002B, + 0x033, 0x00000065, + 0x03F, 0x0000002E, + 0x033, 0x00000066, + 0x03F, 0x0000006B, + 0x033, 0x00000067, + 0x03F, 0x0000006E, + 0x033, 0x00000068, + 0x03F, 0x00000071, + 0x033, 0x00000069, + 0x03F, 0x00000074, + 0x033, 0x0000006A, + 0x03F, 0x00000077, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000007, + 0x033, 0x00000061, + 0x03F, 0x0000000A, + 0x033, 0x00000062, + 0x03F, 0x0000000D, + 0x033, 0x00000063, + 0x03F, 0x0000002A, + 0x033, 0x00000064, + 0x03F, 0x0000002D, + 0x033, 0x00000065, + 0x03F, 0x00000030, + 0x033, 0x00000066, + 0x03F, 0x0000006D, + 0x033, 0x00000067, + 0x03F, 0x00000070, + 0x033, 0x00000068, + 0x03F, 0x000000ED, + 0x033, 0x00000069, + 0x03F, 0x000000F0, + 0x033, 0x0000006A, + 0x03F, 0x000000F3, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000005, + 0x033, 0x00000061, + 0x03F, 0x00000008, + 0x033, 0x00000062, + 0x03F, 0x0000000B, + 0x033, 0x00000063, + 0x03F, 0x0000000E, + 0x033, 0x00000064, + 0x03F, 0x0000002B, + 0x033, 0x00000065, + 0x03F, 0x00000068, + 0x033, 0x00000066, + 0x03F, 0x0000006B, + 0x033, 0x00000067, + 0x03F, 0x0000006E, + 0x033, 0x00000068, + 0x03F, 0x00000071, + 0x033, 0x00000069, + 0x03F, 0x00000074, + 0x033, 0x0000006A, + 0x03F, 0x00000077, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x0000042C, + 0x033, 0x00000061, + 0x03F, 0x0000082B, + 0x033, 0x00000062, + 0x03F, 0x0000084A, + 0x033, 0x00000063, + 0x03F, 0x0000084D, + 0x033, 0x00000064, + 0x03F, 0x00000C4E, + 0x033, 0x00000065, + 0x03F, 0x00000C8C, + 0x033, 0x00000066, + 0x03F, 0x00000C8F, + 0x033, 0x00000067, + 0x03F, 0x00000CEC, + 0x033, 0x00000068, + 0x03F, 0x00000CEF, + 0x033, 0x00000069, + 0x03F, 0x00000CF2, + 0x033, 0x0000006A, + 0x03F, 0x00000CF5, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000005, + 0x033, 0x00000061, + 0x03F, 0x00000008, + 0x033, 0x00000062, + 0x03F, 0x0000000B, + 0x033, 0x00000063, + 0x03F, 0x0000000E, + 0x033, 0x00000064, + 0x03F, 0x0000002B, + 0x033, 0x00000065, + 0x03F, 0x00000068, + 0x033, 0x00000066, + 0x03F, 0x0000006B, + 0x033, 0x00000067, + 0x03F, 0x0000006E, + 0x033, 0x00000068, + 0x03F, 0x00000071, + 0x033, 0x00000069, + 0x03F, 0x00000074, + 0x033, 0x0000006A, + 0x03F, 0x00000077, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x0000042C, + 0x033, 0x00000061, + 0x03F, 0x0000082B, + 0x033, 0x00000062, + 0x03F, 0x0000084A, + 0x033, 0x00000063, + 0x03F, 0x0000084D, + 0x033, 0x00000064, + 0x03F, 0x00000C4E, + 0x033, 0x00000065, + 0x03F, 0x00000C8C, + 0x033, 0x00000066, + 0x03F, 0x00000C8F, + 0x033, 0x00000067, + 0x03F, 0x00000CEC, + 0x033, 0x00000068, + 0x03F, 0x00000CEF, + 0x033, 0x00000069, + 0x03F, 0x00000CF2, + 0x033, 0x0000006A, + 0x03F, 0x00000CF5, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000007, + 0x033, 0x00000061, + 0x03F, 0x0000000A, + 0x033, 0x00000062, + 0x03F, 0x0000000D, + 0x033, 0x00000063, + 0x03F, 0x0000002A, + 0x033, 0x00000064, + 0x03F, 0x0000002D, + 0x033, 0x00000065, + 0x03F, 0x00000030, + 0x033, 0x00000066, + 0x03F, 0x0000006D, + 0x033, 0x00000067, + 0x03F, 0x00000070, + 0x033, 0x00000068, + 0x03F, 0x000000ED, + 0x033, 0x00000069, + 0x03F, 0x000000F0, + 0x033, 0x0000006A, + 0x03F, 0x000000F3, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000007, + 0x033, 0x00000061, + 0x03F, 0x0000000A, + 0x033, 0x00000062, + 0x03F, 0x0000000D, + 0x033, 0x00000063, + 0x03F, 0x0000002A, + 0x033, 0x00000064, + 0x03F, 0x0000002D, + 0x033, 0x00000065, + 0x03F, 0x00000030, + 0x033, 0x00000066, + 0x03F, 0x0000006D, + 0x033, 0x00000067, + 0x03F, 0x00000070, + 0x033, 0x00000068, + 0x03F, 0x000000ED, + 0x033, 0x00000069, + 0x03F, 0x000000F0, + 0x033, 0x0000006A, + 0x03F, 0x000000F3, + 0xA0000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000C0A, + 0x033, 0x00000061, + 0x03F, 0x00000C0D, + 0x033, 0x00000062, + 0x03F, 0x00000C2A, + 0x033, 0x00000063, + 0x03F, 0x00000C2D, + 0x033, 0x00000064, + 0x03F, 0x00000C6A, + 0x033, 0x00000065, + 0x03F, 0x00000CAA, + 0x033, 0x00000066, + 0x03F, 0x00000CAD, + 0x033, 0x00000067, + 0x03F, 0x00000CB0, + 0x033, 0x00000068, + 0x03F, 0x00000CF1, + 0x033, 0x00000069, + 0x03F, 0x00000CF4, + 0x033, 0x0000006A, + 0x03F, 0x00000CF7, + 0xB0000000, 0x00000000, + 0x83000000, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000C09, + 0x033, 0x000000A1, + 0x03F, 0x00000C0C, + 0x033, 0x000000A2, + 0x03F, 0x00000C0F, + 0x033, 0x000000A3, + 0x03F, 0x00000C2C, + 0x033, 0x000000A4, + 0x03F, 0x00000C2F, + 0x033, 0x000000A5, + 0x03F, 0x00000C8A, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000C90, + 0x033, 0x000000A8, + 0x03F, 0x00000CEF, + 0x033, 0x000000A9, + 0x03F, 0x00000CF2, + 0x033, 0x000000AA, + 0x03F, 0x00000CF5, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000007, + 0x033, 0x000000A1, + 0x03F, 0x0000000A, + 0x033, 0x000000A2, + 0x03F, 0x0000000D, + 0x033, 0x000000A3, + 0x03F, 0x0000002A, + 0x033, 0x000000A4, + 0x03F, 0x0000002D, + 0x033, 0x000000A5, + 0x03F, 0x00000030, + 0x033, 0x000000A6, + 0x03F, 0x0000006D, + 0x033, 0x000000A7, + 0x03F, 0x00000070, + 0x033, 0x000000A8, + 0x03F, 0x000000ED, + 0x033, 0x000000A9, + 0x03F, 0x000000F0, + 0x033, 0x000000AA, + 0x03F, 0x000000F3, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000005, + 0x033, 0x000000A1, + 0x03F, 0x00000008, + 0x033, 0x000000A2, + 0x03F, 0x0000000B, + 0x033, 0x000000A3, + 0x03F, 0x0000000E, + 0x033, 0x000000A4, + 0x03F, 0x0000002B, + 0x033, 0x000000A5, + 0x03F, 0x0000002E, + 0x033, 0x000000A6, + 0x03F, 0x00000031, + 0x033, 0x000000A7, + 0x03F, 0x00000034, + 0x033, 0x000000A8, + 0x03F, 0x00000053, + 0x033, 0x000000A9, + 0x03F, 0x00000056, + 0x033, 0x000000AA, + 0x03F, 0x000000D1, + 0x93000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000429, + 0x033, 0x000000A1, + 0x03F, 0x00000828, + 0x033, 0x000000A2, + 0x03F, 0x00000847, + 0x033, 0x000000A3, + 0x03F, 0x0000084A, + 0x033, 0x000000A4, + 0x03F, 0x00000C4B, + 0x033, 0x000000A5, + 0x03F, 0x00000C6C, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000CAF, + 0x033, 0x000000A8, + 0x03F, 0x00000CD1, + 0x033, 0x000000A9, + 0x03F, 0x00000CF3, + 0x033, 0x000000AA, + 0x03F, 0x00000CF6, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000005, + 0x033, 0x000000A1, + 0x03F, 0x00000008, + 0x033, 0x000000A2, + 0x03F, 0x0000000B, + 0x033, 0x000000A3, + 0x03F, 0x0000000E, + 0x033, 0x000000A4, + 0x03F, 0x0000002B, + 0x033, 0x000000A5, + 0x03F, 0x0000002E, + 0x033, 0x000000A6, + 0x03F, 0x00000031, + 0x033, 0x000000A7, + 0x03F, 0x00000034, + 0x033, 0x000000A8, + 0x03F, 0x00000053, + 0x033, 0x000000A9, + 0x03F, 0x00000056, + 0x033, 0x000000AA, + 0x03F, 0x000000D1, + 0x93000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x0000042A, + 0x033, 0x000000A1, + 0x03F, 0x00000829, + 0x033, 0x000000A2, + 0x03F, 0x00000848, + 0x033, 0x000000A3, + 0x03F, 0x0000084B, + 0x033, 0x000000A4, + 0x03F, 0x00000C4C, + 0x033, 0x000000A5, + 0x03F, 0x00000C6C, + 0x033, 0x000000A6, + 0x03F, 0x00000CAC, + 0x033, 0x000000A7, + 0x03F, 0x00000CED, + 0x033, 0x000000A8, + 0x03F, 0x00000CF0, + 0x033, 0x000000A9, + 0x03F, 0x00000CF3, + 0x033, 0x000000AA, + 0x03F, 0x00000CF6, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000007, + 0x033, 0x000000A1, + 0x03F, 0x0000000A, + 0x033, 0x000000A2, + 0x03F, 0x0000000D, + 0x033, 0x000000A3, + 0x03F, 0x0000002A, + 0x033, 0x000000A4, + 0x03F, 0x0000002D, + 0x033, 0x000000A5, + 0x03F, 0x00000030, + 0x033, 0x000000A6, + 0x03F, 0x0000006D, + 0x033, 0x000000A7, + 0x03F, 0x00000070, + 0x033, 0x000000A8, + 0x03F, 0x000000ED, + 0x033, 0x000000A9, + 0x03F, 0x000000F0, + 0x033, 0x000000AA, + 0x03F, 0x000000F3, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000007, + 0x033, 0x000000A1, + 0x03F, 0x0000000A, + 0x033, 0x000000A2, + 0x03F, 0x0000000D, + 0x033, 0x000000A3, + 0x03F, 0x0000002A, + 0x033, 0x000000A4, + 0x03F, 0x0000002D, + 0x033, 0x000000A5, + 0x03F, 0x00000030, + 0x033, 0x000000A6, + 0x03F, 0x0000006D, + 0x033, 0x000000A7, + 0x03F, 0x00000070, + 0x033, 0x000000A8, + 0x03F, 0x000000ED, + 0x033, 0x000000A9, + 0x03F, 0x000000F0, + 0x033, 0x000000AA, + 0x03F, 0x000000F3, + 0x93000008, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000826, + 0x033, 0x000000A1, + 0x03F, 0x00000829, + 0x033, 0x000000A2, + 0x03F, 0x0000082C, + 0x033, 0x000000A3, + 0x03F, 0x0000082F, + 0x033, 0x000000A4, + 0x03F, 0x0000086C, + 0x033, 0x000000A5, + 0x03F, 0x00000CE8, + 0x033, 0x000000A6, + 0x03F, 0x00000CEB, + 0x033, 0x000000A7, + 0x03F, 0x00000CEE, + 0x033, 0x000000A8, + 0x03F, 0x00000CF1, + 0x033, 0x000000A9, + 0x03F, 0x00000CF4, + 0x033, 0x000000AA, + 0x03F, 0x00000CF7, + 0x93000009, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000C09, + 0x033, 0x000000A1, + 0x03F, 0x00000C0C, + 0x033, 0x000000A2, + 0x03F, 0x00000C0F, + 0x033, 0x000000A3, + 0x03F, 0x00000C2C, + 0x033, 0x000000A4, + 0x03F, 0x00000C2F, + 0x033, 0x000000A5, + 0x03F, 0x00000C8A, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000C90, + 0x033, 0x000000A8, + 0x03F, 0x00000CEF, + 0x033, 0x000000A9, + 0x03F, 0x00000CF2, + 0x033, 0x000000AA, + 0x03F, 0x00000CF5, + 0x9300000a, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000C09, + 0x033, 0x000000A1, + 0x03F, 0x00000C0C, + 0x033, 0x000000A2, + 0x03F, 0x00000C0F, + 0x033, 0x000000A3, + 0x03F, 0x00000C2C, + 0x033, 0x000000A4, + 0x03F, 0x00000C2F, + 0x033, 0x000000A5, + 0x03F, 0x00000C8A, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000C90, + 0x033, 0x000000A8, + 0x03F, 0x00000CEF, + 0x033, 0x000000A9, + 0x03F, 0x00000CF2, + 0x033, 0x000000AA, + 0x03F, 0x00000CF5, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000007, + 0x033, 0x000000A1, + 0x03F, 0x0000000A, + 0x033, 0x000000A2, + 0x03F, 0x0000000D, + 0x033, 0x000000A3, + 0x03F, 0x0000002A, + 0x033, 0x000000A4, + 0x03F, 0x0000002D, + 0x033, 0x000000A5, + 0x03F, 0x00000030, + 0x033, 0x000000A6, + 0x03F, 0x0000006D, + 0x033, 0x000000A7, + 0x03F, 0x00000070, + 0x033, 0x000000A8, + 0x03F, 0x000000ED, + 0x033, 0x000000A9, + 0x03F, 0x000000F0, + 0x033, 0x000000AA, + 0x03F, 0x000000F3, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000429, + 0x033, 0x000000A1, + 0x03F, 0x00000828, + 0x033, 0x000000A2, + 0x03F, 0x00000847, + 0x033, 0x000000A3, + 0x03F, 0x0000084A, + 0x033, 0x000000A4, + 0x03F, 0x00000C4B, + 0x033, 0x000000A5, + 0x03F, 0x00000CE5, + 0x033, 0x000000A6, + 0x03F, 0x00000CE8, + 0x033, 0x000000A7, + 0x03F, 0x00000CEB, + 0x033, 0x000000A8, + 0x03F, 0x00000CEE, + 0x033, 0x000000A9, + 0x03F, 0x00000CF1, + 0x033, 0x000000AA, + 0x03F, 0x00000CF4, + 0x9300000d, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x0000080A, + 0x033, 0x000000A1, + 0x03F, 0x0000080D, + 0x033, 0x000000A2, + 0x03F, 0x00000810, + 0x033, 0x000000A3, + 0x03F, 0x00000868, + 0x033, 0x000000A4, + 0x03F, 0x00000C68, + 0x033, 0x000000A5, + 0x03F, 0x00000C6B, + 0x033, 0x000000A6, + 0x03F, 0x00000CAB, + 0x033, 0x000000A7, + 0x03F, 0x00000CAE, + 0x033, 0x000000A8, + 0x03F, 0x00000CEF, + 0x033, 0x000000A9, + 0x03F, 0x00000CF2, + 0x033, 0x000000AA, + 0x03F, 0x00000CF5, + 0x9300000e, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000C08, + 0x033, 0x000000A1, + 0x03F, 0x00000C0B, + 0x033, 0x000000A2, + 0x03F, 0x00000C0E, + 0x033, 0x000000A3, + 0x03F, 0x00000C2B, + 0x033, 0x000000A4, + 0x03F, 0x00000C2E, + 0x033, 0x000000A5, + 0x03F, 0x00000C31, + 0x033, 0x000000A6, + 0x03F, 0x00000CAB, + 0x033, 0x000000A7, + 0x03F, 0x00000CAE, + 0x033, 0x000000A8, + 0x03F, 0x00000CEF, + 0x033, 0x000000A9, + 0x03F, 0x00000CF2, + 0x033, 0x000000AA, + 0x03F, 0x00000CF5, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000429, + 0x033, 0x000000A1, + 0x03F, 0x00000828, + 0x033, 0x000000A2, + 0x03F, 0x00000847, + 0x033, 0x000000A3, + 0x03F, 0x0000084A, + 0x033, 0x000000A4, + 0x03F, 0x00000C4B, + 0x033, 0x000000A5, + 0x03F, 0x00000C8A, + 0x033, 0x000000A6, + 0x03F, 0x00000CEA, + 0x033, 0x000000A7, + 0x03F, 0x00000CED, + 0x033, 0x000000A8, + 0x03F, 0x00000CF0, + 0x033, 0x000000A9, + 0x03F, 0x00000CF3, + 0x033, 0x000000AA, + 0x03F, 0x00000CF6, + 0x93000010, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000429, + 0x033, 0x000000A1, + 0x03F, 0x00000828, + 0x033, 0x000000A2, + 0x03F, 0x00000847, + 0x033, 0x000000A3, + 0x03F, 0x0000084A, + 0x033, 0x000000A4, + 0x03F, 0x00000C4B, + 0x033, 0x000000A5, + 0x03F, 0x00000C6C, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000CAF, + 0x033, 0x000000A8, + 0x03F, 0x00000CD1, + 0x033, 0x000000A9, + 0x03F, 0x00000CF3, + 0x033, 0x000000AA, + 0x03F, 0x00000CF6, + 0x93000011, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000429, + 0x033, 0x000000A1, + 0x03F, 0x00000828, + 0x033, 0x000000A2, + 0x03F, 0x00000847, + 0x033, 0x000000A3, + 0x03F, 0x0000084A, + 0x033, 0x000000A4, + 0x03F, 0x00000C4B, + 0x033, 0x000000A5, + 0x03F, 0x00000C6C, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000CAF, + 0x033, 0x000000A8, + 0x03F, 0x00000CD1, + 0x033, 0x000000A9, + 0x03F, 0x00000CF3, + 0x033, 0x000000AA, + 0x03F, 0x00000CF6, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000005, + 0x033, 0x000000A1, + 0x03F, 0x00000008, + 0x033, 0x000000A2, + 0x03F, 0x0000000B, + 0x033, 0x000000A3, + 0x03F, 0x0000000E, + 0x033, 0x000000A4, + 0x03F, 0x0000002B, + 0x033, 0x000000A5, + 0x03F, 0x0000002E, + 0x033, 0x000000A6, + 0x03F, 0x00000031, + 0x033, 0x000000A7, + 0x03F, 0x00000034, + 0x033, 0x000000A8, + 0x03F, 0x00000053, + 0x033, 0x000000A9, + 0x03F, 0x00000056, + 0x033, 0x000000AA, + 0x03F, 0x000000D1, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000007, + 0x033, 0x000000A1, + 0x03F, 0x0000000A, + 0x033, 0x000000A2, + 0x03F, 0x0000000D, + 0x033, 0x000000A3, + 0x03F, 0x0000002A, + 0x033, 0x000000A4, + 0x03F, 0x0000002D, + 0x033, 0x000000A5, + 0x03F, 0x00000030, + 0x033, 0x000000A6, + 0x03F, 0x0000006D, + 0x033, 0x000000A7, + 0x03F, 0x00000070, + 0x033, 0x000000A8, + 0x03F, 0x000000ED, + 0x033, 0x000000A9, + 0x03F, 0x000000F0, + 0x033, 0x000000AA, + 0x03F, 0x000000F3, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000005, + 0x033, 0x000000A1, + 0x03F, 0x00000008, + 0x033, 0x000000A2, + 0x03F, 0x0000000B, + 0x033, 0x000000A3, + 0x03F, 0x0000000E, + 0x033, 0x000000A4, + 0x03F, 0x00000047, + 0x033, 0x000000A5, + 0x03F, 0x0000004A, + 0x033, 0x000000A6, + 0x03F, 0x0000004D, + 0x033, 0x000000A7, + 0x03F, 0x00000050, + 0x033, 0x000000A8, + 0x03F, 0x00000053, + 0x033, 0x000000A9, + 0x03F, 0x00000056, + 0x033, 0x000000AA, + 0x03F, 0x00000094, + 0x90000003, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x0000042A, + 0x033, 0x000000A1, + 0x03F, 0x00000829, + 0x033, 0x000000A2, + 0x03F, 0x00000848, + 0x033, 0x000000A3, + 0x03F, 0x0000084B, + 0x033, 0x000000A4, + 0x03F, 0x00000C4C, + 0x033, 0x000000A5, + 0x03F, 0x00000C8A, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000CEC, + 0x033, 0x000000A8, + 0x03F, 0x00000CEF, + 0x033, 0x000000A9, + 0x03F, 0x00000CF2, + 0x033, 0x000000AA, + 0x03F, 0x00000CF5, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000005, + 0x033, 0x000000A1, + 0x03F, 0x00000008, + 0x033, 0x000000A2, + 0x03F, 0x0000000B, + 0x033, 0x000000A3, + 0x03F, 0x0000000E, + 0x033, 0x000000A4, + 0x03F, 0x00000047, + 0x033, 0x000000A5, + 0x03F, 0x0000004A, + 0x033, 0x000000A6, + 0x03F, 0x0000004D, + 0x033, 0x000000A7, + 0x03F, 0x00000050, + 0x033, 0x000000A8, + 0x03F, 0x00000053, + 0x033, 0x000000A9, + 0x03F, 0x00000056, + 0x033, 0x000000AA, + 0x03F, 0x00000094, + 0x90000005, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x0000042A, + 0x033, 0x000000A1, + 0x03F, 0x00000829, + 0x033, 0x000000A2, + 0x03F, 0x00000848, + 0x033, 0x000000A3, + 0x03F, 0x0000084B, + 0x033, 0x000000A4, + 0x03F, 0x00000C4C, + 0x033, 0x000000A5, + 0x03F, 0x00000C8A, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000CEC, + 0x033, 0x000000A8, + 0x03F, 0x00000CEF, + 0x033, 0x000000A9, + 0x03F, 0x00000CF2, + 0x033, 0x000000AA, + 0x03F, 0x00000CF5, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000007, + 0x033, 0x000000A1, + 0x03F, 0x0000000A, + 0x033, 0x000000A2, + 0x03F, 0x0000000D, + 0x033, 0x000000A3, + 0x03F, 0x0000002A, + 0x033, 0x000000A4, + 0x03F, 0x0000002D, + 0x033, 0x000000A5, + 0x03F, 0x00000030, + 0x033, 0x000000A6, + 0x03F, 0x0000006D, + 0x033, 0x000000A7, + 0x03F, 0x00000070, + 0x033, 0x000000A8, + 0x03F, 0x000000ED, + 0x033, 0x000000A9, + 0x03F, 0x000000F0, + 0x033, 0x000000AA, + 0x03F, 0x000000F3, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000007, + 0x033, 0x000000A1, + 0x03F, 0x0000000A, + 0x033, 0x000000A2, + 0x03F, 0x0000000D, + 0x033, 0x000000A3, + 0x03F, 0x0000002A, + 0x033, 0x000000A4, + 0x03F, 0x0000002D, + 0x033, 0x000000A5, + 0x03F, 0x00000030, + 0x033, 0x000000A6, + 0x03F, 0x0000006D, + 0x033, 0x000000A7, + 0x03F, 0x00000070, + 0x033, 0x000000A8, + 0x03F, 0x000000ED, + 0x033, 0x000000A9, + 0x03F, 0x000000F0, + 0x033, 0x000000AA, + 0x03F, 0x000000F3, + 0xA0000000, 0x00000000, + 0x033, 0x000000A0, + 0x03F, 0x00000C09, + 0x033, 0x000000A1, + 0x03F, 0x00000C0C, + 0x033, 0x000000A2, + 0x03F, 0x00000C0F, + 0x033, 0x000000A3, + 0x03F, 0x00000C2C, + 0x033, 0x000000A4, + 0x03F, 0x00000C2F, + 0x033, 0x000000A5, + 0x03F, 0x00000C8A, + 0x033, 0x000000A6, + 0x03F, 0x00000C8D, + 0x033, 0x000000A7, + 0x03F, 0x00000C90, + 0x033, 0x000000A8, + 0x03F, 0x00000CEF, + 0x033, 0x000000A9, + 0x03F, 0x00000CF2, + 0x033, 0x000000AA, + 0x03F, 0x00000CF5, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x0EF, 0x00000400, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000265A, + 0x033, 0x00000001, + 0x03F, 0x0000265A, + 0x033, 0x00000002, + 0x03F, 0x0000265A, + 0x033, 0x00000003, + 0x03F, 0x0000265A, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000265A, + 0x033, 0x00000001, + 0x03F, 0x0000265A, + 0x033, 0x00000002, + 0x03F, 0x0000265A, + 0x033, 0x00000003, + 0x03F, 0x0000265A, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000265A, + 0x033, 0x00000001, + 0x03F, 0x0000265A, + 0x033, 0x00000002, + 0x03F, 0x0000265A, + 0x033, 0x00000003, + 0x03F, 0x0000265A, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000265A, + 0x033, 0x00000001, + 0x03F, 0x0000265A, + 0x033, 0x00000002, + 0x03F, 0x0000265A, + 0x033, 0x00000003, + 0x03F, 0x0000265A, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000265A, + 0x033, 0x00000001, + 0x03F, 0x0000265A, + 0x033, 0x00000002, + 0x03F, 0x0000265A, + 0x033, 0x00000003, + 0x03F, 0x0000265A, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x000004FB, + 0x033, 0x00000001, + 0x03F, 0x000004FB, + 0x033, 0x00000002, + 0x03F, 0x000004FB, + 0x033, 0x00000003, + 0x03F, 0x000004FB, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000265A, + 0x033, 0x00000001, + 0x03F, 0x0000265A, + 0x033, 0x00000002, + 0x03F, 0x0000265A, + 0x033, 0x00000003, + 0x03F, 0x0000265A, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000265A, + 0x033, 0x00000001, + 0x03F, 0x0000265A, + 0x033, 0x00000002, + 0x03F, 0x0000265A, + 0x033, 0x00000003, + 0x03F, 0x0000265A, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000265A, + 0x033, 0x00000001, + 0x03F, 0x0000265A, + 0x033, 0x00000002, + 0x03F, 0x0000265A, + 0x033, 0x00000003, + 0x03F, 0x0000265A, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000265A, + 0x033, 0x00000001, + 0x03F, 0x0000265A, + 0x033, 0x00000002, + 0x03F, 0x0000265A, + 0x033, 0x00000003, + 0x03F, 0x0000265A, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0000265A, + 0x033, 0x00000001, + 0x03F, 0x0000265A, + 0x033, 0x00000002, + 0x03F, 0x0000265A, + 0x033, 0x00000003, + 0x03F, 0x0000265A, + 0xA0000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x000004BB, + 0x033, 0x00000001, + 0x03F, 0x000004BB, + 0x033, 0x00000002, + 0x03F, 0x000004BB, + 0x033, 0x00000003, + 0x03F, 0x000004BB, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x0EF, 0x00000100, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000745, + 0x033, 0x00000001, + 0x03F, 0x00000745, + 0x033, 0x00000002, + 0x03F, 0x00000745, + 0x033, 0x00000003, + 0x03F, 0x00000745, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000745, + 0x033, 0x00000001, + 0x03F, 0x00000745, + 0x033, 0x00000002, + 0x03F, 0x00000745, + 0x033, 0x00000003, + 0x03F, 0x00000745, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000745, + 0x033, 0x00000001, + 0x03F, 0x00000745, + 0x033, 0x00000002, + 0x03F, 0x00000745, + 0x033, 0x00000003, + 0x03F, 0x00000745, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000745, + 0x033, 0x00000001, + 0x03F, 0x00000745, + 0x033, 0x00000002, + 0x03F, 0x00000745, + 0x033, 0x00000003, + 0x03F, 0x00000745, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000745, + 0x033, 0x00000001, + 0x03F, 0x00000745, + 0x033, 0x00000002, + 0x03F, 0x00000745, + 0x033, 0x00000003, + 0x03F, 0x00000745, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000745, + 0x033, 0x00000001, + 0x03F, 0x00000745, + 0x033, 0x00000002, + 0x03F, 0x00000745, + 0x033, 0x00000003, + 0x03F, 0x00000745, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000745, + 0x033, 0x00000001, + 0x03F, 0x00000745, + 0x033, 0x00000002, + 0x03F, 0x00000745, + 0x033, 0x00000003, + 0x03F, 0x00000745, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000745, + 0x033, 0x00000001, + 0x03F, 0x00000745, + 0x033, 0x00000002, + 0x03F, 0x00000745, + 0x033, 0x00000003, + 0x03F, 0x00000745, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000745, + 0x033, 0x00000001, + 0x03F, 0x00000745, + 0x033, 0x00000002, + 0x03F, 0x00000745, + 0x033, 0x00000003, + 0x03F, 0x00000745, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000745, + 0x033, 0x00000001, + 0x03F, 0x00000745, + 0x033, 0x00000002, + 0x03F, 0x00000745, + 0x033, 0x00000003, + 0x03F, 0x00000745, + 0xA0000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000F34, + 0x033, 0x00000001, + 0x03F, 0x00000F34, + 0x033, 0x00000002, + 0x03F, 0x00000F34, + 0x033, 0x00000003, + 0x03F, 0x00000F34, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x081, 0x0000F400, + 0x087, 0x00016040, + 0x051, 0x00000808, + 0x052, 0x00098002, + 0x053, 0x0000FA47, + 0x054, 0x00058032, + 0x056, 0x00051000, + 0x057, 0x0000CE0A, + 0x058, 0x00082030, + 0xA0000000, 0x00000000, + 0x081, 0x0000F000, + 0x087, 0x00016040, + 0x051, 0x00000C00, + 0x052, 0x0007C241, + 0x053, 0x0001C069, + 0x054, 0x00078032, + 0x057, 0x0000CE0A, + 0x058, 0x00058750, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000800, + 0x83000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000003, + 0x033, 0x00000001, + 0x03F, 0x00000006, + 0x033, 0x00000002, + 0x03F, 0x00000009, + 0x033, 0x00000003, + 0x03F, 0x00000026, + 0x033, 0x00000004, + 0x03F, 0x00000029, + 0x033, 0x00000005, + 0x03F, 0x0000002C, + 0x033, 0x00000006, + 0x03F, 0x0000002F, + 0x033, 0x00000007, + 0x03F, 0x00000033, + 0x033, 0x00000008, + 0x03F, 0x00000036, + 0x033, 0x00000009, + 0x03F, 0x00000039, + 0x033, 0x0000000A, + 0x03F, 0x0000003C, + 0x93000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000002, + 0x033, 0x00000001, + 0x03F, 0x00000005, + 0x033, 0x00000002, + 0x03F, 0x00000008, + 0x033, 0x00000003, + 0x03F, 0x0000000B, + 0x033, 0x00000004, + 0x03F, 0x0000000E, + 0x033, 0x00000005, + 0x03F, 0x0000002B, + 0x033, 0x00000006, + 0x03F, 0x0000002E, + 0x033, 0x00000007, + 0x03F, 0x00000031, + 0x033, 0x00000008, + 0x03F, 0x0000006E, + 0x033, 0x00000009, + 0x03F, 0x00000071, + 0x033, 0x0000000A, + 0x03F, 0x00000074, + 0x93000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000003, + 0x033, 0x00000001, + 0x03F, 0x00000006, + 0x033, 0x00000002, + 0x03F, 0x00000009, + 0x033, 0x00000003, + 0x03F, 0x00000026, + 0x033, 0x00000004, + 0x03F, 0x00000029, + 0x033, 0x00000005, + 0x03F, 0x0000002C, + 0x033, 0x00000006, + 0x03F, 0x0000002F, + 0x033, 0x00000007, + 0x03F, 0x00000033, + 0x033, 0x00000008, + 0x03F, 0x00000036, + 0x033, 0x00000009, + 0x03F, 0x00000039, + 0x033, 0x0000000A, + 0x03F, 0x0000003C, + 0x93000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000003, + 0x033, 0x00000001, + 0x03F, 0x00000006, + 0x033, 0x00000002, + 0x03F, 0x00000009, + 0x033, 0x00000003, + 0x03F, 0x00000026, + 0x033, 0x00000004, + 0x03F, 0x00000029, + 0x033, 0x00000005, + 0x03F, 0x0000002C, + 0x033, 0x00000006, + 0x03F, 0x0000002F, + 0x033, 0x00000007, + 0x03F, 0x00000033, + 0x033, 0x00000008, + 0x03F, 0x00000036, + 0x033, 0x00000009, + 0x03F, 0x00000039, + 0x033, 0x0000000A, + 0x03F, 0x0000003C, + 0x9300000b, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000003, + 0x033, 0x00000001, + 0x03F, 0x00000006, + 0x033, 0x00000002, + 0x03F, 0x00000009, + 0x033, 0x00000003, + 0x03F, 0x00000026, + 0x033, 0x00000004, + 0x03F, 0x00000029, + 0x033, 0x00000005, + 0x03F, 0x0000002C, + 0x033, 0x00000006, + 0x03F, 0x0000002F, + 0x033, 0x00000007, + 0x03F, 0x00000033, + 0x033, 0x00000008, + 0x03F, 0x00000036, + 0x033, 0x00000009, + 0x03F, 0x00000039, + 0x033, 0x0000000A, + 0x03F, 0x0000003C, + 0x9300000c, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0005142C, + 0x033, 0x00000001, + 0x03F, 0x0005142F, + 0x033, 0x00000002, + 0x03F, 0x00051432, + 0x033, 0x00000003, + 0x03F, 0x00051CA5, + 0x033, 0x00000004, + 0x03F, 0x00051CA8, + 0x033, 0x00000005, + 0x03F, 0x00051CAB, + 0x033, 0x00000006, + 0x03F, 0x00051CEB, + 0x033, 0x00000007, + 0x03F, 0x00051CEE, + 0x033, 0x00000008, + 0x03F, 0x00051CF1, + 0x033, 0x00000009, + 0x03F, 0x00051CF4, + 0x033, 0x0000000A, + 0x03F, 0x00051CF7, + 0x9300000f, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0005142C, + 0x033, 0x00000001, + 0x03F, 0x0005144B, + 0x033, 0x00000002, + 0x03F, 0x00051868, + 0x033, 0x00000003, + 0x03F, 0x0005186B, + 0x033, 0x00000004, + 0x03F, 0x0005186E, + 0x033, 0x00000005, + 0x03F, 0x00051871, + 0x033, 0x00000006, + 0x03F, 0x00051874, + 0x033, 0x00000007, + 0x03F, 0x00051895, + 0x033, 0x00000008, + 0x03F, 0x000518B6, + 0x033, 0x00000009, + 0x03F, 0x000518F6, + 0x033, 0x0000000A, + 0x03F, 0x00051CF7, + 0x93000012, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000002, + 0x033, 0x00000001, + 0x03F, 0x00000005, + 0x033, 0x00000002, + 0x03F, 0x00000008, + 0x033, 0x00000003, + 0x03F, 0x0000000B, + 0x033, 0x00000004, + 0x03F, 0x0000000E, + 0x033, 0x00000005, + 0x03F, 0x0000002B, + 0x033, 0x00000006, + 0x03F, 0x0000002E, + 0x033, 0x00000007, + 0x03F, 0x00000031, + 0x033, 0x00000008, + 0x03F, 0x0000006E, + 0x033, 0x00000009, + 0x03F, 0x00000071, + 0x033, 0x0000000A, + 0x03F, 0x00000074, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000003, + 0x033, 0x00000001, + 0x03F, 0x00000006, + 0x033, 0x00000002, + 0x03F, 0x00000009, + 0x033, 0x00000003, + 0x03F, 0x00000026, + 0x033, 0x00000004, + 0x03F, 0x00000029, + 0x033, 0x00000005, + 0x03F, 0x0000002C, + 0x033, 0x00000006, + 0x03F, 0x0000002F, + 0x033, 0x00000007, + 0x03F, 0x00000033, + 0x033, 0x00000008, + 0x03F, 0x00000036, + 0x033, 0x00000009, + 0x03F, 0x00000039, + 0x033, 0x0000000A, + 0x03F, 0x0000003C, + 0x90000004, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000003, + 0x033, 0x00000001, + 0x03F, 0x00000006, + 0x033, 0x00000002, + 0x03F, 0x00000009, + 0x033, 0x00000003, + 0x03F, 0x00000026, + 0x033, 0x00000004, + 0x03F, 0x00000029, + 0x033, 0x00000005, + 0x03F, 0x0000002C, + 0x033, 0x00000006, + 0x03F, 0x0000002F, + 0x033, 0x00000007, + 0x03F, 0x00000033, + 0x033, 0x00000008, + 0x03F, 0x00000036, + 0x033, 0x00000009, + 0x03F, 0x00000039, + 0x033, 0x0000000A, + 0x03F, 0x0000003C, + 0x90000006, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000003, + 0x033, 0x00000001, + 0x03F, 0x00000006, + 0x033, 0x00000002, + 0x03F, 0x00000009, + 0x033, 0x00000003, + 0x03F, 0x00000026, + 0x033, 0x00000004, + 0x03F, 0x00000029, + 0x033, 0x00000005, + 0x03F, 0x0000002C, + 0x033, 0x00000006, + 0x03F, 0x0000002F, + 0x033, 0x00000007, + 0x03F, 0x00000033, + 0x033, 0x00000008, + 0x03F, 0x00000036, + 0x033, 0x00000009, + 0x03F, 0x00000039, + 0x033, 0x0000000A, + 0x03F, 0x0000003C, + 0x90000007, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x00000003, + 0x033, 0x00000001, + 0x03F, 0x00000006, + 0x033, 0x00000002, + 0x03F, 0x00000009, + 0x033, 0x00000003, + 0x03F, 0x00000026, + 0x033, 0x00000004, + 0x03F, 0x00000029, + 0x033, 0x00000005, + 0x03F, 0x0000002C, + 0x033, 0x00000006, + 0x03F, 0x0000002F, + 0x033, 0x00000007, + 0x03F, 0x00000033, + 0x033, 0x00000008, + 0x03F, 0x00000036, + 0x033, 0x00000009, + 0x03F, 0x00000039, + 0x033, 0x0000000A, + 0x03F, 0x0000003C, + 0xA0000000, 0x00000000, + 0x033, 0x00000000, + 0x03F, 0x0005142C, + 0x033, 0x00000001, + 0x03F, 0x0005142F, + 0x033, 0x00000002, + 0x03F, 0x00051432, + 0x033, 0x00000003, + 0x03F, 0x00051C87, + 0x033, 0x00000004, + 0x03F, 0x00051C8A, + 0x033, 0x00000005, + 0x03F, 0x00051C8D, + 0x033, 0x00000006, + 0x03F, 0x00051CEB, + 0x033, 0x00000007, + 0x03F, 0x00051CEE, + 0x033, 0x00000008, + 0x03F, 0x00051CF1, + 0x033, 0x00000009, + 0x03F, 0x00051CF4, + 0x033, 0x0000000A, + 0x03F, 0x00051CF7, + 0xB0000000, 0x00000000, + 0x8300000c, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000000, + 0xA0000000, 0x00000000, + 0x0EF, 0x00000000, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000010, + 0x033, 0x00000000, + 0x008, 0x0009C060, + 0x033, 0x00000001, + 0x008, 0x0009C060, + 0x0EF, 0x00000000, + 0x033, 0x000000A2, + 0x0EF, 0x00080000, + 0x03E, 0x0000593F, + 0x8300000c, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000D0F4F, + 0xA0000000, 0x00000000, + 0x03F, 0x000C0F4F, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x033, 0x000000A3, + 0x0EF, 0x00080000, + 0x03E, 0x00005934, + 0x03F, 0x0005AFCF, + 0x0EF, 0x00000000, +}; + +RTW_DECL_TABLE_RF_RADIO(rtw8822b_rf_b, B); + +static const u8 rtw8822b_txpwr_lmt_type2[] = { + 0, 0, 0, 0, 1, 32, 2, 0, 0, 0, 1, 28, 1, 0, 0, 0, 1, 30, + 0, 0, 0, 0, 2, 32, 2, 0, 0, 0, 2, 28, 1, 0, 0, 0, 2, 30, + 0, 0, 0, 0, 3, 32, 2, 0, 0, 0, 3, 28, 1, 0, 0, 0, 3, 30, + 0, 0, 0, 0, 4, 32, 2, 0, 0, 0, 4, 28, 1, 0, 0, 0, 4, 30, + 0, 0, 0, 0, 5, 32, 2, 0, 0, 0, 5, 28, 1, 0, 0, 0, 5, 30, + 0, 0, 0, 0, 6, 32, 2, 0, 0, 0, 6, 28, 1, 0, 0, 0, 6, 30, + 0, 0, 0, 0, 7, 32, 2, 0, 0, 0, 7, 28, 1, 0, 0, 0, 7, 30, + 0, 0, 0, 0, 8, 32, 2, 0, 0, 0, 8, 28, 1, 0, 0, 0, 8, 30, + 0, 0, 0, 0, 9, 32, 2, 0, 0, 0, 9, 28, 1, 0, 0, 0, 9, 30, + 0, 0, 0, 0, 10, 32, 2, 0, 0, 0, 10, 28, 1, 0, 0, 0, 10, 30, + 0, 0, 0, 0, 11, 32, 2, 0, 0, 0, 11, 28, 1, 0, 0, 0, 11, 30, + 0, 0, 0, 0, 12, 26, 2, 0, 0, 0, 12, 28, 1, 0, 0, 0, 12, 30, + 0, 0, 0, 0, 13, 20, 2, 0, 0, 0, 13, 28, 1, 0, 0, 0, 13, 28, + 0, 0, 0, 0, 14, 63, 2, 0, 0, 0, 14, 63, 1, 0, 0, 0, 14, 32, + 0, 0, 0, 1, 1, 26, 2, 0, 0, 1, 1, 30, 1, 0, 0, 1, 1, 34, + 0, 0, 0, 1, 2, 30, 2, 0, 0, 1, 2, 30, 1, 0, 0, 1, 2, 34, + 0, 0, 0, 1, 3, 32, 2, 0, 0, 1, 3, 30, 1, 0, 0, 1, 3, 34, + 0, 0, 0, 1, 4, 34, 2, 0, 0, 1, 4, 30, 1, 0, 0, 1, 4, 34, + 0, 0, 0, 1, 5, 34, 2, 0, 0, 1, 5, 30, 1, 0, 0, 1, 5, 34, + 0, 0, 0, 1, 6, 34, 2, 0, 0, 1, 6, 30, 1, 0, 0, 1, 6, 34, + 0, 0, 0, 1, 7, 34, 2, 0, 0, 1, 7, 30, 1, 0, 0, 1, 7, 34, + 0, 0, 0, 1, 8, 34, 2, 0, 0, 1, 8, 30, 1, 0, 0, 1, 8, 34, + 0, 0, 0, 1, 9, 32, 2, 0, 0, 1, 9, 30, 1, 0, 0, 1, 9, 34, + 0, 0, 0, 1, 10, 30, 2, 0, 0, 1, 10, 30, 1, 0, 0, 1, 10, 34, + 0, 0, 0, 1, 11, 28, 2, 0, 0, 1, 11, 30, 1, 0, 0, 1, 11, 34, + 0, 0, 0, 1, 12, 22, 2, 0, 0, 1, 12, 30, 1, 0, 0, 1, 12, 34, + 0, 0, 0, 1, 13, 14, 2, 0, 0, 1, 13, 30, 1, 0, 0, 1, 13, 34, + 0, 0, 0, 1, 14, 63, 2, 0, 0, 1, 14, 63, 1, 0, 0, 1, 14, 63, + 0, 0, 0, 2, 1, 26, 2, 0, 0, 2, 1, 30, 1, 0, 0, 2, 1, 34, + 0, 0, 0, 2, 2, 30, 2, 0, 0, 2, 2, 30, 1, 0, 0, 2, 2, 34, + 0, 0, 0, 2, 3, 32, 2, 0, 0, 2, 3, 30, 1, 0, 0, 2, 3, 34, + 0, 0, 0, 2, 4, 34, 2, 0, 0, 2, 4, 30, 1, 0, 0, 2, 4, 34, + 0, 0, 0, 2, 5, 34, 2, 0, 0, 2, 5, 30, 1, 0, 0, 2, 5, 34, + 0, 0, 0, 2, 6, 34, 2, 0, 0, 2, 6, 30, 1, 0, 0, 2, 6, 34, + 0, 0, 0, 2, 7, 34, 2, 0, 0, 2, 7, 30, 1, 0, 0, 2, 7, 34, + 0, 0, 0, 2, 8, 34, 2, 0, 0, 2, 8, 30, 1, 0, 0, 2, 8, 34, + 0, 0, 0, 2, 9, 32, 2, 0, 0, 2, 9, 30, 1, 0, 0, 2, 9, 34, + 0, 0, 0, 2, 10, 30, 2, 0, 0, 2, 10, 30, 1, 0, 0, 2, 10, 34, + 0, 0, 0, 2, 11, 26, 2, 0, 0, 2, 11, 30, 1, 0, 0, 2, 11, 34, + 0, 0, 0, 2, 12, 20, 2, 0, 0, 2, 12, 30, 1, 0, 0, 2, 12, 34, + 0, 0, 0, 2, 13, 14, 2, 0, 0, 2, 13, 30, 1, 0, 0, 2, 13, 34, + 0, 0, 0, 2, 14, 63, 2, 0, 0, 2, 14, 63, 1, 0, 0, 2, 14, 63, + 0, 0, 0, 3, 1, 26, 2, 0, 0, 3, 1, 18, 1, 0, 0, 3, 1, 30, + 0, 0, 0, 3, 2, 28, 2, 0, 0, 3, 2, 18, 1, 0, 0, 3, 2, 30, + 0, 0, 0, 3, 3, 30, 2, 0, 0, 3, 3, 18, 1, 0, 0, 3, 3, 30, + 0, 0, 0, 3, 4, 30, 2, 0, 0, 3, 4, 18, 1, 0, 0, 3, 4, 30, + 0, 0, 0, 3, 5, 32, 2, 0, 0, 3, 5, 18, 1, 0, 0, 3, 5, 30, + 0, 0, 0, 3, 6, 32, 2, 0, 0, 3, 6, 18, 1, 0, 0, 3, 6, 30, + 0, 0, 0, 3, 7, 32, 2, 0, 0, 3, 7, 18, 1, 0, 0, 3, 7, 30, + 0, 0, 0, 3, 8, 30, 2, 0, 0, 3, 8, 18, 1, 0, 0, 3, 8, 30, + 0, 0, 0, 3, 9, 30, 2, 0, 0, 3, 9, 18, 1, 0, 0, 3, 9, 30, + 0, 0, 0, 3, 10, 28, 2, 0, 0, 3, 10, 18, 1, 0, 0, 3, 10, 30, + 0, 0, 0, 3, 11, 26, 2, 0, 0, 3, 11, 18, 1, 0, 0, 3, 11, 30, + 0, 0, 0, 3, 12, 20, 2, 0, 0, 3, 12, 18, 1, 0, 0, 3, 12, 30, + 0, 0, 0, 3, 13, 14, 2, 0, 0, 3, 13, 18, 1, 0, 0, 3, 13, 30, + 0, 0, 0, 3, 14, 63, 2, 0, 0, 3, 14, 63, 1, 0, 0, 3, 14, 63, + 0, 0, 1, 2, 1, 63, 2, 0, 1, 2, 1, 63, 1, 0, 1, 2, 1, 63, + 0, 0, 1, 2, 2, 63, 2, 0, 1, 2, 2, 63, 1, 0, 1, 2, 2, 63, + 0, 0, 1, 2, 3, 26, 2, 0, 1, 2, 3, 30, 1, 0, 1, 2, 3, 34, + 0, 0, 1, 2, 4, 26, 2, 0, 1, 2, 4, 30, 1, 0, 1, 2, 4, 34, + 0, 0, 1, 2, 5, 30, 2, 0, 1, 2, 5, 30, 1, 0, 1, 2, 5, 34, + 0, 0, 1, 2, 6, 32, 2, 0, 1, 2, 6, 30, 1, 0, 1, 2, 6, 34, + 0, 0, 1, 2, 7, 30, 2, 0, 1, 2, 7, 30, 1, 0, 1, 2, 7, 34, + 0, 0, 1, 2, 8, 26, 2, 0, 1, 2, 8, 30, 1, 0, 1, 2, 8, 34, + 0, 0, 1, 2, 9, 26, 2, 0, 1, 2, 9, 30, 1, 0, 1, 2, 9, 34, + 0, 0, 1, 2, 10, 20, 2, 0, 1, 2, 10, 30, 1, 0, 1, 2, 10, 34, + 0, 0, 1, 2, 11, 14, 2, 0, 1, 2, 11, 30, 1, 0, 1, 2, 11, 34, + 0, 0, 1, 2, 12, 63, 2, 0, 1, 2, 12, 63, 1, 0, 1, 2, 12, 63, + 0, 0, 1, 2, 13, 63, 2, 0, 1, 2, 13, 63, 1, 0, 1, 2, 13, 63, + 0, 0, 1, 2, 14, 63, 2, 0, 1, 2, 14, 63, 1, 0, 1, 2, 14, 63, + 0, 0, 1, 3, 1, 63, 2, 0, 1, 3, 1, 63, 1, 0, 1, 3, 1, 63, + 0, 0, 1, 3, 2, 63, 2, 0, 1, 3, 2, 63, 1, 0, 1, 3, 2, 63, + 0, 0, 1, 3, 3, 24, 2, 0, 1, 3, 3, 18, 1, 0, 1, 3, 3, 30, + 0, 0, 1, 3, 4, 24, 2, 0, 1, 3, 4, 18, 1, 0, 1, 3, 4, 30, + 0, 0, 1, 3, 5, 26, 2, 0, 1, 3, 5, 18, 1, 0, 1, 3, 5, 30, + 0, 0, 1, 3, 6, 28, 2, 0, 1, 3, 6, 18, 1, 0, 1, 3, 6, 30, + 0, 0, 1, 3, 7, 26, 2, 0, 1, 3, 7, 18, 1, 0, 1, 3, 7, 30, + 0, 0, 1, 3, 8, 26, 2, 0, 1, 3, 8, 18, 1, 0, 1, 3, 8, 30, + 0, 0, 1, 3, 9, 26, 2, 0, 1, 3, 9, 18, 1, 0, 1, 3, 9, 30, + 0, 0, 1, 3, 10, 20, 2, 0, 1, 3, 10, 18, 1, 0, 1, 3, 10, 30, + 0, 0, 1, 3, 11, 14, 2, 0, 1, 3, 11, 18, 1, 0, 1, 3, 11, 30, + 0, 0, 1, 3, 12, 63, 2, 0, 1, 3, 12, 63, 1, 0, 1, 3, 12, 63, + 0, 0, 1, 3, 13, 63, 2, 0, 1, 3, 13, 63, 1, 0, 1, 3, 13, 63, + 0, 0, 1, 3, 14, 63, 2, 0, 1, 3, 14, 63, 1, 0, 1, 3, 14, 63, + 0, 1, 0, 1, 36, 36, 2, 1, 0, 1, 36, 32, 1, 1, 0, 1, 36, 30, + 0, 1, 0, 1, 40, 38, 2, 1, 0, 1, 40, 32, 1, 1, 0, 1, 40, 30, + 0, 1, 0, 1, 44, 38, 2, 1, 0, 1, 44, 32, 1, 1, 0, 1, 44, 30, + 0, 1, 0, 1, 48, 38, 2, 1, 0, 1, 48, 32, 1, 1, 0, 1, 48, 30, + 0, 1, 0, 1, 52, 38, 2, 1, 0, 1, 52, 32, 1, 1, 0, 1, 52, 28, + 0, 1, 0, 1, 56, 38, 2, 1, 0, 1, 56, 32, 1, 1, 0, 1, 56, 28, + 0, 1, 0, 1, 60, 38, 2, 1, 0, 1, 60, 32, 1, 1, 0, 1, 60, 28, + 0, 1, 0, 1, 64, 34, 2, 1, 0, 1, 64, 32, 1, 1, 0, 1, 64, 28, + 0, 1, 0, 1, 100, 32, 2, 1, 0, 1, 100, 32, 1, 1, 0, 1, 100, 32, + 0, 1, 0, 1, 104, 38, 2, 1, 0, 1, 104, 32, 1, 1, 0, 1, 104, 32, + 0, 1, 0, 1, 108, 38, 2, 1, 0, 1, 108, 32, 1, 1, 0, 1, 108, 32, + 0, 1, 0, 1, 112, 38, 2, 1, 0, 1, 112, 32, 1, 1, 0, 1, 112, 32, + 0, 1, 0, 1, 116, 38, 2, 1, 0, 1, 116, 32, 1, 1, 0, 1, 116, 32, + 0, 1, 0, 1, 120, 38, 2, 1, 0, 1, 120, 32, 1, 1, 0, 1, 120, 32, + 0, 1, 0, 1, 124, 38, 2, 1, 0, 1, 124, 32, 1, 1, 0, 1, 124, 32, + 0, 1, 0, 1, 128, 38, 2, 1, 0, 1, 128, 32, 1, 1, 0, 1, 128, 32, + 0, 1, 0, 1, 132, 38, 2, 1, 0, 1, 132, 32, 1, 1, 0, 1, 132, 32, + 0, 1, 0, 1, 136, 38, 2, 1, 0, 1, 136, 32, 1, 1, 0, 1, 136, 32, + 0, 1, 0, 1, 140, 34, 2, 1, 0, 1, 140, 32, 1, 1, 0, 1, 140, 32, + 0, 1, 0, 1, 144, 34, 2, 1, 0, 1, 144, 32, 1, 1, 0, 1, 144, 63, + 0, 1, 0, 1, 149, 38, 2, 1, 0, 1, 149, 63, 1, 1, 0, 1, 149, 63, + 0, 1, 0, 1, 153, 38, 2, 1, 0, 1, 153, 63, 1, 1, 0, 1, 153, 63, + 0, 1, 0, 1, 157, 38, 2, 1, 0, 1, 157, 63, 1, 1, 0, 1, 157, 63, + 0, 1, 0, 1, 161, 38, 2, 1, 0, 1, 161, 63, 1, 1, 0, 1, 161, 63, + 0, 1, 0, 1, 165, 38, 2, 1, 0, 1, 165, 63, 1, 1, 0, 1, 165, 63, + 0, 1, 0, 2, 36, 36, 2, 1, 0, 2, 36, 32, 1, 1, 0, 2, 36, 28, + 0, 1, 0, 2, 40, 38, 2, 1, 0, 2, 40, 32, 1, 1, 0, 2, 40, 28, + 0, 1, 0, 2, 44, 38, 2, 1, 0, 2, 44, 32, 1, 1, 0, 2, 44, 28, + 0, 1, 0, 2, 48, 38, 2, 1, 0, 2, 48, 32, 1, 1, 0, 2, 48, 28, + 0, 1, 0, 2, 52, 38, 2, 1, 0, 2, 52, 32, 1, 1, 0, 2, 52, 28, + 0, 1, 0, 2, 56, 38, 2, 1, 0, 2, 56, 32, 1, 1, 0, 2, 56, 28, + 0, 1, 0, 2, 60, 38, 2, 1, 0, 2, 60, 32, 1, 1, 0, 2, 60, 28, + 0, 1, 0, 2, 64, 34, 2, 1, 0, 2, 64, 32, 1, 1, 0, 2, 64, 28, + 0, 1, 0, 2, 100, 32, 2, 1, 0, 2, 100, 32, 1, 1, 0, 2, 100, 32, + 0, 1, 0, 2, 104, 38, 2, 1, 0, 2, 104, 32, 1, 1, 0, 2, 104, 32, + 0, 1, 0, 2, 108, 38, 2, 1, 0, 2, 108, 32, 1, 1, 0, 2, 108, 32, + 0, 1, 0, 2, 112, 38, 2, 1, 0, 2, 112, 32, 1, 1, 0, 2, 112, 32, + 0, 1, 0, 2, 116, 38, 2, 1, 0, 2, 116, 32, 1, 1, 0, 2, 116, 32, + 0, 1, 0, 2, 120, 38, 2, 1, 0, 2, 120, 32, 1, 1, 0, 2, 120, 32, + 0, 1, 0, 2, 124, 38, 2, 1, 0, 2, 124, 32, 1, 1, 0, 2, 124, 32, + 0, 1, 0, 2, 128, 38, 2, 1, 0, 2, 128, 32, 1, 1, 0, 2, 128, 32, + 0, 1, 0, 2, 132, 38, 2, 1, 0, 2, 132, 32, 1, 1, 0, 2, 132, 32, + 0, 1, 0, 2, 136, 38, 2, 1, 0, 2, 136, 32, 1, 1, 0, 2, 136, 32, + 0, 1, 0, 2, 140, 32, 2, 1, 0, 2, 140, 32, 1, 1, 0, 2, 140, 32, + 0, 1, 0, 2, 144, 26, 2, 1, 0, 2, 144, 63, 1, 1, 0, 2, 144, 63, + 0, 1, 0, 2, 149, 38, 2, 1, 0, 2, 149, 63, 1, 1, 0, 2, 149, 63, + 0, 1, 0, 2, 153, 38, 2, 1, 0, 2, 153, 63, 1, 1, 0, 2, 153, 63, + 0, 1, 0, 2, 157, 38, 2, 1, 0, 2, 157, 63, 1, 1, 0, 2, 157, 63, + 0, 1, 0, 2, 161, 38, 2, 1, 0, 2, 161, 63, 1, 1, 0, 2, 161, 63, + 0, 1, 0, 2, 165, 38, 2, 1, 0, 2, 165, 63, 1, 1, 0, 2, 165, 63, + 0, 1, 0, 3, 36, 34, 2, 1, 0, 3, 36, 20, 1, 1, 0, 3, 36, 22, + 0, 1, 0, 3, 40, 36, 2, 1, 0, 3, 40, 20, 1, 1, 0, 3, 40, 22, + 0, 1, 0, 3, 44, 36, 2, 1, 0, 3, 44, 20, 1, 1, 0, 3, 44, 22, + 0, 1, 0, 3, 48, 36, 2, 1, 0, 3, 48, 20, 1, 1, 0, 3, 48, 22, + 0, 1, 0, 3, 52, 36, 2, 1, 0, 3, 52, 20, 1, 1, 0, 3, 52, 22, + 0, 1, 0, 3, 56, 36, 2, 1, 0, 3, 56, 20, 1, 1, 0, 3, 56, 22, + 0, 1, 0, 3, 60, 36, 2, 1, 0, 3, 60, 20, 1, 1, 0, 3, 60, 22, + 0, 1, 0, 3, 64, 34, 2, 1, 0, 3, 64, 20, 1, 1, 0, 3, 64, 22, + 0, 1, 0, 3, 100, 32, 2, 1, 0, 3, 100, 20, 1, 1, 0, 3, 100, 30, + 0, 1, 0, 3, 104, 36, 2, 1, 0, 3, 104, 20, 1, 1, 0, 3, 104, 30, + 0, 1, 0, 3, 108, 38, 2, 1, 0, 3, 108, 20, 1, 1, 0, 3, 108, 30, + 0, 1, 0, 3, 112, 38, 2, 1, 0, 3, 112, 20, 1, 1, 0, 3, 112, 30, + 0, 1, 0, 3, 116, 38, 2, 1, 0, 3, 116, 20, 1, 1, 0, 3, 116, 30, + 0, 1, 0, 3, 120, 38, 2, 1, 0, 3, 120, 20, 1, 1, 0, 3, 120, 30, + 0, 1, 0, 3, 124, 38, 2, 1, 0, 3, 124, 20, 1, 1, 0, 3, 124, 30, + 0, 1, 0, 3, 128, 38, 2, 1, 0, 3, 128, 20, 1, 1, 0, 3, 128, 30, + 0, 1, 0, 3, 132, 38, 2, 1, 0, 3, 132, 20, 1, 1, 0, 3, 132, 30, + 0, 1, 0, 3, 136, 36, 2, 1, 0, 3, 136, 20, 1, 1, 0, 3, 136, 30, + 0, 1, 0, 3, 140, 32, 2, 1, 0, 3, 140, 20, 1, 1, 0, 3, 140, 30, + 0, 1, 0, 3, 144, 26, 2, 1, 0, 3, 144, 63, 1, 1, 0, 3, 144, 63, + 0, 1, 0, 3, 149, 38, 2, 1, 0, 3, 149, 63, 1, 1, 0, 3, 149, 63, + 0, 1, 0, 3, 153, 38, 2, 1, 0, 3, 153, 63, 1, 1, 0, 3, 153, 63, + 0, 1, 0, 3, 157, 38, 2, 1, 0, 3, 157, 63, 1, 1, 0, 3, 157, 63, + 0, 1, 0, 3, 161, 38, 2, 1, 0, 3, 161, 63, 1, 1, 0, 3, 161, 63, + 0, 1, 0, 3, 165, 38, 2, 1, 0, 3, 165, 63, 1, 1, 0, 3, 165, 63, + 0, 1, 1, 2, 38, 28, 2, 1, 1, 2, 38, 30, 1, 1, 1, 2, 38, 30, + 0, 1, 1, 2, 46, 36, 2, 1, 1, 2, 46, 30, 1, 1, 1, 2, 46, 30, + 0, 1, 1, 2, 54, 36, 2, 1, 1, 2, 54, 30, 1, 1, 1, 2, 54, 30, + 0, 1, 1, 2, 62, 30, 2, 1, 1, 2, 62, 30, 1, 1, 1, 2, 62, 30, + 0, 1, 1, 2, 102, 30, 2, 1, 1, 2, 102, 30, 1, 1, 1, 2, 102, 30, + 0, 1, 1, 2, 110, 36, 2, 1, 1, 2, 110, 30, 1, 1, 1, 2, 110, 30, + 0, 1, 1, 2, 118, 36, 2, 1, 1, 2, 118, 30, 1, 1, 1, 2, 118, 30, + 0, 1, 1, 2, 126, 36, 2, 1, 1, 2, 126, 30, 1, 1, 1, 2, 126, 30, + 0, 1, 1, 2, 134, 36, 2, 1, 1, 2, 134, 30, 1, 1, 1, 2, 134, 30, + 0, 1, 1, 2, 142, 30, 2, 1, 1, 2, 142, 63, 1, 1, 1, 2, 142, 63, + 0, 1, 1, 2, 151, 36, 2, 1, 1, 2, 151, 63, 1, 1, 1, 2, 151, 63, + 0, 1, 1, 2, 159, 36, 2, 1, 1, 2, 159, 63, 1, 1, 1, 2, 159, 63, + 0, 1, 1, 3, 38, 26, 2, 1, 1, 3, 38, 20, 1, 1, 1, 3, 38, 22, + 0, 1, 1, 3, 46, 36, 2, 1, 1, 3, 46, 20, 1, 1, 1, 3, 46, 22, + 0, 1, 1, 3, 54, 36, 2, 1, 1, 3, 54, 20, 1, 1, 1, 3, 54, 22, + 0, 1, 1, 3, 62, 28, 2, 1, 1, 3, 62, 20, 1, 1, 1, 3, 62, 22, + 0, 1, 1, 3, 102, 28, 2, 1, 1, 3, 102, 20, 1, 1, 1, 3, 102, 30, + 0, 1, 1, 3, 110, 36, 2, 1, 1, 3, 110, 20, 1, 1, 1, 3, 110, 30, + 0, 1, 1, 3, 118, 36, 2, 1, 1, 3, 118, 20, 1, 1, 1, 3, 118, 30, + 0, 1, 1, 3, 126, 36, 2, 1, 1, 3, 126, 20, 1, 1, 1, 3, 126, 30, + 0, 1, 1, 3, 134, 36, 2, 1, 1, 3, 134, 20, 1, 1, 1, 3, 134, 30, + 0, 1, 1, 3, 142, 30, 2, 1, 1, 3, 142, 63, 1, 1, 1, 3, 142, 63, + 0, 1, 1, 3, 151, 36, 2, 1, 1, 3, 151, 63, 1, 1, 1, 3, 151, 63, + 0, 1, 1, 3, 159, 36, 2, 1, 1, 3, 159, 63, 1, 1, 1, 3, 159, 63, + 0, 1, 2, 4, 42, 26, 2, 1, 2, 4, 42, 30, 1, 1, 2, 4, 42, 28, + 0, 1, 2, 4, 58, 26, 2, 1, 2, 4, 58, 30, 1, 1, 2, 4, 58, 28, + 0, 1, 2, 4, 106, 26, 2, 1, 2, 4, 106, 30, 1, 1, 2, 4, 106, 30, + 0, 1, 2, 4, 122, 36, 2, 1, 2, 4, 122, 30, 1, 1, 2, 4, 122, 30, + 0, 1, 2, 4, 138, 36, 2, 1, 2, 4, 138, 63, 1, 1, 2, 4, 138, 63, + 0, 1, 2, 4, 155, 36, 2, 1, 2, 4, 155, 63, 1, 1, 2, 4, 155, 63, + 0, 1, 2, 5, 42, 24, 2, 1, 2, 5, 42, 20, 1, 1, 2, 5, 42, 22, + 0, 1, 2, 5, 58, 24, 2, 1, 2, 5, 58, 20, 1, 1, 2, 5, 58, 22, + 0, 1, 2, 5, 106, 26, 2, 1, 2, 5, 106, 20, 1, 1, 2, 5, 106, 30, + 0, 1, 2, 5, 122, 36, 2, 1, 2, 5, 122, 20, 1, 1, 2, 5, 122, 30, + 0, 1, 2, 5, 138, 36, 2, 1, 2, 5, 138, 63, 1, 1, 2, 5, 138, 63, + 0, 1, 2, 5, 155, 36, 2, 1, 2, 5, 155, 63, 1, 1, 2, 5, 155, 63 +}; + +RTW_DECL_TABLE_TXPWR_LMT(rtw8822b_txpwr_lmt_type2); + +static const u8 rtw8822b_txpwr_lmt_type5[] = { + 0, 0, 0, 0, 1, 32, 2, 0, 0, 0, 1, 28, 1, 0, 0, 0, 1, 30, + 0, 0, 0, 0, 2, 32, 2, 0, 0, 0, 2, 28, 1, 0, 0, 0, 2, 30, + 0, 0, 0, 0, 3, 32, 2, 0, 0, 0, 3, 28, 1, 0, 0, 0, 3, 30, + 0, 0, 0, 0, 4, 32, 2, 0, 0, 0, 4, 28, 1, 0, 0, 0, 4, 30, + 0, 0, 0, 0, 5, 32, 2, 0, 0, 0, 5, 28, 1, 0, 0, 0, 5, 30, + 0, 0, 0, 0, 6, 32, 2, 0, 0, 0, 6, 28, 1, 0, 0, 0, 6, 30, + 0, 0, 0, 0, 7, 32, 2, 0, 0, 0, 7, 28, 1, 0, 0, 0, 7, 30, + 0, 0, 0, 0, 8, 32, 2, 0, 0, 0, 8, 28, 1, 0, 0, 0, 8, 30, + 0, 0, 0, 0, 9, 32, 2, 0, 0, 0, 9, 28, 1, 0, 0, 0, 9, 30, + 0, 0, 0, 0, 10, 32, 2, 0, 0, 0, 10, 28, 1, 0, 0, 0, 10, 30, + 0, 0, 0, 0, 11, 32, 2, 0, 0, 0, 11, 28, 1, 0, 0, 0, 11, 30, + 0, 0, 0, 0, 12, 26, 2, 0, 0, 0, 12, 28, 1, 0, 0, 0, 12, 30, + 0, 0, 0, 0, 13, 20, 2, 0, 0, 0, 13, 28, 1, 0, 0, 0, 13, 28, + 0, 0, 0, 0, 14, 63, 2, 0, 0, 0, 14, 63, 1, 0, 0, 0, 14, 32, + 0, 0, 0, 1, 1, 26, 2, 0, 0, 1, 1, 30, 1, 0, 0, 1, 1, 34, + 0, 0, 0, 1, 2, 30, 2, 0, 0, 1, 2, 30, 1, 0, 0, 1, 2, 34, + 0, 0, 0, 1, 3, 32, 2, 0, 0, 1, 3, 30, 1, 0, 0, 1, 3, 34, + 0, 0, 0, 1, 4, 34, 2, 0, 0, 1, 4, 30, 1, 0, 0, 1, 4, 34, + 0, 0, 0, 1, 5, 34, 2, 0, 0, 1, 5, 30, 1, 0, 0, 1, 5, 34, + 0, 0, 0, 1, 6, 34, 2, 0, 0, 1, 6, 30, 1, 0, 0, 1, 6, 34, + 0, 0, 0, 1, 7, 34, 2, 0, 0, 1, 7, 30, 1, 0, 0, 1, 7, 34, + 0, 0, 0, 1, 8, 34, 2, 0, 0, 1, 8, 30, 1, 0, 0, 1, 8, 34, + 0, 0, 0, 1, 9, 32, 2, 0, 0, 1, 9, 30, 1, 0, 0, 1, 9, 34, + 0, 0, 0, 1, 10, 30, 2, 0, 0, 1, 10, 30, 1, 0, 0, 1, 10, 34, + 0, 0, 0, 1, 11, 28, 2, 0, 0, 1, 11, 30, 1, 0, 0, 1, 11, 34, + 0, 0, 0, 1, 12, 22, 2, 0, 0, 1, 12, 30, 1, 0, 0, 1, 12, 34, + 0, 0, 0, 1, 13, 14, 2, 0, 0, 1, 13, 30, 1, 0, 0, 1, 13, 34, + 0, 0, 0, 1, 14, 63, 2, 0, 0, 1, 14, 63, 1, 0, 0, 1, 14, 63, + 0, 0, 0, 2, 1, 26, 2, 0, 0, 2, 1, 30, 1, 0, 0, 2, 1, 34, + 0, 0, 0, 2, 2, 30, 2, 0, 0, 2, 2, 30, 1, 0, 0, 2, 2, 34, + 0, 0, 0, 2, 3, 32, 2, 0, 0, 2, 3, 30, 1, 0, 0, 2, 3, 34, + 0, 0, 0, 2, 4, 34, 2, 0, 0, 2, 4, 30, 1, 0, 0, 2, 4, 34, + 0, 0, 0, 2, 5, 34, 2, 0, 0, 2, 5, 30, 1, 0, 0, 2, 5, 34, + 0, 0, 0, 2, 6, 34, 2, 0, 0, 2, 6, 30, 1, 0, 0, 2, 6, 34, + 0, 0, 0, 2, 7, 34, 2, 0, 0, 2, 7, 30, 1, 0, 0, 2, 7, 34, + 0, 0, 0, 2, 8, 34, 2, 0, 0, 2, 8, 30, 1, 0, 0, 2, 8, 34, + 0, 0, 0, 2, 9, 32, 2, 0, 0, 2, 9, 30, 1, 0, 0, 2, 9, 34, + 0, 0, 0, 2, 10, 30, 2, 0, 0, 2, 10, 30, 1, 0, 0, 2, 10, 34, + 0, 0, 0, 2, 11, 26, 2, 0, 0, 2, 11, 30, 1, 0, 0, 2, 11, 34, + 0, 0, 0, 2, 12, 20, 2, 0, 0, 2, 12, 30, 1, 0, 0, 2, 12, 34, + 0, 0, 0, 2, 13, 14, 2, 0, 0, 2, 13, 30, 1, 0, 0, 2, 13, 34, + 0, 0, 0, 2, 14, 63, 2, 0, 0, 2, 14, 63, 1, 0, 0, 2, 14, 63, + 0, 0, 0, 3, 1, 26, 2, 0, 0, 3, 1, 18, 1, 0, 0, 3, 1, 30, + 0, 0, 0, 3, 2, 28, 2, 0, 0, 3, 2, 18, 1, 0, 0, 3, 2, 30, + 0, 0, 0, 3, 3, 30, 2, 0, 0, 3, 3, 18, 1, 0, 0, 3, 3, 30, + 0, 0, 0, 3, 4, 30, 2, 0, 0, 3, 4, 18, 1, 0, 0, 3, 4, 30, + 0, 0, 0, 3, 5, 32, 2, 0, 0, 3, 5, 18, 1, 0, 0, 3, 5, 30, + 0, 0, 0, 3, 6, 32, 2, 0, 0, 3, 6, 18, 1, 0, 0, 3, 6, 30, + 0, 0, 0, 3, 7, 32, 2, 0, 0, 3, 7, 18, 1, 0, 0, 3, 7, 30, + 0, 0, 0, 3, 8, 30, 2, 0, 0, 3, 8, 18, 1, 0, 0, 3, 8, 30, + 0, 0, 0, 3, 9, 30, 2, 0, 0, 3, 9, 18, 1, 0, 0, 3, 9, 30, + 0, 0, 0, 3, 10, 28, 2, 0, 0, 3, 10, 18, 1, 0, 0, 3, 10, 30, + 0, 0, 0, 3, 11, 26, 2, 0, 0, 3, 11, 18, 1, 0, 0, 3, 11, 30, + 0, 0, 0, 3, 12, 20, 2, 0, 0, 3, 12, 18, 1, 0, 0, 3, 12, 30, + 0, 0, 0, 3, 13, 14, 2, 0, 0, 3, 13, 18, 1, 0, 0, 3, 13, 30, + 0, 0, 0, 3, 14, 63, 2, 0, 0, 3, 14, 63, 1, 0, 0, 3, 14, 63, + 0, 0, 1, 2, 1, 63, 2, 0, 1, 2, 1, 63, 1, 0, 1, 2, 1, 63, + 0, 0, 1, 2, 2, 63, 2, 0, 1, 2, 2, 63, 1, 0, 1, 2, 2, 63, + 0, 0, 1, 2, 3, 26, 2, 0, 1, 2, 3, 30, 1, 0, 1, 2, 3, 34, + 0, 0, 1, 2, 4, 26, 2, 0, 1, 2, 4, 30, 1, 0, 1, 2, 4, 34, + 0, 0, 1, 2, 5, 30, 2, 0, 1, 2, 5, 30, 1, 0, 1, 2, 5, 34, + 0, 0, 1, 2, 6, 32, 2, 0, 1, 2, 6, 30, 1, 0, 1, 2, 6, 34, + 0, 0, 1, 2, 7, 30, 2, 0, 1, 2, 7, 30, 1, 0, 1, 2, 7, 34, + 0, 0, 1, 2, 8, 26, 2, 0, 1, 2, 8, 30, 1, 0, 1, 2, 8, 34, + 0, 0, 1, 2, 9, 26, 2, 0, 1, 2, 9, 30, 1, 0, 1, 2, 9, 34, + 0, 0, 1, 2, 10, 20, 2, 0, 1, 2, 10, 30, 1, 0, 1, 2, 10, 34, + 0, 0, 1, 2, 11, 14, 2, 0, 1, 2, 11, 30, 1, 0, 1, 2, 11, 34, + 0, 0, 1, 2, 12, 63, 2, 0, 1, 2, 12, 63, 1, 0, 1, 2, 12, 63, + 0, 0, 1, 2, 13, 63, 2, 0, 1, 2, 13, 63, 1, 0, 1, 2, 13, 63, + 0, 0, 1, 2, 14, 63, 2, 0, 1, 2, 14, 63, 1, 0, 1, 2, 14, 63, + 0, 0, 1, 3, 1, 63, 2, 0, 1, 3, 1, 63, 1, 0, 1, 3, 1, 63, + 0, 0, 1, 3, 2, 63, 2, 0, 1, 3, 2, 63, 1, 0, 1, 3, 2, 63, + 0, 0, 1, 3, 3, 24, 2, 0, 1, 3, 3, 18, 1, 0, 1, 3, 3, 30, + 0, 0, 1, 3, 4, 24, 2, 0, 1, 3, 4, 18, 1, 0, 1, 3, 4, 30, + 0, 0, 1, 3, 5, 26, 2, 0, 1, 3, 5, 18, 1, 0, 1, 3, 5, 30, + 0, 0, 1, 3, 6, 28, 2, 0, 1, 3, 6, 18, 1, 0, 1, 3, 6, 30, + 0, 0, 1, 3, 7, 26, 2, 0, 1, 3, 7, 18, 1, 0, 1, 3, 7, 30, + 0, 0, 1, 3, 8, 26, 2, 0, 1, 3, 8, 18, 1, 0, 1, 3, 8, 30, + 0, 0, 1, 3, 9, 26, 2, 0, 1, 3, 9, 18, 1, 0, 1, 3, 9, 30, + 0, 0, 1, 3, 10, 20, 2, 0, 1, 3, 10, 18, 1, 0, 1, 3, 10, 30, + 0, 0, 1, 3, 11, 14, 2, 0, 1, 3, 11, 18, 1, 0, 1, 3, 11, 30, + 0, 0, 1, 3, 12, 63, 2, 0, 1, 3, 12, 63, 1, 0, 1, 3, 12, 63, + 0, 0, 1, 3, 13, 63, 2, 0, 1, 3, 13, 63, 1, 0, 1, 3, 13, 63, + 0, 0, 1, 3, 14, 63, 2, 0, 1, 3, 14, 63, 1, 0, 1, 3, 14, 63, + 0, 1, 0, 1, 36, 30, 2, 1, 0, 1, 36, 32, 1, 1, 0, 1, 36, 30, + 0, 1, 0, 1, 40, 32, 2, 1, 0, 1, 40, 32, 1, 1, 0, 1, 40, 30, + 0, 1, 0, 1, 44, 32, 2, 1, 0, 1, 44, 32, 1, 1, 0, 1, 44, 30, + 0, 1, 0, 1, 48, 32, 2, 1, 0, 1, 48, 32, 1, 1, 0, 1, 48, 30, + 0, 1, 0, 1, 52, 32, 2, 1, 0, 1, 52, 32, 1, 1, 0, 1, 52, 28, + 0, 1, 0, 1, 56, 32, 2, 1, 0, 1, 56, 32, 1, 1, 0, 1, 56, 28, + 0, 1, 0, 1, 60, 32, 2, 1, 0, 1, 60, 32, 1, 1, 0, 1, 60, 28, + 0, 1, 0, 1, 64, 28, 2, 1, 0, 1, 64, 32, 1, 1, 0, 1, 64, 28, + 0, 1, 0, 1, 100, 26, 2, 1, 0, 1, 100, 32, 1, 1, 0, 1, 100, 32, + 0, 1, 0, 1, 104, 32, 2, 1, 0, 1, 104, 32, 1, 1, 0, 1, 104, 32, + 0, 1, 0, 1, 108, 32, 2, 1, 0, 1, 108, 32, 1, 1, 0, 1, 108, 32, + 0, 1, 0, 1, 112, 32, 2, 1, 0, 1, 112, 32, 1, 1, 0, 1, 112, 32, + 0, 1, 0, 1, 116, 32, 2, 1, 0, 1, 116, 32, 1, 1, 0, 1, 116, 32, + 0, 1, 0, 1, 120, 32, 2, 1, 0, 1, 120, 32, 1, 1, 0, 1, 120, 32, + 0, 1, 0, 1, 124, 32, 2, 1, 0, 1, 124, 32, 1, 1, 0, 1, 124, 32, + 0, 1, 0, 1, 128, 32, 2, 1, 0, 1, 128, 32, 1, 1, 0, 1, 128, 32, + 0, 1, 0, 1, 132, 32, 2, 1, 0, 1, 132, 32, 1, 1, 0, 1, 132, 32, + 0, 1, 0, 1, 136, 32, 2, 1, 0, 1, 136, 32, 1, 1, 0, 1, 136, 32, + 0, 1, 0, 1, 140, 28, 2, 1, 0, 1, 140, 32, 1, 1, 0, 1, 140, 32, + 0, 1, 0, 1, 144, 28, 2, 1, 0, 1, 144, 63, 1, 1, 0, 1, 144, 63, + 0, 1, 0, 1, 149, 32, 2, 1, 0, 1, 149, 63, 1, 1, 0, 1, 149, 63, + 0, 1, 0, 1, 153, 32, 2, 1, 0, 1, 153, 63, 1, 1, 0, 1, 153, 63, + 0, 1, 0, 1, 157, 32, 2, 1, 0, 1, 157, 63, 1, 1, 0, 1, 157, 63, + 0, 1, 0, 1, 161, 32, 2, 1, 0, 1, 161, 63, 1, 1, 0, 1, 161, 63, + 0, 1, 0, 1, 165, 32, 2, 1, 0, 1, 165, 63, 1, 1, 0, 1, 165, 63, + 0, 1, 0, 2, 36, 30, 2, 1, 0, 2, 36, 32, 1, 1, 0, 2, 36, 28, + 0, 1, 0, 2, 40, 32, 2, 1, 0, 2, 40, 32, 1, 1, 0, 2, 40, 28, + 0, 1, 0, 2, 44, 32, 2, 1, 0, 2, 44, 32, 1, 1, 0, 2, 44, 28, + 0, 1, 0, 2, 48, 32, 2, 1, 0, 2, 48, 32, 1, 1, 0, 2, 48, 28, + 0, 1, 0, 2, 52, 32, 2, 1, 0, 2, 52, 32, 1, 1, 0, 2, 52, 28, + 0, 1, 0, 2, 56, 32, 2, 1, 0, 2, 56, 32, 1, 1, 0, 2, 56, 28, + 0, 1, 0, 2, 60, 32, 2, 1, 0, 2, 60, 32, 1, 1, 0, 2, 60, 28, + 0, 1, 0, 2, 64, 28, 2, 1, 0, 2, 64, 32, 1, 1, 0, 2, 64, 28, + 0, 1, 0, 2, 100, 26, 2, 1, 0, 2, 100, 32, 1, 1, 0, 2, 100, 32, + 0, 1, 0, 2, 104, 32, 2, 1, 0, 2, 104, 32, 1, 1, 0, 2, 104, 32, + 0, 1, 0, 2, 108, 32, 2, 1, 0, 2, 108, 32, 1, 1, 0, 2, 108, 32, + 0, 1, 0, 2, 112, 32, 2, 1, 0, 2, 112, 32, 1, 1, 0, 2, 112, 32, + 0, 1, 0, 2, 116, 32, 2, 1, 0, 2, 116, 32, 1, 1, 0, 2, 116, 32, + 0, 1, 0, 2, 120, 32, 2, 1, 0, 2, 120, 32, 1, 1, 0, 2, 120, 32, + 0, 1, 0, 2, 124, 32, 2, 1, 0, 2, 124, 32, 1, 1, 0, 2, 124, 32, + 0, 1, 0, 2, 128, 32, 2, 1, 0, 2, 128, 32, 1, 1, 0, 2, 128, 32, + 0, 1, 0, 2, 132, 32, 2, 1, 0, 2, 132, 32, 1, 1, 0, 2, 132, 32, + 0, 1, 0, 2, 136, 32, 2, 1, 0, 2, 136, 32, 1, 1, 0, 2, 136, 32, + 0, 1, 0, 2, 140, 26, 2, 1, 0, 2, 140, 32, 1, 1, 0, 2, 140, 32, + 0, 1, 0, 2, 144, 26, 2, 1, 0, 2, 144, 63, 1, 1, 0, 2, 144, 63, + 0, 1, 0, 2, 149, 32, 2, 1, 0, 2, 149, 63, 1, 1, 0, 2, 149, 63, + 0, 1, 0, 2, 153, 32, 2, 1, 0, 2, 153, 63, 1, 1, 0, 2, 153, 63, + 0, 1, 0, 2, 157, 32, 2, 1, 0, 2, 157, 63, 1, 1, 0, 2, 157, 63, + 0, 1, 0, 2, 161, 32, 2, 1, 0, 2, 161, 63, 1, 1, 0, 2, 161, 63, + 0, 1, 0, 2, 165, 32, 2, 1, 0, 2, 165, 63, 1, 1, 0, 2, 165, 63, + 0, 1, 0, 3, 36, 28, 2, 1, 0, 3, 36, 20, 1, 1, 0, 3, 36, 22, + 0, 1, 0, 3, 40, 30, 2, 1, 0, 3, 40, 20, 1, 1, 0, 3, 40, 22, + 0, 1, 0, 3, 44, 30, 2, 1, 0, 3, 44, 20, 1, 1, 0, 3, 44, 22, + 0, 1, 0, 3, 48, 30, 2, 1, 0, 3, 48, 20, 1, 1, 0, 3, 48, 22, + 0, 1, 0, 3, 52, 30, 2, 1, 0, 3, 52, 20, 1, 1, 0, 3, 52, 22, + 0, 1, 0, 3, 56, 30, 2, 1, 0, 3, 56, 20, 1, 1, 0, 3, 56, 22, + 0, 1, 0, 3, 60, 30, 2, 1, 0, 3, 60, 20, 1, 1, 0, 3, 60, 22, + 0, 1, 0, 3, 64, 28, 2, 1, 0, 3, 64, 20, 1, 1, 0, 3, 64, 22, + 0, 1, 0, 3, 100, 26, 2, 1, 0, 3, 100, 20, 1, 1, 0, 3, 100, 30, + 0, 1, 0, 3, 104, 30, 2, 1, 0, 3, 104, 20, 1, 1, 0, 3, 104, 30, + 0, 1, 0, 3, 108, 32, 2, 1, 0, 3, 108, 20, 1, 1, 0, 3, 108, 30, + 0, 1, 0, 3, 112, 32, 2, 1, 0, 3, 112, 20, 1, 1, 0, 3, 112, 30, + 0, 1, 0, 3, 116, 32, 2, 1, 0, 3, 116, 20, 1, 1, 0, 3, 116, 30, + 0, 1, 0, 3, 120, 32, 2, 1, 0, 3, 120, 20, 1, 1, 0, 3, 120, 30, + 0, 1, 0, 3, 124, 32, 2, 1, 0, 3, 124, 20, 1, 1, 0, 3, 124, 30, + 0, 1, 0, 3, 128, 32, 2, 1, 0, 3, 128, 20, 1, 1, 0, 3, 128, 30, + 0, 1, 0, 3, 132, 32, 2, 1, 0, 3, 132, 20, 1, 1, 0, 3, 132, 30, + 0, 1, 0, 3, 136, 30, 2, 1, 0, 3, 136, 20, 1, 1, 0, 3, 136, 30, + 0, 1, 0, 3, 140, 26, 2, 1, 0, 3, 140, 20, 1, 1, 0, 3, 140, 30, + 0, 1, 0, 3, 144, 26, 2, 1, 0, 3, 144, 63, 1, 1, 0, 3, 144, 63, + 0, 1, 0, 3, 149, 32, 2, 1, 0, 3, 149, 63, 1, 1, 0, 3, 149, 63, + 0, 1, 0, 3, 153, 32, 2, 1, 0, 3, 153, 63, 1, 1, 0, 3, 153, 63, + 0, 1, 0, 3, 157, 32, 2, 1, 0, 3, 157, 63, 1, 1, 0, 3, 157, 63, + 0, 1, 0, 3, 161, 32, 2, 1, 0, 3, 161, 63, 1, 1, 0, 3, 161, 63, + 0, 1, 0, 3, 165, 32, 2, 1, 0, 3, 165, 63, 1, 1, 0, 3, 165, 63, + 0, 1, 1, 2, 38, 22, 2, 1, 1, 2, 38, 30, 1, 1, 1, 2, 38, 30, + 0, 1, 1, 2, 46, 30, 2, 1, 1, 2, 46, 30, 1, 1, 1, 2, 46, 30, + 0, 1, 1, 2, 54, 30, 2, 1, 1, 2, 54, 30, 1, 1, 1, 2, 54, 30, + 0, 1, 1, 2, 62, 24, 2, 1, 1, 2, 62, 30, 1, 1, 1, 2, 62, 30, + 0, 1, 1, 2, 102, 24, 2, 1, 1, 2, 102, 30, 1, 1, 1, 2, 102, 30, + 0, 1, 1, 2, 110, 30, 2, 1, 1, 2, 110, 30, 1, 1, 1, 2, 110, 30, + 0, 1, 1, 2, 118, 30, 2, 1, 1, 2, 118, 30, 1, 1, 1, 2, 118, 30, + 0, 1, 1, 2, 126, 30, 2, 1, 1, 2, 126, 30, 1, 1, 1, 2, 126, 30, + 0, 1, 1, 2, 134, 30, 2, 1, 1, 2, 134, 30, 1, 1, 1, 2, 134, 30, + 0, 1, 1, 2, 142, 30, 2, 1, 1, 2, 142, 63, 1, 1, 1, 2, 142, 63, + 0, 1, 1, 2, 151, 30, 2, 1, 1, 2, 151, 63, 1, 1, 1, 2, 151, 63, + 0, 1, 1, 2, 159, 30, 2, 1, 1, 2, 159, 63, 1, 1, 1, 2, 159, 63, + 0, 1, 1, 3, 38, 20, 2, 1, 1, 3, 38, 20, 1, 1, 1, 3, 38, 22, + 0, 1, 1, 3, 46, 30, 2, 1, 1, 3, 46, 20, 1, 1, 1, 3, 46, 22, + 0, 1, 1, 3, 54, 30, 2, 1, 1, 3, 54, 20, 1, 1, 1, 3, 54, 22, + 0, 1, 1, 3, 62, 22, 2, 1, 1, 3, 62, 20, 1, 1, 1, 3, 62, 22, + 0, 1, 1, 3, 102, 22, 2, 1, 1, 3, 102, 20, 1, 1, 1, 3, 102, 30, + 0, 1, 1, 3, 110, 30, 2, 1, 1, 3, 110, 20, 1, 1, 1, 3, 110, 30, + 0, 1, 1, 3, 118, 30, 2, 1, 1, 3, 118, 20, 1, 1, 1, 3, 118, 30, + 0, 1, 1, 3, 126, 30, 2, 1, 1, 3, 126, 20, 1, 1, 1, 3, 126, 30, + 0, 1, 1, 3, 134, 30, 2, 1, 1, 3, 134, 20, 1, 1, 1, 3, 134, 30, + 0, 1, 1, 3, 142, 30, 2, 1, 1, 3, 142, 63, 1, 1, 1, 3, 142, 63, + 0, 1, 1, 3, 151, 30, 2, 1, 1, 3, 151, 63, 1, 1, 1, 3, 151, 63, + 0, 1, 1, 3, 159, 30, 2, 1, 1, 3, 159, 63, 1, 1, 1, 3, 159, 63, + 0, 1, 2, 4, 42, 20, 2, 1, 2, 4, 42, 30, 1, 1, 2, 4, 42, 28, + 0, 1, 2, 4, 58, 20, 2, 1, 2, 4, 58, 30, 1, 1, 2, 4, 58, 28, + 0, 1, 2, 4, 106, 20, 2, 1, 2, 4, 106, 30, 1, 1, 2, 4, 106, 30, + 0, 1, 2, 4, 122, 30, 2, 1, 2, 4, 122, 30, 1, 1, 2, 4, 122, 30, + 0, 1, 2, 4, 138, 30, 2, 1, 2, 4, 138, 63, 1, 1, 2, 4, 138, 63, + 0, 1, 2, 4, 155, 30, 2, 1, 2, 4, 155, 63, 1, 1, 2, 4, 155, 63, + 0, 1, 2, 5, 42, 18, 2, 1, 2, 5, 42, 20, 1, 1, 2, 5, 42, 22, + 0, 1, 2, 5, 58, 18, 2, 1, 2, 5, 58, 20, 1, 1, 2, 5, 58, 22, + 0, 1, 2, 5, 106, 20, 2, 1, 2, 5, 106, 20, 1, 1, 2, 5, 106, 30, + 0, 1, 2, 5, 122, 30, 2, 1, 2, 5, 122, 20, 1, 1, 2, 5, 122, 30, + 0, 1, 2, 5, 138, 30, 2, 1, 2, 5, 138, 63, 1, 1, 2, 5, 138, 63, + 0, 1, 2, 5, 155, 30, 2, 1, 2, 5, 155, 63, 1, 1, 2, 5, 155, 63, +}; + +RTW_DECL_TABLE_TXPWR_LMT(rtw8822b_txpwr_lmt_type5); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b_table.h b/drivers/net/wireless/realtek/rtw88/rtw8822b_table.h new file mode 100644 index 000000000000..d4c268889368 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b_table.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW8822B_TABLE_H__ +#define __RTW8822B_TABLE_H__ + +extern const struct rtw_table rtw8822b_mac_tbl; +extern const struct rtw_table rtw8822b_agc_tbl; +extern const struct rtw_table rtw8822b_bb_tbl; +extern const struct rtw_table rtw8822b_bb_pg_type2_tbl; +extern const struct rtw_table rtw8822b_bb_pg_type5_tbl; +extern const struct rtw_table rtw8822b_rf_a_tbl; +extern const struct rtw_table rtw8822b_rf_b_tbl; +extern const struct rtw_table rtw8822b_txpwr_lmt_type2_tbl; +extern const struct rtw_table rtw8822b_txpwr_lmt_type5_tbl; + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c new file mode 100644 index 000000000000..b4f7242e5aa3 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -0,0 +1,1890 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "fw.h" +#include "tx.h" +#include "rx.h" +#include "phy.h" +#include "rtw8822c.h" +#include "rtw8822c_table.h" +#include "mac.h" +#include "reg.h" +#include "debug.h" + +static void rtw8822c_config_trx_mode(struct rtw_dev *rtwdev, u8 tx_path, + u8 rx_path, bool is_tx2_path); + +static void rtw8822ce_efuse_parsing(struct rtw_efuse *efuse, + struct rtw8822c_efuse *map) +{ + ether_addr_copy(efuse->addr, map->e.mac_addr); +} + +static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw8822c_efuse *map; + int i; + + map = (struct rtw8822c_efuse *)log_map; + + efuse->rfe_option = map->rfe_option; + efuse->crystal_cap = map->xtal_k; + efuse->channel_plan = map->channel_plan; + efuse->country_code[0] = map->country_code[0]; + efuse->country_code[1] = map->country_code[1]; + efuse->bt_setting = map->rf_bt_setting; + efuse->regd = map->rf_board_option & 0x7; + + for (i = 0; i < 4; i++) + efuse->txpwr_idx_table[i] = map->txpwr_idx_table[i]; + + switch (rtw_hci_type(rtwdev)) { + case RTW_HCI_TYPE_PCIE: + rtw8822ce_efuse_parsing(efuse, map); + break; + default: + /* unsupported now */ + return -ENOTSUPP; + } + + return 0; +} + +static void rtw8822c_header_file_init(struct rtw_dev *rtwdev, bool pre) +{ + rtw_write32_set(rtwdev, REG_3WIRE, BIT_3WIRE_TX_EN | BIT_3WIRE_RX_EN); + rtw_write32_set(rtwdev, REG_3WIRE, BIT_3WIRE_PI_ON); + rtw_write32_set(rtwdev, REG_3WIRE2, BIT_3WIRE_TX_EN | BIT_3WIRE_RX_EN); + rtw_write32_set(rtwdev, REG_3WIRE2, BIT_3WIRE_PI_ON); + + if (pre) + rtw_write32_clr(rtwdev, REG_ENCCK, BIT_CCK_OFDM_BLK_EN); + else + rtw_write32_set(rtwdev, REG_ENCCK, BIT_CCK_OFDM_BLK_EN); +} + +static void rtw8822c_dac_backup_reg(struct rtw_dev *rtwdev, + struct rtw_backup_info *backup, + struct rtw_backup_info *backup_rf) +{ + u32 path, i; + u32 val; + u32 reg; + u32 rf_addr[DACK_RF_8822C] = {0x8f}; + u32 addrs[DACK_REG_8822C] = {0x180c, 0x1810, 0x410c, 0x4110, + 0x1c3c, 0x1c24, 0x1d70, 0x9b4, + 0x1a00, 0x1a14, 0x1d58, 0x1c38, + 0x1e24, 0x1e28, 0x1860, 0x4160}; + + for (i = 0; i < DACK_REG_8822C; i++) { + backup[i].len = 4; + backup[i].reg = addrs[i]; + backup[i].val = rtw_read32(rtwdev, addrs[i]); + } + + for (path = 0; path < DACK_PATH_8822C; path++) { + for (i = 0; i < DACK_RF_8822C; i++) { + reg = rf_addr[i]; + val = rtw_read_rf(rtwdev, path, reg, RFREG_MASK); + backup_rf[path * i + i].reg = reg; + backup_rf[path * i + i].val = val; + } + } +} + +static void rtw8822c_dac_restore_reg(struct rtw_dev *rtwdev, + struct rtw_backup_info *backup, + struct rtw_backup_info *backup_rf) +{ + u32 path, i; + u32 val; + u32 reg; + + rtw_restore_reg(rtwdev, backup, DACK_REG_8822C); + + for (path = 0; path < DACK_PATH_8822C; path++) { + for (i = 0; i < DACK_RF_8822C; i++) { + val = backup_rf[path * i + i].val; + reg = backup_rf[path * i + i].reg; + rtw_write_rf(rtwdev, path, reg, RFREG_MASK, val); + } + } +} + +static void rtw8822c_rf_minmax_cmp(struct rtw_dev *rtwdev, u32 value, + u32 *min, u32 *max) +{ + if (value >= 0x200) { + if (*min >= 0x200) { + if (*min > value) + *min = value; + } else { + *min = value; + } + if (*max >= 0x200) { + if (*max < value) + *max = value; + } + } else { + if (*min < 0x200) { + if (*min > value) + *min = value; + } + + if (*max >= 0x200) { + *max = value; + } else { + if (*max < value) + *max = value; + } + } +} + +static void swap_u32(u32 *v1, u32 *v2) +{ + u32 tmp; + + tmp = *v1; + *v1 = *v2; + *v2 = tmp; +} + +static void __rtw8822c_dac_iq_sort(struct rtw_dev *rtwdev, u32 *v1, u32 *v2) +{ + if (*v1 >= 0x200 && *v2 >= 0x200) { + if (*v1 > *v2) + swap_u32(v1, v2); + } else if (*v1 < 0x200 && *v2 < 0x200) { + if (*v1 > *v2) + swap_u32(v1, v2); + } else if (*v1 < 0x200 && *v2 >= 0x200) { + swap_u32(v1, v2); + } +} + +static void rtw8822c_dac_iq_sort(struct rtw_dev *rtwdev, u32 *iv, u32 *qv) +{ + u32 i, j; + + for (i = 0; i < DACK_SN_8822C - 1; i++) { + for (j = 0; j < (DACK_SN_8822C - 1 - i) ; j++) { + __rtw8822c_dac_iq_sort(rtwdev, &iv[j], &iv[j + 1]); + __rtw8822c_dac_iq_sort(rtwdev, &qv[j], &qv[j + 1]); + } + } +} + +static void rtw8822c_dac_iq_offset(struct rtw_dev *rtwdev, u32 *vec, u32 *val) +{ + u32 p, m, t, i; + + m = 0; + p = 0; + for (i = 10; i < DACK_SN_8822C - 10; i++) { + if (vec[i] > 0x200) + m = (0x400 - vec[i]) + m; + else + p = vec[i] + p; + } + + if (p > m) { + t = p - m; + t = t / (DACK_SN_8822C - 20); + } else { + t = m - p; + t = t / (DACK_SN_8822C - 20); + if (t != 0x0) + t = 0x400 - t; + } + + *val = t; +} + +static u32 rtw8822c_get_path_base_addr(u8 path) +{ + u32 base_addr; + + switch (path) { + case RF_PATH_A: + base_addr = 0x1800; + break; + case RF_PATH_B: + base_addr = 0x4100; + break; + default: + WARN_ON(1); + return -1; + } + + return base_addr; +} + +static bool rtw8822c_dac_iq_check(struct rtw_dev *rtwdev, u32 value) +{ + bool ret = true; + + if ((value >= 0x200 && (0x400 - value) > 0x64) || + (value < 0x200 && value > 0x64)) { + ret = false; + rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] Error overflow\n"); + } + + return ret; +} + +static void rtw8822c_dac_cal_iq_sample(struct rtw_dev *rtwdev, u32 *iv, u32 *qv) +{ + u32 temp; + int i = 0, cnt = 0; + + while (i < DACK_SN_8822C && cnt < 10000) { + cnt++; + temp = rtw_read32_mask(rtwdev, 0x2dbc, 0x3fffff); + iv[i] = (temp & 0x3ff000) >> 12; + qv[i] = temp & 0x3ff; + + if (rtw8822c_dac_iq_check(rtwdev, iv[i]) && + rtw8822c_dac_iq_check(rtwdev, qv[i])) + i++; + } +} + +static void rtw8822c_dac_cal_iq_search(struct rtw_dev *rtwdev, + u32 *iv, u32 *qv, + u32 *i_value, u32 *q_value) +{ + u32 i_max = 0, q_max = 0, i_min = 0, q_min = 0; + u32 i_delta, q_delta; + u32 temp; + int i, cnt = 0; + + do { + i_min = iv[0]; + i_max = iv[0]; + q_min = qv[0]; + q_max = qv[0]; + for (i = 0; i < DACK_SN_8822C; i++) { + rtw8822c_rf_minmax_cmp(rtwdev, iv[i], &i_min, &i_max); + rtw8822c_rf_minmax_cmp(rtwdev, qv[i], &q_min, &q_max); + } + + if (i_max < 0x200 && i_min < 0x200) + i_delta = i_max - i_min; + else if (i_max >= 0x200 && i_min >= 0x200) + i_delta = i_max - i_min; + else + i_delta = i_max + (0x400 - i_min); + + if (q_max < 0x200 && q_min < 0x200) + q_delta = q_max - q_min; + else if (q_max >= 0x200 && q_min >= 0x200) + q_delta = q_max - q_min; + else + q_delta = q_max + (0x400 - q_min); + + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[DACK] i: min=0x%08x, max=0x%08x, delta=0x%08x\n", + i_min, i_max, i_delta); + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[DACK] q: min=0x%08x, max=0x%08x, delta=0x%08x\n", + q_min, q_max, q_delta); + + rtw8822c_dac_iq_sort(rtwdev, iv, qv); + + if (i_delta > 5 || q_delta > 5) { + temp = rtw_read32_mask(rtwdev, 0x2dbc, 0x3fffff); + iv[0] = (temp & 0x3ff000) >> 12; + qv[0] = temp & 0x3ff; + temp = rtw_read32_mask(rtwdev, 0x2dbc, 0x3fffff); + iv[DACK_SN_8822C - 1] = (temp & 0x3ff000) >> 12; + qv[DACK_SN_8822C - 1] = temp & 0x3ff; + } else { + break; + } + } while (cnt++ < 100); + + rtw8822c_dac_iq_offset(rtwdev, iv, i_value); + rtw8822c_dac_iq_offset(rtwdev, qv, q_value); +} + +static void rtw8822c_dac_cal_rf_mode(struct rtw_dev *rtwdev, + u32 *i_value, u32 *q_value) +{ + u32 iv[DACK_SN_8822C], qv[DACK_SN_8822C]; + u32 rf_a, rf_b; + + mdelay(10); + + rf_a = rtw_read_rf(rtwdev, RF_PATH_A, 0x0, RFREG_MASK); + rf_b = rtw_read_rf(rtwdev, RF_PATH_B, 0x0, RFREG_MASK); + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] RF path-A=0x%05x\n", rf_a); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] RF path-B=0x%05x\n", rf_b); + + rtw8822c_dac_cal_iq_sample(rtwdev, iv, qv); + rtw8822c_dac_cal_iq_search(rtwdev, iv, qv, i_value, q_value); +} + +static void rtw8822c_dac_bb_setting(struct rtw_dev *rtwdev) +{ + rtw_write32_mask(rtwdev, 0x1d58, 0xff8, 0x1ff); + rtw_write32_mask(rtwdev, 0x1a00, 0x3, 0x2); + rtw_write32_mask(rtwdev, 0x1a14, 0x300, 0x3); + rtw_write32(rtwdev, 0x1d70, 0x7e7e7e7e); + rtw_write32_mask(rtwdev, 0x180c, 0x3, 0x0); + rtw_write32_mask(rtwdev, 0x410c, 0x3, 0x0); + rtw_write32(rtwdev, 0x1b00, 0x00000008); + rtw_write8(rtwdev, 0x1bcc, 0x3f); + rtw_write32(rtwdev, 0x1b00, 0x0000000a); + rtw_write8(rtwdev, 0x1bcc, 0x3f); + rtw_write32_mask(rtwdev, 0x1e24, BIT(31), 0x0); + rtw_write32_mask(rtwdev, 0x1e28, 0xf, 0x3); +} + +static void rtw8822c_dac_cal_adc(struct rtw_dev *rtwdev, + u8 path, u32 *adc_ic, u32 *adc_qc) +{ + u32 ic = 0, qc = 0, temp = 0; + u32 base_addr; + u32 path_sel; + int i; + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] ADCK path(%d)\n", path); + + base_addr = rtw8822c_get_path_base_addr(path); + switch (path) { + case RF_PATH_A: + path_sel = 0xa0000; + break; + case RF_PATH_B: + path_sel = 0x80000; + break; + default: + WARN_ON(1); + return; + } + + /* ADCK step1 */ + rtw_write32_mask(rtwdev, base_addr + 0x30, BIT(30), 0x0); + if (path == RF_PATH_B) + rtw_write32(rtwdev, base_addr + 0x30, 0x30db8041); + rtw_write32(rtwdev, base_addr + 0x60, 0xf0040ff0); + rtw_write32(rtwdev, base_addr + 0x0c, 0xdff00220); + rtw_write32(rtwdev, base_addr + 0x10, 0x02dd08c4); + rtw_write32(rtwdev, base_addr + 0x0c, 0x10000260); + rtw_write_rf(rtwdev, RF_PATH_A, 0x0, RFREG_MASK, 0x10000); + rtw_write_rf(rtwdev, RF_PATH_B, 0x0, RFREG_MASK, 0x10000); + for (i = 0; i < 10; i++) { + rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] ADCK count=%d\n", i); + rtw_write32(rtwdev, 0x1c3c, path_sel + 0x8003); + rtw_write32(rtwdev, 0x1c24, 0x00010002); + rtw8822c_dac_cal_rf_mode(rtwdev, &ic, &qc); + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[DACK] before: i=0x%x, q=0x%x\n", ic, qc); + + /* compensation value */ + if (ic != 0x0) { + ic = 0x400 - ic; + *adc_ic = ic; + } + if (qc != 0x0) { + qc = 0x400 - qc; + *adc_qc = qc; + } + temp = (ic & 0x3ff) | ((qc & 0x3ff) << 10); + rtw_write32(rtwdev, base_addr + 0x68, temp); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] ADCK 0x%08x=0x08%x\n", + base_addr + 0x68, temp); + /* check ADC DC offset */ + rtw_write32(rtwdev, 0x1c3c, path_sel + 0x8103); + rtw8822c_dac_cal_rf_mode(rtwdev, &ic, &qc); + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[DACK] after: i=0x%08x, q=0x%08x\n", ic, qc); + if (ic >= 0x200) + ic = 0x400 - ic; + if (qc >= 0x200) + qc = 0x400 - qc; + if (ic < 5 && qc < 5) + break; + } + + /* ADCK step2 */ + rtw_write32(rtwdev, 0x1c3c, 0x00000003); + rtw_write32(rtwdev, base_addr + 0x0c, 0x10000260); + rtw_write32(rtwdev, base_addr + 0x10, 0x02d508c4); + + /* release pull low switch on IQ path */ + rtw_write_rf(rtwdev, path, 0x8f, BIT(13), 0x1); +} + +static void rtw8822c_dac_cal_step1(struct rtw_dev *rtwdev, u8 path) +{ + u32 base_addr; + + base_addr = rtw8822c_get_path_base_addr(path); + + rtw_write32(rtwdev, base_addr + 0x0c, 0xdff00220); + if (path == RF_PATH_A) { + rtw_write32(rtwdev, base_addr + 0x60, 0xf0040ff0); + rtw_write32(rtwdev, 0x1c38, 0xffffffff); + } + rtw_write32(rtwdev, base_addr + 0x10, 0x02d508c5); + rtw_write32(rtwdev, 0x9b4, 0xdb66db00); + rtw_write32(rtwdev, base_addr + 0xb0, 0x0a11fb88); + rtw_write32(rtwdev, base_addr + 0xbc, 0x0008ff81); + rtw_write32(rtwdev, base_addr + 0xc0, 0x0003d208); + rtw_write32(rtwdev, base_addr + 0xcc, 0x0a11fb88); + rtw_write32(rtwdev, base_addr + 0xd8, 0x0008ff81); + rtw_write32(rtwdev, base_addr + 0xdc, 0x0003d208); + rtw_write32(rtwdev, base_addr + 0xb8, 0x60000000); + mdelay(2); + rtw_write32(rtwdev, base_addr + 0xbc, 0x000aff8d); + mdelay(2); + rtw_write32(rtwdev, base_addr + 0xb0, 0x0a11fb89); + rtw_write32(rtwdev, base_addr + 0xcc, 0x0a11fb89); + mdelay(1); + rtw_write32(rtwdev, base_addr + 0xb8, 0x62000000); + mdelay(20); + rtw_write32(rtwdev, base_addr + 0xd4, 0x62000000); + mdelay(20); + rtw_write32(rtwdev, base_addr + 0xb8, 0x02000000); + mdelay(20); + rtw_write32(rtwdev, base_addr + 0xbc, 0x0008ff87); + rtw_write32(rtwdev, 0x9b4, 0xdb6db600); + rtw_write32(rtwdev, base_addr + 0x10, 0x02d508c5); + rtw_write32(rtwdev, base_addr + 0xbc, 0x0008ff87); + rtw_write32(rtwdev, base_addr + 0x60, 0xf0000000); +} + +static void rtw8822c_dac_cal_step2(struct rtw_dev *rtwdev, + u8 path, u32 *ic_out, u32 *qc_out) +{ + u32 base_addr; + u32 ic, qc, ic_in, qc_in; + + base_addr = rtw8822c_get_path_base_addr(path); + rtw_write32_mask(rtwdev, base_addr + 0xbc, 0xf0000000, 0x0); + rtw_write32_mask(rtwdev, base_addr + 0xc0, 0xf, 0x8); + rtw_write32_mask(rtwdev, base_addr + 0xd8, 0xf0000000, 0x0); + rtw_write32_mask(rtwdev, base_addr + 0xdc, 0xf, 0x8); + + rtw_write32(rtwdev, 0x1b00, 0x00000008); + rtw_write8(rtwdev, 0x1bcc, 0x03f); + rtw_write32(rtwdev, base_addr + 0x0c, 0xdff00220); + rtw_write32(rtwdev, base_addr + 0x10, 0x02d508c5); + rtw_write32(rtwdev, 0x1c3c, 0x00088103); + + rtw8822c_dac_cal_rf_mode(rtwdev, &ic_in, &qc_in); + ic = ic_in; + qc = qc_in; + + /* compensation value */ + if (ic != 0x0) + ic = 0x400 - ic; + if (qc != 0x0) + qc = 0x400 - qc; + if (ic < 0x300) { + ic = ic * 2 * 6 / 5; + ic = ic + 0x80; + } else { + ic = (0x400 - ic) * 2 * 6 / 5; + ic = 0x7f - ic; + } + if (qc < 0x300) { + qc = qc * 2 * 6 / 5; + qc = qc + 0x80; + } else { + qc = (0x400 - qc) * 2 * 6 / 5; + qc = 0x7f - qc; + } + + *ic_out = ic; + *qc_out = qc; + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] before i=0x%x, q=0x%x\n", ic_in, qc_in); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] after i=0x%x, q=0x%x\n", ic, qc); +} + +static void rtw8822c_dac_cal_step3(struct rtw_dev *rtwdev, u8 path, + u32 adc_ic, u32 adc_qc, + u32 *ic_in, u32 *qc_in, + u32 *i_out, u32 *q_out) +{ + u32 base_addr; + u32 ic, qc; + u32 temp; + + base_addr = rtw8822c_get_path_base_addr(path); + ic = *ic_in; + qc = *qc_in; + + rtw_write32(rtwdev, base_addr + 0x0c, 0xdff00220); + rtw_write32(rtwdev, base_addr + 0x10, 0x02d508c5); + rtw_write32(rtwdev, 0x9b4, 0xdb66db00); + rtw_write32(rtwdev, base_addr + 0xb0, 0x0a11fb88); + rtw_write32(rtwdev, base_addr + 0xbc, 0xc008ff81); + rtw_write32(rtwdev, base_addr + 0xc0, 0x0003d208); + rtw_write32_mask(rtwdev, base_addr + 0xbc, 0xf0000000, ic & 0xf); + rtw_write32_mask(rtwdev, base_addr + 0xc0, 0xf, (ic & 0xf0) >> 4); + rtw_write32(rtwdev, base_addr + 0xcc, 0x0a11fb88); + rtw_write32(rtwdev, base_addr + 0xd8, 0xe008ff81); + rtw_write32(rtwdev, base_addr + 0xdc, 0x0003d208); + rtw_write32_mask(rtwdev, base_addr + 0xd8, 0xf0000000, qc & 0xf); + rtw_write32_mask(rtwdev, base_addr + 0xdc, 0xf, (qc & 0xf0) >> 4); + rtw_write32(rtwdev, base_addr + 0xb8, 0x60000000); + mdelay(2); + rtw_write32_mask(rtwdev, base_addr + 0xbc, 0xe, 0x6); + mdelay(2); + rtw_write32(rtwdev, base_addr + 0xb0, 0x0a11fb89); + rtw_write32(rtwdev, base_addr + 0xcc, 0x0a11fb89); + mdelay(1); + rtw_write32(rtwdev, base_addr + 0xb8, 0x62000000); + mdelay(20); + rtw_write32(rtwdev, base_addr + 0xd4, 0x62000000); + mdelay(20); + rtw_write32(rtwdev, base_addr + 0xb8, 0x02000000); + mdelay(20); + rtw_write32_mask(rtwdev, base_addr + 0xbc, 0xe, 0x3); + rtw_write32(rtwdev, 0x9b4, 0xdb6db600); + + /* check DAC DC offset */ + temp = ((adc_ic + 0x10) & 0x3ff) | (((adc_qc + 0x10) & 0x3ff) << 10); + rtw_write32(rtwdev, base_addr + 0x68, temp); + rtw_write32(rtwdev, base_addr + 0x10, 0x02d508c5); + rtw_write32(rtwdev, base_addr + 0x60, 0xf0000000); + rtw8822c_dac_cal_rf_mode(rtwdev, &ic, &qc); + if (ic >= 0x10) + ic = ic - 0x10; + else + ic = 0x400 - (0x10 - ic); + + if (qc >= 0x10) + qc = qc - 0x10; + else + qc = 0x400 - (0x10 - qc); + + *i_out = ic; + *q_out = qc; + + if (ic >= 0x200) + ic = 0x400 - ic; + if (qc >= 0x200) + qc = 0x400 - qc; + + *ic_in = ic; + *qc_in = qc; + + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[DACK] after DACK i=0x%x, q=0x%x\n", *i_out, *q_out); +} + +static void rtw8822c_dac_cal_step4(struct rtw_dev *rtwdev, u8 path) +{ + u32 base_addr = rtw8822c_get_path_base_addr(path); + + rtw_write32(rtwdev, base_addr + 0x68, 0x0); + rtw_write32(rtwdev, base_addr + 0x10, 0x02d508c4); + rtw_write32_mask(rtwdev, base_addr + 0xbc, 0x1, 0x0); + rtw_write32_mask(rtwdev, base_addr + 0x30, BIT(30), 0x1); +} + +static void rtw8822c_rf_dac_cal(struct rtw_dev *rtwdev) +{ + struct rtw_backup_info backup_rf[DACK_RF_8822C * DACK_PATH_8822C]; + struct rtw_backup_info backup[DACK_REG_8822C]; + u32 ic = 0, qc = 0, i; + u32 i_a = 0x0, q_a = 0x0, i_b = 0x0, q_b = 0x0; + u32 ic_a = 0x0, qc_a = 0x0, ic_b = 0x0, qc_b = 0x0; + u32 adc_ic_a = 0x0, adc_qc_a = 0x0, adc_ic_b = 0x0, adc_qc_b = 0x0; + + rtw8822c_dac_backup_reg(rtwdev, backup, backup_rf); + + rtw8822c_dac_bb_setting(rtwdev); + + /* path-A */ + rtw8822c_dac_cal_adc(rtwdev, RF_PATH_A, &adc_ic_a, &adc_qc_a); + for (i = 0; i < 10; i++) { + rtw8822c_dac_cal_step1(rtwdev, RF_PATH_A); + rtw8822c_dac_cal_step2(rtwdev, RF_PATH_A, &ic, &qc); + ic_a = ic; + qc_a = qc; + + rtw8822c_dac_cal_step3(rtwdev, RF_PATH_A, adc_ic_a, adc_qc_a, + &ic, &qc, &i_a, &q_a); + + if (ic < 5 && qc < 5) + break; + } + rtw8822c_dac_cal_step4(rtwdev, RF_PATH_A); + + /* path-B */ + rtw8822c_dac_cal_adc(rtwdev, RF_PATH_B, &adc_ic_b, &adc_qc_b); + for (i = 0; i < 10; i++) { + rtw8822c_dac_cal_step1(rtwdev, RF_PATH_B); + rtw8822c_dac_cal_step2(rtwdev, RF_PATH_B, &ic, &qc); + ic_b = ic; + qc_b = qc; + + rtw8822c_dac_cal_step3(rtwdev, RF_PATH_B, adc_ic_b, adc_qc_b, + &ic, &qc, &i_b, &q_b); + + if (ic < 5 && qc < 5) + break; + } + rtw8822c_dac_cal_step4(rtwdev, RF_PATH_B); + + rtw_write32(rtwdev, 0x1b00, 0x00000008); + rtw_write32_mask(rtwdev, 0x4130, BIT(30), 0x1); + rtw_write8(rtwdev, 0x1bcc, 0x0); + rtw_write32(rtwdev, 0x1b00, 0x0000000a); + rtw_write8(rtwdev, 0x1bcc, 0x0); + + rtw8822c_dac_restore_reg(rtwdev, backup, backup_rf); + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] path A: ic=0x%x, qc=0x%x\n", ic_a, qc_a); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] path B: ic=0x%x, qc=0x%x\n", ic_b, qc_b); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] path A: i=0x%x, q=0x%x\n", i_a, q_a); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[DACK] path B: i=0x%x, q=0x%x\n", i_b, q_b); +} + +static void rtw8822c_rf_x2_check(struct rtw_dev *rtwdev) +{ + u8 x2k_busy; + + mdelay(1); + x2k_busy = rtw_read_rf(rtwdev, RF_PATH_A, 0xb8, BIT(15)); + if (x2k_busy == 1) { + rtw_write_rf(rtwdev, RF_PATH_A, 0xb8, RFREG_MASK, 0xC4440); + rtw_write_rf(rtwdev, RF_PATH_A, 0xba, RFREG_MASK, 0x6840D); + rtw_write_rf(rtwdev, RF_PATH_A, 0xb8, RFREG_MASK, 0x80440); + mdelay(1); + } +} + +static void rtw8822c_rf_init(struct rtw_dev *rtwdev) +{ + rtw8822c_rf_dac_cal(rtwdev); + rtw8822c_rf_x2_check(rtwdev); +} + +static void rtw8822c_phy_set_param(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_hal *hal = &rtwdev->hal; + u8 crystal_cap; + u8 cck_gi_u_bnd_msb = 0; + u8 cck_gi_u_bnd_lsb = 0; + u8 cck_gi_l_bnd_msb = 0; + u8 cck_gi_l_bnd_lsb = 0; + bool is_tx2_path; + + /* power on BB/RF domain */ + rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, + BIT_FEN_BB_GLB_RST | BIT_FEN_BB_RSTB); + rtw_write8_set(rtwdev, REG_RF_CTRL, + BIT_RF_EN | BIT_RF_RSTB | BIT_RF_SDM_RSTB); + rtw_write32_set(rtwdev, REG_WLRF1, BIT_WLRF1_BBRF_EN); + + /* pre init before header files config */ + rtw8822c_header_file_init(rtwdev, true); + + rtw_phy_load_tables(rtwdev); + + crystal_cap = rtwdev->efuse.crystal_cap & 0x7f; + rtw_write32_mask(rtwdev, REG_ANAPAR_XTAL_0, 0xfffc00, + crystal_cap | (crystal_cap << 7)); + + /* post init after header files config */ + rtw8822c_header_file_init(rtwdev, false); + + is_tx2_path = false; + rtw8822c_config_trx_mode(rtwdev, hal->antenna_tx, hal->antenna_rx, + is_tx2_path); + rtw_phy_init(rtwdev); + + cck_gi_u_bnd_msb = (u8)rtw_read32_mask(rtwdev, 0x1a98, 0xc000); + cck_gi_u_bnd_lsb = (u8)rtw_read32_mask(rtwdev, 0x1aa8, 0xf0000); + cck_gi_l_bnd_msb = (u8)rtw_read32_mask(rtwdev, 0x1a98, 0xc0); + cck_gi_l_bnd_lsb = (u8)rtw_read32_mask(rtwdev, 0x1a70, 0x0f000000); + + dm_info->cck_gi_u_bnd = ((cck_gi_u_bnd_msb << 4) | (cck_gi_u_bnd_lsb)); + dm_info->cck_gi_l_bnd = ((cck_gi_l_bnd_msb << 4) | (cck_gi_l_bnd_lsb)); + + rtw8822c_rf_init(rtwdev); + /* wifi path controller */ + rtw_write32_mask(rtwdev, 0x70, 0xff000000, 0x0e); + rtw_write32_mask(rtwdev, 0x1704, 0xffffffff, 0x7700); + rtw_write32_mask(rtwdev, 0x1700, 0xffffffff, 0xc00f0038); + rtw_write32_mask(rtwdev, 0x6c0, 0xffffffff, 0xaaaaaaaa); + rtw_write32_mask(rtwdev, 0x6c4, 0xffffffff, 0xaaaaaaaa); +} + +#define WLAN_TXQ_RPT_EN 0x1F +#define WLAN_SLOT_TIME 0x09 +#define WLAN_PIFS_TIME 0x1C +#define WLAN_SIFS_CCK_CONT_TX 0x0A +#define WLAN_SIFS_OFDM_CONT_TX 0x0E +#define WLAN_SIFS_CCK_TRX 0x0A +#define WLAN_SIFS_OFDM_TRX 0x10 +#define WLAN_NAV_MAX 0xC8 +#define WLAN_RDG_NAV 0x05 +#define WLAN_TXOP_NAV 0x1B +#define WLAN_CCK_RX_TSF 0x30 +#define WLAN_OFDM_RX_TSF 0x30 +#define WLAN_TBTT_PROHIBIT 0x04 /* unit : 32us */ +#define WLAN_TBTT_HOLD_TIME 0x064 /* unit : 32us */ +#define WLAN_DRV_EARLY_INT 0x04 +#define WLAN_BCN_CTRL_CLT0 0x10 +#define WLAN_BCN_DMA_TIME 0x02 +#define WLAN_BCN_MAX_ERR 0xFF +#define WLAN_SIFS_CCK_DUR_TUNE 0x0A +#define WLAN_SIFS_OFDM_DUR_TUNE 0x10 +#define WLAN_SIFS_CCK_CTX 0x0A +#define WLAN_SIFS_CCK_IRX 0x0A +#define WLAN_SIFS_OFDM_CTX 0x0E +#define WLAN_SIFS_OFDM_IRX 0x0E +#define WLAN_EIFS_DUR_TUNE 0x40 +#define WLAN_EDCA_VO_PARAM 0x002FA226 +#define WLAN_EDCA_VI_PARAM 0x005EA328 +#define WLAN_EDCA_BE_PARAM 0x005EA42B +#define WLAN_EDCA_BK_PARAM 0x0000A44F + +#define WLAN_RX_FILTER0 0xFFFFFFFF +#define WLAN_RX_FILTER2 0xFFFF +#define WLAN_RCR_CFG 0xE400220E +#define WLAN_RXPKT_MAX_SZ 12288 +#define WLAN_RXPKT_MAX_SZ_512 (WLAN_RXPKT_MAX_SZ >> 9) + +#define WLAN_AMPDU_MAX_TIME 0x70 +#define WLAN_RTS_LEN_TH 0xFF +#define WLAN_RTS_TX_TIME_TH 0x08 +#define WLAN_MAX_AGG_PKT_LIMIT 0x20 +#define WLAN_RTS_MAX_AGG_PKT_LIMIT 0x20 +#define WLAN_PRE_TXCNT_TIME_TH 0x1E0 +#define FAST_EDCA_VO_TH 0x06 +#define FAST_EDCA_VI_TH 0x06 +#define FAST_EDCA_BE_TH 0x06 +#define FAST_EDCA_BK_TH 0x06 +#define WLAN_BAR_RETRY_LIMIT 0x01 +#define WLAN_BAR_ACK_TYPE 0x05 +#define WLAN_RA_TRY_RATE_AGG_LIMIT 0x08 +#define WLAN_RESP_TXRATE 0x84 +#define WLAN_ACK_TO 0x21 +#define WLAN_ACK_TO_CCK 0x6A +#define WLAN_DATA_RATE_FB_CNT_1_4 0x01000000 +#define WLAN_DATA_RATE_FB_CNT_5_8 0x08070504 +#define WLAN_RTS_RATE_FB_CNT_5_8 0x08070504 +#define WLAN_DATA_RATE_FB_RATE0 0xFE01F010 +#define WLAN_DATA_RATE_FB_RATE0_H 0x40000000 +#define WLAN_RTS_RATE_FB_RATE1 0x003FF010 +#define WLAN_RTS_RATE_FB_RATE1_H 0x40000000 +#define WLAN_RTS_RATE_FB_RATE4 0x0600F010 +#define WLAN_RTS_RATE_FB_RATE4_H 0x400003E0 +#define WLAN_RTS_RATE_FB_RATE5 0x0600F015 +#define WLAN_RTS_RATE_FB_RATE5_H 0x000000E0 + +#define WLAN_TX_FUNC_CFG1 0x30 +#define WLAN_TX_FUNC_CFG2 0x30 +#define WLAN_MAC_OPT_NORM_FUNC1 0x98 +#define WLAN_MAC_OPT_LB_FUNC1 0x80 +#define WLAN_MAC_OPT_FUNC2 0x30810041 + +#define WLAN_SIFS_CFG (WLAN_SIFS_CCK_CONT_TX | \ + (WLAN_SIFS_OFDM_CONT_TX << BIT_SHIFT_SIFS_OFDM_CTX) | \ + (WLAN_SIFS_CCK_TRX << BIT_SHIFT_SIFS_CCK_TRX) | \ + (WLAN_SIFS_OFDM_TRX << BIT_SHIFT_SIFS_OFDM_TRX)) + +#define WLAN_SIFS_DUR_TUNE (WLAN_SIFS_CCK_DUR_TUNE | \ + (WLAN_SIFS_OFDM_DUR_TUNE << 8)) + +#define WLAN_TBTT_TIME (WLAN_TBTT_PROHIBIT |\ + (WLAN_TBTT_HOLD_TIME << BIT_SHIFT_TBTT_HOLD_TIME_AP)) + +#define WLAN_NAV_CFG (WLAN_RDG_NAV | (WLAN_TXOP_NAV << 16)) +#define WLAN_RX_TSF_CFG (WLAN_CCK_RX_TSF | (WLAN_OFDM_RX_TSF) << 8) + +#define MAC_CLK_SPEED 80 /* 80M */ +#define EFUSE_PCB_INFO_OFFSET 0xCA + +static int rtw8822c_mac_init(struct rtw_dev *rtwdev) +{ + u8 value8; + u16 value16; + u32 value32; + u16 pre_txcnt; + + /* txq control */ + value8 = rtw_read8(rtwdev, REG_FWHW_TXQ_CTRL); + value8 |= (BIT(7) & ~BIT(1) & ~BIT(2)); + rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL, value8); + rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 1, WLAN_TXQ_RPT_EN); + /* sifs control */ + rtw_write16(rtwdev, REG_SPEC_SIFS, WLAN_SIFS_DUR_TUNE); + rtw_write32(rtwdev, REG_SIFS, WLAN_SIFS_CFG); + rtw_write16(rtwdev, REG_RESP_SIFS_CCK, + WLAN_SIFS_CCK_CTX | WLAN_SIFS_CCK_IRX << 8); + rtw_write16(rtwdev, REG_RESP_SIFS_OFDM, + WLAN_SIFS_OFDM_CTX | WLAN_SIFS_OFDM_IRX << 8); + /* rate fallback control */ + rtw_write32(rtwdev, REG_DARFRC, WLAN_DATA_RATE_FB_CNT_1_4); + rtw_write32(rtwdev, REG_DARFRCH, WLAN_DATA_RATE_FB_CNT_5_8); + rtw_write32(rtwdev, REG_RARFRCH, WLAN_RTS_RATE_FB_CNT_5_8); + rtw_write32(rtwdev, REG_ARFR0, WLAN_DATA_RATE_FB_RATE0); + rtw_write32(rtwdev, REG_ARFRH0, WLAN_DATA_RATE_FB_RATE0_H); + rtw_write32(rtwdev, REG_ARFR1_V1, WLAN_RTS_RATE_FB_RATE1); + rtw_write32(rtwdev, REG_ARFRH1_V1, WLAN_RTS_RATE_FB_RATE1_H); + rtw_write32(rtwdev, REG_ARFR4, WLAN_RTS_RATE_FB_RATE4); + rtw_write32(rtwdev, REG_ARFRH4, WLAN_RTS_RATE_FB_RATE4_H); + rtw_write32(rtwdev, REG_ARFR5, WLAN_RTS_RATE_FB_RATE5); + rtw_write32(rtwdev, REG_ARFRH5, WLAN_RTS_RATE_FB_RATE5_H); + /* protocol configuration */ + rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, WLAN_AMPDU_MAX_TIME); + rtw_write8_set(rtwdev, REG_TX_HANG_CTRL, BIT_EN_EOF_V1); + pre_txcnt = WLAN_PRE_TXCNT_TIME_TH | BIT_EN_PRECNT; + rtw_write8(rtwdev, REG_PRECNT_CTRL, (u8)(pre_txcnt & 0xFF)); + rtw_write8(rtwdev, REG_PRECNT_CTRL + 1, (u8)(pre_txcnt >> 8)); + value32 = WLAN_RTS_LEN_TH | (WLAN_RTS_TX_TIME_TH << 8) | + (WLAN_MAX_AGG_PKT_LIMIT << 16) | + (WLAN_RTS_MAX_AGG_PKT_LIMIT << 24); + rtw_write32(rtwdev, REG_PROT_MODE_CTRL, value32); + rtw_write16(rtwdev, REG_BAR_MODE_CTRL + 2, + WLAN_BAR_RETRY_LIMIT | WLAN_RA_TRY_RATE_AGG_LIMIT << 8); + rtw_write8(rtwdev, REG_FAST_EDCA_VOVI_SETTING, FAST_EDCA_VO_TH); + rtw_write8(rtwdev, REG_FAST_EDCA_VOVI_SETTING + 2, FAST_EDCA_VI_TH); + rtw_write8(rtwdev, REG_FAST_EDCA_BEBK_SETTING, FAST_EDCA_BE_TH); + rtw_write8(rtwdev, REG_FAST_EDCA_BEBK_SETTING + 2, FAST_EDCA_BK_TH); + /* close BA parser */ + rtw_write8_clr(rtwdev, REG_LIFETIME_EN, BIT_BA_PARSER_EN); + rtw_write32_clr(rtwdev, REG_RRSR, BITS_RRSR_RSC); + + /* EDCA configuration */ + rtw_write32(rtwdev, REG_EDCA_VO_PARAM, WLAN_EDCA_VO_PARAM); + rtw_write32(rtwdev, REG_EDCA_VI_PARAM, WLAN_EDCA_VI_PARAM); + rtw_write32(rtwdev, REG_EDCA_BE_PARAM, WLAN_EDCA_BE_PARAM); + rtw_write32(rtwdev, REG_EDCA_BK_PARAM, WLAN_EDCA_BK_PARAM); + rtw_write8(rtwdev, REG_PIFS, WLAN_PIFS_TIME); + rtw_write8_clr(rtwdev, REG_TX_PTCL_CTRL + 1, BIT_SIFS_BK_EN >> 8); + rtw_write8_set(rtwdev, REG_RD_CTRL + 1, + (BIT_DIS_TXOP_CFE | BIT_DIS_LSIG_CFE | + BIT_DIS_STBC_CFE) >> 8); + + /* MAC clock configuration */ + rtw_write32_clr(rtwdev, REG_AFE_CTRL1, BIT_MAC_CLK_SEL); + rtw_write8(rtwdev, REG_USTIME_TSF, MAC_CLK_SPEED); + rtw_write8(rtwdev, REG_USTIME_EDCA, MAC_CLK_SPEED); + + rtw_write8_set(rtwdev, REG_MISC_CTRL, + BIT_EN_FREE_CNT | BIT_DIS_SECOND_CCA); + rtw_write8_clr(rtwdev, REG_TIMER0_SRC_SEL, BIT_TSFT_SEL_TIMER0); + rtw_write16(rtwdev, REG_TXPAUSE, 0x0000); + rtw_write8(rtwdev, REG_SLOT, WLAN_SLOT_TIME); + rtw_write32(rtwdev, REG_RD_NAV_NXT, WLAN_NAV_CFG); + rtw_write16(rtwdev, REG_RXTSF_OFFSET_CCK, WLAN_RX_TSF_CFG); + /* Set beacon cotnrol - enable TSF and other related functions */ + rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); + /* Set send beacon related registers */ + rtw_write32(rtwdev, REG_TBTT_PROHIBIT, WLAN_TBTT_TIME); + rtw_write8(rtwdev, REG_DRVERLYINT, WLAN_DRV_EARLY_INT); + rtw_write8(rtwdev, REG_BCN_CTRL_CLINT0, WLAN_BCN_CTRL_CLT0); + rtw_write8(rtwdev, REG_BCNDMATIM, WLAN_BCN_DMA_TIME); + rtw_write8(rtwdev, REG_BCN_MAX_ERR, WLAN_BCN_MAX_ERR); + + /* WMAC configuration */ + rtw_write8(rtwdev, REG_BBPSF_CTRL + 2, WLAN_RESP_TXRATE); + rtw_write8(rtwdev, REG_ACKTO, WLAN_ACK_TO); + rtw_write8(rtwdev, REG_ACKTO_CCK, WLAN_ACK_TO_CCK); + rtw_write16(rtwdev, REG_EIFS, WLAN_EIFS_DUR_TUNE); + rtw_write8(rtwdev, REG_NAV_CTRL + 2, WLAN_NAV_MAX); + rtw_write8(rtwdev, REG_WMAC_TRXPTCL_CTL_H + 2, WLAN_BAR_ACK_TYPE); + rtw_write32(rtwdev, REG_RXFLTMAP0, WLAN_RX_FILTER0); + rtw_write16(rtwdev, REG_RXFLTMAP2, WLAN_RX_FILTER2); + rtw_write32(rtwdev, REG_RCR, WLAN_RCR_CFG); + rtw_write8(rtwdev, REG_RX_PKT_LIMIT, WLAN_RXPKT_MAX_SZ_512); + rtw_write8(rtwdev, REG_TCR + 2, WLAN_TX_FUNC_CFG2); + rtw_write8(rtwdev, REG_TCR + 1, WLAN_TX_FUNC_CFG1); + rtw_write32_set(rtwdev, REG_GENERAL_OPTION, BIT_DUMMY_FCS_READY_MASK_EN); + rtw_write32(rtwdev, REG_WMAC_OPTION_FUNCTION + 8, WLAN_MAC_OPT_FUNC2); + rtw_write8(rtwdev, REG_WMAC_OPTION_FUNCTION_1, WLAN_MAC_OPT_NORM_FUNC1); + + /* init low power */ + value16 = rtw_read16(rtwdev, REG_RXPSF_CTRL + 2) & 0xF00F; + value16 |= (BIT_RXGCK_VHT_FIFOTHR(1) | BIT_RXGCK_HT_FIFOTHR(1) | + BIT_RXGCK_OFDM_FIFOTHR(1) | BIT_RXGCK_CCK_FIFOTHR(1)) >> 16; + rtw_write16(rtwdev, REG_RXPSF_CTRL + 2, value16); + value16 = 0; + value16 = BIT_SET_RXPSF_PKTLENTHR(value16, 1); + value16 |= BIT_RXPSF_CTRLEN | BIT_RXPSF_VHTCHKEN | BIT_RXPSF_HTCHKEN + | BIT_RXPSF_OFDMCHKEN | BIT_RXPSF_CCKCHKEN + | BIT_RXPSF_OFDMRST; + rtw_write16(rtwdev, REG_RXPSF_CTRL, value16); + rtw_write32(rtwdev, REG_RXPSF_TYPE_CTRL, 0xFFFFFFFF); + /* rx ignore configuration */ + value16 = rtw_read16(rtwdev, REG_RXPSF_CTRL); + value16 &= ~(BIT_RXPSF_MHCHKEN | BIT_RXPSF_CCKRST | + BIT_RXPSF_CONT_ERRCHKEN); + value16 = BIT_SET_RXPSF_ERRTHR(value16, 0x07); + rtw_write16(rtwdev, REG_RXPSF_CTRL, value16); + + return 0; +} + +static void rtw8822c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw) +{ +#define RF18_BAND_MASK (BIT(16) | BIT(9) | BIT(8)) +#define RF18_BAND_2G (0) +#define RF18_BAND_5G (BIT(16) | BIT(8)) +#define RF18_CHANNEL_MASK (MASKBYTE0) +#define RF18_RFSI_MASK (BIT(18) | BIT(17)) +#define RF18_RFSI_GE_CH80 (BIT(17)) +#define RF18_RFSI_GT_CH140 (BIT(18)) +#define RF18_BW_MASK (BIT(13) | BIT(12)) +#define RF18_BW_20M (BIT(13) | BIT(12)) +#define RF18_BW_40M (BIT(13)) +#define RF18_BW_80M (BIT(12)) + + u32 rf_reg18 = 0; + u32 rf_rxbb = 0; + + rf_reg18 = rtw_read_rf(rtwdev, RF_PATH_A, 0x18, RFREG_MASK); + + rf_reg18 &= ~(RF18_BAND_MASK | RF18_CHANNEL_MASK | RF18_RFSI_MASK | + RF18_BW_MASK); + + rf_reg18 |= (channel <= 14 ? RF18_BAND_2G : RF18_BAND_5G); + rf_reg18 |= (channel & RF18_CHANNEL_MASK); + if (channel > 144) + rf_reg18 |= RF18_RFSI_GT_CH140; + else if (channel >= 80) + rf_reg18 |= RF18_RFSI_GE_CH80; + + switch (bw) { + case RTW_CHANNEL_WIDTH_5: + case RTW_CHANNEL_WIDTH_10: + case RTW_CHANNEL_WIDTH_20: + default: + rf_reg18 |= RF18_BW_20M; + rf_rxbb = 0x18; + break; + case RTW_CHANNEL_WIDTH_40: + /* RF bandwidth */ + rf_reg18 |= RF18_BW_40M; + rf_rxbb = 0x10; + break; + case RTW_CHANNEL_WIDTH_80: + rf_reg18 |= RF18_BW_80M; + rf_rxbb = 0x8; + break; + } + + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, 0x04, 0x01); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, 0x1f, 0x12); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, 0xfffff, rf_rxbb); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, 0x04, 0x00); + + rtw_write_rf(rtwdev, RF_PATH_B, RF_LUTWE2, 0x04, 0x01); + rtw_write_rf(rtwdev, RF_PATH_B, RF_LUTWA, 0x1f, 0x12); + rtw_write_rf(rtwdev, RF_PATH_B, RF_LUTWD0, 0xfffff, rf_rxbb); + rtw_write_rf(rtwdev, RF_PATH_B, RF_LUTWE2, 0x04, 0x00); + + rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, rf_reg18); + rtw_write_rf(rtwdev, RF_PATH_B, RF_CFGCH, RFREG_MASK, rf_reg18); +} + +static void rtw8822c_toggle_igi(struct rtw_dev *rtwdev) +{ + u32 igi; + + igi = rtw_read32_mask(rtwdev, REG_RXIGI, 0x7f); + rtw_write32_mask(rtwdev, REG_RXIGI, 0x7f, igi - 2); + rtw_write32_mask(rtwdev, REG_RXIGI, 0x7f00, igi - 2); + rtw_write32_mask(rtwdev, REG_RXIGI, 0x7f, igi); + rtw_write32_mask(rtwdev, REG_RXIGI, 0x7f00, igi); +} + +static void rtw8822c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw, + u8 primary_ch_idx) +{ + if (channel <= 14) { + rtw_write32_clr(rtwdev, REG_BGCTRL, BITS_RX_IQ_WEIGHT); + rtw_write32_mask(rtwdev, REG_RXCCKSEL, 0xf0000000, 0x8); + rtw_write32_set(rtwdev, REG_TXF4, BIT(20)); + rtw_write32_clr(rtwdev, REG_CCK_CHECK, BIT_CHECK_CCK_EN); + rtw_write32_clr(rtwdev, REG_CCKTXONLY, BIT_BB_CCK_CHECK_EN); + rtw_write32_mask(rtwdev, REG_CCAMSK, 0x3F000000, 0xF); + + rtw_write32_mask(rtwdev, REG_RXAGCCTL0, 0x1f0, 0x0); + rtw_write32_mask(rtwdev, REG_RXAGCCTL, 0x1f0, 0x0); + if (channel == 13 || channel == 14) + rtw_write32_mask(rtwdev, REG_SCOTRK, 0xfff, 0x969); + else if (channel == 11 || channel == 12) + rtw_write32_mask(rtwdev, REG_SCOTRK, 0xfff, 0x96a); + else + rtw_write32_mask(rtwdev, REG_SCOTRK, 0xfff, 0x9aa); + if (channel == 14) { + rtw_write32_mask(rtwdev, REG_TXF0, MASKHWORD, 0x3da0); + rtw_write32_mask(rtwdev, REG_TXF1, MASKDWORD, + 0x4962c931); + rtw_write32_mask(rtwdev, REG_TXF2, MASKLWORD, 0x6aa3); + rtw_write32_mask(rtwdev, REG_TXF3, MASKHWORD, 0xaa7b); + rtw_write32_mask(rtwdev, REG_TXF4, MASKLWORD, 0xf3d7); + rtw_write32_mask(rtwdev, REG_TXF5, MASKDWORD, 0x0); + rtw_write32_mask(rtwdev, REG_TXF6, MASKDWORD, + 0xff012455); + rtw_write32_mask(rtwdev, REG_TXF7, MASKDWORD, 0xffff); + } else { + rtw_write32_mask(rtwdev, REG_TXF0, MASKHWORD, 0x5284); + rtw_write32_mask(rtwdev, REG_TXF1, MASKDWORD, + 0x3e18fec8); + rtw_write32_mask(rtwdev, REG_TXF2, MASKLWORD, 0x0a88); + rtw_write32_mask(rtwdev, REG_TXF3, MASKHWORD, 0xacc4); + rtw_write32_mask(rtwdev, REG_TXF4, MASKLWORD, 0xc8b2); + rtw_write32_mask(rtwdev, REG_TXF5, MASKDWORD, + 0x00faf0de); + rtw_write32_mask(rtwdev, REG_TXF6, MASKDWORD, + 0x00122344); + rtw_write32_mask(rtwdev, REG_TXF7, MASKDWORD, + 0x0fffffff); + } + if (channel == 13) + rtw_write32_mask(rtwdev, REG_TXDFIR0, 0x70, 0x3); + else + rtw_write32_mask(rtwdev, REG_TXDFIR0, 0x70, 0x1); + } else if (channel > 35) { + rtw_write32_set(rtwdev, REG_CCKTXONLY, BIT_BB_CCK_CHECK_EN); + rtw_write32_set(rtwdev, REG_CCK_CHECK, BIT_CHECK_CCK_EN); + rtw_write32_set(rtwdev, REG_BGCTRL, BITS_RX_IQ_WEIGHT); + rtw_write32_clr(rtwdev, REG_TXF4, BIT(20)); + rtw_write32_mask(rtwdev, REG_RXCCKSEL, 0xf0000000, 0x0); + rtw_write32_mask(rtwdev, REG_CCAMSK, 0x3F000000, 0x22); + rtw_write32_mask(rtwdev, REG_TXDFIR0, 0x70, 0x3); + if (channel >= 36 && channel <= 64) { + rtw_write32_mask(rtwdev, REG_RXAGCCTL0, 0x1f0, 0x1); + rtw_write32_mask(rtwdev, REG_RXAGCCTL, 0x1f0, 0x1); + } else if (channel >= 100 && channel <= 144) { + rtw_write32_mask(rtwdev, REG_RXAGCCTL0, 0x1f0, 0x2); + rtw_write32_mask(rtwdev, REG_RXAGCCTL, 0x1f0, 0x2); + } else if (channel >= 149) { + rtw_write32_mask(rtwdev, REG_RXAGCCTL0, 0x1f0, 0x3); + rtw_write32_mask(rtwdev, REG_RXAGCCTL, 0x1f0, 0x3); + } + + if (channel >= 36 && channel <= 51) + rtw_write32_mask(rtwdev, REG_SCOTRK, 0xfff, 0x494); + else if (channel >= 52 && channel <= 55) + rtw_write32_mask(rtwdev, REG_SCOTRK, 0xfff, 0x493); + else if (channel >= 56 && channel <= 111) + rtw_write32_mask(rtwdev, REG_SCOTRK, 0xfff, 0x453); + else if (channel >= 112 && channel <= 119) + rtw_write32_mask(rtwdev, REG_SCOTRK, 0xfff, 0x452); + else if (channel >= 120 && channel <= 172) + rtw_write32_mask(rtwdev, REG_SCOTRK, 0xfff, 0x412); + else if (channel >= 173 && channel <= 177) + rtw_write32_mask(rtwdev, REG_SCOTRK, 0xfff, 0x411); + } + + switch (bw) { + case RTW_CHANNEL_WIDTH_20: + rtw_write32_mask(rtwdev, REG_DFIRBW, 0x3FF0, 0x19B); + rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xf, 0x0); + rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xffc0, 0x0); + rtw_write32_mask(rtwdev, REG_TXCLK, 0x700, 0x7); + rtw_write32_mask(rtwdev, REG_TXCLK, 0x700000, 0x6); + break; + case RTW_CHANNEL_WIDTH_40: + rtw_write32_mask(rtwdev, REG_CCKSB, BIT(4), + (primary_ch_idx == 1 ? 1 : 0)); + rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xf, 0x5); + rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xc0, 0x0); + rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xff00, + (primary_ch_idx | (primary_ch_idx << 4))); + break; + case RTW_CHANNEL_WIDTH_80: + rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xf, 0xa); + rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xc0, 0x0); + rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xff00, + (primary_ch_idx | (primary_ch_idx << 4))); + break; + case RTW_CHANNEL_WIDTH_5: + rtw_write32_mask(rtwdev, REG_DFIRBW, 0x3FF0, 0x2AB); + rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xf, 0x0); + rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xffc0, 0x1); + rtw_write32_mask(rtwdev, REG_TXCLK, 0x700, 0x4); + rtw_write32_mask(rtwdev, REG_TXCLK, 0x700000, 0x4); + break; + case RTW_CHANNEL_WIDTH_10: + rtw_write32_mask(rtwdev, REG_DFIRBW, 0x3FF0, 0x2AB); + rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xf, 0x0); + rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xffc0, 0x2); + rtw_write32_mask(rtwdev, REG_TXCLK, 0x700, 0x6); + rtw_write32_mask(rtwdev, REG_TXCLK, 0x700000, 0x5); + break; + } +} + +static void rtw8822c_set_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw, + u8 primary_chan_idx) +{ + rtw8822c_set_channel_bb(rtwdev, channel, bw, primary_chan_idx); + rtw_set_channel_mac(rtwdev, channel, bw, primary_chan_idx); + rtw8822c_set_channel_rf(rtwdev, channel, bw); + rtw8822c_toggle_igi(rtwdev); +} + +static void rtw8822c_config_cck_rx_path(struct rtw_dev *rtwdev, u8 rx_path) +{ + if (rx_path == BB_PATH_A || rx_path == BB_PATH_B) { + rtw_write32_mask(rtwdev, REG_CCANRX, 0x00060000, 0x0); + rtw_write32_mask(rtwdev, REG_CCANRX, 0x00600000, 0x0); + } else if (rx_path == BB_PATH_AB) { + rtw_write32_mask(rtwdev, REG_CCANRX, 0x00600000, 0x1); + rtw_write32_mask(rtwdev, REG_CCANRX, 0x00060000, 0x1); + } + + if (rx_path == BB_PATH_A) + rtw_write32_mask(rtwdev, REG_RXCCKSEL, 0x0f000000, 0x0); + else if (rx_path == BB_PATH_B) + rtw_write32_mask(rtwdev, REG_RXCCKSEL, 0x0f000000, 0x5); + else if (rx_path == BB_PATH_AB) + rtw_write32_mask(rtwdev, REG_RXCCKSEL, 0x0f000000, 0x1); +} + +static void rtw8822c_config_ofdm_rx_path(struct rtw_dev *rtwdev, u8 rx_path) +{ + if (rx_path == BB_PATH_A || rx_path == BB_PATH_B) { + rtw_write32_mask(rtwdev, REG_RXFNCTL, 0x300, 0x0); + rtw_write32_mask(rtwdev, REG_RXFNCTL, 0x600000, 0x0); + rtw_write32_mask(rtwdev, REG_AGCSWSH, BIT(17), 0x0); + rtw_write32_mask(rtwdev, REG_ANTWTPD, BIT(20), 0x0); + rtw_write32_mask(rtwdev, REG_MRCM, BIT(24), 0x0); + } else if (rx_path == BB_PATH_AB) { + rtw_write32_mask(rtwdev, REG_RXFNCTL, 0x300, 0x1); + rtw_write32_mask(rtwdev, REG_RXFNCTL, 0x600000, 0x1); + rtw_write32_mask(rtwdev, REG_AGCSWSH, BIT(17), 0x1); + rtw_write32_mask(rtwdev, REG_ANTWTPD, BIT(20), 0x1); + rtw_write32_mask(rtwdev, REG_MRCM, BIT(24), 0x1); + } + + rtw_write32_mask(rtwdev, 0x824, 0x0f000000, rx_path); + rtw_write32_mask(rtwdev, 0x824, 0x000f0000, rx_path); +} + +static void rtw8822c_config_rx_path(struct rtw_dev *rtwdev, u8 rx_path) +{ + rtw8822c_config_cck_rx_path(rtwdev, rx_path); + rtw8822c_config_ofdm_rx_path(rtwdev, rx_path); +} + +static void rtw8822c_config_cck_tx_path(struct rtw_dev *rtwdev, u8 tx_path, + bool is_tx2_path) +{ + if (tx_path == BB_PATH_A) { + rtw_write32_mask(rtwdev, REG_RXCCKSEL, 0xf0000000, 0x8); + } else if (tx_path == BB_PATH_B) { + rtw_write32_mask(rtwdev, REG_RXCCKSEL, 0xf0000000, 0x4); + } else { + if (is_tx2_path) + rtw_write32_mask(rtwdev, REG_RXCCKSEL, 0xf0000000, 0xc); + else + rtw_write32_mask(rtwdev, REG_RXCCKSEL, 0xf0000000, 0x8); + } +} + +static void rtw8822c_config_ofdm_tx_path(struct rtw_dev *rtwdev, u8 tx_path, + bool is_tx2_path) +{ + if (tx_path == BB_PATH_A) { + rtw_write32_mask(rtwdev, REG_ANTMAP0, 0xff, 0x11); + rtw_write32_mask(rtwdev, REG_TXLGMAP, 0xff, 0x0); + } else if (tx_path == BB_PATH_B) { + rtw_write32_mask(rtwdev, REG_ANTMAP0, 0xff, 0x12); + rtw_write32_mask(rtwdev, REG_TXLGMAP, 0xff, 0x0); + } else { + if (is_tx2_path) { + rtw_write32_mask(rtwdev, REG_ANTMAP0, 0xff, 0x33); + rtw_write32_mask(rtwdev, REG_TXLGMAP, 0xffff, 0x0404); + } else { + rtw_write32_mask(rtwdev, REG_ANTMAP0, 0xff, 0x31); + rtw_write32_mask(rtwdev, REG_TXLGMAP, 0xffff, 0x0400); + } + } +} + +static void rtw8822c_config_tx_path(struct rtw_dev *rtwdev, u8 tx_path, + bool is_tx2_path) +{ + rtw8822c_config_cck_tx_path(rtwdev, tx_path, is_tx2_path); + rtw8822c_config_ofdm_tx_path(rtwdev, tx_path, is_tx2_path); +} + +static void rtw8822c_config_trx_mode(struct rtw_dev *rtwdev, u8 tx_path, + u8 rx_path, bool is_tx2_path) +{ + if ((tx_path | rx_path) & BB_PATH_A) + rtw_write32_mask(rtwdev, REG_ORITXCODE, MASK20BITS, 0x33312); + else + rtw_write32_mask(rtwdev, REG_ORITXCODE, MASK20BITS, 0x11111); + if ((tx_path | rx_path) & BB_PATH_B) + rtw_write32_mask(rtwdev, REG_ORITXCODE2, MASK20BITS, 0x33312); + else + rtw_write32_mask(rtwdev, REG_ORITXCODE2, MASK20BITS, 0x11111); + + rtw8822c_config_rx_path(rtwdev, rx_path); + rtw8822c_config_tx_path(rtwdev, tx_path, is_tx2_path); + + rtw8822c_toggle_igi(rtwdev); +} + +static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status, + struct rtw_rx_pkt_stat *pkt_stat) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u8 l_bnd, u_bnd; + u8 gain_a, gain_b; + s8 rx_power[RTW_RF_PATH_MAX]; + s8 min_rx_power = -120; + + rx_power[RF_PATH_A] = GET_PHY_STAT_P0_PWDB_A(phy_status); + rx_power[RF_PATH_B] = GET_PHY_STAT_P0_PWDB_B(phy_status); + l_bnd = dm_info->cck_gi_l_bnd; + u_bnd = dm_info->cck_gi_u_bnd; + gain_a = GET_PHY_STAT_P0_GAIN_A(phy_status); + gain_b = GET_PHY_STAT_P0_GAIN_B(phy_status); + if (gain_a < l_bnd) + rx_power[RF_PATH_A] += (l_bnd - gain_a) << 1; + else if (gain_a > u_bnd) + rx_power[RF_PATH_A] -= (gain_a - u_bnd) << 1; + if (gain_b < l_bnd) + rx_power[RF_PATH_A] += (l_bnd - gain_b) << 1; + else if (gain_b > u_bnd) + rx_power[RF_PATH_A] -= (gain_b - u_bnd) << 1; + + rx_power[RF_PATH_A] -= 110; + rx_power[RF_PATH_B] -= 110; + + pkt_stat->rx_power[RF_PATH_A] = max3(rx_power[RF_PATH_A], + rx_power[RF_PATH_B], + min_rx_power); + pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1); + pkt_stat->bw = RTW_CHANNEL_WIDTH_20; + pkt_stat->signal_power = max(pkt_stat->rx_power[RF_PATH_A], + min_rx_power); +} + +static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status, + struct rtw_rx_pkt_stat *pkt_stat) +{ + u8 rxsc, bw; + s8 min_rx_power = -120; + + if (pkt_stat->rate > DESC_RATE11M && pkt_stat->rate < DESC_RATEMCS0) + rxsc = GET_PHY_STAT_P1_L_RXSC(phy_status); + else + rxsc = GET_PHY_STAT_P1_HT_RXSC(phy_status); + + if (rxsc >= 9 && rxsc <= 12) + bw = RTW_CHANNEL_WIDTH_40; + else if (rxsc >= 13) + bw = RTW_CHANNEL_WIDTH_80; + else + bw = RTW_CHANNEL_WIDTH_20; + + pkt_stat->rx_power[RF_PATH_A] = GET_PHY_STAT_P1_PWDB_A(phy_status) - 110; + pkt_stat->rx_power[RF_PATH_B] = GET_PHY_STAT_P1_PWDB_B(phy_status) - 110; + pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 2); + pkt_stat->bw = bw; + pkt_stat->signal_power = max3(pkt_stat->rx_power[RF_PATH_A], + pkt_stat->rx_power[RF_PATH_B], + min_rx_power); +} + +static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, + struct rtw_rx_pkt_stat *pkt_stat) +{ + u8 page; + + page = *phy_status & 0xf; + + switch (page) { + case 0: + query_phy_status_page0(rtwdev, phy_status, pkt_stat); + break; + case 1: + query_phy_status_page1(rtwdev, phy_status, pkt_stat); + break; + default: + rtw_warn(rtwdev, "unused phy status page (%d)\n", page); + return; + } +} + +static void rtw8822c_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, + struct rtw_rx_pkt_stat *pkt_stat, + struct ieee80211_rx_status *rx_status) +{ + struct ieee80211_hdr *hdr; + u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; + u8 *phy_status = NULL; + + memset(pkt_stat, 0, sizeof(*pkt_stat)); + + pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); + pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); + pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); + pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc); + pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); + pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); + pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); + pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); + pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); + pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); + pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc); + pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); + + /* drv_info_sz is in unit of 8-bytes */ + pkt_stat->drv_info_sz *= 8; + + /* c2h cmd pkt's rx/phy status is not interested */ + if (pkt_stat->is_c2h) + return; + + hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + + pkt_stat->drv_info_sz); + if (pkt_stat->phy_status) { + phy_status = rx_desc + desc_sz + pkt_stat->shift; + query_phy_status(rtwdev, phy_status, pkt_stat); + } + + rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); +} + +static void +rtw8822c_set_write_tx_power_ref(struct rtw_dev *rtwdev, u8 *tx_pwr_ref_cck, + u8 *tx_pwr_ref_ofdm) +{ + struct rtw_hal *hal = &rtwdev->hal; + u32 txref_cck[2] = {0x18a0, 0x41a0}; + u32 txref_ofdm[2] = {0x18e8, 0x41e8}; + u8 path; + + for (path = 0; path < hal->rf_path_num; path++) { + rtw_write32_mask(rtwdev, 0x1c90, BIT(15), 0); + rtw_write32_mask(rtwdev, txref_cck[path], 0x7f0000, + tx_pwr_ref_cck[path]); + } + for (path = 0; path < hal->rf_path_num; path++) { + rtw_write32_mask(rtwdev, 0x1c90, BIT(15), 0); + rtw_write32_mask(rtwdev, txref_ofdm[path], 0x1fc00, + tx_pwr_ref_ofdm[path]); + } +} + +static void rtw8822c_set_tx_power_diff(struct rtw_dev *rtwdev, u8 rate, + s8 *diff_idx) +{ + u32 offset_txagc = 0x3a00; + u8 rate_idx = rate & 0xfc; + u8 pwr_idx[4]; + u32 phy_pwr_idx; + int i; + + for (i = 0; i < 4; i++) + pwr_idx[i] = diff_idx[i] & 0x7f; + + phy_pwr_idx = pwr_idx[0] | + (pwr_idx[1] << 8) | + (pwr_idx[2] << 16) | + (pwr_idx[3] << 24); + + rtw_write32_mask(rtwdev, 0x1c90, BIT(15), 0x0); + rtw_write32_mask(rtwdev, offset_txagc + rate_idx, MASKDWORD, + phy_pwr_idx); +} + +static void rtw8822c_set_tx_power_index(struct rtw_dev *rtwdev) +{ + struct rtw_hal *hal = &rtwdev->hal; + u8 rs, rate, j; + u8 pwr_ref_cck[2] = {hal->tx_pwr_tbl[RF_PATH_A][DESC_RATE11M], + hal->tx_pwr_tbl[RF_PATH_B][DESC_RATE11M]}; + u8 pwr_ref_ofdm[2] = {hal->tx_pwr_tbl[RF_PATH_A][DESC_RATEMCS7], + hal->tx_pwr_tbl[RF_PATH_B][DESC_RATEMCS7]}; + s8 diff_a, diff_b; + u8 pwr_a, pwr_b; + s8 diff_idx[4]; + + rtw8822c_set_write_tx_power_ref(rtwdev, pwr_ref_cck, pwr_ref_ofdm); + for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++) { + for (j = 0; j < rtw_rate_size[rs]; j++) { + rate = rtw_rate_section[rs][j]; + pwr_a = hal->tx_pwr_tbl[RF_PATH_A][rate]; + pwr_b = hal->tx_pwr_tbl[RF_PATH_B][rate]; + if (rs == 0) { + diff_a = (s8)pwr_a - (s8)pwr_ref_cck[0]; + diff_b = (s8)pwr_b - (s8)pwr_ref_cck[1]; + } else { + diff_a = (s8)pwr_a - (s8)pwr_ref_ofdm[0]; + diff_b = (s8)pwr_b - (s8)pwr_ref_ofdm[1]; + } + diff_idx[rate % 4] = min(diff_a, diff_b); + if (rate % 4 == 3) + rtw8822c_set_tx_power_diff(rtwdev, rate - 3, + diff_idx); + } + } +} + +static void rtw8822c_cfg_ldo25(struct rtw_dev *rtwdev, bool enable) +{ + u8 ldo_pwr; + + ldo_pwr = rtw_read8(rtwdev, REG_ANAPARLDO_POW_MAC); + ldo_pwr = enable ? ldo_pwr | BIT_LDOE25_PON : ldo_pwr & ~BIT_LDOE25_PON; + rtw_write8(rtwdev, REG_ANAPARLDO_POW_MAC, ldo_pwr); +} + +static void rtw8822c_false_alarm_statistics(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u32 cck_enable; + u32 cck_fa_cnt; + u32 ofdm_fa_cnt; + u32 ofdm_tx_counter; + + cck_enable = rtw_read32(rtwdev, REG_ENCCK) & BIT_CCK_BLK_EN; + cck_fa_cnt = rtw_read16(rtwdev, REG_CCK_FACNT); + ofdm_fa_cnt = rtw_read16(rtwdev, REG_OFDM_FACNT); + ofdm_tx_counter = rtw_read16(rtwdev, REG_OFDM_TXCNT); + ofdm_fa_cnt -= ofdm_tx_counter; + + dm_info->cck_fa_cnt = cck_fa_cnt; + dm_info->ofdm_fa_cnt = ofdm_fa_cnt; + dm_info->total_fa_cnt = ofdm_fa_cnt; + dm_info->total_fa_cnt += cck_enable ? cck_fa_cnt : 0; + + rtw_write32_mask(rtwdev, REG_CCANRX, BIT_CCK_FA_RST, 0); + rtw_write32_mask(rtwdev, REG_CCANRX, BIT_CCK_FA_RST, 2); + rtw_write32_mask(rtwdev, REG_CCANRX, BIT_OFDM_FA_RST, 0); + rtw_write32_mask(rtwdev, REG_CCANRX, BIT_OFDM_FA_RST, 2); + rtw_write32_set(rtwdev, REG_CNT_CTRL, BIT_ALL_CNT_RST); + rtw_write32_clr(rtwdev, REG_CNT_CTRL, BIT_ALL_CNT_RST); +} + +static void rtw8822c_do_iqk(struct rtw_dev *rtwdev) +{ +} + +static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = { + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, BIT(0), 0}, + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_POLLING, BIT(1), BIT(1)}, + {0x002E, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(2), BIT(2)}, + {0x002D, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), 0}, + {0x007F, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(7), 0}, + {0x004A, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), 0}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(3) | BIT(4) | BIT(7), 0}, + {0xFFFF, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + 0, + RTW_PWR_CMD_END, 0, 0}, +}; + +static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822c[] = { + {0x0000, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(5), 0}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, (BIT(4) | BIT(3) | BIT(2)), 0}, + {0x0075, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_PCI_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, + {0x0006, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_POLLING, BIT(1), BIT(1)}, + {0x0075, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_PCI_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), 0}, + {0xFF1A, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0}, + {0x002E, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(3), 0}, + {0x0006, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(7), 0}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, (BIT(4) | BIT(3)), 0}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_POLLING, BIT(0), 0}, + {0x0074, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_PCI_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(5), BIT(5)}, + {0x0071, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_PCI_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(4), 0}, + {0x0062, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_PCI_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, (BIT(7) | BIT(6) | BIT(5)), + (BIT(7) | BIT(6) | BIT(5))}, + {0x0061, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_PCI_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, (BIT(7) | BIT(6) | BIT(5)), 0}, + {0x001F, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, (BIT(7) | BIT(6)), BIT(7)}, + {0x00EF, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, (BIT(7) | BIT(6)), BIT(7)}, + {0x1045, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(4), BIT(4)}, + {0x0010, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(2), BIT(2)}, + {0xFFFF, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + 0, + RTW_PWR_CMD_END, 0, 0}, +}; + +static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822c[] = { + {0x0093, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(3), 0}, + {0x001F, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0}, + {0x00EF, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0}, + {0x1045, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(4), 0}, + {0xFF1A, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0x30}, + {0x0049, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(1), 0}, + {0x0006, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, + {0x0002, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(1), 0}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(1), BIT(1)}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_POLLING, BIT(1), 0}, + {0x0000, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(5), BIT(5)}, + {0xFFFF, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + 0, + RTW_PWR_CMD_END, 0, 0}, +}; + +static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822c[] = { + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(7), BIT(7)}, + {0x0007, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0x00}, + {0x0067, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(5), 0}, + {0x004A, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), 0}, + {0x0081, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(7) | BIT(6), 0}, + {0x0090, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(1), 0}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)}, + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_PCI_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(2), BIT(2)}, + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, + {0xFFFF, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + 0, + RTW_PWR_CMD_END, 0, 0}, +}; + +static struct rtw_pwr_seq_cmd *card_enable_flow_8822c[] = { + trans_carddis_to_cardemu_8822c, + trans_cardemu_to_act_8822c, + NULL +}; + +static struct rtw_pwr_seq_cmd *card_disable_flow_8822c[] = { + trans_act_to_cardemu_8822c, + trans_cardemu_to_carddis_8822c, + NULL +}; + +static struct rtw_intf_phy_para usb2_param_8822c[] = { + {0xFFFF, 0x00, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_ALL, + RTW_INTF_PHY_PLATFORM_ALL}, +}; + +static struct rtw_intf_phy_para usb3_param_8822c[] = { + {0xFFFF, 0x0000, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_ALL, + RTW_INTF_PHY_PLATFORM_ALL}, +}; + +static struct rtw_intf_phy_para pcie_gen1_param_8822c[] = { + {0xFFFF, 0x0000, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_ALL, + RTW_INTF_PHY_PLATFORM_ALL}, +}; + +static struct rtw_intf_phy_para pcie_gen2_param_8822c[] = { + {0xFFFF, 0x0000, + RTW_IP_SEL_PHY, + RTW_INTF_PHY_CUT_ALL, + RTW_INTF_PHY_PLATFORM_ALL}, +}; + +static struct rtw_intf_phy_para_table phy_para_table_8822c = { + .usb2_para = usb2_param_8822c, + .usb3_para = usb3_param_8822c, + .gen1_para = pcie_gen1_param_8822c, + .gen2_para = pcie_gen2_param_8822c, + .n_usb2_para = ARRAY_SIZE(usb2_param_8822c), + .n_usb3_para = ARRAY_SIZE(usb2_param_8822c), + .n_gen1_para = ARRAY_SIZE(pcie_gen1_param_8822c), + .n_gen2_para = ARRAY_SIZE(pcie_gen2_param_8822c), +}; + +static const struct rtw_rfe_def rtw8822c_rfe_defs[] = { + [0] = RTW_DEF_RFE(8822c, 0, 0), + [1] = RTW_DEF_RFE(8822c, 0, 0), + [2] = RTW_DEF_RFE(8822c, 0, 0), +}; + +static struct rtw_hw_reg rtw8822c_dig[] = { + [0] = { .addr = 0x1d70, .mask = 0x7f }, + [1] = { .addr = 0x1d70, .mask = 0x7f00 }, +}; + +static struct rtw_page_table page_table_8822c[] = { + {64, 64, 64, 64, 1}, + {64, 64, 64, 64, 1}, + {64, 64, 0, 0, 1}, + {64, 64, 64, 0, 1}, + {64, 64, 64, 64, 1}, +}; + +static struct rtw_rqpn rqpn_table_8822c[] = { + {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, + RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, + RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, + {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, + RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, + RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, + {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, + RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_HIGH, + RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH}, + {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, + RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, + RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH}, + {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, + RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, + RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, +}; + +static struct rtw_chip_ops rtw8822c_ops = { + .phy_set_param = rtw8822c_phy_set_param, + .read_efuse = rtw8822c_read_efuse, + .query_rx_desc = rtw8822c_query_rx_desc, + .set_channel = rtw8822c_set_channel, + .mac_init = rtw8822c_mac_init, + .read_rf = rtw_phy_read_rf, + .write_rf = rtw_phy_write_rf_reg_mix, + .set_tx_power_index = rtw8822c_set_tx_power_index, + .cfg_ldo25 = rtw8822c_cfg_ldo25, + .false_alarm_statistics = rtw8822c_false_alarm_statistics, + .do_iqk = rtw8822c_do_iqk, +}; + +struct rtw_chip_info rtw8822c_hw_spec = { + .ops = &rtw8822c_ops, + .id = RTW_CHIP_TYPE_8822C, + .fw_name = "rtw88/rtw8822c_fw.bin", + .tx_pkt_desc_sz = 48, + .tx_buf_desc_sz = 16, + .rx_pkt_desc_sz = 24, + .rx_buf_desc_sz = 8, + .phy_efuse_size = 512, + .log_efuse_size = 768, + .ptct_efuse_size = 124, + .txff_size = 262144, + .rxff_size = 24576, + .txgi_factor = 2, + .is_pwr_by_rate_dec = false, + .max_power_index = 0x7f, + .csi_buf_pg_num = 50, + .band = RTW_BAND_2G | RTW_BAND_5G, + .page_size = 128, + .dig_min = 0x20, + .ht_supported = true, + .vht_supported = true, + .sys_func_en = 0xD8, + .pwr_on_seq = card_enable_flow_8822c, + .pwr_off_seq = card_disable_flow_8822c, + .page_table = page_table_8822c, + .rqpn_table = rqpn_table_8822c, + .intf_table = &phy_para_table_8822c, + .dig = rtw8822c_dig, + .rf_base_addr = {0x3c00, 0x4c00}, + .rf_sipi_addr = {0x1808, 0x4108}, + .mac_tbl = &rtw8822c_mac_tbl, + .agc_tbl = &rtw8822c_agc_tbl, + .bb_tbl = &rtw8822c_bb_tbl, + .rfk_init_tbl = &rtw8822c_array_mp_cal_init_tbl, + .rf_tbl = {&rtw8822c_rf_a_tbl, &rtw8822c_rf_b_tbl}, + .rfe_defs = rtw8822c_rfe_defs, + .rfe_defs_size = ARRAY_SIZE(rtw8822c_rfe_defs), +}; +EXPORT_SYMBOL(rtw8822c_hw_spec); + +MODULE_FIRMWARE("rtw88/rtw8822c_fw.bin"); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.h b/drivers/net/wireless/realtek/rtw88/rtw8822c.h new file mode 100644 index 000000000000..d3bd9850baa0 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.h @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW8822C_H__ +#define __RTW8822C_H__ + +#include <asm/byteorder.h> + +struct rtw8822cu_efuse { + u8 res0[0x30]; /* 0x120 */ + u8 vid[2]; /* 0x150 */ + u8 pid[2]; + u8 res1[3]; + u8 mac_addr[ETH_ALEN]; /* 0x157 */ + u8 res2[0x3d]; +}; + +struct rtw8822ce_efuse { + u8 mac_addr[ETH_ALEN]; /* 0x120 */ + u8 vender_id[2]; + u8 device_id[2]; + u8 sub_vender_id[2]; + u8 sub_device_id[2]; + u8 pmc[2]; + u8 exp_device_cap[2]; + u8 msi_cap; + u8 ltr_cap; /* 0x133 */ + u8 exp_link_control[2]; + u8 link_cap[4]; + u8 link_control[2]; + u8 serial_number[8]; + u8 res0:2; /* 0x144 */ + u8 ltr_en:1; + u8 res1:2; + u8 obff:2; + u8 res2:3; + u8 obff_cap:2; + u8 res3:4; + u8 class_code[3]; + u8 res4; + u8 pci_pm_L1_2_supp:1; + u8 pci_pm_L1_1_supp:1; + u8 aspm_pm_L1_2_supp:1; + u8 aspm_pm_L1_1_supp:1; + u8 L1_pm_substates_supp:1; + u8 res5:3; + u8 port_common_mode_restore_time; + u8 port_t_power_on_scale:2; + u8 res6:1; + u8 port_t_power_on_value:5; + u8 res7; +}; + +struct rtw8822c_efuse { + __le16 rtl_id; + u8 res0[0x0e]; + + /* power index for four RF paths */ + struct rtw_txpwr_idx txpwr_idx_table[4]; + + u8 channel_plan; /* 0xb8 */ + u8 xtal_k; + u8 res1; + u8 iqk_lck; + u8 res2[5]; /* 0xbc */ + u8 rf_board_option; + u8 rf_feature_option; + u8 rf_bt_setting; + u8 eeprom_version; + u8 eeprom_customer_id; + u8 tx_bb_swing_setting_2g; + u8 tx_bb_swing_setting_5g; + u8 tx_pwr_calibrate_rate; + u8 rf_antenna_option; /* 0xc9 */ + u8 rfe_option; + u8 country_code[2]; + u8 res3[3]; + u8 path_a_thermal; /* 0xd0 */ + u8 path_b_thermal; + u8 res4[2]; + u8 rx_gain_gap_2g_ofdm; + u8 res5; + u8 rx_gain_gap_2g_cck; + u8 res6; + u8 rx_gain_gap_5gl; + u8 res7; + u8 rx_gain_gap_5gm; + u8 res8; + u8 rx_gain_gap_5gh; + u8 res9; + u8 res10[0x42]; + union { + struct rtw8822cu_efuse u; + struct rtw8822ce_efuse e; + }; +}; + +#define DACK_PATH_8822C 2 +#define DACK_REG_8822C 16 +#define DACK_RF_8822C 1 +#define DACK_SN_8822C 100 + +/* phy status page0 */ +#define GET_PHY_STAT_P0_PWDB_A(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8)) +#define GET_PHY_STAT_P0_PWDB_B(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0)) +#define GET_PHY_STAT_P0_GAIN_A(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(21, 16)) +#define GET_PHY_STAT_P0_GAIN_B(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(29, 24)) + +/* phy status page1 */ +#define GET_PHY_STAT_P1_PWDB_A(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8)) +#define GET_PHY_STAT_P1_PWDB_B(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(23, 16)) +#define GET_PHY_STAT_P1_L_RXSC(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(11, 8)) +#define GET_PHY_STAT_P1_HT_RXSC(phy_stat) \ + le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(15, 12)) + +#define REG_ANAPARLDO_POW_MAC 0x0029 +#define BIT_LDOE25_PON BIT(0) +#define REG_RRSR 0x0440 +#define BITS_RRSR_RSC (BIT(21) | BIT(22)) + +#define REG_TXDFIR0 0x808 +#define REG_DFIRBW 0x810 +#define REG_ANTMAP0 0x820 +#define REG_ANTMAP 0x824 +#define REG_DYMPRITH 0x86c +#define REG_DYMENTH0 0x870 +#define REG_DYMENTH 0x874 +#define REG_DYMTHMIN 0x8a4 +#define REG_TXBWCTL 0x9b0 +#define REG_TXCLK 0x9b4 +#define REG_SCOTRK 0xc30 +#define REG_MRCM 0xc38 +#define REG_AGCSWSH 0xc44 +#define REG_ANTWTPD 0xc54 +#define REG_ORITXCODE 0x1800 +#define REG_3WIRE 0x180c +#define BIT_3WIRE_TX_EN BIT(0) +#define BIT_3WIRE_RX_EN BIT(1) +#define BIT_3WIRE_PI_ON BIT(28) +#define REG_RXAGCCTL0 0x18ac +#define REG_CCKSB 0x1a00 +#define REG_RXCCKSEL 0x1a04 +#define REG_BGCTRL 0x1a14 +#define BITS_RX_IQ_WEIGHT (BIT(8) | BIT(9)) +#define REG_TXF0 0x1a20 +#define REG_TXF1 0x1a24 +#define REG_TXF2 0x1a28 +#define REG_CCANRX 0x1a2c +#define BIT_CCK_FA_RST (BIT(14) | BIT(15)) +#define BIT_OFDM_FA_RST (BIT(12) | BIT(13)) +#define REG_CCK_FACNT 0x1a5c +#define REG_CCKTXONLY 0x1a80 +#define BIT_BB_CCK_CHECK_EN BIT(18) +#define REG_TXF3 0x1a98 +#define REG_TXF4 0x1a9c +#define REG_TXF5 0x1aa0 +#define REG_TXF6 0x1aac +#define REG_TXF7 0x1ab0 +#define REG_TXANT 0x1c28 +#define REG_ENCCK 0x1c3c +#define BIT_CCK_BLK_EN BIT(1) +#define BIT_CCK_OFDM_BLK_EN (BIT(0) | BIT(1)) +#define REG_CCAMSK 0x1c80 +#define REG_RXFNCTL 0x1d30 +#define REG_RXIGI 0x1d70 +#define REG_ENFN 0x1e24 +#define REG_TXANTSEG 0x1e28 +#define REG_TXLGMAP 0x1e2c +#define REG_CCKPATH 0x1e5c +#define REG_CNT_CTRL 0x1eb4 +#define BIT_ALL_CNT_RST BIT(25) +#define REG_OFDM_FACNT 0x2d00 +#define REG_OFDM_TXCNT 0x2de0 +#define REG_ORITXCODE2 0x4100 +#define REG_3WIRE2 0x410c +#define REG_RXAGCCTL 0x41ac + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c b/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c new file mode 100644 index 000000000000..49044f510c6c --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c @@ -0,0 +1,11753 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "phy.h" +#include "rtw8822c_table.h" + +static const u32 rtw8822c_mac[] = { +}; + +RTW_DECL_TABLE_PHY_COND(rtw8822c_mac, rtw_phy_cfg_mac); + +static const u32 rtw8822c_agc[] = { + 0x1D90, 0x300001FF, + 0x1D90, 0x300101FF, + 0x1D90, 0x300201FE, + 0x1D90, 0x300301FD, + 0x1D90, 0x300401FC, + 0x1D90, 0x300501FB, + 0x1D90, 0x300601FA, + 0x1D90, 0x300701F9, + 0x1D90, 0x300801F8, + 0x1D90, 0x300901F7, + 0x1D90, 0x300A01F6, + 0x1D90, 0x300B01F5, + 0x1D90, 0x300C01F4, + 0x1D90, 0x300D01F3, + 0x1D90, 0x300E01F2, + 0x1D90, 0x300F01F1, + 0x1D90, 0x301001F0, + 0x1D90, 0x301101EF, + 0x1D90, 0x301201EE, + 0x1D90, 0x301301ED, + 0x1D90, 0x301401EC, + 0x1D90, 0x301501EB, + 0x1D90, 0x30160192, + 0x1D90, 0x30170191, + 0x1D90, 0x30180190, + 0x1D90, 0x3019018F, + 0x1D90, 0x301A018E, + 0x1D90, 0x301B018D, + 0x1D90, 0x301C018C, + 0x1D90, 0x301D018B, + 0x1D90, 0x301E018A, + 0x1D90, 0x301F0189, + 0x1D90, 0x30200188, + 0x1D90, 0x30210187, + 0x1D90, 0x30220186, + 0x1D90, 0x30230185, + 0x1D90, 0x3024014B, + 0x1D90, 0x3025014A, + 0x1D90, 0x30260149, + 0x1D90, 0x30270148, + 0x1D90, 0x30280147, + 0x1D90, 0x30290146, + 0x1D90, 0x302A0145, + 0x1D90, 0x302B0144, + 0x1D90, 0x302C0143, + 0x1D90, 0x302D0142, + 0x1D90, 0x302E00C8, + 0x1D90, 0x302F00C7, + 0x1D90, 0x303000C6, + 0x1D90, 0x303100C5, + 0x1D90, 0x303200C4, + 0x1D90, 0x30330088, + 0x1D90, 0x30340087, + 0x1D90, 0x30350086, + 0x1D90, 0x30360045, + 0x1D90, 0x30370044, + 0x1D90, 0x30380043, + 0x1D90, 0x30390023, + 0x1D90, 0x303A0022, + 0x1D90, 0x303B0021, + 0x1D90, 0x303C0020, + 0x1D90, 0x303D0002, + 0x1D90, 0x303E0001, + 0x1D90, 0x303F0000, + 0x1D90, 0x304000FF, + 0x1D90, 0x304100FF, + 0x1D90, 0x304200FF, + 0x1D90, 0x304300FF, + 0x1D90, 0x304400FE, + 0x1D90, 0x304500FD, + 0x1D90, 0x304600FC, + 0x1D90, 0x304700FB, + 0x1D90, 0x304800FA, + 0x1D90, 0x304900F9, + 0x1D90, 0x304A00F8, + 0x1D90, 0x304B00F7, + 0x1D90, 0x304C00F6, + 0x1D90, 0x304D00F5, + 0x1D90, 0x304E00F4, + 0x1D90, 0x304F00F3, + 0x1D90, 0x305000F2, + 0x1D90, 0x305100F1, + 0x1D90, 0x305200F0, + 0x1D90, 0x305300EF, + 0x1D90, 0x305400EE, + 0x1D90, 0x305500ED, + 0x1D90, 0x305600EC, + 0x1D90, 0x305700EB, + 0x1D90, 0x305800EA, + 0x1D90, 0x305900E9, + 0x1D90, 0x305A00E8, + 0x1D90, 0x305B00E7, + 0x1D90, 0x305C00E6, + 0x1D90, 0x305D00C7, + 0x1D90, 0x305E00C6, + 0x1D90, 0x305F00C5, + 0x1D90, 0x306000C4, + 0x1D90, 0x306100C3, + 0x1D90, 0x306200C2, + 0x1D90, 0x306300A4, + 0x1D90, 0x306400A3, + 0x1D90, 0x306500A2, + 0x1D90, 0x30660086, + 0x1D90, 0x30670085, + 0x1D90, 0x30680084, + 0x1D90, 0x30690083, + 0x1D90, 0x306A0082, + 0x1D90, 0x306B0069, + 0x1D90, 0x306C0068, + 0x1D90, 0x306D0067, + 0x1D90, 0x306E0066, + 0x1D90, 0x306F0065, + 0x1D90, 0x30700064, + 0x1D90, 0x30710063, + 0x1D90, 0x30720044, + 0x1D90, 0x30730043, + 0x1D90, 0x30740042, + 0x1D90, 0x30750025, + 0x1D90, 0x30760024, + 0x1D90, 0x30770023, + 0x1D90, 0x30780022, + 0x1D90, 0x30790021, + 0x1D90, 0x307A0020, + 0x1D90, 0x307B0003, + 0x1D90, 0x307C0002, + 0x1D90, 0x307D0001, + 0x1D90, 0x307E0000, + 0x1D90, 0x307F0000, + 0x1D90, 0x308000FF, + 0x1D90, 0x308100FF, + 0x1D90, 0x308200FF, + 0x1D90, 0x308300FF, + 0x1D90, 0x308400FE, + 0x1D90, 0x308500FD, + 0x1D90, 0x308600FC, + 0x1D90, 0x308700FB, + 0x1D90, 0x308800FA, + 0x1D90, 0x308900F9, + 0x1D90, 0x308A00F8, + 0x1D90, 0x308B00F7, + 0x1D90, 0x308C00F6, + 0x1D90, 0x308D00F5, + 0x1D90, 0x308E00F4, + 0x1D90, 0x308F00F3, + 0x1D90, 0x309000F2, + 0x1D90, 0x309100F1, + 0x1D90, 0x309200F0, + 0x1D90, 0x309300EF, + 0x1D90, 0x309400EE, + 0x1D90, 0x309500ED, + 0x1D90, 0x309600EC, + 0x1D90, 0x309700EB, + 0x1D90, 0x309800EA, + 0x1D90, 0x309900E9, + 0x1D90, 0x309A00E8, + 0x1D90, 0x309B00E7, + 0x1D90, 0x309C00E6, + 0x1D90, 0x309D00C7, + 0x1D90, 0x309E00C6, + 0x1D90, 0x309F00C5, + 0x1D90, 0x30A000C4, + 0x1D90, 0x30A100C3, + 0x1D90, 0x30A200C2, + 0x1D90, 0x30A300A4, + 0x1D90, 0x30A400A3, + 0x1D90, 0x30A500A2, + 0x1D90, 0x30A60086, + 0x1D90, 0x30A70085, + 0x1D90, 0x30A80084, + 0x1D90, 0x30A90083, + 0x1D90, 0x30AA0082, + 0x1D90, 0x30AB0069, + 0x1D90, 0x30AC0068, + 0x1D90, 0x30AD0067, + 0x1D90, 0x30AE0066, + 0x1D90, 0x30AF0065, + 0x1D90, 0x30B00064, + 0x1D90, 0x30B10063, + 0x1D90, 0x30B20044, + 0x1D90, 0x30B30043, + 0x1D90, 0x30B40042, + 0x1D90, 0x30B50025, + 0x1D90, 0x30B60024, + 0x1D90, 0x30B70023, + 0x1D90, 0x30B80022, + 0x1D90, 0x30B90021, + 0x1D90, 0x30BA0020, + 0x1D90, 0x30BB0003, + 0x1D90, 0x30BC0002, + 0x1D90, 0x30BD0001, + 0x1D90, 0x30BE0000, + 0x1D90, 0x30BF0000, + 0x1D90, 0x30C000FF, + 0x1D90, 0x30C100FF, + 0x1D90, 0x30C200FF, + 0x1D90, 0x30C300FF, + 0x1D90, 0x30C400FE, + 0x1D90, 0x30C500FD, + 0x1D90, 0x30C600FC, + 0x1D90, 0x30C700FB, + 0x1D90, 0x30C800FA, + 0x1D90, 0x30C900F9, + 0x1D90, 0x30CA00F8, + 0x1D90, 0x30CB00F7, + 0x1D90, 0x30CC00F6, + 0x1D90, 0x30CD00F5, + 0x1D90, 0x30CE00F4, + 0x1D90, 0x30CF00F3, + 0x1D90, 0x30D000F2, + 0x1D90, 0x30D100F1, + 0x1D90, 0x30D200F0, + 0x1D90, 0x30D300EF, + 0x1D90, 0x30D400EE, + 0x1D90, 0x30D500ED, + 0x1D90, 0x30D600EC, + 0x1D90, 0x30D700EB, + 0x1D90, 0x30D800EA, + 0x1D90, 0x30D900E9, + 0x1D90, 0x30DA00E8, + 0x1D90, 0x30DB00E7, + 0x1D90, 0x30DC00E6, + 0x1D90, 0x30DD00C7, + 0x1D90, 0x30DE00C6, + 0x1D90, 0x30DF00C5, + 0x1D90, 0x30E000C4, + 0x1D90, 0x30E100C3, + 0x1D90, 0x30E200C2, + 0x1D90, 0x30E300A4, + 0x1D90, 0x30E400A3, + 0x1D90, 0x30E500A2, + 0x1D90, 0x30E60086, + 0x1D90, 0x30E70085, + 0x1D90, 0x30E80084, + 0x1D90, 0x30E90083, + 0x1D90, 0x30EA0082, + 0x1D90, 0x30EB0069, + 0x1D90, 0x30EC0068, + 0x1D90, 0x30ED0067, + 0x1D90, 0x30EE0066, + 0x1D90, 0x30EF0065, + 0x1D90, 0x30F00064, + 0x1D90, 0x30F10063, + 0x1D90, 0x30F20044, + 0x1D90, 0x30F30043, + 0x1D90, 0x30F40042, + 0x1D90, 0x30F50025, + 0x1D90, 0x30F60024, + 0x1D90, 0x30F70023, + 0x1D90, 0x30F80022, + 0x1D90, 0x30F90021, + 0x1D90, 0x30FA0020, + 0x1D90, 0x30FB0003, + 0x1D90, 0x30FC0002, + 0x1D90, 0x30FD0001, + 0x1D90, 0x30FE0000, + 0x1D90, 0x30FF0000, + 0x1D90, 0x310001FF, + 0x1D90, 0x310101FF, + 0x1D90, 0x310201FF, + 0x1D90, 0x310301FF, + 0x1D90, 0x310401FF, + 0x1D90, 0x310501FF, + 0x1D90, 0x310601FF, + 0x1D90, 0x310701FF, + 0x1D90, 0x310801FF, + 0x1D90, 0x310901FE, + 0x1D90, 0x310A01FD, + 0x1D90, 0x310B01FC, + 0x1D90, 0x310C01FB, + 0x1D90, 0x310D01FA, + 0x1D90, 0x310E01F9, + 0x1D90, 0x310F01F8, + 0x1D90, 0x311001F7, + 0x1D90, 0x311101F6, + 0x1D90, 0x311201F5, + 0x1D90, 0x311301F4, + 0x1D90, 0x311401F3, + 0x1D90, 0x311501F2, + 0x1D90, 0x311601F1, + 0x1D90, 0x311701F0, + 0x1D90, 0x311801EF, + 0x1D90, 0x311901EE, + 0x1D90, 0x311A01ED, + 0x1D90, 0x311B01EC, + 0x1D90, 0x311C01EB, + 0x1D90, 0x311D0192, + 0x1D90, 0x311E0191, + 0x1D90, 0x311F0190, + 0x1D90, 0x3120018F, + 0x1D90, 0x3121018E, + 0x1D90, 0x3122018D, + 0x1D90, 0x3123018C, + 0x1D90, 0x3124018B, + 0x1D90, 0x3125018A, + 0x1D90, 0x31260189, + 0x1D90, 0x31270188, + 0x1D90, 0x31280187, + 0x1D90, 0x31290186, + 0x1D90, 0x312A0185, + 0x1D90, 0x312B0149, + 0x1D90, 0x312C0148, + 0x1D90, 0x312D0147, + 0x1D90, 0x312E0146, + 0x1D90, 0x312F0145, + 0x1D90, 0x31300144, + 0x1D90, 0x31310143, + 0x1D90, 0x31320142, + 0x1D90, 0x31330141, + 0x1D90, 0x31340140, + 0x1D90, 0x313500C7, + 0x1D90, 0x313600C6, + 0x1D90, 0x313700C5, + 0x1D90, 0x313800C4, + 0x1D90, 0x313900C3, + 0x1D90, 0x313A0088, + 0x1D90, 0x313B0087, + 0x1D90, 0x313C0086, + 0x1D90, 0x313D0045, + 0x1D90, 0x313E0044, + 0x1D90, 0x313F0043, + 0x1D90, 0x314001FF, + 0x1D90, 0x314101FF, + 0x1D90, 0x314201FF, + 0x1D90, 0x314301FF, + 0x1D90, 0x314401FF, + 0x1D90, 0x314501FF, + 0x1D90, 0x314601FF, + 0x1D90, 0x314701FE, + 0x1D90, 0x314801FD, + 0x1D90, 0x314901FC, + 0x1D90, 0x314A01FB, + 0x1D90, 0x314B01FA, + 0x1D90, 0x314C01F9, + 0x1D90, 0x314D01F8, + 0x1D90, 0x314E01F7, + 0x1D90, 0x314F01F6, + 0x1D90, 0x315001F5, + 0x1D90, 0x315101F4, + 0x1D90, 0x315201F3, + 0x1D90, 0x315301F2, + 0x1D90, 0x315401F1, + 0x1D90, 0x315501F0, + 0x1D90, 0x315601EF, + 0x1D90, 0x315701EE, + 0x1D90, 0x315801ED, + 0x1D90, 0x315901EC, + 0x1D90, 0x315A01EB, + 0x1D90, 0x315B01EA, + 0x1D90, 0x315C01E9, + 0x1D90, 0x315D018F, + 0x1D90, 0x315E018E, + 0x1D90, 0x315F018D, + 0x1D90, 0x3160018C, + 0x1D90, 0x3161018B, + 0x1D90, 0x3162018A, + 0x1D90, 0x31630189, + 0x1D90, 0x31640188, + 0x1D90, 0x31650187, + 0x1D90, 0x31660186, + 0x1D90, 0x31670185, + 0x1D90, 0x31680184, + 0x1D90, 0x31690183, + 0x1D90, 0x316A0182, + 0x1D90, 0x316B0149, + 0x1D90, 0x316C0148, + 0x1D90, 0x316D0147, + 0x1D90, 0x316E0146, + 0x1D90, 0x316F0145, + 0x1D90, 0x31700144, + 0x1D90, 0x31710143, + 0x1D90, 0x31720142, + 0x1D90, 0x31730141, + 0x1D90, 0x31740140, + 0x1D90, 0x317500C7, + 0x1D90, 0x317600C6, + 0x1D90, 0x317700C5, + 0x1D90, 0x317800C4, + 0x1D90, 0x317900C3, + 0x1D90, 0x317A0088, + 0x1D90, 0x317B0087, + 0x1D90, 0x317C0086, + 0x1D90, 0x317D0045, + 0x1D90, 0x317E0044, + 0x1D90, 0x317F0043, + 0x1D90, 0x318001FE, + 0x1D90, 0x318101FD, + 0x1D90, 0x318201FC, + 0x1D90, 0x318301FB, + 0x1D90, 0x318401FA, + 0x1D90, 0x318501F9, + 0x1D90, 0x318601F8, + 0x1D90, 0x318701F7, + 0x1D90, 0x318801F6, + 0x1D90, 0x318901F5, + 0x1D90, 0x318A01F4, + 0x1D90, 0x318B01F3, + 0x1D90, 0x318C01F2, + 0x1D90, 0x318D01F1, + 0x1D90, 0x318E01F0, + 0x1D90, 0x318F01EF, + 0x1D90, 0x319001EE, + 0x1D90, 0x319101ED, + 0x1D90, 0x319201EC, + 0x1D90, 0x319301EB, + 0x1D90, 0x319401EA, + 0x1D90, 0x319501E9, + 0x1D90, 0x3196018F, + 0x1D90, 0x3197018E, + 0x1D90, 0x3198018D, + 0x1D90, 0x3199018C, + 0x1D90, 0x319A018B, + 0x1D90, 0x319B018A, + 0x1D90, 0x319C0189, + 0x1D90, 0x319D0188, + 0x1D90, 0x319E0187, + 0x1D90, 0x319F0186, + 0x1D90, 0x31A00185, + 0x1D90, 0x31A10184, + 0x1D90, 0x31A20183, + 0x1D90, 0x31A30182, + 0x1D90, 0x31A40149, + 0x1D90, 0x31A50148, + 0x1D90, 0x31A60147, + 0x1D90, 0x31A70146, + 0x1D90, 0x31A80145, + 0x1D90, 0x31A90144, + 0x1D90, 0x31AA0143, + 0x1D90, 0x31AB0142, + 0x1D90, 0x31AC0141, + 0x1D90, 0x31AD0140, + 0x1D90, 0x31AE00C7, + 0x1D90, 0x31AF00C6, + 0x1D90, 0x31B000C5, + 0x1D90, 0x31B100C4, + 0x1D90, 0x31B200C3, + 0x1D90, 0x31B30088, + 0x1D90, 0x31B40087, + 0x1D90, 0x31B50086, + 0x1D90, 0x31B60045, + 0x1D90, 0x31B70044, + 0x1D90, 0x31B80043, + 0x1D90, 0x31B90023, + 0x1D90, 0x31BA0022, + 0x1D90, 0x31BB0021, + 0x1D90, 0x31BC0020, + 0x1D90, 0x31BD0002, + 0x1D90, 0x31BE0001, + 0x1D90, 0x31BF0000, + 0x1D70, 0x22222222, + 0x1D70, 0x20202020, +}; + +RTW_DECL_TABLE_PHY_COND(rtw8822c_agc, rtw_phy_cfg_agc); + +static const u32 rtw8822c_bb[] = { + 0x1D0C, 0x00410000, + 0x1C3C, 0x01038040, + 0x1C90, 0x00E49708, + 0x800, 0x00000000, + 0x804, 0xD6300000, + 0x808, 0x60956093, + 0x80C, 0x00000025, + 0x810, 0x11B019B0, + 0x814, 0x00904080, + 0x818, 0xC30056F1, + 0x81C, 0x00050000, + 0x820, 0x11111133, + 0x824, 0xC3C3CCC4, + 0x828, 0x30FB186C, + 0x82C, 0x185D6556, + 0x830, 0x1751145B, + 0x834, 0x776995D7, + 0x838, 0x74777A7D, + 0x83C, 0xF9AA9982, + 0x840, 0x89AA9ABB, + 0x844, 0x0DEEDDC1, + 0x848, 0xCDEEDEFF, + 0x84C, 0xFFFF5555, + 0x850, 0x6F7A727D, + 0x854, 0x6C776F7A, + 0x858, 0x6F7A6C77, + 0x85C, 0x69746974, + 0x860, 0x6F7A6C77, + 0x864, 0x6C776C77, + 0x868, 0x727D6F7A, + 0x86C, 0x69D7B196, + 0x870, 0x1A6D769B, + 0x874, 0x55823917, + 0x878, 0x00C025BD, + 0x87C, 0x4140557D, + 0x880, 0x9A1D9D47, + 0x884, 0x1DE7134F, + 0x888, 0x2857A857, + 0x88C, 0x520E8A24, + 0x890, 0x8F628C44, + 0x894, 0x72745F43, + 0x898, 0x03F02F0D, + 0x89C, 0x5DB6886F, + 0x8A0, 0x07DC309F, + 0x8A4, 0x09412495, + 0x8A8, 0x222222A9, + 0x8AC, 0x89628C44, + 0x8B0, 0x72745F43, + 0x8B4, 0x03F02F0D, + 0x8B8, 0x55B6886F, + 0x8BC, 0x07D0309F, + 0x8C0, 0x70404023, + 0x8C4, 0x00440001, + 0x8C8, 0x7A7A2E26, + 0x8CC, 0x25297777, + 0x8D0, 0x6CEB6DCE, + 0x8D4, 0x0005A632, + 0x8D8, 0x00000000, + 0x8DC, 0x00000000, + 0x8E0, 0x00000000, + 0x8E4, 0x00000000, + 0x8E8, 0x00000000, + 0x8EC, 0x00000000, + 0x8F0, 0x00000000, + 0x8F4, 0x00000000, + 0x8F8, 0x25239843, + 0x900, 0x00000000, + 0x904, 0x00000000, + 0x908, 0x000008CB, + 0x90C, 0x00000000, + 0x910, 0x00000000, + 0x914, 0x20000000, + 0x918, 0x20000000, + 0x91C, 0x20000000, + 0x920, 0x20000000, + 0x924, 0x00000000, + 0x928, 0x0000003A, + 0x92C, 0x0000003A, + 0x930, 0x0000003A, + 0x934, 0x0000003A, + 0x938, 0x0000000F, + 0x93C, 0x00000000, + 0x940, 0x4E1F3E81, + 0x944, 0x4E1F3E81, + 0x948, 0x4E1F3E81, + 0x94C, 0x4E1F3E81, + 0x950, 0x03020100, + 0x954, 0x07060504, + 0x958, 0x0B0A0908, + 0x95C, 0x0F0E0D0C, + 0x960, 0x13121110, + 0x964, 0x17161514, + 0x968, 0x03020100, + 0x96C, 0x07060504, + 0x970, 0x0B0A0908, + 0x974, 0x0F0E0D0C, + 0x978, 0x13121110, + 0x97C, 0x17161514, + 0x980, 0x03020100, + 0x984, 0x07060504, + 0x988, 0x0B0A0908, + 0x98C, 0x0F0E0D0C, + 0x990, 0x13121110, + 0x994, 0x17161514, + 0x998, 0x03020100, + 0x99C, 0x07060504, + 0x9A0, 0x0B0A0908, + 0x9A4, 0x0F0E0D0C, + 0x9A8, 0x13121110, + 0x9AC, 0x17161514, + 0x9B0, 0x00002200, + 0x9B4, 0xDB6FFF00, + 0x9B8, 0x00400064, + 0x9BC, 0x00000000, + 0x9C0, 0x01010101, + 0x9C4, 0x00640064, + 0x9C8, 0x00640064, + 0x9CC, 0x00007777, + 0x9D0, 0x00000000, + 0x9D4, 0x00000000, + 0x9D8, 0x00000000, + 0x9DC, 0x00000000, + 0x9E0, 0x00000000, + 0x9E4, 0x00000000, + 0x9E8, 0x00000000, + 0x9EC, 0x00000000, + 0x9F0, 0x100024E0, + 0x9F4, 0x00000000, + 0x9F8, 0x00000000, + 0xA00, 0x02001208, + 0xA04, 0x00000000, + 0xA08, 0x00000000, + 0xA0C, 0x00000000, + 0xA10, 0x00000000, + 0xA14, 0x00000000, + 0xA18, 0x00000000, + 0xA1C, 0x00000000, + 0xA20, 0xEB31B333, + 0xA24, 0x00275485, + 0xA28, 0x00166366, + 0xA2C, 0x00275485, + 0xA30, 0x00166366, + 0xA34, 0x00275485, + 0xA38, 0x00200400, + 0xA3C, 0x00200400, + 0xA40, 0xB35DC5BD, + 0xA44, 0x3033BEBD, + 0xA48, 0x2A521254, + 0xA4C, 0xA2733345, + 0xA50, 0x617BE003, + 0xA54, 0x50000968, + 0xA58, 0x00020000, + 0xA5C, 0x01000000, + 0xA60, 0x02000000, + 0xA64, 0x03000000, + 0xA68, 0x00020000, + 0xA6C, 0x00000000, + 0xA70, 0x00000000, + 0xA74, 0x00000000, + 0xA78, 0x00000000, + 0xA7C, 0x00000000, + 0xA80, 0x00000000, + 0xA84, 0x00000000, + 0xA88, 0x00000000, + 0xA8C, 0x00000000, + 0xA90, 0x00000000, + 0xA94, 0x00000000, + 0xA98, 0x00000000, + 0xA9C, 0x00000000, + 0xAA0, 0x00000000, + 0xAA4, 0x00000000, + 0xAA8, 0x00000000, + 0xAAC, 0x00000000, + 0xAB0, 0x00000000, + 0xAB4, 0x00000000, + 0xAB8, 0x00000000, + 0xABC, 0x00000000, + 0xAC0, 0x00000000, + 0xAC4, 0x00000000, + 0xAC8, 0x00000000, + 0xACC, 0x00000000, + 0xAD0, 0x00000000, + 0xAD4, 0x00000000, + 0xAD8, 0x00000000, + 0xADC, 0x00000000, + 0xAE0, 0x00000000, + 0xAE4, 0x00000000, + 0xAE8, 0x00000000, + 0xAEC, 0x00000000, + 0xAF0, 0x00000000, + 0xAF4, 0x00000000, + 0xAF8, 0x00000000, + 0xB00, 0x00000000, + 0xB04, 0x00000000, + 0xB08, 0x00000000, + 0xB0C, 0x00000000, + 0xB10, 0x00000000, + 0xB14, 0x00000000, + 0xB18, 0x00000000, + 0xB1C, 0x00000000, + 0xB20, 0x00000000, + 0xB24, 0x00000000, + 0xB28, 0x00000000, + 0xB2C, 0x00000000, + 0xB30, 0x00000000, + 0xB34, 0x00000000, + 0xB38, 0x00000000, + 0xB3C, 0x00000000, + 0xB40, 0x00000000, + 0xB44, 0x00000000, + 0xB48, 0x00000000, + 0xB4C, 0x00000000, + 0xB50, 0x00000000, + 0xB54, 0x00000000, + 0xB58, 0x00060100, + 0xB5C, 0x00000000, + 0xB60, 0x00000000, + 0xB64, 0x00000000, + 0xB68, 0x00000000, + 0xB6C, 0x00000000, + 0xB70, 0x00000000, + 0xB74, 0x00000000, + 0xB78, 0x00000000, + 0xB7C, 0x00000000, + 0xB80, 0x00000000, + 0xB84, 0x00000000, + 0xB88, 0x00000000, + 0xB8C, 0x00000000, + 0xB90, 0x00000000, + 0xB94, 0x00000000, + 0xB98, 0x00000000, + 0xB9C, 0x00000000, + 0xBA0, 0x00000000, + 0xBA4, 0x00000000, + 0xBA8, 0x00000000, + 0xBAC, 0x00000000, + 0xBB0, 0x00000000, + 0xBB4, 0x00000000, + 0xBB8, 0x00000000, + 0xBBC, 0x00000000, + 0xBC0, 0x00000000, + 0xBC4, 0x00000000, + 0xBC8, 0x00000000, + 0xBCC, 0x00000000, + 0xBD0, 0x00000000, + 0xBD4, 0x00000000, + 0xBD8, 0x00000000, + 0xBDC, 0x00000000, + 0xBE0, 0x00000000, + 0xBE4, 0x00000000, + 0xBE8, 0x00000000, + 0xBEC, 0x00000000, + 0xBF0, 0x00000000, + 0xBF4, 0x00000000, + 0xBF8, 0x00000000, + 0xC00, 0x1C8BA0D6, + 0xC04, 0x00000001, + 0xC08, 0x00000000, + 0xC0C, 0x02F1D8B7, + 0xC10, 0x000000B0, + 0xC14, 0x0000D891, + 0xC18, 0x00087672, + 0xC1C, 0x15260000, + 0xC20, 0x00000000, + 0xC24, 0x40600000, + 0xC28, 0x06400F76, + 0xC2C, 0xE30020E1, + 0xC30, 0x140C9494, + 0xC34, 0x00A04946, + 0xC38, 0x011D4820, + 0xC3C, 0x168DB61B, + 0xC40, 0x009C50F8, + 0xC44, 0x2013BAD1, + 0xC48, 0xFFFFF7CC, + 0xC4C, 0xA000FFFF, + 0xC50, 0x20D0F800, + 0xC54, 0x941A0200, + 0xC58, 0x18380111, + 0xC5C, 0x006E01B8, + 0xC60, 0x2CA5555B, + 0xC64, 0x0210005F, + 0xC68, 0x039A5300, + 0xC6C, 0x0265C2BA, + 0xC70, 0x000CEB21, + 0xC74, 0x0E149CA1, + 0xC78, 0x1AB4956B, + 0xC7C, 0x00000ABF, + 0xC80, 0xC02A8799, + 0xC84, 0x06C636C6, + 0xC88, 0x08090202, + 0xC8C, 0x00204048, + 0xC90, 0x00F85F85, + 0xC94, 0x00000F85, + 0xC98, 0x58385858, + 0xC9C, 0x18382838, + 0xCA0, 0x00002838, + 0xCA4, 0x3A253A3A, + 0xCA8, 0x10251A25, + 0xCAC, 0x00001025, + 0xCB0, 0x3A133A3A, + 0xCB4, 0x08130D13, + 0xCB8, 0x00000813, + 0xCBC, 0x001F1066, + 0xCC0, 0x88A00400, + 0xCC4, 0x00200400, + 0xCC8, 0x0B200400, + 0xCCC, 0x00600400, + 0xCD0, 0x00000092, + 0xCD4, 0x22220000, + 0xCD8, 0x22222222, + 0xCDC, 0x22222222, + 0xCE0, 0x22222222, + 0xCE4, 0x22222222, + 0xCE8, 0x00002222, + 0xCEC, 0x00000000, + 0xCF0, 0x00000000, + 0xCF4, 0x00000000, + 0xCF8, 0x00000000, + 0xD00, 0x1083A10A, + 0xD04, 0x0EC42948, + 0xD08, 0x10852108, + 0xD0C, 0x0CC41D08, + 0xD10, 0x108620EC, + 0xD14, 0x0CA42108, + 0xD18, 0x107620E8, + 0xD1C, 0x0E742108, + 0xD20, 0x0E8618C8, + 0xD24, 0x00000108, + 0xD28, 0x288C224C, + 0xD2C, 0x11C6320C, + 0xD30, 0x30CEBD98, + 0xD34, 0x10C31908, + 0xD38, 0x310A318C, + 0xD3C, 0x18C41D08, + 0xD40, 0x28CC4190, + 0xD44, 0x19062108, + 0xD48, 0x294A5A17, + 0xD4C, 0x00000108, + 0xD50, 0x10A3A908, + 0xD54, 0x10842148, + 0xD58, 0x14C5314A, + 0xD5C, 0x1086258C, + 0xD60, 0x10A42948, + 0xD64, 0x10842108, + 0xD68, 0x08C42108, + 0xD6C, 0x10842148, + 0xD70, 0x08822084, + 0xD74, 0x10841D04, + 0xD78, 0x08421088, + 0xD7C, 0x1083A104, + 0xD80, 0x10842108, + 0xD84, 0x1085294A, + 0xD88, 0x08822104, + 0xD8C, 0x10852948, + 0xD90, 0x08421084, + 0xD94, 0x10852104, + 0xD98, 0x08421084, + 0xD9C, 0x10863184, + 0xDA0, 0x1083B10A, + 0xDA4, 0x10842148, + 0xDA8, 0x1984718C, + 0xDAC, 0x108C33AF, + 0xDB0, 0x00000000, + 0xDB4, 0x00000000, + 0xDB8, 0x00000000, + 0xDBC, 0x00000000, + 0xDC0, 0x00000000, + 0xDC4, 0x00000000, + 0xDC8, 0x00000000, + 0xDCC, 0x00000000, + 0xDD0, 0x00000000, + 0xDD4, 0x00000000, + 0xDD8, 0x00000000, + 0xDDC, 0x00000000, + 0xDE0, 0x00000000, + 0xDE4, 0x00000000, + 0xDE8, 0x00000000, + 0xDEC, 0x00000000, + 0xDF0, 0x00000000, + 0xDF4, 0x00000000, + 0xDF8, 0x00000000, + 0x1800, 0x00033312, + 0x1804, 0x00033312, + 0x180C, 0x17F40060, + 0x1810, 0x62F508C4, + 0x1814, 0x506AA5B4, + 0x1818, 0x000014FF, + 0x181C, 0x00000000, + 0x1820, 0x02D508CC, + 0x1824, 0x506AA5B4, + 0x1828, 0x000004FD, + 0x182C, 0x00000000, + 0x1834, 0x00000000, + 0x1838, 0x20000000, + 0x183C, 0x00000000, + 0x1840, 0x00000000, + 0x1844, 0x00000000, + 0x1848, 0x00000000, + 0x184C, 0x00000000, + 0x1850, 0x00000000, + 0x1854, 0x00000000, + 0x1858, 0x00000000, + 0x185C, 0x00000000, + 0x1860, 0xF0040FF8, + 0x1864, 0x7F000000, + 0x1868, 0x00000000, + 0x186C, 0x0000FF00, + 0x1870, 0x00000000, + 0x1874, 0x00000000, + 0x1878, 0x00000000, + 0x187C, 0x00000000, + 0x1880, 0x00000000, + 0x1884, 0x02B00000, + 0x1888, 0x00000000, + 0x188C, 0x00000000, + 0x1890, 0x00000000, + 0x1894, 0x00000000, + 0x1898, 0x00000000, + 0x18A0, 0x00510000, + 0x18A4, 0x183C1F7F, + 0x18A8, 0x0A02C99A, + 0x18AC, 0x00004200, + 0x18B0, 0x0809FB08, + 0x18B0, 0x0809FB09, + 0x18B4, 0x00000000, + 0x18B8, 0x00000000, + 0x18BC, 0x00C3FF80, + 0x18C0, 0x0002D100, + 0x18C4, 0x00000004, + 0x18C8, 0x001FFFE0, + 0x18CC, 0x0809FB08, + 0x18CC, 0x0809FB09, + 0x18D0, 0x00000000, + 0x18D4, 0x00000000, + 0x18D8, 0x00C3FF80, + 0x18DC, 0x0002D100, + 0x18E0, 0x00000004, + 0x18E4, 0x001FFFE0, + 0x18E8, 0x00800000, + 0x18EC, 0x1EC08000, + 0x18F0, 0x7F000064, + 0x18F4, 0x1F7DE75C, + 0x18F8, 0x7F7F7F7F, + 0x18FC, 0x7F7F7F7F, + 0x1900, 0xA7A7A7A7, + 0x1904, 0x95959595, + 0x1908, 0x00777788, + 0x190C, 0x77776666, + 0x1910, 0x00033333, + 0x1914, 0xAAAC875A, + 0x1918, 0x2AA2A8A2, + 0x191C, 0x2AAAA8A2, + 0x1920, 0x00878766, + 0x1924, 0x000C4924, + 0x1928, 0x5669B6C0, + 0x192C, 0x00409190, + 0x1930, 0xB85C0492, + 0x1934, 0x00B4A298, + 0x1938, 0x00030151, + 0x193C, 0x0058C618, + 0x1940, 0x41000000, + 0x1944, 0x00000BCB, + 0x1948, 0xAAAAAAAA, + 0x194C, 0x00B99999, + 0x1950, 0x88886665, + 0x1954, 0x08888888, + 0x1958, 0x00000618, + 0x195C, 0x00000000, + 0x1960, 0x00000000, + 0x1964, 0x00000000, + 0x1968, 0x00000000, + 0x196C, 0x00000000, + 0x1970, 0x00000000, + 0x1974, 0x00000000, + 0x1978, 0x00000000, + 0x197C, 0x00000000, + 0x1980, 0x00000000, + 0x1984, 0x00000000, + 0x1988, 0x00000000, + 0x198C, 0x00000000, + 0x1990, 0x00000000, + 0x1994, 0x00000000, + 0x1998, 0x00000000, + 0x199C, 0x00000000, + 0x19A0, 0x00000000, + 0x19A4, 0x00000000, + 0x19A8, 0x00000000, + 0x19AC, 0x00000000, + 0x19B0, 0x00000000, + 0x19B4, 0x00000000, + 0x19B8, 0x00000000, + 0x19BC, 0x00000000, + 0x19C0, 0x00000000, + 0x19C4, 0x00000000, + 0x19C8, 0x00000000, + 0x19CC, 0x00000000, + 0x19D0, 0x00000000, + 0x19D4, 0x00000000, + 0x19D8, 0x00000000, + 0x19DC, 0x00000000, + 0x19E0, 0x00000000, + 0x19E4, 0x00000000, + 0x19E8, 0x00000000, + 0x19EC, 0x00000000, + 0x19F0, 0x00000000, + 0x19F4, 0x00000000, + 0x19F8, 0x00000000, + 0x1C00, 0x00000000, + 0x1C04, 0x00000000, + 0x1C08, 0x00000000, + 0x1C0C, 0x00000000, + 0x1C10, 0x00000000, + 0x1C14, 0x00000000, + 0x1C18, 0x00000000, + 0x1C1C, 0x00000000, + 0x1C20, 0x03C23F00, + 0x1C24, 0xF101F002, + 0x1C28, 0x0FFE0010, + 0x1C2C, 0x453090FF, + 0x1C30, 0xFE0090FE, + 0x1C34, 0xE4E42000, + 0x1C38, 0xFFA1005E, + 0x1C40, 0x8F588837, + 0x1C44, 0x04400300, + 0x1C48, 0x00000000, + 0x1C4C, 0x00000200, + 0x1C50, 0x8E588837, + 0x1C54, 0x04400300, + 0x1C58, 0x00000000, + 0x1C5C, 0xFFFFFFFF, + 0x1C60, 0x0F030032, + 0x1C64, 0x360F0000, + 0x1C68, 0x007F0000, + 0x1C6C, 0x00010000, + 0x1C70, 0x00037FFE, + 0x1C74, 0x00000000, + 0x1C78, 0x00020000, + 0x1C7C, 0x00310000, + 0x1C80, 0x0E38E000, + 0x1C84, 0x245120D4, + 0x1C88, 0xC8400483, + 0x1C8C, 0x40005A20, + 0x1C94, 0x00000000, + 0x1C98, 0x00000000, + 0x1C9C, 0x00000000, + 0x1CA0, 0x00000000, + 0x1CA4, 0x20000000, + 0x1CA8, 0x0E000000, + 0x1CAC, 0xE424A2CC, + 0x1CB0, 0x00000000, + 0x1CB4, 0x00000000, + 0x1CB8, 0x24800000, + 0x1CBC, 0x60004800, + 0x1CC0, 0x24800000, + 0x1CC4, 0x60004800, + 0x1CC8, 0xF0444900, + 0x1CCC, 0x030300F1, + 0x1CD0, 0x0F000000, + 0x1CD4, 0x02024B00, + 0x1CD8, 0x04000000, + 0x1CDC, 0x10000000, + 0x1CE0, 0x60000000, + 0x1CE4, 0x00000000, + 0x1CE8, 0xC0000000, + 0x1CEC, 0x00000000, + 0x1CF0, 0x00000000, + 0x1CF4, 0xE4000000, + 0x1CF8, 0x00000000, + 0x1D00, 0x00000000, + 0x1D04, 0x08A3C000, + 0x1D08, 0xA0000000, + 0x1D10, 0x08B5BBBB, + 0x1D14, 0x77777777, + 0x1D18, 0x99999999, + 0x1D1C, 0x99999999, + 0x1D20, 0x000081E0, + 0x1D24, 0x00000000, + 0x1D28, 0x00000000, + 0x1D2C, 0xC0000000, + 0x1D30, 0x50009C00, + 0x1D34, 0x00000000, + 0x1D38, 0x00000000, + 0x1D3C, 0xF8000000, + 0x1D40, 0x00000000, + 0x1D44, 0x74740000, + 0x1D48, 0x14147474, + 0x1D4C, 0x00FFFF14, + 0x1D50, 0x00000000, + 0x1D54, 0x03A00000, + 0x1D58, 0x80800000, + 0x1D5C, 0x00000000, + 0x1D60, 0x00000000, + 0x1D64, 0x88000000, + 0x1D68, 0x00000000, + 0x1D6C, 0x666D8001, + 0x1D70, 0x20202020, + 0x1D74, 0x4E4E4E4E, + 0x1D78, 0x18189818, + 0x1D7C, 0x0005A000, + 0x1D80, 0x00080000, + 0x1D84, 0x00080000, + 0x1D88, 0x000000EF, + 0x1D8C, 0x0C0C0C0C, + 0x1D90, 0x103F003F, + 0x1D94, 0x00000000, + 0x1D98, 0x00000000, + 0x1D9C, 0x00000000, + 0x1DA0, 0x00000000, + 0x1DA4, 0x00000000, + 0x1DA8, 0x00000000, + 0x1DAC, 0x00000000, + 0x1DB0, 0x00000000, + 0x1DB4, 0x00000000, + 0x1DB8, 0x00000000, + 0x1DBC, 0x00000000, + 0x1DC0, 0x00000000, + 0x1DC4, 0x00000000, + 0x1DC8, 0x00000000, + 0x1DCC, 0x00000000, + 0x1DD0, 0x00000000, + 0x1DD4, 0x00000000, + 0x1DD8, 0x00000000, + 0x1DDC, 0x1FDF0000, + 0x1DE0, 0x01010000, + 0x1DE4, 0x05210123, + 0x1DE8, 0xFFFF4848, + 0x1DEC, 0x00000000, + 0x1DF0, 0x00000000, + 0x1DF4, 0x80000002, + 0x1DF8, 0x00000000, + 0x1E00, 0x00000000, + 0x1E04, 0x00000000, + 0x1E08, 0x00000000, + 0x1E0C, 0x00000000, + 0x1E10, 0x00000000, + 0x1E14, 0x00000000, + 0x1E18, 0x00000000, + 0x1E1C, 0x00000000, + 0x1E20, 0x00000000, + 0x1E24, 0x80003000, + 0x1E28, 0x000CC0C3, + 0x1E2C, 0xE4E40404, + 0x1E30, 0xE4E4E4E4, + 0x1E34, 0xF3001234, + 0x1E38, 0x00000000, + 0x1E3C, 0x00000000, + 0x1E40, 0x00000000, + 0x1E44, 0x00000000, + 0x1E48, 0x00000000, + 0x1E4C, 0x00000000, + 0x1E50, 0x00000000, + 0x1E54, 0x00000000, + 0x1E58, 0x00000000, + 0x1E5C, 0xC1000000, + 0x1E60, 0x00000000, + 0x1E64, 0xF3A00001, + 0x1E68, 0x0028846E, + 0x1E6C, 0x40274906, + 0x1E70, 0x00001000, + 0x1E74, 0x00000000, + 0x1E78, 0x00000000, + 0x1E7C, 0x00000000, + 0x1E80, 0x00000000, + 0x1E84, 0x00000000, + 0x1E84, 0x40000000, + 0x1E84, 0x41000000, + 0x1E84, 0x42000000, + 0x1E84, 0x43000000, + 0x1E84, 0x44000000, + 0x1E84, 0x45000000, + 0x1E84, 0x46000000, + 0x1E84, 0x47000000, + 0x1E84, 0x48000000, + 0x1E84, 0x49000000, + 0x1E84, 0x4A000000, + 0x1E84, 0x4B000000, + 0x1E84, 0x4C000000, + 0x1E84, 0x4D000000, + 0x1E84, 0x4E000000, + 0x1E84, 0x4F000000, + 0x1E84, 0x50000000, + 0x1E84, 0x51000000, + 0x1E84, 0x52000000, + 0x1E84, 0x53000000, + 0x1E84, 0x54000000, + 0x1E84, 0x55000000, + 0x1E84, 0x56000000, + 0x1E84, 0x57000000, + 0x1E84, 0x58000000, + 0x1E84, 0x59000000, + 0x1E84, 0x5A000000, + 0x1E84, 0x5B000000, + 0x1E84, 0x5C000000, + 0x1E84, 0x5D000000, + 0x1E84, 0x5E000000, + 0x1E84, 0x5F000000, + 0x1E84, 0x60000000, + 0x1E84, 0x61000000, + 0x1E84, 0x62000000, + 0x1E84, 0x63000000, + 0x1E84, 0x64000000, + 0x1E84, 0x65000000, + 0x1E84, 0x66000000, + 0x1E84, 0x67000000, + 0x1E84, 0x68000000, + 0x1E84, 0x69000000, + 0x1E84, 0x6A000000, + 0x1E84, 0x6B000000, + 0x1E84, 0x6C000000, + 0x1E84, 0x6D000000, + 0x1E84, 0x6E000000, + 0x1E84, 0x6F000000, + 0x1E84, 0x70000000, + 0x1E84, 0x71000000, + 0x1E84, 0x72000000, + 0x1E84, 0x73000000, + 0x1E84, 0x74000000, + 0x1E84, 0x75000000, + 0x1E84, 0x76000000, + 0x1E84, 0x77000000, + 0x1E84, 0x78000000, + 0x1E84, 0x79000000, + 0x1E84, 0x7A000000, + 0x1E84, 0x7B000000, + 0x1E84, 0x7C000000, + 0x1E84, 0x7D000000, + 0x1E84, 0x7E000000, + 0x1E84, 0x7F000000, + 0x1E84, 0x80000000, + 0x1E84, 0x00000000, + 0x1E88, 0x0200FC1C, + 0x1E8C, 0x00000000, + 0x1E90, 0x00000000, + 0x1E94, 0x04000000, + 0x1E98, 0x00000000, + 0x1E9C, 0x00000000, + 0x1EA0, 0x00000000, + 0x1EA4, 0x00000000, + 0x1EA8, 0xAA464646, + 0x1EAC, 0x01800030, + 0x1EB0, 0x00003002, + 0x1EB4, 0x31800002, + 0x1EB8, 0x00000000, + 0x1EBC, 0x00000000, + 0x1EC0, 0x00000000, + 0x1EC4, 0x00000000, + 0x1EC8, 0x00000000, + 0x1ECC, 0x00000000, + 0x1ED0, 0x00000000, + 0x1ED4, 0x8000000A, + 0x1ED8, 0x800B03E8, + 0x1EDC, 0x83E90FFF, + 0x1EE0, 0x8000FFFF, + 0x1EE4, 0x70000000, + 0x1EE8, 0x00000000, + 0x1EEC, 0x0280A933, + 0x1EF0, 0x00000A80, + 0x1EF4, 0x00001266, + 0x1EF8, 0x01000100, + 0x3A00, 0x0004080C, + 0x3A04, 0x1C202428, + 0x3A08, 0x0C101418, + 0x3A0C, 0x181C2024, + 0x3A10, 0x080C1014, + 0x3A14, 0x181C2024, + 0x3A18, 0x080C1014, + 0x3A1C, 0x00000000, + 0x3A20, 0x00000000, + 0x3A24, 0x00000000, + 0x3A28, 0x00000000, + 0x3A2C, 0x181C2024, + 0x3A30, 0x080C1014, + 0x3A34, 0x20240004, + 0x3A38, 0x1014181C, + 0x3A3C, 0x0004080C, + 0x3A40, 0x00000000, + 0x3A44, 0x00000000, + 0x3A48, 0x00000000, + 0x3A4C, 0x00000000, + 0x3A50, 0x00000000, + 0x3A54, 0x00000000, + 0x3A58, 0x00000000, + 0x3A5C, 0x00000000, + 0x3A60, 0x00000000, + 0x3A64, 0x00000000, + 0x3A68, 0x00000000, + 0x3A6C, 0x00000000, + 0x3A70, 0x00000000, + 0x3A74, 0x00000000, + 0x3A78, 0x00000000, + 0x3A7C, 0x00000000, + 0x3A80, 0x00000000, + 0x3A84, 0x00000000, + 0x3A88, 0x00000000, + 0x3A8C, 0x00000000, + 0x3A90, 0x00000000, + 0x3A94, 0x00000000, + 0x3A98, 0x00000000, + 0x3A9C, 0x00000000, + 0x3AA0, 0x00000000, + 0x3AA4, 0x00000000, + 0x4000, 0xA6A6A6A6, + 0x4004, 0x95959595, + 0x4008, 0x00777777, + 0x400C, 0x77776666, + 0x4010, 0x00033333, + 0x4014, 0xAAAC875A, + 0x4018, 0x2AA2A8A2, + 0x401C, 0x2AAAA8A2, + 0x4020, 0x00878766, + 0x4024, 0x000C4924, + 0x4028, 0x5669B6C0, + 0x402C, 0x00409190, + 0x4030, 0xB85C0492, + 0x4034, 0x00B4A298, + 0x4038, 0x00030151, + 0x403C, 0x0058C618, + 0x4040, 0x41000000, + 0x4044, 0x00000BCB, + 0x4048, 0xAAAAAAAA, + 0x404C, 0x00B98989, + 0x4050, 0x88886665, + 0x4054, 0x08888888, + 0x4058, 0x00000618, + 0x405C, 0x00000000, + 0x4060, 0x00000000, + 0x4064, 0x00000000, + 0x4068, 0x00000000, + 0x406C, 0x00000000, + 0x4070, 0x00000000, + 0x4074, 0x00000000, + 0x4078, 0x00000000, + 0x407C, 0x00000000, + 0x4080, 0x00000000, + 0x4084, 0x00000000, + 0x4088, 0x00000000, + 0x408C, 0x00000000, + 0x4090, 0x00000000, + 0x4094, 0x00000000, + 0x4098, 0x00000000, + 0x409C, 0x00000000, + 0x40A0, 0x00000000, + 0x40A4, 0x00000000, + 0x40A8, 0x00000000, + 0x40AC, 0x00000000, + 0x40B0, 0x00000000, + 0x40B4, 0x00000000, + 0x40B8, 0x00000000, + 0x40BC, 0x00000000, + 0x40C0, 0x00000000, + 0x40C4, 0x00000000, + 0x40C8, 0x00000000, + 0x40CC, 0x00000000, + 0x40D0, 0x00000000, + 0x40D4, 0x00000000, + 0x40D8, 0x00000000, + 0x40DC, 0x00000000, + 0x40E0, 0x00000000, + 0x40E4, 0x00000000, + 0x40E8, 0x00000000, + 0x40EC, 0x00000000, + 0x40F0, 0x00000000, + 0x40F4, 0x00000000, + 0x40F8, 0x00000000, + 0x4100, 0x00033312, + 0x4104, 0x00033312, + 0x410C, 0x17F40060, + 0x4110, 0x62D508C4, + 0x4114, 0x506AA5B4, + 0x4118, 0x000014FF, + 0x411C, 0x00000000, + 0x4120, 0x02D508CC, + 0x4124, 0x506AA5B4, + 0x4128, 0x000004FD, + 0x412C, 0x00000000, + 0x4134, 0x00000000, + 0x4138, 0x20000000, + 0x413C, 0x00000000, + 0x4140, 0x00000000, + 0x4144, 0x00000000, + 0x4148, 0x00000000, + 0x414C, 0x00000000, + 0x4150, 0x00000000, + 0x4154, 0x00000000, + 0x4158, 0x00000000, + 0x415C, 0x00000000, + 0x4160, 0xF0040FF8, + 0x4164, 0x7F000000, + 0x4168, 0x00000000, + 0x416C, 0x00008000, + 0x4170, 0x00000000, + 0x4174, 0x00000000, + 0x4178, 0x00000000, + 0x417C, 0x00000000, + 0x4180, 0x00000000, + 0x4184, 0x02B00000, + 0x4188, 0x00000000, + 0x418C, 0x00000000, + 0x4190, 0x00000000, + 0x4194, 0x00000000, + 0x4198, 0x00000000, + 0x41A0, 0x00510000, + 0x41A4, 0x183C1F7F, + 0x41A8, 0x1402C99A, + 0x41AC, 0x00004200, + 0x41B0, 0x0809FB08, + 0x41B0, 0x0809FB09, + 0x41B4, 0x00000000, + 0x41B8, 0x00000000, + 0x41BC, 0x00C3FF80, + 0x41C0, 0x0002D100, + 0x41C4, 0x00000004, + 0x41C8, 0x001FFFE0, + 0x41CC, 0x0809FB08, + 0x41CC, 0x0809FB09, + 0x41D0, 0x00000000, + 0x41D4, 0x00000000, + 0x41D8, 0x00C3FF80, + 0x41DC, 0x0002D100, + 0x41E0, 0x00000004, + 0x41E4, 0x001FFFE0, + 0x41E8, 0x00000200, + 0x41EC, 0x1E008000, + 0x41F0, 0x7F000064, + 0x41F4, 0x1F7DE75C, + 0x41F8, 0x7F7F7F7F, + 0x41FC, 0x7F7F7F7F, + 0x1830, 0x700B8001, + 0x1830, 0x700B8001, + 0x1830, 0x70144001, + 0x1830, 0x70244001, + 0x1830, 0x70344001, + 0x1830, 0x70444001, + 0x1830, 0x705B8001, + 0x1830, 0x70644001, + 0x1830, 0x707B8001, + 0x1830, 0x708B8001, + 0x1830, 0x709B8001, + 0x1830, 0x70AB8001, + 0x1830, 0x70BB8001, + 0x1830, 0x70CB8001, + 0x1830, 0x70DB8001, + 0x1830, 0x70EB8001, + 0x1830, 0x70FB8001, + 0x1830, 0x70FB8001, + 0x4130, 0x700B8001, + 0x4130, 0x700B8001, + 0x4130, 0x70144001, + 0x4130, 0x70244001, + 0x4130, 0x70344001, + 0x4130, 0x70444001, + 0x4130, 0x705B8001, + 0x4130, 0x70644001, + 0x4130, 0x707B8001, + 0x4130, 0x708B8001, + 0x4130, 0x709B8001, + 0x4130, 0x70AB8001, + 0x4130, 0x70BB8001, + 0x4130, 0x70CB8001, + 0x4130, 0x70DB8001, + 0x4130, 0x70EB8001, + 0x4130, 0x70FB8001, + 0x4130, 0x70FB8001, + 0x1A00, 0x00D047C8, + 0x1A04, 0xC0000008, + 0x1A08, 0x88838300, + 0x1A0C, 0x2E20100F, + 0x1A10, 0x9500BB78, + 0x1A14, 0x111440A8, + 0x1A18, 0x00881117, + 0x1A1C, 0x89140F00, + 0x1A20, 0x52840000, + 0x1A24, 0x3E18FEC8, + 0x1A28, 0x00150A88, + 0x1A2C, 0x12988000, + 0x1A30, 0x10114007, + 0x1A34, 0x1011C007, + 0x1A38, 0x00000000, + 0x1A3C, 0x00000000, + 0x1A40, 0x00000000, + 0x1A44, 0x00000000, + 0x1A48, 0x000C0000, + 0x1A4C, 0xB00000C0, + 0x1A50, 0x22040700, + 0x1A54, 0x09003000, + 0x1A58, 0x00000881, + 0x1A5C, 0x00000128, + 0x1A60, 0x85830000, + 0x1A64, 0x00000128, + 0x1A68, 0x00222211, + 0x1A6C, 0x00000000, + 0x1A70, 0x00008000, + 0x1A74, 0x00000048, + 0x1A78, 0x000089F0, + 0x1A7C, 0x225B0606, + 0x1A80, 0x208A7532, + 0x1A84, 0x85200200, + 0x1A88, 0x048C0000, + 0x1A8C, 0x00000000, + 0x1A90, 0x00000000, + 0x1A94, 0x00000000, + 0x1A98, 0xACC4C040, + 0x1A9C, 0x0016C8B2, + 0x1AA0, 0x00FAF0DE, + 0x1AA4, 0x00020000, + 0x1AA8, 0xBA0F0004, + 0x1AAC, 0x00122344, + 0x1AB0, 0x0FFFFFFF, + 0x1AB4, 0x0F201402, + 0x1AB8, 0x00000000, + 0x1ABC, 0xC2008080, + 0x1AC0, 0x54D0A742, + 0x1AC4, 0x00000000, + 0x1AC8, 0x00000807, + 0x1ACC, 0x00000707, + 0x1AD0, 0xA33529AD, + 0x1AD4, 0x0D8D8452, + 0x1AD8, 0x08024024, + 0x1ADC, 0x000DB001, + 0x1AE0, 0x00600391, + 0x1AE4, 0x08000080, + 0x1AE8, 0x00000002, + 0x1AEC, 0x00000000, + 0x1AF0, 0x00000000, + 0x1AF4, 0x00000000, + 0x1AF8, 0x00000000, + 0x1AFC, 0x00000000, + 0x1D0C, 0x00400000, + 0x1D0C, 0x00410000, + 0x1EE8, 0x00000003, + 0xC0C, 0x02F1D8BF, + 0x1D94, 0x40000000, + 0x1D94, 0x40010000, + 0x1D94, 0x40020000, + 0x1D94, 0x40030000, + 0x1D94, 0x40040000, + 0x1D94, 0x40050000, + 0x1D94, 0x40060000, + 0x1D94, 0x40070000, + 0x1D94, 0x40080000, + 0x1D94, 0x40090000, + 0x1D94, 0x400A0000, + 0x1D94, 0x400B0000, + 0x1D94, 0x400C0000, + 0x1D94, 0x400D0000, + 0x1D94, 0x400E0000, + 0x1D94, 0x400F0000, + 0x1D94, 0x40100000, + 0x1D94, 0x40110000, + 0x1D94, 0x40120000, + 0x1D94, 0x40130000, + 0x1D94, 0x40140000, + 0x1D94, 0x40150000, + 0x1D94, 0x40160000, + 0x1D94, 0x40170000, + 0x1D94, 0x40180000, + 0x1D94, 0x40190000, + 0x1D94, 0x401A0000, + 0x1D94, 0x401B0000, + 0x1D94, 0x401C0000, + 0x1D94, 0x401D0000, + 0x1D94, 0x401E0000, + 0x1D94, 0x401F0000, + 0x1D94, 0x40200000, + 0x1D94, 0x40210000, + 0x1D94, 0x40220000, + 0x1D94, 0x40230000, + 0x1D94, 0x40240000, + 0x1D94, 0x40250000, + 0x1D94, 0x40260000, + 0x1D94, 0x40270000, + 0x1D94, 0x40280000, + 0x1D94, 0x40290000, + 0x1D94, 0x402A0000, + 0x1D94, 0x402B0000, + 0x1D94, 0x402C0000, + 0x1D94, 0x402D0000, + 0x1D94, 0x402E0000, + 0x1D94, 0x402F0000, + 0x1D94, 0x40300000, + 0x1D94, 0x40310000, + 0x1D94, 0x40320000, + 0x1D94, 0x40330000, + 0x1D94, 0x40340000, + 0x1D94, 0x40350000, + 0x1D94, 0x40360000, + 0x1D94, 0x40370000, + 0x1D94, 0x40380000, + 0x1D94, 0x40390000, + 0x1D94, 0x403A0000, + 0x1D94, 0x403B0000, + 0x1D94, 0x403C0000, + 0x1D94, 0x403D0000, + 0x1D94, 0x403E0000, + 0x1D94, 0x403F0000, + 0x1D94, 0x40400000, + 0x1D94, 0x40410000, + 0x1D94, 0x40420000, + 0x1D94, 0x40430000, + 0x1D94, 0x40440000, + 0x1D94, 0x40450000, + 0x1D94, 0x40460000, + 0x1D94, 0x40470000, + 0x1D94, 0x40480000, + 0x1D94, 0x40490000, + 0x1D94, 0x404A0000, + 0x1D94, 0x404B0000, + 0x1D94, 0x404C0000, + 0x1D94, 0x404D0000, + 0x1D94, 0x404E0000, + 0x1D94, 0x404F0000, + 0x1D94, 0x40500000, + 0x1D94, 0x40510000, + 0x1D94, 0x40520000, + 0x1D94, 0x40530000, + 0x1D94, 0x40540000, + 0x1D94, 0x40550000, + 0x1D94, 0x40560000, + 0x1D94, 0x40570000, + 0x1D94, 0x40580000, + 0x1D94, 0x40590000, + 0x1D94, 0x405A0000, + 0x1D94, 0x405B0000, + 0x1D94, 0x405C0000, + 0x1D94, 0x405D0000, + 0x1D94, 0x405E0000, + 0x1D94, 0x405F0000, + 0x1D94, 0x40600000, + 0x1D94, 0x40610000, + 0x1D94, 0x40620000, + 0x1D94, 0x40630000, + 0x1D94, 0x40640000, + 0x1D94, 0x40650000, + 0x1D94, 0x40660000, + 0x1D94, 0x40670000, + 0x1D94, 0x40680000, + 0x1D94, 0x40690000, + 0x1D94, 0x406A0000, + 0x1D94, 0x406B0000, + 0x1D94, 0x406C0000, + 0x1D94, 0x406D0000, + 0x1D94, 0x406E0000, + 0x1D94, 0x406F0000, + 0x1D94, 0x40700000, + 0x1D94, 0x40710000, + 0x1D94, 0x40720000, + 0x1D94, 0x40730000, + 0x1D94, 0x40740000, + 0x1D94, 0x40750000, + 0x1D94, 0x40760000, + 0x1D94, 0x40770000, + 0x1D94, 0x40780000, + 0x1D94, 0x40790000, + 0x1D94, 0x407A0000, + 0x1D94, 0x407B0000, + 0x1D94, 0x407C0000, + 0x1D94, 0x407D0000, + 0x1D94, 0x407E0000, + 0x1D94, 0x407F0000, + 0x1D94, 0x40800000, + 0x1D94, 0x40810000, + 0x1D94, 0x40820000, + 0x1D94, 0x40830000, + 0x1D94, 0x40840000, + 0x1D94, 0x40850000, + 0x1D94, 0x40860000, + 0x1D94, 0x40870000, + 0x1D94, 0x40880000, + 0x1D94, 0x40890000, + 0x1D94, 0x408A0000, + 0x1D94, 0x408B0000, + 0x1D94, 0x408C0000, + 0x1D94, 0x408D0000, + 0x1D94, 0x408E0000, + 0x1D94, 0x408F0000, + 0x1D94, 0x40900000, + 0x1D94, 0x40910000, + 0x1D94, 0x40920000, + 0x1D94, 0x40930000, + 0x1D94, 0x40940000, + 0x1D94, 0x40950000, + 0x1D94, 0x40960000, + 0x1D94, 0x40970000, + 0x1D94, 0x40980000, + 0x1D94, 0x40990000, + 0x1D94, 0x409A0000, + 0x1D94, 0x409B0000, + 0x1D94, 0x409C0000, + 0x1D94, 0x409D0000, + 0x1D94, 0x409E0000, + 0x1D94, 0x409F0000, + 0x1D94, 0x40A00000, + 0x1D94, 0x40A10000, + 0x1D94, 0x40A20000, + 0x1D94, 0x40A30000, + 0x1D94, 0x40A40000, + 0x1D94, 0x40A50000, + 0x1D94, 0x40A60000, + 0x1D94, 0x40A70000, + 0x1D94, 0x40A80000, + 0x1D94, 0x40A90000, + 0x1D94, 0x40AA0000, + 0x1D94, 0x40AB0000, + 0x1D94, 0x40AC0000, + 0x1D94, 0x40AD0000, + 0x1D94, 0x40AE0000, + 0x1D94, 0x40AF0000, + 0x1D94, 0x40B00000, + 0x1D94, 0x40B10000, + 0x1D94, 0x40B20000, + 0x1D94, 0x40B30000, + 0x1D94, 0x40B40000, + 0x1D94, 0x40B50000, + 0x1D94, 0x40B60000, + 0x1D94, 0x40B70000, + 0x1D94, 0x40B80000, + 0x1D94, 0x40B90000, + 0x1D94, 0x40BA0000, + 0x1D94, 0x40BB0000, + 0x1D94, 0x40BC0000, + 0x1D94, 0x40BD0000, + 0x1D94, 0x40BE0000, + 0x1D94, 0x40BF0000, + 0x1D94, 0x40C00000, + 0x1D94, 0x40C10000, + 0x1D94, 0x40C20000, + 0x1D94, 0x40C30000, + 0x1D94, 0x40C40000, + 0x1D94, 0x40C50000, + 0x1D94, 0x40C60000, + 0x1D94, 0x40C70000, + 0x1D94, 0x40C80000, + 0x1D94, 0x40C90000, + 0x1D94, 0x40CA0000, + 0x1D94, 0x40CB0000, + 0x1D94, 0x40CC0000, + 0x1D94, 0x40CD0000, + 0x1D94, 0x40CE0000, + 0x1D94, 0x40CF0000, + 0x1D94, 0x40D00000, + 0x1D94, 0x40D10000, + 0x1D94, 0x40D20000, + 0x1D94, 0x40D30000, + 0x1D94, 0x40D40000, + 0x1D94, 0x40D50000, + 0x1D94, 0x40D60000, + 0x1D94, 0x40D70000, + 0x1D94, 0x40D80000, + 0x1D94, 0x40D90000, + 0x1D94, 0x40DA0000, + 0x1D94, 0x40DB0000, + 0x1D94, 0x40DC0000, + 0x1D94, 0x40DD0000, + 0x1D94, 0x40DE0000, + 0x1D94, 0x40DF0000, + 0x1D94, 0x40E00000, + 0x1D94, 0x40E10000, + 0x1D94, 0x40E20000, + 0x1D94, 0x40E30000, + 0x1D94, 0x40E40000, + 0x1D94, 0x40E50000, + 0x1D94, 0x40E60000, + 0x1D94, 0x40E70000, + 0x1D94, 0x40E80000, + 0x1D94, 0x40E90000, + 0x1D94, 0x40EA0000, + 0x1D94, 0x40EB0000, + 0x1D94, 0x40EC0000, + 0x1D94, 0x40ED0000, + 0x1D94, 0x40EE0000, + 0x1D94, 0x40EF0000, + 0x1D94, 0x40F00000, + 0x1D94, 0x40F10000, + 0x1D94, 0x40F20000, + 0x1D94, 0x40F30000, + 0x1D94, 0x40F40000, + 0x1D94, 0x40F50000, + 0x1D94, 0x40F60000, + 0x1D94, 0x40F70000, + 0x1D94, 0x40F80000, + 0x1D94, 0x40F90000, + 0x1D94, 0x40FA0000, + 0x1D94, 0x40FB0000, + 0x1D94, 0x40FC0000, + 0x1D94, 0x40FD0000, + 0x1D94, 0x40FE0000, + 0x1D94, 0x40FF0000, + 0xC0C, 0x02F1D8B7, + 0x1EE8, 0x00000000, +}; + +RTW_DECL_TABLE_PHY_COND(rtw8822c_bb, rtw_phy_cfg_bb); + +static const u32 rtw8822c_bb_pg_type0[] = { + 0, 0, 0, 0x00000c20, 0xffffffff, 0x484c5054, + 0, 0, 0, 0x00000c24, 0xffffffff, 0x54585c60, + 0, 0, 0, 0x00000c28, 0xffffffff, 0x44484c50, + 0, 0, 0, 0x00000c2c, 0xffffffff, 0x5054585c, + 0, 0, 0, 0x00000c30, 0xffffffff, 0x4044484c, + 0, 0, 1, 0x00000c34, 0xffffffff, 0x5054585c, + 0, 0, 1, 0x00000c38, 0xffffffff, 0x4044484c, + 0, 0, 0, 0x00000c3c, 0xffffffff, 0x5054585c, + 0, 0, 0, 0x00000c40, 0xffffffff, 0x4044484c, + 0, 0, 0, 0x00000c44, 0xffffffff, 0x585c383c, + 0, 0, 1, 0x00000c48, 0xffffffff, 0x484c5054, + 0, 0, 1, 0x00000c4c, 0xffffffff, 0x383c4044, + 0, 1, 0, 0x00000e20, 0xffffffff, 0x484c5054, + 0, 1, 0, 0x00000e24, 0xffffffff, 0x54585c60, + 0, 1, 0, 0x00000e28, 0xffffffff, 0x44484c50, + 0, 1, 0, 0x00000e2c, 0xffffffff, 0x5054585c, + 0, 1, 0, 0x00000e30, 0xffffffff, 0x4044484c, + 0, 1, 1, 0x00000e34, 0xffffffff, 0x5054585c, + 0, 1, 1, 0x00000e38, 0xffffffff, 0x4044484c, + 0, 1, 0, 0x00000e3c, 0xffffffff, 0x5054585c, + 0, 1, 0, 0x00000e40, 0xffffffff, 0x4044484c, + 0, 1, 0, 0x00000e44, 0xffffffff, 0x585c383c, + 0, 1, 1, 0x00000e48, 0xffffffff, 0x484c5054, + 0, 1, 1, 0x00000e4c, 0xffffffff, 0x383c4044, + 1, 0, 0, 0x00000c24, 0xffffffff, 0x54585c60, + 1, 0, 0, 0x00000c28, 0xffffffff, 0x44484c50, + 1, 0, 0, 0x00000c2c, 0xffffffff, 0x5054585c, + 1, 0, 0, 0x00000c30, 0xffffffff, 0x4044484c, + 1, 0, 1, 0x00000c34, 0xffffffff, 0x5054585c, + 1, 0, 1, 0x00000c38, 0xffffffff, 0x4044484c, + 1, 0, 0, 0x00000c3c, 0xffffffff, 0x5054585c, + 1, 0, 0, 0x00000c40, 0xffffffff, 0x4044484c, + 1, 0, 0, 0x00000c44, 0xffffffff, 0x585c383c, + 1, 0, 1, 0x00000c48, 0xffffffff, 0x484c5054, + 1, 0, 1, 0x00000c4c, 0xffffffff, 0x383c4044, + 1, 1, 0, 0x00000e24, 0xffffffff, 0x54585c60, + 1, 1, 0, 0x00000e28, 0xffffffff, 0x44484c50, + 1, 1, 0, 0x00000e2c, 0xffffffff, 0x5054585c, + 1, 1, 0, 0x00000e30, 0xffffffff, 0x4044484c, + 1, 1, 1, 0x00000e34, 0xffffffff, 0x5054585c, + 1, 1, 1, 0x00000e38, 0xffffffff, 0x4044484c, + 1, 1, 0, 0x00000e3c, 0xffffffff, 0x5054585c, + 1, 1, 0, 0x00000e40, 0xffffffff, 0x4044484c, + 1, 1, 0, 0x00000e44, 0xffffffff, 0x585c383c, + 1, 1, 1, 0x00000e48, 0xffffffff, 0x484c5054, + 1, 1, 1, 0x00000e4c, 0xffffffff, 0x383c4044 +}; + +RTW_DECL_TABLE_BB_PG(rtw8822c_bb_pg_type0); + +static const u32 rtw8822c_rf_a[] = { + 0x000, 0x00030000, + 0x018, 0x00013124, + 0x093, 0x0008483F, + 0x0DE, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000B9140, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000B9140, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, + 0xA0000000, 0x00000000, + 0x08E, 0x000A5540, + 0xB0000000, 0x00000000, + 0x081, 0x0000FC01, + 0x081, 0x0002FC01, + 0x081, 0x0003FC01, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x085, 0x0006A06C, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x085, 0x0006A06C, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x085, 0x0006A06C, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x085, 0x0006A06C, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x085, 0x0006A06C, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x085, 0x0006A06C, + 0xA0000000, 0x00000000, + 0x085, 0x0006A06C, + 0xB0000000, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000002, + 0x03F, 0x0000002A, + 0x0EE, 0x00000000, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000002, + 0x03F, 0x0000002A, + 0x0EE, 0x00000000, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000002, + 0x03F, 0x0000002A, + 0x0EE, 0x00000000, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000002, + 0x03F, 0x0000002A, + 0x0EE, 0x00000000, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000002, + 0x03F, 0x0000002A, + 0x0EE, 0x00000000, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000002, + 0x03F, 0x0000002A, + 0x0EE, 0x00000000, + 0xA0000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, + 0x03F, 0x0000003F, + 0x033, 0x00000001, + 0x03F, 0x0000003F, + 0x033, 0x00000002, + 0x03F, 0x0000003F, + 0x0EE, 0x00000000, + 0xB0000000, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, + 0x033, 0x0000000E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000000D, + 0x03F, 0x000773E8, + 0x033, 0x0000000C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000000B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000000A, + 0x03F, 0x000002A8, + 0x033, 0x00000009, + 0x03F, 0x00000280, + 0x033, 0x00000008, + 0x03F, 0x000FF280, + 0x033, 0x00000007, + 0x03F, 0x00000200, + 0x033, 0x00000006, + 0x03F, 0x000001C0, + 0x033, 0x00000005, + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, + 0x033, 0x0000000E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000000D, + 0x03F, 0x000773E8, + 0x033, 0x0000000C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000000B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000000A, + 0x03F, 0x000002A8, + 0x033, 0x00000009, + 0x03F, 0x00000280, + 0x033, 0x00000008, + 0x03F, 0x000FF280, + 0x033, 0x00000007, + 0x03F, 0x00000200, + 0x033, 0x00000006, + 0x03F, 0x000001C0, + 0x033, 0x00000005, + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, + 0x033, 0x0000000E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000000D, + 0x03F, 0x000773E8, + 0x033, 0x0000000C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000000B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000000A, + 0x03F, 0x000002A8, + 0x033, 0x00000009, + 0x03F, 0x00000280, + 0x033, 0x00000008, + 0x03F, 0x000FF280, + 0x033, 0x00000007, + 0x03F, 0x00000200, + 0x033, 0x00000006, + 0x03F, 0x000001C0, + 0x033, 0x00000005, + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, + 0x033, 0x0000000E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000000D, + 0x03F, 0x000773E8, + 0x033, 0x0000000C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000000B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000000A, + 0x03F, 0x000002A8, + 0x033, 0x00000009, + 0x03F, 0x00000280, + 0x033, 0x00000008, + 0x03F, 0x000FF280, + 0x033, 0x00000007, + 0x03F, 0x00000200, + 0x033, 0x00000006, + 0x03F, 0x000001C0, + 0x033, 0x00000005, + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, + 0x033, 0x0000000E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000000D, + 0x03F, 0x000773E8, + 0x033, 0x0000000C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000000B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000000A, + 0x03F, 0x000002A8, + 0x033, 0x00000009, + 0x03F, 0x00000280, + 0x033, 0x00000008, + 0x03F, 0x000FF280, + 0x033, 0x00000007, + 0x03F, 0x00000200, + 0x033, 0x00000006, + 0x03F, 0x000001C0, + 0x033, 0x00000005, + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, + 0x033, 0x0000000E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000000D, + 0x03F, 0x000773E8, + 0x033, 0x0000000C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000000B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000000A, + 0x03F, 0x000002A8, + 0x033, 0x00000009, + 0x03F, 0x00000280, + 0x033, 0x00000008, + 0x03F, 0x000FF280, + 0x033, 0x00000007, + 0x03F, 0x00000200, + 0x033, 0x00000006, + 0x03F, 0x000001C0, + 0x033, 0x00000005, + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, + 0xA0000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773E8, + 0x033, 0x0000000E, + 0x03F, 0x000FF3A0, + 0x033, 0x0000000D, + 0x03F, 0x00000380, + 0x033, 0x0000000C, + 0x03F, 0x000FF380, + 0x033, 0x0000000B, + 0x03F, 0x00000300, + 0x033, 0x0000000A, + 0x03F, 0x000002A8, + 0x033, 0x00000009, + 0x03F, 0x00000280, + 0x033, 0x00000008, + 0x03F, 0x000FF280, + 0x033, 0x00000007, + 0x03F, 0x00000200, + 0x033, 0x00000006, + 0x03F, 0x000001C0, + 0x033, 0x00000005, + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, + 0xB0000000, 0x00000000, + 0x033, 0x00000003, + 0x03F, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000001D, + 0x03F, 0x000773E8, + 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000001B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, + 0x03F, 0x00000280, + 0x033, 0x00000018, + 0x03F, 0x000FF280, + 0x033, 0x00000017, + 0x03F, 0x00000200, + 0x033, 0x00000016, + 0x03F, 0x000001C0, + 0x033, 0x00000015, + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000001D, + 0x03F, 0x000773E8, + 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000001B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, + 0x03F, 0x00000280, + 0x033, 0x00000018, + 0x03F, 0x000FF280, + 0x033, 0x00000017, + 0x03F, 0x00000200, + 0x033, 0x00000016, + 0x03F, 0x000001C0, + 0x033, 0x00000015, + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000001D, + 0x03F, 0x000773E8, + 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000001B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, + 0x03F, 0x00000280, + 0x033, 0x00000018, + 0x03F, 0x000FF280, + 0x033, 0x00000017, + 0x03F, 0x00000200, + 0x033, 0x00000016, + 0x03F, 0x000001C0, + 0x033, 0x00000015, + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000001D, + 0x03F, 0x000773E8, + 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000001B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, + 0x03F, 0x00000280, + 0x033, 0x00000018, + 0x03F, 0x000FF280, + 0x033, 0x00000017, + 0x03F, 0x00000200, + 0x033, 0x00000016, + 0x03F, 0x000001C0, + 0x033, 0x00000015, + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000001D, + 0x03F, 0x000773E8, + 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000001B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, + 0x03F, 0x00000280, + 0x033, 0x00000018, + 0x03F, 0x000FF280, + 0x033, 0x00000017, + 0x03F, 0x00000200, + 0x033, 0x00000016, + 0x03F, 0x000001C0, + 0x033, 0x00000015, + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000001D, + 0x03F, 0x000773E8, + 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000001B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, + 0x03F, 0x00000280, + 0x033, 0x00000018, + 0x03F, 0x000FF280, + 0x033, 0x00000017, + 0x03F, 0x00000200, + 0x033, 0x00000016, + 0x03F, 0x000001C0, + 0x033, 0x00000015, + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, + 0xA0000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773E8, + 0x033, 0x0000001E, + 0x03F, 0x000FF3A0, + 0x033, 0x0000001D, + 0x03F, 0x00000380, + 0x033, 0x0000001C, + 0x03F, 0x000FF380, + 0x033, 0x0000001B, + 0x03F, 0x00000300, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, + 0x03F, 0x00000280, + 0x033, 0x00000018, + 0x03F, 0x000FF280, + 0x033, 0x00000017, + 0x03F, 0x00000200, + 0x033, 0x00000016, + 0x03F, 0x000001C0, + 0x033, 0x00000015, + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, + 0xB0000000, 0x00000000, + 0x033, 0x00000013, + 0x03F, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000002D, + 0x03F, 0x000773E8, + 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000002B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, + 0x03F, 0x00000280, + 0x033, 0x00000028, + 0x03F, 0x000FF280, + 0x033, 0x00000027, + 0x03F, 0x00000200, + 0x033, 0x00000026, + 0x03F, 0x000001C0, + 0x033, 0x00000025, + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000002D, + 0x03F, 0x000773E8, + 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000002B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, + 0x03F, 0x00000280, + 0x033, 0x00000028, + 0x03F, 0x000FF280, + 0x033, 0x00000027, + 0x03F, 0x00000200, + 0x033, 0x00000026, + 0x03F, 0x000001C0, + 0x033, 0x00000025, + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000002D, + 0x03F, 0x000773E8, + 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000002B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, + 0x03F, 0x00000280, + 0x033, 0x00000028, + 0x03F, 0x000FF280, + 0x033, 0x00000027, + 0x03F, 0x00000200, + 0x033, 0x00000026, + 0x03F, 0x000001C0, + 0x033, 0x00000025, + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000002D, + 0x03F, 0x000773E8, + 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000002B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, + 0x03F, 0x00000280, + 0x033, 0x00000028, + 0x03F, 0x000FF280, + 0x033, 0x00000027, + 0x03F, 0x00000200, + 0x033, 0x00000026, + 0x03F, 0x000001C0, + 0x033, 0x00000025, + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000002D, + 0x03F, 0x000773E8, + 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000002B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, + 0x03F, 0x00000280, + 0x033, 0x00000028, + 0x03F, 0x000FF280, + 0x033, 0x00000027, + 0x03F, 0x00000200, + 0x033, 0x00000026, + 0x03F, 0x000001C0, + 0x033, 0x00000025, + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000002D, + 0x03F, 0x000773E8, + 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000002B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, + 0x03F, 0x00000280, + 0x033, 0x00000028, + 0x03F, 0x000FF280, + 0x033, 0x00000027, + 0x03F, 0x00000200, + 0x033, 0x00000026, + 0x03F, 0x000001C0, + 0x033, 0x00000025, + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, + 0xA0000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773E8, + 0x033, 0x0000002E, + 0x03F, 0x000FF3A0, + 0x033, 0x0000002D, + 0x03F, 0x00000380, + 0x033, 0x0000002C, + 0x03F, 0x000FF380, + 0x033, 0x0000002B, + 0x03F, 0x00000300, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, + 0x03F, 0x00000280, + 0x033, 0x00000028, + 0x03F, 0x000FF280, + 0x033, 0x00000027, + 0x03F, 0x00000200, + 0x033, 0x00000026, + 0x03F, 0x000001C0, + 0x033, 0x00000025, + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, + 0xB0000000, 0x00000000, + 0x033, 0x00000023, + 0x03F, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000003D, + 0x03F, 0x000773E8, + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, + 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, + 0x03F, 0x00000200, + 0x033, 0x00000036, + 0x03F, 0x000001C0, + 0x033, 0x00000035, + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000003D, + 0x03F, 0x000773E8, + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, + 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, + 0x03F, 0x00000200, + 0x033, 0x00000036, + 0x03F, 0x000001C0, + 0x033, 0x00000035, + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000003D, + 0x03F, 0x000773E8, + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, + 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, + 0x03F, 0x00000200, + 0x033, 0x00000036, + 0x03F, 0x000001C0, + 0x033, 0x00000035, + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000003D, + 0x03F, 0x000773E8, + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, + 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, + 0x03F, 0x00000200, + 0x033, 0x00000036, + 0x03F, 0x000001C0, + 0x033, 0x00000035, + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000003D, + 0x03F, 0x000773E8, + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, + 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, + 0x03F, 0x00000200, + 0x033, 0x00000036, + 0x03F, 0x000001C0, + 0x033, 0x00000035, + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000003D, + 0x03F, 0x000773E8, + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, + 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, + 0x03F, 0x00000200, + 0x033, 0x00000036, + 0x03F, 0x000001C0, + 0x033, 0x00000035, + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, + 0xA0000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773E8, + 0x033, 0x0000003E, + 0x03F, 0x000FF3A0, + 0x033, 0x0000003D, + 0x03F, 0x00000380, + 0x033, 0x0000003C, + 0x03F, 0x000FF380, + 0x033, 0x0000003B, + 0x03F, 0x00000300, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, + 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, + 0x03F, 0x00000200, + 0x033, 0x00000036, + 0x03F, 0x000001C0, + 0x033, 0x00000035, + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, + 0xB0000000, 0x00000000, + 0x033, 0x00000033, + 0x03F, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000004D, + 0x03F, 0x000773E8, + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, + 0x03F, 0x00000280, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, + 0x03F, 0x00000200, + 0x033, 0x00000046, + 0x03F, 0x000001C0, + 0x033, 0x00000045, + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000004D, + 0x03F, 0x000773E8, + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, + 0x03F, 0x00000280, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, + 0x03F, 0x00000200, + 0x033, 0x00000046, + 0x03F, 0x000001C0, + 0x033, 0x00000045, + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000004D, + 0x03F, 0x000773E8, + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, + 0x03F, 0x00000280, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, + 0x03F, 0x00000200, + 0x033, 0x00000046, + 0x03F, 0x000001C0, + 0x033, 0x00000045, + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000004D, + 0x03F, 0x000773E8, + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, + 0x03F, 0x00000280, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, + 0x03F, 0x00000200, + 0x033, 0x00000046, + 0x03F, 0x000001C0, + 0x033, 0x00000045, + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000004D, + 0x03F, 0x000773E8, + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, + 0x03F, 0x00000280, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, + 0x03F, 0x00000200, + 0x033, 0x00000046, + 0x03F, 0x000001C0, + 0x033, 0x00000045, + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000004D, + 0x03F, 0x000773E8, + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, + 0x03F, 0x00000280, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, + 0x03F, 0x00000200, + 0x033, 0x00000046, + 0x03F, 0x000001C0, + 0x033, 0x00000045, + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, + 0xA0000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773E8, + 0x033, 0x0000004E, + 0x03F, 0x000FF3A0, + 0x033, 0x0000004D, + 0x03F, 0x00000380, + 0x033, 0x0000004C, + 0x03F, 0x000FF380, + 0x033, 0x0000004B, + 0x03F, 0x00000300, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, + 0x03F, 0x00000280, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, + 0x03F, 0x00000200, + 0x033, 0x00000046, + 0x03F, 0x000001C0, + 0x033, 0x00000045, + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, + 0xB0000000, 0x00000000, + 0x033, 0x00000043, + 0x03F, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000005D, + 0x03F, 0x000773E8, + 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, + 0x03F, 0x00000280, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, + 0x03F, 0x00000200, + 0x033, 0x00000056, + 0x03F, 0x000001C0, + 0x033, 0x00000055, + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000005D, + 0x03F, 0x000773E8, + 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, + 0x03F, 0x00000280, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, + 0x03F, 0x00000200, + 0x033, 0x00000056, + 0x03F, 0x000001C0, + 0x033, 0x00000055, + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000005D, + 0x03F, 0x000773E8, + 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, + 0x03F, 0x00000280, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, + 0x03F, 0x00000200, + 0x033, 0x00000056, + 0x03F, 0x000001C0, + 0x033, 0x00000055, + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000005D, + 0x03F, 0x000773E8, + 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, + 0x03F, 0x00000280, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, + 0x03F, 0x00000200, + 0x033, 0x00000056, + 0x03F, 0x000001C0, + 0x033, 0x00000055, + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000005D, + 0x03F, 0x000773E8, + 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, + 0x03F, 0x00000280, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, + 0x03F, 0x00000200, + 0x033, 0x00000056, + 0x03F, 0x000001C0, + 0x033, 0x00000055, + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000005D, + 0x03F, 0x000773E8, + 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, + 0x03F, 0x00000280, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, + 0x03F, 0x00000200, + 0x033, 0x00000056, + 0x03F, 0x000001C0, + 0x033, 0x00000055, + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, + 0xA0000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773E8, + 0x033, 0x0000005E, + 0x03F, 0x000FF3A0, + 0x033, 0x0000005D, + 0x03F, 0x00000380, + 0x033, 0x0000005C, + 0x03F, 0x000FF380, + 0x033, 0x0000005B, + 0x03F, 0x00000300, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, + 0x03F, 0x00000280, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, + 0x03F, 0x00000200, + 0x033, 0x00000056, + 0x03F, 0x000001C0, + 0x033, 0x00000055, + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, + 0xB0000000, 0x00000000, + 0x033, 0x00000053, + 0x03F, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000000, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000000, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000000, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000000, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000000, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000000, + 0xA0000000, 0x00000000, + 0x0EF, 0x00000000, + 0xB0000000, 0x00000000, + 0x08A, 0x000E7DE3, + 0x08B, 0x0008FE00, + 0x0EE, 0x00000008, + 0x033, 0x00000000, + 0x03F, 0x00000023, + 0x033, 0x00000001, + 0x03F, 0x00000023, + 0x0EE, 0x00000000, + 0x0EF, 0x00004000, + 0x033, 0x00000000, + 0x03F, 0x0000000F, + 0x033, 0x00000002, + 0x03F, 0x00000000, + 0x0EF, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000002, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000003, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000004, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000005, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000006, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000008, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000000A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000000B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000000C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000000D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000000E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000010, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000012, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000013, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000014, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000015, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000016, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000017, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000001A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000001B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000001C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000001D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000001E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000001F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000022, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000023, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000024, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000025, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000026, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000027, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000002A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000002B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000002C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000002D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000002E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000002F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000002, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000003, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000004, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000005, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000006, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000008, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000000A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000000B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000000C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000000D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000000E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000010, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000012, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000013, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000014, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000015, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000016, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000017, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000001A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000001B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000001C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000001D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000001E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000001F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000022, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000023, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000024, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000025, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000026, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000027, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000002A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000002B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000002C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000002D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000002E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000002F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000002, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000003, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000004, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000005, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000006, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000008, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000000A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000000B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000000C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000000D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000000E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000010, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000012, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000013, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000014, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000015, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000016, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000017, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000001A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000001B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000001C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000001D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000001E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000001F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000022, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000023, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000024, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000025, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000026, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000027, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000002A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000002B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000002C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000002D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000002E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000002F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000002, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000003, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000004, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000005, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000006, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000008, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000000A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000000B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000000C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000000D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000000E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000010, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000012, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000013, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000014, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000015, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000016, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000017, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000001A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000001B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000001C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000001D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000001E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000001F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000022, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000023, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000024, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000025, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000026, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000027, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000002A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000002B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000002C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000002D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000002E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000002F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000002, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000003, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000004, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000005, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000006, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000008, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000000A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000000B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000000C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000000D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000000E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000010, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000012, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000013, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000014, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000015, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000016, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000017, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000001A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000001B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000001C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000001D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000001E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000001F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000022, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000023, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000024, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000025, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000026, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000027, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000002A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000002B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000002C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000002D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000002E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000002F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000002, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000003, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000004, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000005, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000006, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000008, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000000A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000000B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000000C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000000D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000000E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000010, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000012, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000013, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000014, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000015, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000016, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000017, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000001A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000001B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000001C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000001D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000001E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000001F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000022, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000023, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000024, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000025, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000026, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000027, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000002A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000002B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000002C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000002D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000002E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000002F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0xA0000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000002, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000003, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000004, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000005, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000006, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000008, + 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000000A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000000B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000000C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000000D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000000E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000010, + 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000012, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000013, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000014, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000015, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000016, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000017, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, + 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000001A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000001B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000001C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000001D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000001E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000001F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, + 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000022, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000023, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000024, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000025, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000026, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000027, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, + 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000002A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000002B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000002C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000002D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000002E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000002F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0xB0000000, 0x00000000, + 0x0FE, 0x00000000, + 0x01B, 0x00003A40, + 0x061, 0x0000D233, + 0x062, 0x0004D232, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x063, 0x00000002, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x063, 0x00000002, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x063, 0x00000002, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x063, 0x00000002, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x063, 0x00000002, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x063, 0x00000002, + 0xA0000000, 0x00000000, + 0x063, 0x00000C02, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000200, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000237, + 0x030, 0x00001237, + 0x030, 0x00002237, + 0x030, 0x00003237, + 0x030, 0x00004207, + 0x030, 0x00005237, + 0x030, 0x00006237, + 0x030, 0x00007237, + 0x030, 0x00008207, + 0x030, 0x00009237, + 0x030, 0x0000A237, + 0x030, 0x0000B237, + 0x030, 0x0000C237, + 0x030, 0x0000D237, + 0x030, 0x0000E207, + 0x030, 0x0000F237, + 0x030, 0x00010237, + 0x030, 0x00011237, + 0x030, 0x00012207, + 0x030, 0x00013237, + 0x030, 0x00014237, + 0x030, 0x00015237, + 0x030, 0x00016207, + 0x030, 0x00017237, + 0x030, 0x00018207, + 0x030, 0x00019237, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000237, + 0x030, 0x00001237, + 0x030, 0x00002237, + 0x030, 0x00003237, + 0x030, 0x00004207, + 0x030, 0x00005237, + 0x030, 0x00006237, + 0x030, 0x00007237, + 0x030, 0x00008207, + 0x030, 0x00009237, + 0x030, 0x0000A237, + 0x030, 0x0000B237, + 0x030, 0x0000C237, + 0x030, 0x0000D237, + 0x030, 0x0000E207, + 0x030, 0x0000F237, + 0x030, 0x00010237, + 0x030, 0x00011237, + 0x030, 0x00012207, + 0x030, 0x00013237, + 0x030, 0x00014237, + 0x030, 0x00015237, + 0x030, 0x00016207, + 0x030, 0x00017237, + 0x030, 0x00018207, + 0x030, 0x00019237, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000237, + 0x030, 0x00001237, + 0x030, 0x00002237, + 0x030, 0x00003237, + 0x030, 0x00004207, + 0x030, 0x00005237, + 0x030, 0x00006237, + 0x030, 0x00007237, + 0x030, 0x00008207, + 0x030, 0x00009237, + 0x030, 0x0000A237, + 0x030, 0x0000B237, + 0x030, 0x0000C237, + 0x030, 0x0000D237, + 0x030, 0x0000E207, + 0x030, 0x0000F237, + 0x030, 0x00010237, + 0x030, 0x00011237, + 0x030, 0x00012207, + 0x030, 0x00013237, + 0x030, 0x00014237, + 0x030, 0x00015237, + 0x030, 0x00016207, + 0x030, 0x00017237, + 0x030, 0x00018207, + 0x030, 0x00019237, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000237, + 0x030, 0x00001237, + 0x030, 0x00002237, + 0x030, 0x00003237, + 0x030, 0x00004207, + 0x030, 0x00005237, + 0x030, 0x00006237, + 0x030, 0x00007237, + 0x030, 0x00008207, + 0x030, 0x00009237, + 0x030, 0x0000A237, + 0x030, 0x0000B237, + 0x030, 0x0000C237, + 0x030, 0x0000D237, + 0x030, 0x0000E207, + 0x030, 0x0000F237, + 0x030, 0x00010237, + 0x030, 0x00011237, + 0x030, 0x00012207, + 0x030, 0x00013237, + 0x030, 0x00014237, + 0x030, 0x00015237, + 0x030, 0x00016207, + 0x030, 0x00017237, + 0x030, 0x00018207, + 0x030, 0x00019237, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000237, + 0x030, 0x00001237, + 0x030, 0x00002237, + 0x030, 0x00003237, + 0x030, 0x00004207, + 0x030, 0x00005237, + 0x030, 0x00006237, + 0x030, 0x00007237, + 0x030, 0x00008207, + 0x030, 0x00009237, + 0x030, 0x0000A237, + 0x030, 0x0000B237, + 0x030, 0x0000C237, + 0x030, 0x0000D237, + 0x030, 0x0000E207, + 0x030, 0x0000F237, + 0x030, 0x00010237, + 0x030, 0x00011237, + 0x030, 0x00012207, + 0x030, 0x00013237, + 0x030, 0x00014237, + 0x030, 0x00015237, + 0x030, 0x00016207, + 0x030, 0x00017237, + 0x030, 0x00018207, + 0x030, 0x00019237, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000237, + 0x030, 0x00001237, + 0x030, 0x00002237, + 0x030, 0x00003237, + 0x030, 0x00004207, + 0x030, 0x00005237, + 0x030, 0x00006237, + 0x030, 0x00007237, + 0x030, 0x00008207, + 0x030, 0x00009237, + 0x030, 0x0000A237, + 0x030, 0x0000B237, + 0x030, 0x0000C237, + 0x030, 0x0000D237, + 0x030, 0x0000E207, + 0x030, 0x0000F237, + 0x030, 0x00010237, + 0x030, 0x00011237, + 0x030, 0x00012207, + 0x030, 0x00013237, + 0x030, 0x00014237, + 0x030, 0x00015237, + 0x030, 0x00016207, + 0x030, 0x00017237, + 0x030, 0x00018207, + 0x030, 0x00019237, + 0xA0000000, 0x00000000, + 0x030, 0x00000233, + 0x030, 0x00001233, + 0x030, 0x00002233, + 0x030, 0x00003233, + 0x030, 0x00004203, + 0x030, 0x00005233, + 0x030, 0x00006233, + 0x030, 0x00007233, + 0x030, 0x00008203, + 0x030, 0x00009233, + 0x030, 0x0000A233, + 0x030, 0x0000B233, + 0x030, 0x0000C233, + 0x030, 0x0000D233, + 0x030, 0x0000E203, + 0x030, 0x0000F233, + 0x030, 0x00010233, + 0x030, 0x00011233, + 0x030, 0x00012203, + 0x030, 0x00013233, + 0x030, 0x00014233, + 0x030, 0x00015233, + 0x030, 0x00016203, + 0x030, 0x00017233, + 0x030, 0x00018203, + 0x030, 0x00019233, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x0EF, 0x00000080, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000334, + 0x030, 0x00001334, + 0x030, 0x00002334, + 0x030, 0x00003334, + 0x030, 0x00004334, + 0x030, 0x00005334, + 0x030, 0x00006334, + 0x030, 0x00007334, + 0x030, 0x00008334, + 0x030, 0x00009334, + 0x030, 0x0000A334, + 0x030, 0x0000B334, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000334, + 0x030, 0x00001334, + 0x030, 0x00002334, + 0x030, 0x00003334, + 0x030, 0x00004334, + 0x030, 0x00005334, + 0x030, 0x00006334, + 0x030, 0x00007334, + 0x030, 0x00008334, + 0x030, 0x00009334, + 0x030, 0x0000A334, + 0x030, 0x0000B334, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000334, + 0x030, 0x00001334, + 0x030, 0x00002334, + 0x030, 0x00003334, + 0x030, 0x00004334, + 0x030, 0x00005334, + 0x030, 0x00006334, + 0x030, 0x00007334, + 0x030, 0x00008334, + 0x030, 0x00009334, + 0x030, 0x0000A334, + 0x030, 0x0000B334, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000334, + 0x030, 0x00001334, + 0x030, 0x00002334, + 0x030, 0x00003334, + 0x030, 0x00004334, + 0x030, 0x00005334, + 0x030, 0x00006334, + 0x030, 0x00007334, + 0x030, 0x00008334, + 0x030, 0x00009334, + 0x030, 0x0000A334, + 0x030, 0x0000B334, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000334, + 0x030, 0x00001334, + 0x030, 0x00002334, + 0x030, 0x00003334, + 0x030, 0x00004334, + 0x030, 0x00005334, + 0x030, 0x00006334, + 0x030, 0x00007334, + 0x030, 0x00008334, + 0x030, 0x00009334, + 0x030, 0x0000A334, + 0x030, 0x0000B334, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000334, + 0x030, 0x00001334, + 0x030, 0x00002334, + 0x030, 0x00003334, + 0x030, 0x00004334, + 0x030, 0x00005334, + 0x030, 0x00006334, + 0x030, 0x00007334, + 0x030, 0x00008334, + 0x030, 0x00009334, + 0x030, 0x0000A334, + 0x030, 0x0000B334, + 0xA0000000, 0x00000000, + 0x030, 0x00000232, + 0x030, 0x00001232, + 0x030, 0x00002232, + 0x030, 0x00003232, + 0x030, 0x00004232, + 0x030, 0x00005232, + 0x030, 0x00006232, + 0x030, 0x00007232, + 0x030, 0x00008232, + 0x030, 0x00009232, + 0x030, 0x0000A232, + 0x030, 0x0000B232, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000770, + 0x030, 0x00001770, + 0x030, 0x00002440, + 0x030, 0x00003440, + 0x030, 0x00004330, + 0x030, 0x00005330, + 0x030, 0x00008770, + 0x030, 0x0000A440, + 0x030, 0x0000C330, + 0x0EF, 0x00000000, + 0x0EE, 0x00010000, + 0x033, 0x00000200, + 0x03F, 0x0000006A, + 0x033, 0x00000201, + 0x03F, 0x0000006D, + 0x033, 0x00000202, + 0x03F, 0x0000046A, + 0x033, 0x00000203, + 0x03F, 0x0000086A, + 0x033, 0x00000204, + 0x03F, 0x00000C89, + 0x033, 0x00000205, + 0x03F, 0x00000CE8, + 0x033, 0x00000206, + 0x03F, 0x00000CEB, + 0x033, 0x00000207, + 0x03F, 0x00000CEE, + 0x033, 0x00000208, + 0x03F, 0x00000CF1, + 0x033, 0x00000209, + 0x03F, 0x00000CF4, + 0x033, 0x0000020A, + 0x03F, 0x00000CF7, + 0x033, 0x00000280, + 0x03F, 0x0000006A, + 0x033, 0x00000281, + 0x03F, 0x0000006D, + 0x033, 0x00000282, + 0x03F, 0x0000046A, + 0x033, 0x00000283, + 0x03F, 0x0000086A, + 0x033, 0x00000284, + 0x03F, 0x00000C89, + 0x033, 0x00000285, + 0x03F, 0x00000CE8, + 0x033, 0x00000286, + 0x03F, 0x00000CEB, + 0x033, 0x00000287, + 0x03F, 0x00000CEE, + 0x033, 0x00000288, + 0x03F, 0x00000CF1, + 0x033, 0x00000289, + 0x03F, 0x00000CF4, + 0x033, 0x0000028A, + 0x03F, 0x00000CF7, + 0x033, 0x00000300, + 0x03F, 0x0000006A, + 0x033, 0x00000301, + 0x03F, 0x0000006D, + 0x033, 0x00000302, + 0x03F, 0x0000046A, + 0x033, 0x00000303, + 0x03F, 0x0000086A, + 0x033, 0x00000304, + 0x03F, 0x00000C89, + 0x033, 0x00000305, + 0x03F, 0x00000CE8, + 0x033, 0x00000306, + 0x03F, 0x00000CEB, + 0x033, 0x00000307, + 0x03F, 0x00000CEE, + 0x033, 0x00000308, + 0x03F, 0x00000CF1, + 0x033, 0x00000309, + 0x03F, 0x00000CF4, + 0x033, 0x0000030A, + 0x03F, 0x00000CF7, + 0x0EE, 0x00000000, + 0x051, 0x0003C800, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0xA0000000, 0x00000000, + 0x052, 0x000942CA, + 0xB0000000, 0x00000000, + 0x053, 0x000090F9, + 0x054, 0x00088000, + 0x057, 0x0004C80A, + 0x0EF, 0x00000020, + 0x033, 0x00000000, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000001, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000002, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000003, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000004, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000005, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000006, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000007, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000008, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000009, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000A, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000B, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000C, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000D, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000E, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00010E46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000F, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000010, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000011, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00030246, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000012, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000013, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000014, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000015, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000016, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000017, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000018, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000019, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001A, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001B, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001C, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001D, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001E, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001F, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000020, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000021, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000022, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000023, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000024, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000025, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000026, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000027, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000028, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x00000029, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00031E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x033, 0x0000002A, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0000EA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00021E46, + 0xA0000000, 0x00000000, + 0x03F, 0x00002A46, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x0EE, 0x00010000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000468, + 0x033, 0x00000061, + 0x03F, 0x00000868, + 0x033, 0x00000062, + 0x03F, 0x00000909, + 0x033, 0x00000063, + 0x03F, 0x00000D0A, + 0x033, 0x00000064, + 0x03F, 0x00000D4A, + 0x033, 0x00000065, + 0x03F, 0x00000D8B, + 0x033, 0x00000066, + 0x03F, 0x00000DEB, + 0x033, 0x00000067, + 0x03F, 0x00000DEE, + 0x033, 0x00000068, + 0x03F, 0x00000DF1, + 0x033, 0x00000069, + 0x03F, 0x00000DF4, + 0x033, 0x0000006A, + 0x03F, 0x00000DF7, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000468, + 0x033, 0x00000061, + 0x03F, 0x00000868, + 0x033, 0x00000062, + 0x03F, 0x00000909, + 0x033, 0x00000063, + 0x03F, 0x00000D0A, + 0x033, 0x00000064, + 0x03F, 0x00000D4A, + 0x033, 0x00000065, + 0x03F, 0x00000D8B, + 0x033, 0x00000066, + 0x03F, 0x00000DEB, + 0x033, 0x00000067, + 0x03F, 0x00000DEE, + 0x033, 0x00000068, + 0x03F, 0x00000DF1, + 0x033, 0x00000069, + 0x03F, 0x00000DF4, + 0x033, 0x0000006A, + 0x03F, 0x00000DF7, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000468, + 0x033, 0x00000061, + 0x03F, 0x00000868, + 0x033, 0x00000062, + 0x03F, 0x00000909, + 0x033, 0x00000063, + 0x03F, 0x00000D0A, + 0x033, 0x00000064, + 0x03F, 0x00000D4A, + 0x033, 0x00000065, + 0x03F, 0x00000D8B, + 0x033, 0x00000066, + 0x03F, 0x00000DEB, + 0x033, 0x00000067, + 0x03F, 0x00000DEE, + 0x033, 0x00000068, + 0x03F, 0x00000DF1, + 0x033, 0x00000069, + 0x03F, 0x00000DF4, + 0x033, 0x0000006A, + 0x03F, 0x00000DF7, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000468, + 0x033, 0x00000061, + 0x03F, 0x00000868, + 0x033, 0x00000062, + 0x03F, 0x00000909, + 0x033, 0x00000063, + 0x03F, 0x00000D0A, + 0x033, 0x00000064, + 0x03F, 0x00000D4A, + 0x033, 0x00000065, + 0x03F, 0x00000D8B, + 0x033, 0x00000066, + 0x03F, 0x00000DEB, + 0x033, 0x00000067, + 0x03F, 0x00000DEE, + 0x033, 0x00000068, + 0x03F, 0x00000DF1, + 0x033, 0x00000069, + 0x03F, 0x00000DF4, + 0x033, 0x0000006A, + 0x03F, 0x00000DF7, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000468, + 0x033, 0x00000061, + 0x03F, 0x00000868, + 0x033, 0x00000062, + 0x03F, 0x00000909, + 0x033, 0x00000063, + 0x03F, 0x00000D0A, + 0x033, 0x00000064, + 0x03F, 0x00000D4A, + 0x033, 0x00000065, + 0x03F, 0x00000D8B, + 0x033, 0x00000066, + 0x03F, 0x00000DEB, + 0x033, 0x00000067, + 0x03F, 0x00000DEE, + 0x033, 0x00000068, + 0x03F, 0x00000DF1, + 0x033, 0x00000069, + 0x03F, 0x00000DF4, + 0x033, 0x0000006A, + 0x03F, 0x00000DF7, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000468, + 0x033, 0x00000061, + 0x03F, 0x00000868, + 0x033, 0x00000062, + 0x03F, 0x00000909, + 0x033, 0x00000063, + 0x03F, 0x00000D0A, + 0x033, 0x00000064, + 0x03F, 0x00000D4A, + 0x033, 0x00000065, + 0x03F, 0x00000D8B, + 0x033, 0x00000066, + 0x03F, 0x00000DEB, + 0x033, 0x00000067, + 0x03F, 0x00000DEE, + 0x033, 0x00000068, + 0x03F, 0x00000DF1, + 0x033, 0x00000069, + 0x03F, 0x00000DF4, + 0x033, 0x0000006A, + 0x03F, 0x00000DF7, + 0xA0000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000487, + 0x033, 0x00000061, + 0x03F, 0x00000887, + 0x033, 0x00000062, + 0x03F, 0x00000947, + 0x033, 0x00000063, + 0x03F, 0x00000D48, + 0x033, 0x00000064, + 0x03F, 0x00000D88, + 0x033, 0x00000065, + 0x03F, 0x00000DE8, + 0x033, 0x00000066, + 0x03F, 0x00000DEB, + 0x033, 0x00000067, + 0x03F, 0x00000DEE, + 0x033, 0x00000068, + 0x03F, 0x00000DF1, + 0x033, 0x00000069, + 0x03F, 0x00000DF4, + 0x033, 0x0000006A, + 0x03F, 0x00000DF7, + 0xB0000000, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000468, + 0x033, 0x00000021, + 0x03F, 0x00000868, + 0x033, 0x00000022, + 0x03F, 0x00000909, + 0x033, 0x00000023, + 0x03F, 0x00000D0A, + 0x033, 0x00000024, + 0x03F, 0x00000D4A, + 0x033, 0x00000025, + 0x03F, 0x00000D8B, + 0x033, 0x00000026, + 0x03F, 0x00000DEB, + 0x033, 0x00000027, + 0x03F, 0x00000DEE, + 0x033, 0x00000028, + 0x03F, 0x00000DF1, + 0x033, 0x00000029, + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000468, + 0x033, 0x00000021, + 0x03F, 0x00000868, + 0x033, 0x00000022, + 0x03F, 0x00000909, + 0x033, 0x00000023, + 0x03F, 0x00000D0A, + 0x033, 0x00000024, + 0x03F, 0x00000D4A, + 0x033, 0x00000025, + 0x03F, 0x00000D8B, + 0x033, 0x00000026, + 0x03F, 0x00000DEB, + 0x033, 0x00000027, + 0x03F, 0x00000DEE, + 0x033, 0x00000028, + 0x03F, 0x00000DF1, + 0x033, 0x00000029, + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000468, + 0x033, 0x00000021, + 0x03F, 0x00000868, + 0x033, 0x00000022, + 0x03F, 0x00000909, + 0x033, 0x00000023, + 0x03F, 0x00000D0A, + 0x033, 0x00000024, + 0x03F, 0x00000D4A, + 0x033, 0x00000025, + 0x03F, 0x00000D8B, + 0x033, 0x00000026, + 0x03F, 0x00000DEB, + 0x033, 0x00000027, + 0x03F, 0x00000DEE, + 0x033, 0x00000028, + 0x03F, 0x00000DF1, + 0x033, 0x00000029, + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000468, + 0x033, 0x00000021, + 0x03F, 0x00000868, + 0x033, 0x00000022, + 0x03F, 0x00000909, + 0x033, 0x00000023, + 0x03F, 0x00000D0A, + 0x033, 0x00000024, + 0x03F, 0x00000D4A, + 0x033, 0x00000025, + 0x03F, 0x00000D8B, + 0x033, 0x00000026, + 0x03F, 0x00000DEB, + 0x033, 0x00000027, + 0x03F, 0x00000DEE, + 0x033, 0x00000028, + 0x03F, 0x00000DF1, + 0x033, 0x00000029, + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000468, + 0x033, 0x00000021, + 0x03F, 0x00000868, + 0x033, 0x00000022, + 0x03F, 0x00000909, + 0x033, 0x00000023, + 0x03F, 0x00000D0A, + 0x033, 0x00000024, + 0x03F, 0x00000D4A, + 0x033, 0x00000025, + 0x03F, 0x00000D8B, + 0x033, 0x00000026, + 0x03F, 0x00000DEB, + 0x033, 0x00000027, + 0x03F, 0x00000DEE, + 0x033, 0x00000028, + 0x03F, 0x00000DF1, + 0x033, 0x00000029, + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000468, + 0x033, 0x00000021, + 0x03F, 0x00000868, + 0x033, 0x00000022, + 0x03F, 0x00000909, + 0x033, 0x00000023, + 0x03F, 0x00000D0A, + 0x033, 0x00000024, + 0x03F, 0x00000D4A, + 0x033, 0x00000025, + 0x03F, 0x00000D8B, + 0x033, 0x00000026, + 0x03F, 0x00000DEB, + 0x033, 0x00000027, + 0x03F, 0x00000DEE, + 0x033, 0x00000028, + 0x03F, 0x00000DF1, + 0x033, 0x00000029, + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, + 0xA0000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000487, + 0x033, 0x00000021, + 0x03F, 0x00000887, + 0x033, 0x00000022, + 0x03F, 0x00000947, + 0x033, 0x00000023, + 0x03F, 0x00000D48, + 0x033, 0x00000024, + 0x03F, 0x00000D88, + 0x033, 0x00000025, + 0x03F, 0x00000DE8, + 0x033, 0x00000026, + 0x03F, 0x00000DEB, + 0x033, 0x00000027, + 0x03F, 0x00000DEE, + 0x033, 0x00000028, + 0x03F, 0x00000DF1, + 0x033, 0x00000029, + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, + 0xB0000000, 0x00000000, + 0x0EE, 0x00000000, + 0x05C, 0x000FCC00, + 0x067, 0x0000A505, + 0x0D3, 0x00000542, + 0x043, 0x00005000, + 0x07F, 0x00000000, + 0x0B0, 0x0001F0FC, + 0x0B1, 0x0007DBE4, + 0x0B2, 0x00022400, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C760, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C760, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C760, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C760, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C760, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C760, + 0xA0000000, 0x00000000, + 0x0B3, 0x0007C760, + 0xB0000000, 0x00000000, + 0x0B4, 0x00099D40, + 0x0B5, 0x0004103F, + 0x0B6, 0x000187F8, + 0x0B7, 0x00030018, + 0x0BC, 0x00000008, + 0x0D3, 0x00000542, + 0x0DD, 0x00000500, + 0x0BB, 0x00040010, + 0x0B0, 0x0001F0FA, + 0x0FE, 0x00000000, + 0x0CA, 0x00080000, + 0x0CA, 0x00080001, + 0x0FE, 0x00000000, + 0x0B0, 0x0001F0F8, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C700, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C700, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C700, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C700, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C700, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C700, + 0xA0000000, 0x00000000, + 0x0B3, 0x0007C700, + 0xB0000000, 0x00000000, + 0x018, 0x0001B124, + 0xFFE, 0x00000000, + 0xFFE, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C760, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C760, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C760, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C760, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C760, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0B3, 0x0007C760, + 0xA0000000, 0x00000000, + 0x0B3, 0x0007C760, + 0xB0000000, 0x00000000, + 0x018, 0x00013124, + 0x0CC, 0x0000F000, + 0x0CD, 0x00089600, + 0x018, 0x00013108, + 0x0FE, 0x00000000, + 0x0B8, 0x000C0440, + 0x0BA, 0x000E840D, + 0x0FE, 0x00000000, + 0x018, 0x00013124, + 0x059, 0x000A0000, + 0x05A, 0x00060000, + 0x05B, 0x00014000, + 0x0ED, 0x00000008, + 0x033, 0x00000001, + 0x03F, 0x0000000F, + 0x0ED, 0x00000000, + 0x0EE, 0x00000002, + 0x033, 0x00000017, + 0x03F, 0x0000003F, + 0x033, 0x00000018, + 0x03F, 0x0000003F, + 0x033, 0x00000019, + 0x03F, 0x00000000, + 0x033, 0x0000001A, + 0x03F, 0x0000003F, + 0x033, 0x0000001B, + 0x03F, 0x0000003F, + 0x033, 0x0000001C, + 0x03F, 0x0000003F, + 0x0EE, 0x00000000, + 0x0ED, 0x00000200, + 0x033, 0x00000000, + 0x03F, 0x000F45A4, + 0x033, 0x00000001, + 0x03F, 0x000F49A4, + 0x033, 0x00000002, + 0x03F, 0x000F49A4, + 0x033, 0x00000003, + 0x03F, 0x000F69A4, + 0x033, 0x00000004, + 0x03F, 0x000F69A4, + 0x033, 0x00000005, + 0x03F, 0x000F69A4, + 0x033, 0x00000006, + 0x03F, 0x000F6DA4, + 0x033, 0x00000007, + 0x03F, 0x000F6DA4, + 0x033, 0x00000008, + 0x03F, 0x000F6DA4, + 0x033, 0x00000009, + 0x03F, 0x000F8DA4, + 0x033, 0x0000000A, + 0x03F, 0x000F8DA4, + 0x033, 0x0000000B, + 0x03F, 0x000F8DA4, + 0x033, 0x0000000C, + 0x03F, 0x000F91A4, + 0x033, 0x0000000D, + 0x03F, 0x000F91A4, + 0x033, 0x0000000E, + 0x03F, 0x000F91A4, + 0x033, 0x0000000F, + 0x03F, 0x000FB1A4, + 0x033, 0x00000010, + 0x03F, 0x000FB1A4, + 0x033, 0x00000011, + 0x03F, 0x000FB1A4, + 0x033, 0x00000012, + 0x03F, 0x000FB5A4, + 0x033, 0x00000013, + 0x03F, 0x000FB5A4, + 0x033, 0x00000014, + 0x03F, 0x000FD9A4, + 0x033, 0x00000015, + 0x03F, 0x000FD9A4, + 0x033, 0x00000016, + 0x03F, 0x000FF9A4, + 0x033, 0x00000017, + 0x03F, 0x000FF9A4, + 0x033, 0x00000018, + 0x03F, 0x000FFDA4, + 0x033, 0x00000019, + 0x03F, 0x000FFDA4, + 0x033, 0x0000001A, + 0x03F, 0x000FFDA4, + 0x0ED, 0x00000000, + 0x092, 0x00084800, + 0x092, 0x00084801, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x092, 0x00084800, + 0x08F, 0x0000182C, + 0x088, 0x0004326B, + 0x019, 0x00000005, +}; + +RTW_DECL_TABLE_RF_RADIO(rtw8822c_rf_a, A); + +static const u32 rtw8822c_rf_b[] = { + 0x000, 0x00030000, + 0x018, 0x00013124, + 0x093, 0x0008483F, + 0x0EF, 0x00080000, + 0x033, 0x00000001, + 0x03F, 0x00091020, + 0x0EF, 0x00000000, + 0x0DE, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000B9140, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000B9140, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x08E, 0x000A5540, + 0xA0000000, 0x00000000, + 0x08E, 0x000A5540, + 0xB0000000, 0x00000000, + 0x081, 0x0000FC01, + 0x081, 0x0002FC01, + 0x081, 0x0003FC01, + 0x085, 0x0006A06C, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000002, + 0x03F, 0x0000002A, + 0x0EE, 0x00000000, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000002, + 0x03F, 0x0000002A, + 0x0EE, 0x00000000, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000002, + 0x03F, 0x0000002A, + 0x0EE, 0x00000000, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000002, + 0x03F, 0x0000002A, + 0x0EE, 0x00000000, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000002, + 0x03F, 0x0000002A, + 0x0EE, 0x00000000, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000001, + 0x03F, 0x0000002A, + 0x033, 0x00000002, + 0x03F, 0x0000002A, + 0x0EE, 0x00000000, + 0xA0000000, 0x00000000, + 0x0EE, 0x00000010, + 0x033, 0x00000001, + 0x03F, 0x0000003F, + 0x033, 0x00000001, + 0x03F, 0x0000003F, + 0x033, 0x00000002, + 0x03F, 0x0000003F, + 0x0EE, 0x00000000, + 0xB0000000, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, + 0x033, 0x0000000E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000000D, + 0x03F, 0x000773E8, + 0x033, 0x0000000C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000000B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000000A, + 0x03F, 0x000002A8, + 0x033, 0x00000009, + 0x03F, 0x00000280, + 0x033, 0x00000008, + 0x03F, 0x000FF280, + 0x033, 0x00000007, + 0x03F, 0x00000200, + 0x033, 0x00000006, + 0x03F, 0x000001C0, + 0x033, 0x00000005, + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, + 0x033, 0x0000000E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000000D, + 0x03F, 0x000773E8, + 0x033, 0x0000000C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000000B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000000A, + 0x03F, 0x000002A8, + 0x033, 0x00000009, + 0x03F, 0x00000280, + 0x033, 0x00000008, + 0x03F, 0x000FF280, + 0x033, 0x00000007, + 0x03F, 0x00000200, + 0x033, 0x00000006, + 0x03F, 0x000001C0, + 0x033, 0x00000005, + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, + 0x033, 0x0000000E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000000D, + 0x03F, 0x000773E8, + 0x033, 0x0000000C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000000B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000000A, + 0x03F, 0x000002A8, + 0x033, 0x00000009, + 0x03F, 0x00000280, + 0x033, 0x00000008, + 0x03F, 0x000FF280, + 0x033, 0x00000007, + 0x03F, 0x00000200, + 0x033, 0x00000006, + 0x03F, 0x000001C0, + 0x033, 0x00000005, + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, + 0x033, 0x0000000E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000000D, + 0x03F, 0x000773E8, + 0x033, 0x0000000C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000000B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000000A, + 0x03F, 0x000002A8, + 0x033, 0x00000009, + 0x03F, 0x00000280, + 0x033, 0x00000008, + 0x03F, 0x000FF280, + 0x033, 0x00000007, + 0x03F, 0x00000200, + 0x033, 0x00000006, + 0x03F, 0x000001C0, + 0x033, 0x00000005, + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, + 0x033, 0x0000000E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000000D, + 0x03F, 0x000773E8, + 0x033, 0x0000000C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000000B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000000A, + 0x03F, 0x000002A8, + 0x033, 0x00000009, + 0x03F, 0x00000280, + 0x033, 0x00000008, + 0x03F, 0x000FF280, + 0x033, 0x00000007, + 0x03F, 0x00000200, + 0x033, 0x00000006, + 0x03F, 0x000001C0, + 0x033, 0x00000005, + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773C0, + 0x033, 0x0000000E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000000D, + 0x03F, 0x000773E8, + 0x033, 0x0000000C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000000B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000000A, + 0x03F, 0x000002A8, + 0x033, 0x00000009, + 0x03F, 0x00000280, + 0x033, 0x00000008, + 0x03F, 0x000FF280, + 0x033, 0x00000007, + 0x03F, 0x00000200, + 0x033, 0x00000006, + 0x03F, 0x000001C0, + 0x033, 0x00000005, + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, + 0xA0000000, 0x00000000, + 0x0EF, 0x00010000, + 0x033, 0x0000000F, + 0x03F, 0x000773E8, + 0x033, 0x0000000E, + 0x03F, 0x000FF3A0, + 0x033, 0x0000000D, + 0x03F, 0x00000380, + 0x033, 0x0000000C, + 0x03F, 0x000FF380, + 0x033, 0x0000000B, + 0x03F, 0x00000300, + 0x033, 0x0000000A, + 0x03F, 0x000002A8, + 0x033, 0x00000009, + 0x03F, 0x00000280, + 0x033, 0x00000008, + 0x03F, 0x000FF280, + 0x033, 0x00000007, + 0x03F, 0x00000200, + 0x033, 0x00000006, + 0x03F, 0x000001C0, + 0x033, 0x00000005, + 0x03F, 0x00000180, + 0x033, 0x00000004, + 0x03F, 0x00000040, + 0xB0000000, 0x00000000, + 0x033, 0x00000003, + 0x03F, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000001D, + 0x03F, 0x000773E8, + 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000001B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, + 0x03F, 0x00000280, + 0x033, 0x00000018, + 0x03F, 0x000FF280, + 0x033, 0x00000017, + 0x03F, 0x00000200, + 0x033, 0x00000016, + 0x03F, 0x000001C0, + 0x033, 0x00000015, + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000001D, + 0x03F, 0x000773E8, + 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000001B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, + 0x03F, 0x00000280, + 0x033, 0x00000018, + 0x03F, 0x000FF280, + 0x033, 0x00000017, + 0x03F, 0x00000200, + 0x033, 0x00000016, + 0x03F, 0x000001C0, + 0x033, 0x00000015, + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000001D, + 0x03F, 0x000773E8, + 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000001B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, + 0x03F, 0x00000280, + 0x033, 0x00000018, + 0x03F, 0x000FF280, + 0x033, 0x00000017, + 0x03F, 0x00000200, + 0x033, 0x00000016, + 0x03F, 0x000001C0, + 0x033, 0x00000015, + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000001D, + 0x03F, 0x000773E8, + 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000001B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, + 0x03F, 0x00000280, + 0x033, 0x00000018, + 0x03F, 0x000FF280, + 0x033, 0x00000017, + 0x03F, 0x00000200, + 0x033, 0x00000016, + 0x03F, 0x000001C0, + 0x033, 0x00000015, + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000001D, + 0x03F, 0x000773E8, + 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000001B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, + 0x03F, 0x00000280, + 0x033, 0x00000018, + 0x03F, 0x000FF280, + 0x033, 0x00000017, + 0x03F, 0x00000200, + 0x033, 0x00000016, + 0x03F, 0x000001C0, + 0x033, 0x00000015, + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773C0, + 0x033, 0x0000001E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000001D, + 0x03F, 0x000773E8, + 0x033, 0x0000001C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000001B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, + 0x03F, 0x00000280, + 0x033, 0x00000018, + 0x03F, 0x000FF280, + 0x033, 0x00000017, + 0x03F, 0x00000200, + 0x033, 0x00000016, + 0x03F, 0x000001C0, + 0x033, 0x00000015, + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, + 0xA0000000, 0x00000000, + 0x033, 0x0000001F, + 0x03F, 0x000773E8, + 0x033, 0x0000001E, + 0x03F, 0x000FF3A0, + 0x033, 0x0000001D, + 0x03F, 0x00000380, + 0x033, 0x0000001C, + 0x03F, 0x000FF380, + 0x033, 0x0000001B, + 0x03F, 0x00000300, + 0x033, 0x0000001A, + 0x03F, 0x000002A8, + 0x033, 0x00000019, + 0x03F, 0x00000280, + 0x033, 0x00000018, + 0x03F, 0x000FF280, + 0x033, 0x00000017, + 0x03F, 0x00000200, + 0x033, 0x00000016, + 0x03F, 0x000001C0, + 0x033, 0x00000015, + 0x03F, 0x00000180, + 0x033, 0x00000014, + 0x03F, 0x00000040, + 0xB0000000, 0x00000000, + 0x033, 0x00000013, + 0x03F, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000002D, + 0x03F, 0x000773E8, + 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000002B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, + 0x03F, 0x00000280, + 0x033, 0x00000028, + 0x03F, 0x000FF280, + 0x033, 0x00000027, + 0x03F, 0x00000200, + 0x033, 0x00000026, + 0x03F, 0x000001C0, + 0x033, 0x00000025, + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000002D, + 0x03F, 0x000773E8, + 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000002B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, + 0x03F, 0x00000280, + 0x033, 0x00000028, + 0x03F, 0x000FF280, + 0x033, 0x00000027, + 0x03F, 0x00000200, + 0x033, 0x00000026, + 0x03F, 0x000001C0, + 0x033, 0x00000025, + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000002D, + 0x03F, 0x000773E8, + 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000002B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, + 0x03F, 0x00000280, + 0x033, 0x00000028, + 0x03F, 0x000FF280, + 0x033, 0x00000027, + 0x03F, 0x00000200, + 0x033, 0x00000026, + 0x03F, 0x000001C0, + 0x033, 0x00000025, + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000002D, + 0x03F, 0x000773E8, + 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000002B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, + 0x03F, 0x00000280, + 0x033, 0x00000028, + 0x03F, 0x000FF280, + 0x033, 0x00000027, + 0x03F, 0x00000200, + 0x033, 0x00000026, + 0x03F, 0x000001C0, + 0x033, 0x00000025, + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000002D, + 0x03F, 0x000773E8, + 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000002B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, + 0x03F, 0x00000280, + 0x033, 0x00000028, + 0x03F, 0x000FF280, + 0x033, 0x00000027, + 0x03F, 0x00000200, + 0x033, 0x00000026, + 0x03F, 0x000001C0, + 0x033, 0x00000025, + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773C0, + 0x033, 0x0000002E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000002D, + 0x03F, 0x000773E8, + 0x033, 0x0000002C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000002B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, + 0x03F, 0x00000280, + 0x033, 0x00000028, + 0x03F, 0x000FF280, + 0x033, 0x00000027, + 0x03F, 0x00000200, + 0x033, 0x00000026, + 0x03F, 0x000001C0, + 0x033, 0x00000025, + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, + 0xA0000000, 0x00000000, + 0x033, 0x0000002F, + 0x03F, 0x000773E8, + 0x033, 0x0000002E, + 0x03F, 0x000FF3A0, + 0x033, 0x0000002D, + 0x03F, 0x00000380, + 0x033, 0x0000002C, + 0x03F, 0x000FF380, + 0x033, 0x0000002B, + 0x03F, 0x00000300, + 0x033, 0x0000002A, + 0x03F, 0x000002A8, + 0x033, 0x00000029, + 0x03F, 0x00000280, + 0x033, 0x00000028, + 0x03F, 0x000FF280, + 0x033, 0x00000027, + 0x03F, 0x00000200, + 0x033, 0x00000026, + 0x03F, 0x000001C0, + 0x033, 0x00000025, + 0x03F, 0x00000180, + 0x033, 0x00000024, + 0x03F, 0x00000040, + 0xB0000000, 0x00000000, + 0x033, 0x00000023, + 0x03F, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000003D, + 0x03F, 0x000773E8, + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, + 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, + 0x03F, 0x00000200, + 0x033, 0x00000036, + 0x03F, 0x000001C0, + 0x033, 0x00000035, + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000003D, + 0x03F, 0x000773E8, + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, + 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, + 0x03F, 0x00000200, + 0x033, 0x00000036, + 0x03F, 0x000001C0, + 0x033, 0x00000035, + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000003D, + 0x03F, 0x000773E8, + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, + 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, + 0x03F, 0x00000200, + 0x033, 0x00000036, + 0x03F, 0x000001C0, + 0x033, 0x00000035, + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000003D, + 0x03F, 0x000773E8, + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, + 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, + 0x03F, 0x00000200, + 0x033, 0x00000036, + 0x03F, 0x000001C0, + 0x033, 0x00000035, + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000003D, + 0x03F, 0x000773E8, + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, + 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, + 0x03F, 0x00000200, + 0x033, 0x00000036, + 0x03F, 0x000001C0, + 0x033, 0x00000035, + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773C0, + 0x033, 0x0000003E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000003D, + 0x03F, 0x000773E8, + 0x033, 0x0000003C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000003B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, + 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, + 0x03F, 0x00000200, + 0x033, 0x00000036, + 0x03F, 0x000001C0, + 0x033, 0x00000035, + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, + 0xA0000000, 0x00000000, + 0x033, 0x0000003F, + 0x03F, 0x000773E8, + 0x033, 0x0000003E, + 0x03F, 0x000FF3A0, + 0x033, 0x0000003D, + 0x03F, 0x00000380, + 0x033, 0x0000003C, + 0x03F, 0x000FF380, + 0x033, 0x0000003B, + 0x03F, 0x00000300, + 0x033, 0x0000003A, + 0x03F, 0x000002A8, + 0x033, 0x00000039, + 0x03F, 0x00000280, + 0x033, 0x00000038, + 0x03F, 0x000FF280, + 0x033, 0x00000037, + 0x03F, 0x00000200, + 0x033, 0x00000036, + 0x03F, 0x000001C0, + 0x033, 0x00000035, + 0x03F, 0x00000180, + 0x033, 0x00000034, + 0x03F, 0x00000040, + 0xB0000000, 0x00000000, + 0x033, 0x00000033, + 0x03F, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000004D, + 0x03F, 0x000773E8, + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, + 0x03F, 0x00000280, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, + 0x03F, 0x00000200, + 0x033, 0x00000046, + 0x03F, 0x000001C0, + 0x033, 0x00000045, + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000004D, + 0x03F, 0x000773E8, + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, + 0x03F, 0x00000280, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, + 0x03F, 0x00000200, + 0x033, 0x00000046, + 0x03F, 0x000001C0, + 0x033, 0x00000045, + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000004D, + 0x03F, 0x000773E8, + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, + 0x03F, 0x00000280, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, + 0x03F, 0x00000200, + 0x033, 0x00000046, + 0x03F, 0x000001C0, + 0x033, 0x00000045, + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000004D, + 0x03F, 0x000773E8, + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, + 0x03F, 0x00000280, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, + 0x03F, 0x00000200, + 0x033, 0x00000046, + 0x03F, 0x000001C0, + 0x033, 0x00000045, + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000004D, + 0x03F, 0x000773E8, + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, + 0x03F, 0x00000280, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, + 0x03F, 0x00000200, + 0x033, 0x00000046, + 0x03F, 0x000001C0, + 0x033, 0x00000045, + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773C0, + 0x033, 0x0000004E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000004D, + 0x03F, 0x000773E8, + 0x033, 0x0000004C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000004B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, + 0x03F, 0x00000280, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, + 0x03F, 0x00000200, + 0x033, 0x00000046, + 0x03F, 0x000001C0, + 0x033, 0x00000045, + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, + 0xA0000000, 0x00000000, + 0x033, 0x0000004F, + 0x03F, 0x000773E8, + 0x033, 0x0000004E, + 0x03F, 0x000FF3A0, + 0x033, 0x0000004D, + 0x03F, 0x00000380, + 0x033, 0x0000004C, + 0x03F, 0x000FF380, + 0x033, 0x0000004B, + 0x03F, 0x00000300, + 0x033, 0x0000004A, + 0x03F, 0x000002A8, + 0x033, 0x00000049, + 0x03F, 0x00000280, + 0x033, 0x00000048, + 0x03F, 0x000FF280, + 0x033, 0x00000047, + 0x03F, 0x00000200, + 0x033, 0x00000046, + 0x03F, 0x000001C0, + 0x033, 0x00000045, + 0x03F, 0x00000180, + 0x033, 0x00000044, + 0x03F, 0x00000040, + 0xB0000000, 0x00000000, + 0x033, 0x00000043, + 0x03F, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000005D, + 0x03F, 0x000773E8, + 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, + 0x03F, 0x00000280, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, + 0x03F, 0x00000200, + 0x033, 0x00000056, + 0x03F, 0x000001C0, + 0x033, 0x00000055, + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000005D, + 0x03F, 0x000773E8, + 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, + 0x03F, 0x00000280, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, + 0x03F, 0x00000200, + 0x033, 0x00000056, + 0x03F, 0x000001C0, + 0x033, 0x00000055, + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000005D, + 0x03F, 0x000773E8, + 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, + 0x03F, 0x00000280, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, + 0x03F, 0x00000200, + 0x033, 0x00000056, + 0x03F, 0x000001C0, + 0x033, 0x00000055, + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000005D, + 0x03F, 0x000773E8, + 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, + 0x03F, 0x00000280, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, + 0x03F, 0x00000200, + 0x033, 0x00000056, + 0x03F, 0x000001C0, + 0x033, 0x00000055, + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000005D, + 0x03F, 0x000773E8, + 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, + 0x03F, 0x00000280, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, + 0x03F, 0x00000200, + 0x033, 0x00000056, + 0x03F, 0x000001C0, + 0x033, 0x00000055, + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773C0, + 0x033, 0x0000005E, + 0x03F, 0x000FF3C0, + 0x033, 0x0000005D, + 0x03F, 0x000773E8, + 0x033, 0x0000005C, + 0x03F, 0x000FF3E8, + 0x033, 0x0000005B, + 0x03F, 0x000FF3A0, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, + 0x03F, 0x00000280, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, + 0x03F, 0x00000200, + 0x033, 0x00000056, + 0x03F, 0x000001C0, + 0x033, 0x00000055, + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, + 0xA0000000, 0x00000000, + 0x033, 0x0000005F, + 0x03F, 0x000773E8, + 0x033, 0x0000005E, + 0x03F, 0x000FF3A0, + 0x033, 0x0000005D, + 0x03F, 0x00000380, + 0x033, 0x0000005C, + 0x03F, 0x000FF380, + 0x033, 0x0000005B, + 0x03F, 0x00000300, + 0x033, 0x0000005A, + 0x03F, 0x000002A8, + 0x033, 0x00000059, + 0x03F, 0x00000280, + 0x033, 0x00000058, + 0x03F, 0x000FF280, + 0x033, 0x00000057, + 0x03F, 0x00000200, + 0x033, 0x00000056, + 0x03F, 0x000001C0, + 0x033, 0x00000055, + 0x03F, 0x00000180, + 0x033, 0x00000054, + 0x03F, 0x00000040, + 0xB0000000, 0x00000000, + 0x033, 0x00000053, + 0x03F, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000000, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000000, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000000, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000000, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000000, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00000000, + 0xA0000000, 0x00000000, + 0x0EF, 0x00000000, + 0xB0000000, 0x00000000, + 0x08A, 0x000E7DE3, + 0x08B, 0x0008FE00, + 0x0EE, 0x00000008, + 0x033, 0x00000000, + 0x03F, 0x00000023, + 0x033, 0x00000001, + 0x03F, 0x00000023, + 0x0EE, 0x00000000, + 0x0EF, 0x00004000, + 0x033, 0x00000000, + 0x03F, 0x0000000F, + 0x033, 0x00000002, + 0x03F, 0x00000000, + 0x0EF, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000002, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000003, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000004, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000005, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000006, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000008, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000000A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000000B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000000C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000000D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000000E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000010, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000012, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000013, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000014, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000015, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000016, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000017, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000001A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000001B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000001C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000001D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000001E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000001F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000022, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000023, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000024, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000025, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000026, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000027, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000002A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000002B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000002C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000002D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000002E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000002F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000002, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000003, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000004, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000005, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000006, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000008, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000000A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000000B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000000C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000000D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000000E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000010, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000012, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000013, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000014, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000015, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000016, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000017, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000001A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000001B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000001C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000001D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000001E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000001F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000022, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000023, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000024, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000025, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000026, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000027, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000002A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000002B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000002C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000002D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000002E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000002F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000002, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000003, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000004, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000005, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000006, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000008, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000000A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000000B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000000C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000000D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000000E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000010, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000012, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000013, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000014, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000015, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000016, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000017, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000001A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000001B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000001C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000001D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000001E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000001F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000022, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000023, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000024, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000025, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000026, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000027, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000002A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000002B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000002C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000002D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000002E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000002F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000002, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000003, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000004, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000005, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000006, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000008, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000000A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000000B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000000C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000000D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000000E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000010, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000012, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000013, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000014, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000015, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000016, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000017, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000001A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000001B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000001C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000001D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000001E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000001F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000022, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000023, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000024, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000025, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000026, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000027, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000002A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000002B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000002C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000002D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000002E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000002F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000002, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000003, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000004, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000005, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000006, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000008, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000000A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000000B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000000C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000000D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000000E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000010, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000012, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000013, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000014, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000015, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000016, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000017, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000001A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000001B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000001C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000001D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000001E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000001F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000022, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000023, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000024, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000025, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000026, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000027, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000002A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000002B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000002C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000002D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000002E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000002F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000002, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000003, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000004, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000005, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000006, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000008, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000000A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000000B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000000C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000000D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000000E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, + 0x03F, 0x0002F81C, + 0x033, 0x00000010, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000012, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000013, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000014, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000015, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000016, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000017, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000001A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000001B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000001C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000001D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000001E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000001F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000022, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000023, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000024, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000025, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000026, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000027, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, + 0x03E, 0x00001C86, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000002A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000002B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000002C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000002D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000002E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000002F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0xA0000000, 0x00000000, + 0x0EF, 0x00020000, + 0x033, 0x00000000, + 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000001, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000002, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000003, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000004, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000005, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000006, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000007, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000008, + 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000009, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000000A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000000B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000000C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000000D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000000E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000000F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000010, + 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000011, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000012, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000013, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000014, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000015, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000016, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000017, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000018, + 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000019, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000001A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000001B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000001C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000001D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000001E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000001F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000020, + 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000021, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x00000022, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x00000023, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x00000024, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x00000025, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x00000026, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x00000027, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x033, 0x00000028, + 0x03E, 0x00001910, + 0x03F, 0x00020000, + 0x033, 0x00000029, + 0x03E, 0x00001C02, + 0x03F, 0x00020000, + 0x033, 0x0000002A, + 0x03E, 0x00000F02, + 0x03F, 0x00020000, + 0x033, 0x0000002B, + 0x03E, 0x00000F00, + 0x03F, 0x00020000, + 0x033, 0x0000002C, + 0x03E, 0x00000086, + 0x03F, 0x00020000, + 0x033, 0x0000002D, + 0x03E, 0x00000002, + 0x03F, 0x00020000, + 0x033, 0x0000002E, + 0x03E, 0x00000000, + 0x03F, 0x00020000, + 0x033, 0x0000002F, + 0x03E, 0x00000000, + 0x03F, 0x0002C010, + 0x0EF, 0x00000000, + 0xB0000000, 0x00000000, + 0x0FE, 0x00000000, + 0x01B, 0x00003A40, + 0x061, 0x0000D233, + 0x062, 0x0004D232, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x063, 0x00000002, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x063, 0x00000002, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x063, 0x00000002, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x063, 0x00000002, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x063, 0x00000002, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x063, 0x00000002, + 0xA0000000, 0x00000000, + 0x063, 0x00000C02, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000200, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000237, + 0x030, 0x00001237, + 0x030, 0x00002237, + 0x030, 0x00003237, + 0x030, 0x00004207, + 0x030, 0x00005237, + 0x030, 0x00006237, + 0x030, 0x00007237, + 0x030, 0x00008207, + 0x030, 0x00009237, + 0x030, 0x0000A237, + 0x030, 0x0000B237, + 0x030, 0x0000C237, + 0x030, 0x0000D237, + 0x030, 0x0000E207, + 0x030, 0x0000F237, + 0x030, 0x00010237, + 0x030, 0x00011237, + 0x030, 0x00012207, + 0x030, 0x00013237, + 0x030, 0x00014237, + 0x030, 0x00015237, + 0x030, 0x00016207, + 0x030, 0x00017237, + 0x030, 0x00018207, + 0x030, 0x00019237, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000237, + 0x030, 0x00001237, + 0x030, 0x00002237, + 0x030, 0x00003237, + 0x030, 0x00004207, + 0x030, 0x00005237, + 0x030, 0x00006237, + 0x030, 0x00007237, + 0x030, 0x00008207, + 0x030, 0x00009237, + 0x030, 0x0000A237, + 0x030, 0x0000B237, + 0x030, 0x0000C237, + 0x030, 0x0000D237, + 0x030, 0x0000E207, + 0x030, 0x0000F237, + 0x030, 0x00010237, + 0x030, 0x00011237, + 0x030, 0x00012207, + 0x030, 0x00013237, + 0x030, 0x00014237, + 0x030, 0x00015237, + 0x030, 0x00016207, + 0x030, 0x00017237, + 0x030, 0x00018207, + 0x030, 0x00019237, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000237, + 0x030, 0x00001237, + 0x030, 0x00002237, + 0x030, 0x00003237, + 0x030, 0x00004207, + 0x030, 0x00005237, + 0x030, 0x00006237, + 0x030, 0x00007237, + 0x030, 0x00008207, + 0x030, 0x00009237, + 0x030, 0x0000A237, + 0x030, 0x0000B237, + 0x030, 0x0000C237, + 0x030, 0x0000D237, + 0x030, 0x0000E207, + 0x030, 0x0000F237, + 0x030, 0x00010237, + 0x030, 0x00011237, + 0x030, 0x00012207, + 0x030, 0x00013237, + 0x030, 0x00014237, + 0x030, 0x00015237, + 0x030, 0x00016207, + 0x030, 0x00017237, + 0x030, 0x00018207, + 0x030, 0x00019237, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000237, + 0x030, 0x00001237, + 0x030, 0x00002237, + 0x030, 0x00003237, + 0x030, 0x00004207, + 0x030, 0x00005237, + 0x030, 0x00006237, + 0x030, 0x00007237, + 0x030, 0x00008207, + 0x030, 0x00009237, + 0x030, 0x0000A237, + 0x030, 0x0000B237, + 0x030, 0x0000C237, + 0x030, 0x0000D237, + 0x030, 0x0000E207, + 0x030, 0x0000F237, + 0x030, 0x00010237, + 0x030, 0x00011237, + 0x030, 0x00012207, + 0x030, 0x00013237, + 0x030, 0x00014237, + 0x030, 0x00015237, + 0x030, 0x00016207, + 0x030, 0x00017237, + 0x030, 0x00018207, + 0x030, 0x00019237, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000237, + 0x030, 0x00001237, + 0x030, 0x00002237, + 0x030, 0x00003237, + 0x030, 0x00004207, + 0x030, 0x00005237, + 0x030, 0x00006237, + 0x030, 0x00007237, + 0x030, 0x00008207, + 0x030, 0x00009237, + 0x030, 0x0000A237, + 0x030, 0x0000B237, + 0x030, 0x0000C237, + 0x030, 0x0000D237, + 0x030, 0x0000E207, + 0x030, 0x0000F237, + 0x030, 0x00010237, + 0x030, 0x00011237, + 0x030, 0x00012207, + 0x030, 0x00013237, + 0x030, 0x00014237, + 0x030, 0x00015237, + 0x030, 0x00016207, + 0x030, 0x00017237, + 0x030, 0x00018207, + 0x030, 0x00019237, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000237, + 0x030, 0x00001237, + 0x030, 0x00002237, + 0x030, 0x00003237, + 0x030, 0x00004207, + 0x030, 0x00005237, + 0x030, 0x00006237, + 0x030, 0x00007237, + 0x030, 0x00008207, + 0x030, 0x00009237, + 0x030, 0x0000A237, + 0x030, 0x0000B237, + 0x030, 0x0000C237, + 0x030, 0x0000D237, + 0x030, 0x0000E207, + 0x030, 0x0000F237, + 0x030, 0x00010237, + 0x030, 0x00011237, + 0x030, 0x00012207, + 0x030, 0x00013237, + 0x030, 0x00014237, + 0x030, 0x00015237, + 0x030, 0x00016207, + 0x030, 0x00017237, + 0x030, 0x00018207, + 0x030, 0x00019237, + 0xA0000000, 0x00000000, + 0x030, 0x00000233, + 0x030, 0x00001233, + 0x030, 0x00002233, + 0x030, 0x00003233, + 0x030, 0x00004203, + 0x030, 0x00005233, + 0x030, 0x00006233, + 0x030, 0x00007233, + 0x030, 0x00008203, + 0x030, 0x00009233, + 0x030, 0x0000A233, + 0x030, 0x0000B233, + 0x030, 0x0000C233, + 0x030, 0x0000D233, + 0x030, 0x0000E203, + 0x030, 0x0000F233, + 0x030, 0x00010233, + 0x030, 0x00011233, + 0x030, 0x00012203, + 0x030, 0x00013233, + 0x030, 0x00014233, + 0x030, 0x00015233, + 0x030, 0x00016203, + 0x030, 0x00017233, + 0x030, 0x00018203, + 0x030, 0x00019233, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x0EF, 0x00000080, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000334, + 0x030, 0x00001334, + 0x030, 0x00002334, + 0x030, 0x00003334, + 0x030, 0x00004334, + 0x030, 0x00005334, + 0x030, 0x00006334, + 0x030, 0x00007334, + 0x030, 0x00008334, + 0x030, 0x00009334, + 0x030, 0x0000A334, + 0x030, 0x0000B334, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000334, + 0x030, 0x00001334, + 0x030, 0x00002334, + 0x030, 0x00003334, + 0x030, 0x00004334, + 0x030, 0x00005334, + 0x030, 0x00006334, + 0x030, 0x00007334, + 0x030, 0x00008334, + 0x030, 0x00009334, + 0x030, 0x0000A334, + 0x030, 0x0000B334, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000334, + 0x030, 0x00001334, + 0x030, 0x00002334, + 0x030, 0x00003334, + 0x030, 0x00004334, + 0x030, 0x00005334, + 0x030, 0x00006334, + 0x030, 0x00007334, + 0x030, 0x00008334, + 0x030, 0x00009334, + 0x030, 0x0000A334, + 0x030, 0x0000B334, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000334, + 0x030, 0x00001334, + 0x030, 0x00002334, + 0x030, 0x00003334, + 0x030, 0x00004334, + 0x030, 0x00005334, + 0x030, 0x00006334, + 0x030, 0x00007334, + 0x030, 0x00008334, + 0x030, 0x00009334, + 0x030, 0x0000A334, + 0x030, 0x0000B334, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000334, + 0x030, 0x00001334, + 0x030, 0x00002334, + 0x030, 0x00003334, + 0x030, 0x00004334, + 0x030, 0x00005334, + 0x030, 0x00006334, + 0x030, 0x00007334, + 0x030, 0x00008334, + 0x030, 0x00009334, + 0x030, 0x0000A334, + 0x030, 0x0000B334, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x030, 0x00000334, + 0x030, 0x00001334, + 0x030, 0x00002334, + 0x030, 0x00003334, + 0x030, 0x00004334, + 0x030, 0x00005334, + 0x030, 0x00006334, + 0x030, 0x00007334, + 0x030, 0x00008334, + 0x030, 0x00009334, + 0x030, 0x0000A334, + 0x030, 0x0000B334, + 0xA0000000, 0x00000000, + 0x030, 0x00000232, + 0x030, 0x00001232, + 0x030, 0x00002232, + 0x030, 0x00003232, + 0x030, 0x00004232, + 0x030, 0x00005232, + 0x030, 0x00006232, + 0x030, 0x00007232, + 0x030, 0x00008232, + 0x030, 0x00009232, + 0x030, 0x0000A232, + 0x030, 0x0000B232, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x0EF, 0x00000040, + 0x030, 0x00000770, + 0x030, 0x00001770, + 0x030, 0x00002440, + 0x030, 0x00003440, + 0x030, 0x00004330, + 0x030, 0x00005330, + 0x030, 0x00008770, + 0x030, 0x0000A440, + 0x030, 0x0000C330, + 0x0EF, 0x00000000, + 0x0EE, 0x00010000, + 0x033, 0x00000200, + 0x03F, 0x0000006A, + 0x033, 0x00000201, + 0x03F, 0x0000006D, + 0x033, 0x00000202, + 0x03F, 0x0000046A, + 0x033, 0x00000203, + 0x03F, 0x0000086A, + 0x033, 0x00000204, + 0x03F, 0x00000C89, + 0x033, 0x00000205, + 0x03F, 0x00000CE8, + 0x033, 0x00000206, + 0x03F, 0x00000CEB, + 0x033, 0x00000207, + 0x03F, 0x00000CEE, + 0x033, 0x00000208, + 0x03F, 0x00000CF1, + 0x033, 0x00000209, + 0x03F, 0x00000CF4, + 0x033, 0x0000020A, + 0x03F, 0x00000CF7, + 0x033, 0x00000280, + 0x03F, 0x0000006A, + 0x033, 0x00000281, + 0x03F, 0x0000006D, + 0x033, 0x00000282, + 0x03F, 0x0000046A, + 0x033, 0x00000283, + 0x03F, 0x0000086A, + 0x033, 0x00000284, + 0x03F, 0x00000C89, + 0x033, 0x00000285, + 0x03F, 0x00000CE8, + 0x033, 0x00000286, + 0x03F, 0x00000CEB, + 0x033, 0x00000287, + 0x03F, 0x00000CEE, + 0x033, 0x00000288, + 0x03F, 0x00000CF1, + 0x033, 0x00000289, + 0x03F, 0x00000CF4, + 0x033, 0x0000028A, + 0x03F, 0x00000CF7, + 0x033, 0x00000300, + 0x03F, 0x0000006A, + 0x033, 0x00000301, + 0x03F, 0x0000006D, + 0x033, 0x00000302, + 0x03F, 0x0000046A, + 0x033, 0x00000303, + 0x03F, 0x0000086A, + 0x033, 0x00000304, + 0x03F, 0x00000C89, + 0x033, 0x00000305, + 0x03F, 0x00000CE8, + 0x033, 0x00000306, + 0x03F, 0x00000CEB, + 0x033, 0x00000307, + 0x03F, 0x00000CEE, + 0x033, 0x00000308, + 0x03F, 0x00000CF1, + 0x033, 0x00000309, + 0x03F, 0x00000CF4, + 0x033, 0x0000030A, + 0x03F, 0x00000CF7, + 0x0EE, 0x00000000, + 0x051, 0x0003C800, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x000902CA, + 0xA0000000, 0x00000000, + 0x052, 0x000942C0, + 0xB0000000, 0x00000000, + 0x053, 0x000090F9, + 0x054, 0x00088000, + 0x057, 0x0004C80A, + 0x0EF, 0x00000020, + 0x033, 0x00000000, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, + 0x033, 0x00000001, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, + 0x033, 0x00000002, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0xA0000000, 0x00000000, + 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, + 0x033, 0x00000003, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, + 0x033, 0x00000004, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, + 0x033, 0x00000005, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0xA0000000, 0x00000000, + 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, + 0x033, 0x00000006, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, + 0x033, 0x00000007, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, + 0x033, 0x00000008, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0xA0000000, 0x00000000, + 0x03F, 0x0000C246, + 0xB0000000, 0x00000000, + 0x033, 0x00000009, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000A, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000B, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000C, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000D, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000E, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000000F, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000010, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000011, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00024246, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002C246, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000012, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000013, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000014, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000015, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000016, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000017, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000018, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000019, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001A, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001B, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001C, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001D, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001E, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000001F, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000020, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000021, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000022, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000023, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000024, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000025, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000026, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000027, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000028, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x00000029, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0002CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x033, 0x0000002A, + 0x03E, 0x00000020, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x0001CA46, + 0xA0000000, 0x00000000, + 0x03F, 0x00008E46, + 0xB0000000, 0x00000000, + 0x0EF, 0x00000000, + 0x0EE, 0x00010000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000468, + 0x033, 0x00000061, + 0x03F, 0x00000868, + 0x033, 0x00000062, + 0x03F, 0x00000909, + 0x033, 0x00000063, + 0x03F, 0x00000D0A, + 0x033, 0x00000064, + 0x03F, 0x00000D4A, + 0x033, 0x00000065, + 0x03F, 0x00000D8B, + 0x033, 0x00000066, + 0x03F, 0x00000DEB, + 0x033, 0x00000067, + 0x03F, 0x00000DEE, + 0x033, 0x00000068, + 0x03F, 0x00000DF1, + 0x033, 0x00000069, + 0x03F, 0x00000DF4, + 0x033, 0x0000006A, + 0x03F, 0x00000DF7, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000468, + 0x033, 0x00000061, + 0x03F, 0x00000868, + 0x033, 0x00000062, + 0x03F, 0x00000909, + 0x033, 0x00000063, + 0x03F, 0x00000D0A, + 0x033, 0x00000064, + 0x03F, 0x00000D4A, + 0x033, 0x00000065, + 0x03F, 0x00000D8B, + 0x033, 0x00000066, + 0x03F, 0x00000DEB, + 0x033, 0x00000067, + 0x03F, 0x00000DEE, + 0x033, 0x00000068, + 0x03F, 0x00000DF1, + 0x033, 0x00000069, + 0x03F, 0x00000DF4, + 0x033, 0x0000006A, + 0x03F, 0x00000DF7, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000468, + 0x033, 0x00000061, + 0x03F, 0x00000868, + 0x033, 0x00000062, + 0x03F, 0x00000909, + 0x033, 0x00000063, + 0x03F, 0x00000D0A, + 0x033, 0x00000064, + 0x03F, 0x00000D4A, + 0x033, 0x00000065, + 0x03F, 0x00000D8B, + 0x033, 0x00000066, + 0x03F, 0x00000DEB, + 0x033, 0x00000067, + 0x03F, 0x00000DEE, + 0x033, 0x00000068, + 0x03F, 0x00000DF1, + 0x033, 0x00000069, + 0x03F, 0x00000DF4, + 0x033, 0x0000006A, + 0x03F, 0x00000DF7, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000468, + 0x033, 0x00000061, + 0x03F, 0x00000868, + 0x033, 0x00000062, + 0x03F, 0x00000909, + 0x033, 0x00000063, + 0x03F, 0x00000D0A, + 0x033, 0x00000064, + 0x03F, 0x00000D4A, + 0x033, 0x00000065, + 0x03F, 0x00000D8B, + 0x033, 0x00000066, + 0x03F, 0x00000DEB, + 0x033, 0x00000067, + 0x03F, 0x00000DEE, + 0x033, 0x00000068, + 0x03F, 0x00000DF1, + 0x033, 0x00000069, + 0x03F, 0x00000DF4, + 0x033, 0x0000006A, + 0x03F, 0x00000DF7, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000468, + 0x033, 0x00000061, + 0x03F, 0x00000868, + 0x033, 0x00000062, + 0x03F, 0x00000909, + 0x033, 0x00000063, + 0x03F, 0x00000D0A, + 0x033, 0x00000064, + 0x03F, 0x00000D4A, + 0x033, 0x00000065, + 0x03F, 0x00000D8B, + 0x033, 0x00000066, + 0x03F, 0x00000DEB, + 0x033, 0x00000067, + 0x03F, 0x00000DEE, + 0x033, 0x00000068, + 0x03F, 0x00000DF1, + 0x033, 0x00000069, + 0x03F, 0x00000DF4, + 0x033, 0x0000006A, + 0x03F, 0x00000DF7, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000468, + 0x033, 0x00000061, + 0x03F, 0x00000868, + 0x033, 0x00000062, + 0x03F, 0x00000909, + 0x033, 0x00000063, + 0x03F, 0x00000D0A, + 0x033, 0x00000064, + 0x03F, 0x00000D4A, + 0x033, 0x00000065, + 0x03F, 0x00000D8B, + 0x033, 0x00000066, + 0x03F, 0x00000DEB, + 0x033, 0x00000067, + 0x03F, 0x00000DEE, + 0x033, 0x00000068, + 0x03F, 0x00000DF1, + 0x033, 0x00000069, + 0x03F, 0x00000DF4, + 0x033, 0x0000006A, + 0x03F, 0x00000DF7, + 0xA0000000, 0x00000000, + 0x033, 0x00000060, + 0x03F, 0x00000487, + 0x033, 0x00000061, + 0x03F, 0x00000887, + 0x033, 0x00000062, + 0x03F, 0x00000947, + 0x033, 0x00000063, + 0x03F, 0x00000D48, + 0x033, 0x00000064, + 0x03F, 0x00000D88, + 0x033, 0x00000065, + 0x03F, 0x00000DE8, + 0x033, 0x00000066, + 0x03F, 0x00000DEB, + 0x033, 0x00000067, + 0x03F, 0x00000DEE, + 0x033, 0x00000068, + 0x03F, 0x00000DF1, + 0x033, 0x00000069, + 0x03F, 0x00000DF4, + 0x033, 0x0000006A, + 0x03F, 0x00000DF7, + 0xB0000000, 0x00000000, + 0x81000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000468, + 0x033, 0x00000021, + 0x03F, 0x00000868, + 0x033, 0x00000022, + 0x03F, 0x00000909, + 0x033, 0x00000023, + 0x03F, 0x00000D0A, + 0x033, 0x00000024, + 0x03F, 0x00000D4A, + 0x033, 0x00000025, + 0x03F, 0x00000D8B, + 0x033, 0x00000026, + 0x03F, 0x00000DEB, + 0x033, 0x00000027, + 0x03F, 0x00000DEE, + 0x033, 0x00000028, + 0x03F, 0x00000DF1, + 0x033, 0x00000029, + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, + 0x91000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000468, + 0x033, 0x00000021, + 0x03F, 0x00000868, + 0x033, 0x00000022, + 0x03F, 0x00000909, + 0x033, 0x00000023, + 0x03F, 0x00000D0A, + 0x033, 0x00000024, + 0x03F, 0x00000D4A, + 0x033, 0x00000025, + 0x03F, 0x00000D8B, + 0x033, 0x00000026, + 0x03F, 0x00000DEB, + 0x033, 0x00000027, + 0x03F, 0x00000DEE, + 0x033, 0x00000028, + 0x03F, 0x00000DF1, + 0x033, 0x00000029, + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, + 0x92000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000468, + 0x033, 0x00000021, + 0x03F, 0x00000868, + 0x033, 0x00000022, + 0x03F, 0x00000909, + 0x033, 0x00000023, + 0x03F, 0x00000D0A, + 0x033, 0x00000024, + 0x03F, 0x00000D4A, + 0x033, 0x00000025, + 0x03F, 0x00000D8B, + 0x033, 0x00000026, + 0x03F, 0x00000DEB, + 0x033, 0x00000027, + 0x03F, 0x00000DEE, + 0x033, 0x00000028, + 0x03F, 0x00000DF1, + 0x033, 0x00000029, + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, + 0x92000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000468, + 0x033, 0x00000021, + 0x03F, 0x00000868, + 0x033, 0x00000022, + 0x03F, 0x00000909, + 0x033, 0x00000023, + 0x03F, 0x00000D0A, + 0x033, 0x00000024, + 0x03F, 0x00000D4A, + 0x033, 0x00000025, + 0x03F, 0x00000D8B, + 0x033, 0x00000026, + 0x03F, 0x00000DEB, + 0x033, 0x00000027, + 0x03F, 0x00000DEE, + 0x033, 0x00000028, + 0x03F, 0x00000DF1, + 0x033, 0x00000029, + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, + 0x93000001, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000468, + 0x033, 0x00000021, + 0x03F, 0x00000868, + 0x033, 0x00000022, + 0x03F, 0x00000909, + 0x033, 0x00000023, + 0x03F, 0x00000D0A, + 0x033, 0x00000024, + 0x03F, 0x00000D4A, + 0x033, 0x00000025, + 0x03F, 0x00000D8B, + 0x033, 0x00000026, + 0x03F, 0x00000DEB, + 0x033, 0x00000027, + 0x03F, 0x00000DEE, + 0x033, 0x00000028, + 0x03F, 0x00000DF1, + 0x033, 0x00000029, + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, + 0x93000002, 0x00000000, 0x40000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000468, + 0x033, 0x00000021, + 0x03F, 0x00000868, + 0x033, 0x00000022, + 0x03F, 0x00000909, + 0x033, 0x00000023, + 0x03F, 0x00000D0A, + 0x033, 0x00000024, + 0x03F, 0x00000D4A, + 0x033, 0x00000025, + 0x03F, 0x00000D8B, + 0x033, 0x00000026, + 0x03F, 0x00000DEB, + 0x033, 0x00000027, + 0x03F, 0x00000DEE, + 0x033, 0x00000028, + 0x03F, 0x00000DF1, + 0x033, 0x00000029, + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, + 0xA0000000, 0x00000000, + 0x033, 0x00000020, + 0x03F, 0x00000487, + 0x033, 0x00000021, + 0x03F, 0x00000887, + 0x033, 0x00000022, + 0x03F, 0x00000947, + 0x033, 0x00000023, + 0x03F, 0x00000D48, + 0x033, 0x00000024, + 0x03F, 0x00000D88, + 0x033, 0x00000025, + 0x03F, 0x00000DE8, + 0x033, 0x00000026, + 0x03F, 0x00000DEB, + 0x033, 0x00000027, + 0x03F, 0x00000DEE, + 0x033, 0x00000028, + 0x03F, 0x00000DF1, + 0x033, 0x00000029, + 0x03F, 0x00000DF4, + 0x033, 0x0000002A, + 0x03F, 0x00000DF7, + 0xB0000000, 0x00000000, + 0x0EE, 0x00000000, + 0x05C, 0x000FCC00, + 0x067, 0x0000A505, + 0x0D3, 0x00000542, + 0x043, 0x00005000, + 0x059, 0x000A0000, + 0x05A, 0x00060000, + 0x05B, 0x00014000, + 0x001, 0x00040000, + 0x0EE, 0x00000002, + 0x033, 0x00000017, + 0x03F, 0x0000003F, + 0x033, 0x00000018, + 0x03F, 0x0000003F, + 0x033, 0x00000019, + 0x03F, 0x00000000, + 0x033, 0x0000001A, + 0x03F, 0x0000003F, + 0x033, 0x0000001B, + 0x03F, 0x0000003F, + 0x033, 0x0000001C, + 0x03F, 0x0000003F, + 0x0EE, 0x00000000, + 0x092, 0x00084800, + 0x092, 0x00084801, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x092, 0x00084800, + 0x08F, 0x0000182C, + 0x088, 0x0004326B, + 0x019, 0x00000005, +}; + +RTW_DECL_TABLE_RF_RADIO(rtw8822c_rf_b, B); + +static const u8 rtw8822c_txpwr_lmt_type0[] = { + 0, 0, 0, 0, 1, 72, 2, 0, 0, 0, 1, 60, + 0, 0, 0, 0, 2, 72, 2, 0, 0, 0, 2, 60, + 0, 0, 0, 0, 3, 76, 2, 0, 0, 0, 3, 60, + 0, 0, 0, 0, 4, 76, 2, 0, 0, 0, 4, 60, + 0, 0, 0, 0, 5, 76, 2, 0, 0, 0, 5, 60, + 0, 0, 0, 0, 6, 76, 2, 0, 0, 0, 6, 60, + 0, 0, 0, 0, 7, 76, 2, 0, 0, 0, 7, 60, + 0, 0, 0, 0, 8, 76, 2, 0, 0, 0, 8, 60, + 0, 0, 0, 0, 9, 76, 2, 0, 0, 0, 9, 60, + 0, 0, 0, 0, 10, 72, 2, 0, 0, 0, 10, 60, + 0, 0, 0, 0, 11, 72, 2, 0, 0, 0, 11, 60, + 0, 0, 0, 0, 12, 52, 2, 0, 0, 0, 12, 60, + 0, 0, 0, 0, 13, 48, 2, 0, 0, 0, 13, 60, + 0, 0, 0, 0, 14, 127, 2, 0, 0, 0, 14, 127, + 0, 0, 0, 1, 1, 52, 2, 0, 0, 1, 1, 60, + 0, 0, 0, 1, 2, 60, 2, 0, 0, 1, 2, 60, + 0, 0, 0, 1, 3, 64, 2, 0, 0, 1, 3, 60, + 0, 0, 0, 1, 4, 68, 2, 0, 0, 1, 4, 60, + 0, 0, 0, 1, 5, 76, 2, 0, 0, 1, 5, 60, + 0, 0, 0, 1, 6, 76, 2, 0, 0, 1, 6, 60, + 0, 0, 0, 1, 7, 76, 2, 0, 0, 1, 7, 60, + 0, 0, 0, 1, 8, 68, 2, 0, 0, 1, 8, 60, + 0, 0, 0, 1, 9, 64, 2, 0, 0, 1, 9, 60, + 0, 0, 0, 1, 10, 60, 2, 0, 0, 1, 10, 60, + 0, 0, 0, 1, 11, 52, 2, 0, 0, 1, 11, 60, + 0, 0, 0, 1, 12, 40, 2, 0, 0, 1, 12, 60, + 0, 0, 0, 1, 13, 28, 2, 0, 0, 1, 13, 60, + 0, 0, 0, 1, 14, 127, 2, 0, 0, 1, 14, 127, + 0, 0, 0, 2, 1, 52, 2, 0, 0, 2, 1, 60, + 0, 0, 0, 2, 2, 60, 2, 0, 0, 2, 2, 60, + 0, 0, 0, 2, 3, 64, 2, 0, 0, 2, 3, 60, + 0, 0, 0, 2, 4, 68, 2, 0, 0, 2, 4, 60, + 0, 0, 0, 2, 5, 76, 2, 0, 0, 2, 5, 60, + 0, 0, 0, 2, 6, 76, 2, 0, 0, 2, 6, 60, + 0, 0, 0, 2, 7, 76, 2, 0, 0, 2, 7, 60, + 0, 0, 0, 2, 8, 68, 2, 0, 0, 2, 8, 60, + 0, 0, 0, 2, 9, 64, 2, 0, 0, 2, 9, 60, + 0, 0, 0, 2, 10, 60, 2, 0, 0, 2, 10, 60, + 0, 0, 0, 2, 11, 52, 2, 0, 0, 2, 11, 60, + 0, 0, 0, 2, 12, 40, 2, 0, 0, 2, 12, 60, + 0, 0, 0, 2, 13, 28, 2, 0, 0, 2, 13, 60, + 0, 0, 0, 2, 14, 127, 2, 0, 0, 2, 14, 127, + 0, 0, 0, 3, 1, 52, 2, 0, 0, 3, 1, 36, + 0, 0, 0, 3, 2, 60, 2, 0, 0, 3, 2, 36, + 0, 0, 0, 3, 3, 64, 2, 0, 0, 3, 3, 36, + 0, 0, 0, 3, 4, 68, 2, 0, 0, 3, 4, 36, + 0, 0, 0, 3, 5, 76, 2, 0, 0, 3, 5, 36, + 0, 0, 0, 3, 6, 76, 2, 0, 0, 3, 6, 36, + 0, 0, 0, 3, 7, 76, 2, 0, 0, 3, 7, 36, + 0, 0, 0, 3, 8, 68, 2, 0, 0, 3, 8, 36, + 0, 0, 0, 3, 9, 64, 2, 0, 0, 3, 9, 36, + 0, 0, 0, 3, 10, 60, 2, 0, 0, 3, 10, 36, + 0, 0, 0, 3, 11, 52, 2, 0, 0, 3, 11, 36, + 0, 0, 0, 3, 12, 40, 2, 0, 0, 3, 12, 36, + 0, 0, 0, 3, 13, 28, 2, 0, 0, 3, 13, 36, + 0, 0, 0, 3, 14, 127, 2, 0, 0, 3, 14, 127, + 0, 0, 1, 2, 1, 127, 2, 0, 1, 2, 1, 127, + 0, 0, 1, 2, 2, 127, 2, 0, 1, 2, 2, 127, + 0, 0, 1, 2, 3, 52, 2, 0, 1, 2, 3, 60, + 0, 0, 1, 2, 4, 52, 2, 0, 1, 2, 4, 60, + 0, 0, 1, 2, 5, 60, 2, 0, 1, 2, 5, 60, + 0, 0, 1, 2, 6, 64, 2, 0, 1, 2, 6, 60, + 0, 0, 1, 2, 7, 60, 2, 0, 1, 2, 7, 60, + 0, 0, 1, 2, 8, 52, 2, 0, 1, 2, 8, 60, + 0, 0, 1, 2, 9, 52, 2, 0, 1, 2, 9, 60, + 0, 0, 1, 2, 10, 40, 2, 0, 1, 2, 10, 60, + 0, 0, 1, 2, 11, 28, 2, 0, 1, 2, 11, 60, + 0, 0, 1, 2, 12, 127, 2, 0, 1, 2, 12, 127, + 0, 0, 1, 2, 13, 127, 2, 0, 1, 2, 13, 127, + 0, 0, 1, 2, 14, 127, 2, 0, 1, 2, 14, 127, + 0, 0, 1, 3, 1, 127, 2, 0, 1, 3, 1, 127, + 0, 0, 1, 3, 2, 127, 2, 0, 1, 3, 2, 127, + 0, 0, 1, 3, 3, 48, 2, 0, 1, 3, 3, 36, + 0, 0, 1, 3, 4, 48, 2, 0, 1, 3, 4, 36, + 0, 0, 1, 3, 5, 60, 2, 0, 1, 3, 5, 36, + 0, 0, 1, 3, 6, 64, 2, 0, 1, 3, 6, 36, + 0, 0, 1, 3, 7, 60, 2, 0, 1, 3, 7, 36, + 0, 0, 1, 3, 8, 52, 2, 0, 1, 3, 8, 36, + 0, 0, 1, 3, 9, 52, 2, 0, 1, 3, 9, 36, + 0, 0, 1, 3, 10, 40, 2, 0, 1, 3, 10, 36, + 0, 0, 1, 3, 11, 26, 2, 0, 1, 3, 11, 36, + 0, 0, 1, 3, 12, 127, 2, 0, 1, 3, 12, 127, + 0, 0, 1, 3, 13, 127, 2, 0, 1, 3, 13, 127, + 0, 0, 1, 3, 14, 127, 2, 0, 1, 3, 14, 127, + 0, 1, 0, 1, 36, 74, 2, 1, 0, 1, 36, 62, + 0, 1, 0, 1, 40, 80, 2, 1, 0, 1, 40, 62, + 0, 1, 0, 1, 44, 80, 2, 1, 0, 1, 44, 62, + 0, 1, 0, 1, 48, 80, 2, 1, 0, 1, 48, 62, + 0, 1, 0, 1, 52, 80, 2, 1, 0, 1, 52, 62, + 0, 1, 0, 1, 56, 80, 2, 1, 0, 1, 56, 62, + 0, 1, 0, 1, 60, 80, 2, 1, 0, 1, 60, 62, + 0, 1, 0, 1, 64, 74, 2, 1, 0, 1, 64, 62, + 0, 1, 0, 1, 100, 72, 2, 1, 0, 1, 100, 62, + 0, 1, 0, 1, 104, 80, 2, 1, 0, 1, 104, 62, + 0, 1, 0, 1, 108, 80, 2, 1, 0, 1, 108, 62, + 0, 1, 0, 1, 112, 80, 2, 1, 0, 1, 112, 62, + 0, 1, 0, 1, 116, 80, 2, 1, 0, 1, 116, 62, + 0, 1, 0, 1, 120, 80, 2, 1, 0, 1, 120, 62, + 0, 1, 0, 1, 124, 80, 2, 1, 0, 1, 124, 62, + 0, 1, 0, 1, 128, 80, 2, 1, 0, 1, 128, 62, + 0, 1, 0, 1, 132, 80, 2, 1, 0, 1, 132, 62, + 0, 1, 0, 1, 136, 80, 2, 1, 0, 1, 136, 62, + 0, 1, 0, 1, 140, 72, 2, 1, 0, 1, 140, 62, + 0, 1, 0, 1, 144, 80, 2, 1, 0, 1, 144, 127, + 0, 1, 0, 1, 149, 80, 2, 1, 0, 1, 149, 127, + 0, 1, 0, 1, 153, 80, 2, 1, 0, 1, 153, 127, + 0, 1, 0, 1, 157, 80, 2, 1, 0, 1, 157, 127, + 0, 1, 0, 1, 161, 80, 2, 1, 0, 1, 161, 127, + 0, 1, 0, 1, 165, 80, 2, 1, 0, 1, 165, 127, + 0, 1, 0, 2, 36, 72, 2, 1, 0, 2, 36, 62, + 0, 1, 0, 2, 40, 80, 2, 1, 0, 2, 40, 62, + 0, 1, 0, 2, 44, 80, 2, 1, 0, 2, 44, 62, + 0, 1, 0, 2, 48, 80, 2, 1, 0, 2, 48, 62, + 0, 1, 0, 2, 52, 80, 2, 1, 0, 2, 52, 62, + 0, 1, 0, 2, 56, 80, 2, 1, 0, 2, 56, 62, + 0, 1, 0, 2, 60, 80, 2, 1, 0, 2, 60, 62, + 0, 1, 0, 2, 64, 74, 2, 1, 0, 2, 64, 62, + 0, 1, 0, 2, 100, 70, 2, 1, 0, 2, 100, 62, + 0, 1, 0, 2, 104, 80, 2, 1, 0, 2, 104, 62, + 0, 1, 0, 2, 108, 80, 2, 1, 0, 2, 108, 62, + 0, 1, 0, 2, 112, 80, 2, 1, 0, 2, 112, 62, + 0, 1, 0, 2, 116, 80, 2, 1, 0, 2, 116, 62, + 0, 1, 0, 2, 120, 80, 2, 1, 0, 2, 120, 62, + 0, 1, 0, 2, 124, 80, 2, 1, 0, 2, 124, 62, + 0, 1, 0, 2, 128, 80, 2, 1, 0, 2, 128, 62, + 0, 1, 0, 2, 132, 80, 2, 1, 0, 2, 132, 62, + 0, 1, 0, 2, 136, 80, 2, 1, 0, 2, 136, 62, + 0, 1, 0, 2, 140, 70, 2, 1, 0, 2, 140, 62, + 0, 1, 0, 2, 144, 80, 2, 1, 0, 2, 144, 127, + 0, 1, 0, 2, 149, 80, 2, 1, 0, 2, 149, 127, + 0, 1, 0, 2, 153, 80, 2, 1, 0, 2, 153, 127, + 0, 1, 0, 2, 157, 80, 2, 1, 0, 2, 157, 127, + 0, 1, 0, 2, 161, 80, 2, 1, 0, 2, 161, 127, + 0, 1, 0, 2, 165, 80, 2, 1, 0, 2, 165, 127, + 0, 1, 0, 3, 36, 68, 2, 1, 0, 3, 36, 38, + 0, 1, 0, 3, 40, 68, 2, 1, 0, 3, 40, 38, + 0, 1, 0, 3, 44, 68, 2, 1, 0, 3, 44, 38, + 0, 1, 0, 3, 48, 68, 2, 1, 0, 3, 48, 38, + 0, 1, 0, 3, 52, 68, 2, 1, 0, 3, 52, 38, + 0, 1, 0, 3, 56, 68, 2, 1, 0, 3, 56, 38, + 0, 1, 0, 3, 60, 66, 2, 1, 0, 3, 60, 38, + 0, 1, 0, 3, 64, 68, 2, 1, 0, 3, 64, 38, + 0, 1, 0, 3, 100, 60, 2, 1, 0, 3, 100, 38, + 0, 1, 0, 3, 104, 68, 2, 1, 0, 3, 104, 38, + 0, 1, 0, 3, 108, 68, 2, 1, 0, 3, 108, 38, + 0, 1, 0, 3, 112, 68, 2, 1, 0, 3, 112, 38, + 0, 1, 0, 3, 116, 68, 2, 1, 0, 3, 116, 38, + 0, 1, 0, 3, 120, 68, 2, 1, 0, 3, 120, 38, + 0, 1, 0, 3, 124, 68, 2, 1, 0, 3, 124, 38, + 0, 1, 0, 3, 128, 68, 2, 1, 0, 3, 128, 38, + 0, 1, 0, 3, 132, 68, 2, 1, 0, 3, 132, 38, + 0, 1, 0, 3, 136, 68, 2, 1, 0, 3, 136, 38, + 0, 1, 0, 3, 140, 60, 2, 1, 0, 3, 140, 38, + 0, 1, 0, 3, 144, 68, 2, 1, 0, 3, 144, 127, + 0, 1, 0, 3, 149, 80, 2, 1, 0, 3, 149, 127, + 0, 1, 0, 3, 153, 80, 2, 1, 0, 3, 153, 127, + 0, 1, 0, 3, 157, 80, 2, 1, 0, 3, 157, 127, + 0, 1, 0, 3, 161, 80, 2, 1, 0, 3, 161, 127, + 0, 1, 0, 3, 165, 80, 2, 1, 0, 3, 165, 127, + 0, 1, 1, 2, 38, 66, 2, 1, 1, 2, 38, 64, + 0, 1, 1, 2, 46, 72, 2, 1, 1, 2, 46, 64, + 0, 1, 1, 2, 54, 72, 2, 1, 1, 2, 54, 64, + 0, 1, 1, 2, 62, 64, 2, 1, 1, 2, 62, 64, + 0, 1, 1, 2, 102, 58, 2, 1, 1, 2, 102, 64, + 0, 1, 1, 2, 110, 74, 2, 1, 1, 2, 110, 64, + 0, 1, 1, 2, 118, 74, 2, 1, 1, 2, 118, 64, + 0, 1, 1, 2, 126, 74, 2, 1, 1, 2, 126, 64, + 0, 1, 1, 2, 134, 74, 2, 1, 1, 2, 134, 64, + 0, 1, 1, 2, 142, 74, 2, 1, 1, 2, 142, 127, + 0, 1, 1, 2, 151, 74, 2, 1, 1, 2, 151, 127, + 0, 1, 1, 2, 159, 74, 2, 1, 1, 2, 159, 127, + 0, 1, 1, 3, 38, 60, 2, 1, 1, 3, 38, 40, + 0, 1, 1, 3, 46, 68, 2, 1, 1, 3, 46, 40, + 0, 1, 1, 3, 54, 68, 2, 1, 1, 3, 54, 40, + 0, 1, 1, 3, 62, 58, 2, 1, 1, 3, 62, 40, + 0, 1, 1, 3, 102, 54, 2, 1, 1, 3, 102, 40, + 0, 1, 1, 3, 110, 68, 2, 1, 1, 3, 110, 40, + 0, 1, 1, 3, 118, 68, 2, 1, 1, 3, 118, 40, + 0, 1, 1, 3, 126, 68, 2, 1, 1, 3, 126, 40, + 0, 1, 1, 3, 134, 68, 2, 1, 1, 3, 134, 40, + 0, 1, 1, 3, 142, 68, 2, 1, 1, 3, 142, 127, + 0, 1, 1, 3, 151, 74, 2, 1, 1, 3, 151, 127, + 0, 1, 1, 3, 159, 74, 2, 1, 1, 3, 159, 127, + 0, 1, 2, 4, 42, 64, 2, 1, 2, 4, 42, 64, + 0, 1, 2, 4, 58, 62, 2, 1, 2, 4, 58, 64, + 0, 1, 2, 4, 106, 58, 2, 1, 2, 4, 106, 64, + 0, 1, 2, 4, 122, 72, 2, 1, 2, 4, 122, 64, + 0, 1, 2, 4, 138, 72, 2, 1, 2, 4, 138, 127, + 0, 1, 2, 4, 155, 72, 2, 1, 2, 4, 155, 127, + 0, 1, 2, 5, 42, 54, 2, 1, 2, 5, 42, 40, + 0, 1, 2, 5, 58, 52, 2, 1, 2, 5, 58, 40, + 0, 1, 2, 5, 106, 50, 2, 1, 2, 5, 106, 40, + 0, 1, 2, 5, 122, 66, 2, 1, 2, 5, 122, 40, + 0, 1, 2, 5, 138, 66, 2, 1, 2, 5, 138, 127, + 0, 1, 2, 5, 155, 62, 2, 1, 2, 5, 155, 127 +}; + +RTW_DECL_TABLE_TXPWR_LMT(rtw8822c_txpwr_lmt_type0); + +static const u32 rtw8822c_array_mp_cal_init[] = { + 0x1b00, 0x00000008, + 0x1b00, 0x00A70008, + 0x1b00, 0x00150008, + 0x1b00, 0x00000008, + 0x1b04, 0xE2462952, + 0x1b08, 0x00000080, + 0x1b0c, 0x00000000, + 0x1b10, 0x00010C00, + 0x1b14, 0x00000000, + 0x1b18, 0x00292903, + 0x1b1c, 0xA218FC32, + 0x1b20, 0x01040008, + 0x1b24, 0x00060008, + 0x1b28, 0x00060300, + 0x1b2C, 0x00180018, + 0x1b30, 0x40000000, + 0x1b34, 0x00000800, + 0x1b38, 0x40000000, + 0x1b3C, 0x40000000, + 0x1b98, 0x00000000, + 0x1b9c, 0x00000000, + 0x1bc0, 0x01000000, + 0x1bcc, 0x00000000, + 0x1be4, 0x00000000, + 0x1bec, 0x40000000, + 0x1b40, 0x40000000, + 0x1b44, 0x20004064, + 0x1b48, 0x0005002D, + 0x1b4c, 0x00000000, + 0x1b60, 0x1F100000, + 0x1b64, 0x12000000, + 0x1b4c, 0x00000000, + 0x1b4c, 0x008a0000, + 0x1b50, 0x000003BE, + 0x1b4c, 0x018a0000, + 0x1b50, 0x0000057A, + 0x1b4c, 0x028a0000, + 0x1b50, 0x000006C8, + 0x1b4c, 0x038a0000, + 0x1b50, 0x000007E0, + 0x1b4c, 0x048a0000, + 0x1b50, 0x000008D5, + 0x1b4c, 0x058a0000, + 0x1b50, 0x000009B2, + 0x1b4c, 0x068a0000, + 0x1b50, 0x00000A7D, + 0x1b4c, 0x078a0000, + 0x1b50, 0x00000B3A, + 0x1b4c, 0x088a0000, + 0x1b50, 0x00000BEB, + 0x1b4c, 0x098a0000, + 0x1b50, 0x00000C92, + 0x1b4c, 0x0A8a0000, + 0x1b50, 0x00000D31, + 0x1b4c, 0x0B8a0000, + 0x1b50, 0x00000DC9, + 0x1b4c, 0x0C8a0000, + 0x1b50, 0x00000E5A, + 0x1b4c, 0x0D8a0000, + 0x1b50, 0x00000EE6, + 0x1b4c, 0x0E8a0000, + 0x1b50, 0x00000F6D, + 0x1b4c, 0x0F8a0000, + 0x1b50, 0x00000FF0, + 0x1b4c, 0x108a0000, + 0x1b50, 0x0000106F, + 0x1b4c, 0x118a0000, + 0x1b50, 0x000010E9, + 0x1b4c, 0x128a0000, + 0x1b50, 0x00001161, + 0x1b4c, 0x138a0000, + 0x1b50, 0x000011D5, + 0x1b4c, 0x148a0000, + 0x1b50, 0x00001247, + 0x1b4c, 0x158a0000, + 0x1b50, 0x000012B5, + 0x1b4c, 0x168a0000, + 0x1b50, 0x00001322, + 0x1b4c, 0x178a0000, + 0x1b50, 0x0000138B, + 0x1b4c, 0x188a0000, + 0x1b50, 0x000013F3, + 0x1b4c, 0x198a0000, + 0x1b50, 0x00001459, + 0x1b4c, 0x1A8a0000, + 0x1b50, 0x000014BD, + 0x1b4c, 0x1B8a0000, + 0x1b50, 0x0000151E, + 0x1b4c, 0x1C8a0000, + 0x1b50, 0x0000157F, + 0x1b4c, 0x1D8a0000, + 0x1b50, 0x000015DD, + 0x1b4c, 0x1E8a0000, + 0x1b50, 0x0000163A, + 0x1b4c, 0x1F8a0000, + 0x1b50, 0x00001695, + 0x1b4c, 0x208a0000, + 0x1b50, 0x000016EF, + 0x1b4c, 0x218a0000, + 0x1b50, 0x00001748, + 0x1b4c, 0x228a0000, + 0x1b50, 0x0000179F, + 0x1b4c, 0x238a0000, + 0x1b50, 0x000017F5, + 0x1b4c, 0x248a0000, + 0x1b50, 0x0000184A, + 0x1b4c, 0x258a0000, + 0x1b50, 0x0000189E, + 0x1b4c, 0x268a0000, + 0x1b50, 0x000018F1, + 0x1b4c, 0x278a0000, + 0x1b50, 0x00001942, + 0x1b4c, 0x288a0000, + 0x1b50, 0x00001993, + 0x1b4c, 0x298a0000, + 0x1b50, 0x000019E2, + 0x1b4c, 0x2A8a0000, + 0x1b50, 0x00001A31, + 0x1b4c, 0x2B8a0000, + 0x1b50, 0x00001A7F, + 0x1b4c, 0x2C8a0000, + 0x1b50, 0x00001ACC, + 0x1b4c, 0x2D8a0000, + 0x1b50, 0x00001B18, + 0x1b4c, 0x2E8a0000, + 0x1b50, 0x00001B63, + 0x1b4c, 0x2F8a0000, + 0x1b50, 0x00001BAD, + 0x1b4c, 0x308a0000, + 0x1b50, 0x00001BF7, + 0x1b4c, 0x318a0000, + 0x1b50, 0x00001C40, + 0x1b4c, 0x328a0000, + 0x1b50, 0x00001C88, + 0x1b4c, 0x338a0000, + 0x1b50, 0x00001CCF, + 0x1b4c, 0x348a0000, + 0x1b50, 0x00001D16, + 0x1b4c, 0x358a0000, + 0x1b50, 0x00001D5C, + 0x1b4c, 0x368a0000, + 0x1b50, 0x00001DA2, + 0x1b4c, 0x378a0000, + 0x1b50, 0x00001DE6, + 0x1b4c, 0x388a0000, + 0x1b50, 0x00001E2B, + 0x1b4c, 0x398a0000, + 0x1b50, 0x00001E6E, + 0x1b4c, 0x3A8a0000, + 0x1b50, 0x00001EB1, + 0x1b4c, 0x3B8a0000, + 0x1b50, 0x00001EF4, + 0x1b4c, 0x3C8a0000, + 0x1b50, 0x00001F35, + 0x1b4c, 0x3D8a0000, + 0x1b50, 0x00001F77, + 0x1b4c, 0x3E8a0000, + 0x1b50, 0x00001FB8, + 0x1b4c, 0x3F8a0000, + 0x1b50, 0x00001FF8, + 0x1b4c, 0x00000000, + 0x1b50, 0x00000000, + 0x1b58, 0x00890000, + 0x1b5C, 0x3C6B3FFF, + 0x1b58, 0x02890000, + 0x1b5C, 0x35D9390A, + 0x1b58, 0x04890000, + 0x1b5C, 0x2FFE32D6, + 0x1b58, 0x06890000, + 0x1b5C, 0x2AC62D4F, + 0x1b58, 0x08890000, + 0x1b5C, 0x261F2862, + 0x1b58, 0x0A890000, + 0x1b5C, 0x21FA23FD, + 0x1b58, 0x0C890000, + 0x1b5C, 0x1E482013, + 0x1b58, 0x0E890000, + 0x1b5C, 0x1AFD1C96, + 0x1b58, 0x10890000, + 0x1b5C, 0x180E197B, + 0x1b58, 0x12890000, + 0x1b5C, 0x157016B5, + 0x1b58, 0x14890000, + 0x1b5C, 0x131B143D, + 0x1b58, 0x16890000, + 0x1b5C, 0x1107120A, + 0x1b58, 0x18890000, + 0x1b5C, 0x0F2D1013, + 0x1b58, 0x1A890000, + 0x1b5C, 0x0D870E54, + 0x1b58, 0x1C890000, + 0x1b5C, 0x0C0E0CC5, + 0x1b58, 0x1E890000, + 0x1b5C, 0x0ABF0B62, + 0x1b58, 0x20890000, + 0x1b5C, 0x09930A25, + 0x1b58, 0x22890000, + 0x1b5C, 0x0889090A, + 0x1b58, 0x24890000, + 0x1b5C, 0x079B080F, + 0x1b58, 0x26890000, + 0x1b5C, 0x06C7072E, + 0x1b58, 0x28890000, + 0x1b5C, 0x060B0666, + 0x1b58, 0x2A890000, + 0x1b5C, 0x056305B4, + 0x1b58, 0x2C890000, + 0x1b5C, 0x04CD0515, + 0x1b58, 0x2E890000, + 0x1b5C, 0x04470488, + 0x1b58, 0x30890000, + 0x1b5C, 0x03D0040A, + 0x1b58, 0x32890000, + 0x1b5C, 0x03660399, + 0x1b58, 0x34890000, + 0x1b5C, 0x03070335, + 0x1b58, 0x36890000, + 0x1b5C, 0x02B302DC, + 0x1b58, 0x38890000, + 0x1b5C, 0x0268028C, + 0x1b58, 0x3A890000, + 0x1b5C, 0x02250245, + 0x1b58, 0x3C890000, + 0x1b5C, 0x01E90206, + 0x1b58, 0x3E890000, + 0x1b5C, 0x01B401CE, + 0x1b58, 0x40890000, + 0x1b5C, 0x0185019C, + 0x1b58, 0x42890000, + 0x1b5C, 0x015A016F, + 0x1b58, 0x44890000, + 0x1b5C, 0x01350147, + 0x1b58, 0x46890000, + 0x1b5C, 0x01130123, + 0x1b58, 0x48890000, + 0x1b5C, 0x00F50104, + 0x1b58, 0x4A890000, + 0x1b5C, 0x00DA00E7, + 0x1b58, 0x4C890000, + 0x1b5C, 0x00C300CE, + 0x1b58, 0x4E890000, + 0x1b5C, 0x00AE00B8, + 0x1b58, 0x50890000, + 0x1b5C, 0x009B00A4, + 0x1b58, 0x52890000, + 0x1b5C, 0x008A0092, + 0x1b58, 0x54890000, + 0x1b5C, 0x007B0082, + 0x1b58, 0x56890000, + 0x1b5C, 0x006E0074, + 0x1b58, 0x58890000, + 0x1b5C, 0x00620067, + 0x1b58, 0x5A890000, + 0x1b5C, 0x0057005C, + 0x1b58, 0x5C890000, + 0x1b5C, 0x004E0052, + 0x1b58, 0x5E890000, + 0x1b5C, 0x00450049, + 0x1b58, 0x60890000, + 0x1b5C, 0x003E0041, + 0x1b58, 0x62890000, + 0x1b5C, 0x0037003A, + 0x1b58, 0x62010000, + 0x1b00, 0x0000000A, + 0x1b00, 0x00A7000A, + 0x1b00, 0x0015000A, + 0x1b00, 0x0000000A, + 0x1b04, 0xE2462952, + 0x1b08, 0x00000080, + 0x1b0c, 0x00000000, + 0x1b10, 0x00010C00, + 0x1b14, 0x00000000, + 0x1b18, 0x00292903, + 0x1b1c, 0xA218FC32, + 0x1b20, 0x01040008, + 0x1b24, 0x00060008, + 0x1b28, 0x00060300, + 0x1b2C, 0x00180018, + 0x1b30, 0x40000000, + 0x1b34, 0x00000800, + 0x1b38, 0x40000000, + 0x1b3C, 0x40000000, + 0x1b98, 0x00000000, + 0x1b9c, 0x00000000, + 0x1bc0, 0x01000000, + 0x1bcc, 0x00000000, + 0x1be4, 0x00000000, + 0x1bec, 0x40000000, + 0x1b60, 0x1F100000, + 0x1b64, 0x12000000, + 0x1b58, 0x00890000, + 0x1b5C, 0x3C6B3FFF, + 0x1b58, 0x02890000, + 0x1b5C, 0x35D9390A, + 0x1b58, 0x04890000, + 0x1b5C, 0x2FFE32D6, + 0x1b58, 0x06890000, + 0x1b5C, 0x2AC62D4F, + 0x1b58, 0x08890000, + 0x1b5C, 0x261F2862, + 0x1b58, 0x0A890000, + 0x1b5C, 0x21FA23FD, + 0x1b58, 0x0C890000, + 0x1b5C, 0x1E482013, + 0x1b58, 0x0E890000, + 0x1b5C, 0x1AFD1C96, + 0x1b58, 0x10890000, + 0x1b5C, 0x180E197B, + 0x1b58, 0x12890000, + 0x1b5C, 0x157016B5, + 0x1b58, 0x14890000, + 0x1b5C, 0x131B143D, + 0x1b58, 0x16890000, + 0x1b5C, 0x1107120A, + 0x1b58, 0x18890000, + 0x1b5C, 0x0F2D1013, + 0x1b58, 0x1A890000, + 0x1b5C, 0x0D870E54, + 0x1b58, 0x1C890000, + 0x1b5C, 0x0C0E0CC5, + 0x1b58, 0x1E890000, + 0x1b5C, 0x0ABF0B62, + 0x1b58, 0x20890000, + 0x1b5C, 0x09930A25, + 0x1b58, 0x22890000, + 0x1b5C, 0x0889090A, + 0x1b58, 0x24890000, + 0x1b5C, 0x079B080F, + 0x1b58, 0x26890000, + 0x1b5C, 0x06C7072E, + 0x1b58, 0x28890000, + 0x1b5C, 0x060B0666, + 0x1b58, 0x2A890000, + 0x1b5C, 0x056305B4, + 0x1b58, 0x2C890000, + 0x1b5C, 0x04CD0515, + 0x1b58, 0x2E890000, + 0x1b5C, 0x04470488, + 0x1b58, 0x30890000, + 0x1b5C, 0x03D0040A, + 0x1b58, 0x32890000, + 0x1b5C, 0x03660399, + 0x1b58, 0x34890000, + 0x1b5C, 0x03070335, + 0x1b58, 0x36890000, + 0x1b5C, 0x02B302DC, + 0x1b58, 0x38890000, + 0x1b5C, 0x0268028C, + 0x1b58, 0x3A890000, + 0x1b5C, 0x02250245, + 0x1b58, 0x3C890000, + 0x1b5C, 0x01E90206, + 0x1b58, 0x3E890000, + 0x1b5C, 0x01B401CE, + 0x1b58, 0x40890000, + 0x1b5C, 0x0185019C, + 0x1b58, 0x42890000, + 0x1b5C, 0x015A016F, + 0x1b58, 0x44890000, + 0x1b5C, 0x01350147, + 0x1b58, 0x46890000, + 0x1b5C, 0x01130123, + 0x1b58, 0x48890000, + 0x1b5C, 0x00F50104, + 0x1b58, 0x4A890000, + 0x1b5C, 0x00DA00E7, + 0x1b58, 0x4C890000, + 0x1b5C, 0x00C300CE, + 0x1b58, 0x4E890000, + 0x1b5C, 0x00AE00B8, + 0x1b58, 0x50890000, + 0x1b5C, 0x009B00A4, + 0x1b58, 0x52890000, + 0x1b5C, 0x008A0092, + 0x1b58, 0x54890000, + 0x1b5C, 0x007B0082, + 0x1b58, 0x56890000, + 0x1b5C, 0x006E0074, + 0x1b58, 0x58890000, + 0x1b5C, 0x00620067, + 0x1b58, 0x5A890000, + 0x1b5C, 0x0057005C, + 0x1b58, 0x5C890000, + 0x1b5C, 0x004E0052, + 0x1b58, 0x5E890000, + 0x1b5C, 0x00450049, + 0x1b58, 0x60890000, + 0x1b5C, 0x003E0041, + 0x1b58, 0x62890000, + 0x1b5C, 0x0037003A, + 0x1b58, 0x62010000, + 0x1b00, 0x0000000C, + 0x1bd4, 0x000000F0, + 0x1bb8, 0x20202020, + 0x1bbc, 0x20202020, + 0x1bc0, 0x20202020, + 0x1bc4, 0x20202020, + 0x1bc8, 0x04040404, + 0x1bcc, 0x04040404, + 0x1bd0, 0x04040404, + 0x1bd8, 0x04040404, + 0x1bdc, 0x20202020, + 0x1be0, 0x04040404, + 0x1be4, 0x77472F17, + 0x1be8, 0xEFBFA78F, + 0x1bec, 0x00000000, + 0x1bf0, 0x1F1F1939, + 0x1b04, 0x0000005B, + 0x1b08, 0xB000C000, + 0x1b5c, 0x0000005B, + 0x1b60, 0xB000C000, + 0x1bb4, 0x20000000, + 0x1b00, 0x00000008, + 0x1b80, 0x00000007, + 0x1b80, 0x00080005, + 0x1b80, 0x00080007, + 0x1b80, 0x80000015, + 0x1b80, 0x80000017, + 0x1b80, 0x09080025, + 0x1b80, 0x09080027, + 0x1b80, 0x0f020035, + 0x1b80, 0x0f020037, + 0x1b80, 0x00220045, + 0x1b80, 0x00220047, + 0x1b80, 0x00040055, + 0x1b80, 0x00040057, + 0x1b80, 0x05c00065, + 0x1b80, 0x05c00067, + 0x1b80, 0x00070075, + 0x1b80, 0x00070077, + 0x1b80, 0x64020085, + 0x1b80, 0x64020087, + 0x1b80, 0x00020095, + 0x1b80, 0x00020097, + 0x1b80, 0x000400a5, + 0x1b80, 0x000400a7, + 0x1b80, 0x4a0000b5, + 0x1b80, 0x4a0000b7, + 0x1b80, 0x4b0400c5, + 0x1b80, 0x4b0400c7, + 0x1b80, 0x860300d5, + 0x1b80, 0x860300d7, + 0x1b80, 0x400900e5, + 0x1b80, 0x400900e7, + 0x1b80, 0xe02700f5, + 0x1b80, 0xe02700f7, + 0x1b80, 0x4b050105, + 0x1b80, 0x4b050107, + 0x1b80, 0x87030115, + 0x1b80, 0x87030117, + 0x1b80, 0x400b0125, + 0x1b80, 0x400b0127, + 0x1b80, 0xe0270135, + 0x1b80, 0xe0270137, + 0x1b80, 0x4b060145, + 0x1b80, 0x4b060147, + 0x1b80, 0x88030155, + 0x1b80, 0x88030157, + 0x1b80, 0x400d0165, + 0x1b80, 0x400d0167, + 0x1b80, 0xe0270175, + 0x1b80, 0xe0270177, + 0x1b80, 0x4b000185, + 0x1b80, 0x4b000187, + 0x1b80, 0x00070195, + 0x1b80, 0x00070197, + 0x1b80, 0x4c0001a5, + 0x1b80, 0x4c0001a7, + 0x1b80, 0x000401b5, + 0x1b80, 0x000401b7, + 0x1b80, 0x400801c5, + 0x1b80, 0x400801c7, + 0x1b80, 0x505501d5, + 0x1b80, 0x505501d7, + 0x1b80, 0x090a01e5, + 0x1b80, 0x090a01e7, + 0x1b80, 0x0ffe01f5, + 0x1b80, 0x0ffe01f7, + 0x1b80, 0x00220205, + 0x1b80, 0x00220207, + 0x1b80, 0x00040215, + 0x1b80, 0x00040217, + 0x1b80, 0x05c00225, + 0x1b80, 0x05c00227, + 0x1b80, 0x00070235, + 0x1b80, 0x00070237, + 0x1b80, 0x64000245, + 0x1b80, 0x64000247, + 0x1b80, 0x00020255, + 0x1b80, 0x00020257, + 0x1b80, 0x30000265, + 0x1b80, 0x30000267, + 0x1b80, 0xa5100275, + 0x1b80, 0xa5100277, + 0x1b80, 0xe3520285, + 0x1b80, 0xe3520287, + 0x1b80, 0xf01d0295, + 0x1b80, 0xf01d0297, + 0x1b80, 0xf11d02a5, + 0x1b80, 0xf11d02a7, + 0x1b80, 0xf21d02b5, + 0x1b80, 0xf21d02b7, + 0x1b80, 0xf31d02c5, + 0x1b80, 0xf31d02c7, + 0x1b80, 0xf41d02d5, + 0x1b80, 0xf41d02d7, + 0x1b80, 0xf51d02e5, + 0x1b80, 0xf51d02e7, + 0x1b80, 0xf61d02f5, + 0x1b80, 0xf61d02f7, + 0x1b80, 0xf71d0305, + 0x1b80, 0xf71d0307, + 0x1b80, 0xf81d0315, + 0x1b80, 0xf81d0317, + 0x1b80, 0xf91d0325, + 0x1b80, 0xf91d0327, + 0x1b80, 0xfa1d0335, + 0x1b80, 0xfa1d0337, + 0x1b80, 0xfb1d0345, + 0x1b80, 0xfb1d0347, + 0x1b80, 0xfc1d0355, + 0x1b80, 0xfc1d0357, + 0x1b80, 0xfd1d0365, + 0x1b80, 0xfd1d0367, + 0x1b80, 0xf21d0375, + 0x1b80, 0xf21d0377, + 0x1b80, 0xf31d0385, + 0x1b80, 0xf31d0387, + 0x1b80, 0xf41d0395, + 0x1b80, 0xf41d0397, + 0x1b80, 0xf51d03a5, + 0x1b80, 0xf51d03a7, + 0x1b80, 0xf61d03b5, + 0x1b80, 0xf61d03b7, + 0x1b80, 0xf71d03c5, + 0x1b80, 0xf71d03c7, + 0x1b80, 0xf81d03d5, + 0x1b80, 0xf81d03d7, + 0x1b80, 0xf91d03e5, + 0x1b80, 0xf91d03e7, + 0x1b80, 0xfa1d03f5, + 0x1b80, 0xfa1d03f7, + 0x1b80, 0xfb1d0405, + 0x1b80, 0xfb1d0407, + 0x1b80, 0xfc1d0415, + 0x1b80, 0xfc1d0417, + 0x1b80, 0xfd1d0425, + 0x1b80, 0xfd1d0427, + 0x1b80, 0xfe1d0435, + 0x1b80, 0xfe1d0437, + 0x1b80, 0xff1d0445, + 0x1b80, 0xff1d0447, + 0x1b80, 0x00010455, + 0x1b80, 0x00010457, + 0x1b80, 0x30620465, + 0x1b80, 0x30620467, + 0x1b80, 0x307a0475, + 0x1b80, 0x307a0477, + 0x1b80, 0x307c0485, + 0x1b80, 0x307c0487, + 0x1b80, 0x30eb0495, + 0x1b80, 0x30eb0497, + 0x1b80, 0x308004a5, + 0x1b80, 0x308004a7, + 0x1b80, 0x308c04b5, + 0x1b80, 0x308c04b7, + 0x1b80, 0x309804c5, + 0x1b80, 0x309804c7, + 0x1b80, 0x307f04d5, + 0x1b80, 0x307f04d7, + 0x1b80, 0x308b04e5, + 0x1b80, 0x308b04e7, + 0x1b80, 0x309704f5, + 0x1b80, 0x309704f7, + 0x1b80, 0x30ef0505, + 0x1b80, 0x30ef0507, + 0x1b80, 0x30fa0515, + 0x1b80, 0x30fa0517, + 0x1b80, 0x31050525, + 0x1b80, 0x31050527, + 0x1b80, 0x316a0535, + 0x1b80, 0x316a0537, + 0x1b80, 0x307a0545, + 0x1b80, 0x307a0547, + 0x1b80, 0x30e90555, + 0x1b80, 0x30e90557, + 0x1b80, 0x31870565, + 0x1b80, 0x31870567, + 0x1b80, 0x31a00575, + 0x1b80, 0x31a00577, + 0x1b80, 0x31ba0585, + 0x1b80, 0x31ba0587, + 0x1b80, 0x31c20595, + 0x1b80, 0x31c20597, + 0x1b80, 0x31ca05a5, + 0x1b80, 0x31ca05a7, + 0x1b80, 0x31d205b5, + 0x1b80, 0x31d205b7, + 0x1b80, 0x31da05c5, + 0x1b80, 0x31da05c7, + 0x1b80, 0x31e905d5, + 0x1b80, 0x31e905d7, + 0x1b80, 0x31f805e5, + 0x1b80, 0x31f805e7, + 0x1b80, 0x31fe05f5, + 0x1b80, 0x31fe05f7, + 0x1b80, 0x32040605, + 0x1b80, 0x32040607, + 0x1b80, 0x320a0615, + 0x1b80, 0x320a0617, + 0x1b80, 0xe2eb0625, + 0x1b80, 0xe2eb0627, + 0x1b80, 0x4d040635, + 0x1b80, 0x4d040637, + 0x1b80, 0x20800645, + 0x1b80, 0x20800647, + 0x1b80, 0x00000655, + 0x1b80, 0x00000657, + 0x1b80, 0x4d000665, + 0x1b80, 0x4d000667, + 0x1b80, 0x55070675, + 0x1b80, 0x55070677, + 0x1b80, 0xe2e30685, + 0x1b80, 0xe2e30687, + 0x1b80, 0xe2e30695, + 0x1b80, 0xe2e30697, + 0x1b80, 0x4d0406a5, + 0x1b80, 0x4d0406a7, + 0x1b80, 0x208806b5, + 0x1b80, 0x208806b7, + 0x1b80, 0x020006c5, + 0x1b80, 0x020006c7, + 0x1b80, 0x4d0006d5, + 0x1b80, 0x4d0006d7, + 0x1b80, 0x550f06e5, + 0x1b80, 0x550f06e7, + 0x1b80, 0xe2e306f5, + 0x1b80, 0xe2e306f7, + 0x1b80, 0x4f020705, + 0x1b80, 0x4f020707, + 0x1b80, 0x4e000715, + 0x1b80, 0x4e000717, + 0x1b80, 0x53020725, + 0x1b80, 0x53020727, + 0x1b80, 0x52010735, + 0x1b80, 0x52010737, + 0x1b80, 0xe2e70745, + 0x1b80, 0xe2e70747, + 0x1b80, 0x4d080755, + 0x1b80, 0x4d080757, + 0x1b80, 0x57100765, + 0x1b80, 0x57100767, + 0x1b80, 0x57000775, + 0x1b80, 0x57000777, + 0x1b80, 0x4d000785, + 0x1b80, 0x4d000787, + 0x1b80, 0x00010795, + 0x1b80, 0x00010797, + 0x1b80, 0xe2eb07a5, + 0x1b80, 0xe2eb07a7, + 0x1b80, 0x000107b5, + 0x1b80, 0x000107b7, + 0x1b80, 0x620607c5, + 0x1b80, 0x620607c7, + 0x1b80, 0xe2eb07d5, + 0x1b80, 0xe2eb07d7, + 0x1b80, 0x000107e5, + 0x1b80, 0x000107e7, + 0x1b80, 0x620607f5, + 0x1b80, 0x620607f7, + 0x1b80, 0x30ad0805, + 0x1b80, 0x30ad0807, + 0x1b80, 0x00260815, + 0x1b80, 0x00260817, + 0x1b80, 0xe3450825, + 0x1b80, 0xe3450827, + 0x1b80, 0x00020835, + 0x1b80, 0x00020837, + 0x1b80, 0x54ec0845, + 0x1b80, 0x54ec0847, + 0x1b80, 0x0ba60855, + 0x1b80, 0x0ba60857, + 0x1b80, 0x00260865, + 0x1b80, 0x00260867, + 0x1b80, 0xe3450875, + 0x1b80, 0xe3450877, + 0x1b80, 0x00020885, + 0x1b80, 0x00020887, + 0x1b80, 0x63c30895, + 0x1b80, 0x63c30897, + 0x1b80, 0x30d908a5, + 0x1b80, 0x30d908a7, + 0x1b80, 0x620608b5, + 0x1b80, 0x620608b7, + 0x1b80, 0x30a508c5, + 0x1b80, 0x30a508c7, + 0x1b80, 0x002408d5, + 0x1b80, 0x002408d7, + 0x1b80, 0xe34508e5, + 0x1b80, 0xe34508e7, + 0x1b80, 0x000208f5, + 0x1b80, 0x000208f7, + 0x1b80, 0x54ea0905, + 0x1b80, 0x54ea0907, + 0x1b80, 0x0ba60915, + 0x1b80, 0x0ba60917, + 0x1b80, 0x00240925, + 0x1b80, 0x00240927, + 0x1b80, 0xe3450935, + 0x1b80, 0xe3450937, + 0x1b80, 0x00020945, + 0x1b80, 0x00020947, + 0x1b80, 0x63c30955, + 0x1b80, 0x63c30957, + 0x1b80, 0x30d90965, + 0x1b80, 0x30d90967, + 0x1b80, 0x62060975, + 0x1b80, 0x62060977, + 0x1b80, 0x6c100985, + 0x1b80, 0x6c100987, + 0x1b80, 0x6d0f0995, + 0x1b80, 0x6d0f0997, + 0x1b80, 0xe2eb09a5, + 0x1b80, 0xe2eb09a7, + 0x1b80, 0xe34509b5, + 0x1b80, 0xe34509b7, + 0x1b80, 0x6c2409c5, + 0x1b80, 0x6c2409c7, + 0x1b80, 0xe2eb09d5, + 0x1b80, 0xe2eb09d7, + 0x1b80, 0xe34509e5, + 0x1b80, 0xe34509e7, + 0x1b80, 0x6c4409f5, + 0x1b80, 0x6c4409f7, + 0x1b80, 0xe2eb0a05, + 0x1b80, 0xe2eb0a07, + 0x1b80, 0xe3450a15, + 0x1b80, 0xe3450a17, + 0x1b80, 0x6c640a25, + 0x1b80, 0x6c640a27, + 0x1b80, 0xe2eb0a35, + 0x1b80, 0xe2eb0a37, + 0x1b80, 0xe3450a45, + 0x1b80, 0xe3450a47, + 0x1b80, 0x0baa0a55, + 0x1b80, 0x0baa0a57, + 0x1b80, 0x6c840a65, + 0x1b80, 0x6c840a67, + 0x1b80, 0x6d0f0a75, + 0x1b80, 0x6d0f0a77, + 0x1b80, 0xe2eb0a85, + 0x1b80, 0xe2eb0a87, + 0x1b80, 0xe3450a95, + 0x1b80, 0xe3450a97, + 0x1b80, 0x6ca40aa5, + 0x1b80, 0x6ca40aa7, + 0x1b80, 0xe2eb0ab5, + 0x1b80, 0xe2eb0ab7, + 0x1b80, 0xe3450ac5, + 0x1b80, 0xe3450ac7, + 0x1b80, 0x0bac0ad5, + 0x1b80, 0x0bac0ad7, + 0x1b80, 0x6cc40ae5, + 0x1b80, 0x6cc40ae7, + 0x1b80, 0x6d0f0af5, + 0x1b80, 0x6d0f0af7, + 0x1b80, 0xe2eb0b05, + 0x1b80, 0xe2eb0b07, + 0x1b80, 0xe3450b15, + 0x1b80, 0xe3450b17, + 0x1b80, 0x6ce40b25, + 0x1b80, 0x6ce40b27, + 0x1b80, 0xe2eb0b35, + 0x1b80, 0xe2eb0b37, + 0x1b80, 0xe3450b45, + 0x1b80, 0xe3450b47, + 0x1b80, 0x6cf40b55, + 0x1b80, 0x6cf40b57, + 0x1b80, 0xe2eb0b65, + 0x1b80, 0xe2eb0b67, + 0x1b80, 0xe3450b75, + 0x1b80, 0xe3450b77, + 0x1b80, 0x6c0c0b85, + 0x1b80, 0x6c0c0b87, + 0x1b80, 0x6d000b95, + 0x1b80, 0x6d000b97, + 0x1b80, 0xe2eb0ba5, + 0x1b80, 0xe2eb0ba7, + 0x1b80, 0xe3450bb5, + 0x1b80, 0xe3450bb7, + 0x1b80, 0x6c1c0bc5, + 0x1b80, 0x6c1c0bc7, + 0x1b80, 0xe2eb0bd5, + 0x1b80, 0xe2eb0bd7, + 0x1b80, 0xe3450be5, + 0x1b80, 0xe3450be7, + 0x1b80, 0x6c3c0bf5, + 0x1b80, 0x6c3c0bf7, + 0x1b80, 0xe2eb0c05, + 0x1b80, 0xe2eb0c07, + 0x1b80, 0xe3450c15, + 0x1b80, 0xe3450c17, + 0x1b80, 0xf4bf0c25, + 0x1b80, 0xf4bf0c27, + 0x1b80, 0xf7be0c35, + 0x1b80, 0xf7be0c37, + 0x1b80, 0x6c5c0c45, + 0x1b80, 0x6c5c0c47, + 0x1b80, 0xe2eb0c55, + 0x1b80, 0xe2eb0c57, + 0x1b80, 0xe3450c65, + 0x1b80, 0xe3450c67, + 0x1b80, 0x6c7c0c75, + 0x1b80, 0x6c7c0c77, + 0x1b80, 0xe2eb0c85, + 0x1b80, 0xe2eb0c87, + 0x1b80, 0xe3450c95, + 0x1b80, 0xe3450c97, + 0x1b80, 0xf5c30ca5, + 0x1b80, 0xf5c30ca7, + 0x1b80, 0xf8c20cb5, + 0x1b80, 0xf8c20cb7, + 0x1b80, 0x6c9c0cc5, + 0x1b80, 0x6c9c0cc7, + 0x1b80, 0xe2eb0cd5, + 0x1b80, 0xe2eb0cd7, + 0x1b80, 0xe3450ce5, + 0x1b80, 0xe3450ce7, + 0x1b80, 0x6cbc0cf5, + 0x1b80, 0x6cbc0cf7, + 0x1b80, 0xe2eb0d05, + 0x1b80, 0xe2eb0d07, + 0x1b80, 0xe3450d15, + 0x1b80, 0xe3450d17, + 0x1b80, 0x6cdc0d25, + 0x1b80, 0x6cdc0d27, + 0x1b80, 0xe2eb0d35, + 0x1b80, 0xe2eb0d37, + 0x1b80, 0xe3450d45, + 0x1b80, 0xe3450d47, + 0x1b80, 0x6cf00d55, + 0x1b80, 0x6cf00d57, + 0x1b80, 0xe2eb0d65, + 0x1b80, 0xe2eb0d67, + 0x1b80, 0xe3450d75, + 0x1b80, 0xe3450d77, + 0x1b80, 0x63c30d85, + 0x1b80, 0x63c30d87, + 0x1b80, 0x55010d95, + 0x1b80, 0x55010d97, + 0x1b80, 0x57040da5, + 0x1b80, 0x57040da7, + 0x1b80, 0x57000db5, + 0x1b80, 0x57000db7, + 0x1b80, 0x96000dc5, + 0x1b80, 0x96000dc7, + 0x1b80, 0x57080dd5, + 0x1b80, 0x57080dd7, + 0x1b80, 0x57000de5, + 0x1b80, 0x57000de7, + 0x1b80, 0x95000df5, + 0x1b80, 0x95000df7, + 0x1b80, 0x4d000e05, + 0x1b80, 0x4d000e07, + 0x1b80, 0x63050e15, + 0x1b80, 0x63050e17, + 0x1b80, 0x7b400e25, + 0x1b80, 0x7b400e27, + 0x1b80, 0x7a000e35, + 0x1b80, 0x7a000e37, + 0x1b80, 0x79000e45, + 0x1b80, 0x79000e47, + 0x1b80, 0x7f400e55, + 0x1b80, 0x7f400e57, + 0x1b80, 0x7e000e65, + 0x1b80, 0x7e000e67, + 0x1b80, 0x7d000e75, + 0x1b80, 0x7d000e77, + 0x1b80, 0x00010e85, + 0x1b80, 0x00010e87, + 0x1b80, 0xe3170e95, + 0x1b80, 0xe3170e97, + 0x1b80, 0x00010ea5, + 0x1b80, 0x00010ea7, + 0x1b80, 0x5c320eb5, + 0x1b80, 0x5c320eb7, + 0x1b80, 0xe3410ec5, + 0x1b80, 0xe3410ec7, + 0x1b80, 0xe3170ed5, + 0x1b80, 0xe3170ed7, + 0x1b80, 0x00010ee5, + 0x1b80, 0x00010ee7, + 0x1b80, 0x31260ef5, + 0x1b80, 0x31260ef7, + 0x1b80, 0x00260f05, + 0x1b80, 0x00260f07, + 0x1b80, 0xe34a0f15, + 0x1b80, 0xe34a0f17, + 0x1b80, 0x00020f25, + 0x1b80, 0x00020f27, + 0x1b80, 0x54ec0f35, + 0x1b80, 0x54ec0f37, + 0x1b80, 0x0ba60f45, + 0x1b80, 0x0ba60f47, + 0x1b80, 0x00260f55, + 0x1b80, 0x00260f57, + 0x1b80, 0xe34a0f65, + 0x1b80, 0xe34a0f67, + 0x1b80, 0x00020f75, + 0x1b80, 0x00020f77, + 0x1b80, 0x63830f85, + 0x1b80, 0x63830f87, + 0x1b80, 0x30d90f95, + 0x1b80, 0x30d90f97, + 0x1b80, 0x311a0fa5, + 0x1b80, 0x311a0fa7, + 0x1b80, 0x00240fb5, + 0x1b80, 0x00240fb7, + 0x1b80, 0xe34a0fc5, + 0x1b80, 0xe34a0fc7, + 0x1b80, 0x00020fd5, + 0x1b80, 0x00020fd7, + 0x1b80, 0x54ea0fe5, + 0x1b80, 0x54ea0fe7, + 0x1b80, 0x0ba60ff5, + 0x1b80, 0x0ba60ff7, + 0x1b80, 0x00241005, + 0x1b80, 0x00241007, + 0x1b80, 0xe34a1015, + 0x1b80, 0xe34a1017, + 0x1b80, 0x00021025, + 0x1b80, 0x00021027, + 0x1b80, 0x63831035, + 0x1b80, 0x63831037, + 0x1b80, 0x30d91045, + 0x1b80, 0x30d91047, + 0x1b80, 0x5c321055, + 0x1b80, 0x5c321057, + 0x1b80, 0x54e61065, + 0x1b80, 0x54e61067, + 0x1b80, 0x6e101075, + 0x1b80, 0x6e101077, + 0x1b80, 0x6f0f1085, + 0x1b80, 0x6f0f1087, + 0x1b80, 0xe3171095, + 0x1b80, 0xe3171097, + 0x1b80, 0xe34a10a5, + 0x1b80, 0xe34a10a7, + 0x1b80, 0x5c3210b5, + 0x1b80, 0x5c3210b7, + 0x1b80, 0x54e710c5, + 0x1b80, 0x54e710c7, + 0x1b80, 0x6e2410d5, + 0x1b80, 0x6e2410d7, + 0x1b80, 0xe31710e5, + 0x1b80, 0xe31710e7, + 0x1b80, 0xe34a10f5, + 0x1b80, 0xe34a10f7, + 0x1b80, 0x5c321105, + 0x1b80, 0x5c321107, + 0x1b80, 0x54e81115, + 0x1b80, 0x54e81117, + 0x1b80, 0x6e441125, + 0x1b80, 0x6e441127, + 0x1b80, 0xe3171135, + 0x1b80, 0xe3171137, + 0x1b80, 0xe34a1145, + 0x1b80, 0xe34a1147, + 0x1b80, 0x5c321155, + 0x1b80, 0x5c321157, + 0x1b80, 0x54e91165, + 0x1b80, 0x54e91167, + 0x1b80, 0x6e641175, + 0x1b80, 0x6e641177, + 0x1b80, 0xe3171185, + 0x1b80, 0xe3171187, + 0x1b80, 0xe34a1195, + 0x1b80, 0xe34a1197, + 0x1b80, 0x5c3211a5, + 0x1b80, 0x5c3211a7, + 0x1b80, 0x54ea11b5, + 0x1b80, 0x54ea11b7, + 0x1b80, 0x0baa11c5, + 0x1b80, 0x0baa11c7, + 0x1b80, 0x6e8411d5, + 0x1b80, 0x6e8411d7, + 0x1b80, 0x6f0f11e5, + 0x1b80, 0x6f0f11e7, + 0x1b80, 0xe31711f5, + 0x1b80, 0xe31711f7, + 0x1b80, 0xe34a1205, + 0x1b80, 0xe34a1207, + 0x1b80, 0x5c321215, + 0x1b80, 0x5c321217, + 0x1b80, 0x54eb1225, + 0x1b80, 0x54eb1227, + 0x1b80, 0x6ea41235, + 0x1b80, 0x6ea41237, + 0x1b80, 0xe3171245, + 0x1b80, 0xe3171247, + 0x1b80, 0xe34a1255, + 0x1b80, 0xe34a1257, + 0x1b80, 0x5c321265, + 0x1b80, 0x5c321267, + 0x1b80, 0x54ec1275, + 0x1b80, 0x54ec1277, + 0x1b80, 0x0bac1285, + 0x1b80, 0x0bac1287, + 0x1b80, 0x6ec41295, + 0x1b80, 0x6ec41297, + 0x1b80, 0x6f0f12a5, + 0x1b80, 0x6f0f12a7, + 0x1b80, 0xe31712b5, + 0x1b80, 0xe31712b7, + 0x1b80, 0xe34a12c5, + 0x1b80, 0xe34a12c7, + 0x1b80, 0x5c3212d5, + 0x1b80, 0x5c3212d7, + 0x1b80, 0x54ed12e5, + 0x1b80, 0x54ed12e7, + 0x1b80, 0x6ee412f5, + 0x1b80, 0x6ee412f7, + 0x1b80, 0xe3171305, + 0x1b80, 0xe3171307, + 0x1b80, 0xe34a1315, + 0x1b80, 0xe34a1317, + 0x1b80, 0x5c321325, + 0x1b80, 0x5c321327, + 0x1b80, 0x54ee1335, + 0x1b80, 0x54ee1337, + 0x1b80, 0x6ef41345, + 0x1b80, 0x6ef41347, + 0x1b80, 0xe3171355, + 0x1b80, 0xe3171357, + 0x1b80, 0xe34a1365, + 0x1b80, 0xe34a1367, + 0x1b80, 0x5c321375, + 0x1b80, 0x5c321377, + 0x1b80, 0x54ef1385, + 0x1b80, 0x54ef1387, + 0x1b80, 0x6e0c1395, + 0x1b80, 0x6e0c1397, + 0x1b80, 0x6f0013a5, + 0x1b80, 0x6f0013a7, + 0x1b80, 0xe31713b5, + 0x1b80, 0xe31713b7, + 0x1b80, 0xe34a13c5, + 0x1b80, 0xe34a13c7, + 0x1b80, 0x5c3213d5, + 0x1b80, 0x5c3213d7, + 0x1b80, 0x54f013e5, + 0x1b80, 0x54f013e7, + 0x1b80, 0x6e1c13f5, + 0x1b80, 0x6e1c13f7, + 0x1b80, 0xe3171405, + 0x1b80, 0xe3171407, + 0x1b80, 0xe34a1415, + 0x1b80, 0xe34a1417, + 0x1b80, 0x5c321425, + 0x1b80, 0x5c321427, + 0x1b80, 0x54f11435, + 0x1b80, 0x54f11437, + 0x1b80, 0x6e3c1445, + 0x1b80, 0x6e3c1447, + 0x1b80, 0xe3171455, + 0x1b80, 0xe3171457, + 0x1b80, 0xe34a1465, + 0x1b80, 0xe34a1467, + 0x1b80, 0xfaa91475, + 0x1b80, 0xfaa91477, + 0x1b80, 0x5c321485, + 0x1b80, 0x5c321487, + 0x1b80, 0x54f21495, + 0x1b80, 0x54f21497, + 0x1b80, 0x6e5c14a5, + 0x1b80, 0x6e5c14a7, + 0x1b80, 0xe31714b5, + 0x1b80, 0xe31714b7, + 0x1b80, 0xe34a14c5, + 0x1b80, 0xe34a14c7, + 0x1b80, 0x5c3214d5, + 0x1b80, 0x5c3214d7, + 0x1b80, 0x54f314e5, + 0x1b80, 0x54f314e7, + 0x1b80, 0x6e7c14f5, + 0x1b80, 0x6e7c14f7, + 0x1b80, 0xe3171505, + 0x1b80, 0xe3171507, + 0x1b80, 0xe34a1515, + 0x1b80, 0xe34a1517, + 0x1b80, 0xfba91525, + 0x1b80, 0xfba91527, + 0x1b80, 0x5c321535, + 0x1b80, 0x5c321537, + 0x1b80, 0x54f41545, + 0x1b80, 0x54f41547, + 0x1b80, 0x6e9c1555, + 0x1b80, 0x6e9c1557, + 0x1b80, 0xe3171565, + 0x1b80, 0xe3171567, + 0x1b80, 0xe34a1575, + 0x1b80, 0xe34a1577, + 0x1b80, 0x5c321585, + 0x1b80, 0x5c321587, + 0x1b80, 0x54f51595, + 0x1b80, 0x54f51597, + 0x1b80, 0x6ebc15a5, + 0x1b80, 0x6ebc15a7, + 0x1b80, 0xe31715b5, + 0x1b80, 0xe31715b7, + 0x1b80, 0xe34a15c5, + 0x1b80, 0xe34a15c7, + 0x1b80, 0x5c3215d5, + 0x1b80, 0x5c3215d7, + 0x1b80, 0x54f615e5, + 0x1b80, 0x54f615e7, + 0x1b80, 0x6edc15f5, + 0x1b80, 0x6edc15f7, + 0x1b80, 0xe3171605, + 0x1b80, 0xe3171607, + 0x1b80, 0xe34a1615, + 0x1b80, 0xe34a1617, + 0x1b80, 0x5c321625, + 0x1b80, 0x5c321627, + 0x1b80, 0x54f71635, + 0x1b80, 0x54f71637, + 0x1b80, 0x6ef01645, + 0x1b80, 0x6ef01647, + 0x1b80, 0xe3171655, + 0x1b80, 0xe3171657, + 0x1b80, 0xe34a1665, + 0x1b80, 0xe34a1667, + 0x1b80, 0x63831675, + 0x1b80, 0x63831677, + 0x1b80, 0x30d91685, + 0x1b80, 0x30d91687, + 0x1b80, 0x00011695, + 0x1b80, 0x00011697, + 0x1b80, 0x000416a5, + 0x1b80, 0x000416a7, + 0x1b80, 0x550116b5, + 0x1b80, 0x550116b7, + 0x1b80, 0x5c3116c5, + 0x1b80, 0x5c3116c7, + 0x1b80, 0x5f8216d5, + 0x1b80, 0x5f8216d7, + 0x1b80, 0x660516e5, + 0x1b80, 0x660516e7, + 0x1b80, 0x000616f5, + 0x1b80, 0x000616f7, + 0x1b80, 0x5d801705, + 0x1b80, 0x5d801707, + 0x1b80, 0x09001715, + 0x1b80, 0x09001717, + 0x1b80, 0x0a011725, + 0x1b80, 0x0a011727, + 0x1b80, 0x0b401735, + 0x1b80, 0x0b401737, + 0x1b80, 0x0d001745, + 0x1b80, 0x0d001747, + 0x1b80, 0x0f011755, + 0x1b80, 0x0f011757, + 0x1b80, 0x002a1765, + 0x1b80, 0x002a1767, + 0x1b80, 0x055a1775, + 0x1b80, 0x055a1777, + 0x1b80, 0x05db1785, + 0x1b80, 0x05db1787, + 0x1b80, 0xe3351795, + 0x1b80, 0xe3351797, + 0x1b80, 0xe2e317a5, + 0x1b80, 0xe2e317a7, + 0x1b80, 0x000617b5, + 0x1b80, 0x000617b7, + 0x1b80, 0x06da17c5, + 0x1b80, 0x06da17c7, + 0x1b80, 0x07db17d5, + 0x1b80, 0x07db17d7, + 0x1b80, 0xe33517e5, + 0x1b80, 0xe33517e7, + 0x1b80, 0xe2e317f5, + 0x1b80, 0xe2e317f7, + 0x1b80, 0xe32c1805, + 0x1b80, 0xe32c1807, + 0x1b80, 0x00021815, + 0x1b80, 0x00021817, + 0x1b80, 0xe3311825, + 0x1b80, 0xe3311827, + 0x1b80, 0x5d001835, + 0x1b80, 0x5d001837, + 0x1b80, 0x00041845, + 0x1b80, 0x00041847, + 0x1b80, 0x5fa21855, + 0x1b80, 0x5fa21857, + 0x1b80, 0x00011865, + 0x1b80, 0x00011867, + 0x1b80, 0xe2571875, + 0x1b80, 0xe2571877, + 0x1b80, 0x74081885, + 0x1b80, 0x74081887, + 0x1b80, 0xe2a11895, + 0x1b80, 0xe2a11897, + 0x1b80, 0xe28318a5, + 0x1b80, 0xe28318a7, + 0x1b80, 0xe2c118b5, + 0x1b80, 0xe2c118b7, + 0x1b80, 0xb90018c5, + 0x1b80, 0xb90018c7, + 0x1b80, 0x990018d5, + 0x1b80, 0x990018d7, + 0x1b80, 0x000618e5, + 0x1b80, 0x000618e7, + 0x1b80, 0x770018f5, + 0x1b80, 0x770018f7, + 0x1b80, 0x00041905, + 0x1b80, 0x00041907, + 0x1b80, 0x49041915, + 0x1b80, 0x49041917, + 0x1b80, 0x4bb01925, + 0x1b80, 0x4bb01927, + 0x1b80, 0x00061935, + 0x1b80, 0x00061937, + 0x1b80, 0x75041945, + 0x1b80, 0x75041947, + 0x1b80, 0x77081955, + 0x1b80, 0x77081957, + 0x1b80, 0x00071965, + 0x1b80, 0x00071967, + 0x1b80, 0x77101975, + 0x1b80, 0x77101977, + 0x1b80, 0x00041985, + 0x1b80, 0x00041987, + 0x1b80, 0x44801995, + 0x1b80, 0x44801997, + 0x1b80, 0x45ff19a5, + 0x1b80, 0x45ff19a7, + 0x1b80, 0x463f19b5, + 0x1b80, 0x463f19b7, + 0x1b80, 0x473119c5, + 0x1b80, 0x473119c7, + 0x1b80, 0x400819d5, + 0x1b80, 0x400819d7, + 0x1b80, 0xe23e19e5, + 0x1b80, 0xe23e19e7, + 0x1b80, 0x000119f5, + 0x1b80, 0x000119f7, + 0x1b80, 0xe2571a05, + 0x1b80, 0xe2571a07, + 0x1b80, 0x74081a15, + 0x1b80, 0x74081a17, + 0x1b80, 0xe2b11a25, + 0x1b80, 0xe2b11a27, + 0x1b80, 0xe2831a35, + 0x1b80, 0xe2831a37, + 0x1b80, 0xe2c71a45, + 0x1b80, 0xe2c71a47, + 0x1b80, 0xb9001a55, + 0x1b80, 0xb9001a57, + 0x1b80, 0x99001a65, + 0x1b80, 0x99001a67, + 0x1b80, 0x00061a75, + 0x1b80, 0x00061a77, + 0x1b80, 0x77001a85, + 0x1b80, 0x77001a87, + 0x1b80, 0x00051a95, + 0x1b80, 0x00051a97, + 0x1b80, 0x61041aa5, + 0x1b80, 0x61041aa7, + 0x1b80, 0x63b01ab5, + 0x1b80, 0x63b01ab7, + 0x1b80, 0x00061ac5, + 0x1b80, 0x00061ac7, + 0x1b80, 0x75081ad5, + 0x1b80, 0x75081ad7, + 0x1b80, 0x77081ae5, + 0x1b80, 0x77081ae7, + 0x1b80, 0x00071af5, + 0x1b80, 0x00071af7, + 0x1b80, 0x77201b05, + 0x1b80, 0x77201b07, + 0x1b80, 0x00051b15, + 0x1b80, 0x00051b17, + 0x1b80, 0x5c801b25, + 0x1b80, 0x5c801b27, + 0x1b80, 0x5dff1b35, + 0x1b80, 0x5dff1b37, + 0x1b80, 0x5e3f1b45, + 0x1b80, 0x5e3f1b47, + 0x1b80, 0x5f311b55, + 0x1b80, 0x5f311b57, + 0x1b80, 0x00041b65, + 0x1b80, 0x00041b67, + 0x1b80, 0x400a1b75, + 0x1b80, 0x400a1b77, + 0x1b80, 0xe23e1b85, + 0x1b80, 0xe23e1b87, + 0x1b80, 0x00011b95, + 0x1b80, 0x00011b97, + 0x1b80, 0xe2571ba5, + 0x1b80, 0xe2571ba7, + 0x1b80, 0x74081bb5, + 0x1b80, 0x74081bb7, + 0x1b80, 0xe2a11bc5, + 0x1b80, 0xe2a11bc7, + 0x1b80, 0xe2831bd5, + 0x1b80, 0xe2831bd7, + 0x1b80, 0xe2c11be5, + 0x1b80, 0xe2c11be7, + 0x1b80, 0xe2cd1bf5, + 0x1b80, 0xe2cd1bf7, + 0x1b80, 0xe2101c05, + 0x1b80, 0xe2101c07, + 0x1b80, 0x00011c15, + 0x1b80, 0x00011c17, + 0x1b80, 0xe2571c25, + 0x1b80, 0xe2571c27, + 0x1b80, 0x74081c35, + 0x1b80, 0x74081c37, + 0x1b80, 0xe2b11c45, + 0x1b80, 0xe2b11c47, + 0x1b80, 0xe2831c55, + 0x1b80, 0xe2831c57, + 0x1b80, 0xe2c71c65, + 0x1b80, 0xe2c71c67, + 0x1b80, 0xe2cd1c75, + 0x1b80, 0xe2cd1c77, + 0x1b80, 0xe2261c85, + 0x1b80, 0xe2261c87, + 0x1b80, 0x00011c95, + 0x1b80, 0x00011c97, + 0x1b80, 0xe26d1ca5, + 0x1b80, 0xe26d1ca7, + 0x1b80, 0x74001cb5, + 0x1b80, 0x74001cb7, + 0x1b80, 0xe2a11cc5, + 0x1b80, 0xe2a11cc7, + 0x1b80, 0xe2921cd5, + 0x1b80, 0xe2921cd7, + 0x1b80, 0xe2c11ce5, + 0x1b80, 0xe2c11ce7, + 0x1b80, 0xe2cd1cf5, + 0x1b80, 0xe2cd1cf7, + 0x1b80, 0xe2101d05, + 0x1b80, 0xe2101d07, + 0x1b80, 0x00011d15, + 0x1b80, 0x00011d17, + 0x1b80, 0xe26d1d25, + 0x1b80, 0xe26d1d27, + 0x1b80, 0x74001d35, + 0x1b80, 0x74001d37, + 0x1b80, 0xe2b11d45, + 0x1b80, 0xe2b11d47, + 0x1b80, 0xe2921d55, + 0x1b80, 0xe2921d57, + 0x1b80, 0xe2c71d65, + 0x1b80, 0xe2c71d67, + 0x1b80, 0xe2cd1d75, + 0x1b80, 0xe2cd1d77, + 0x1b80, 0xe2261d85, + 0x1b80, 0xe2261d87, + 0x1b80, 0x00011d95, + 0x1b80, 0x00011d97, + 0x1b80, 0x00041da5, + 0x1b80, 0x00041da7, + 0x1b80, 0x445b1db5, + 0x1b80, 0x445b1db7, + 0x1b80, 0x47b01dc5, + 0x1b80, 0x47b01dc7, + 0x1b80, 0x47301dd5, + 0x1b80, 0x47301dd7, + 0x1b80, 0x47001de5, + 0x1b80, 0x47001de7, + 0x1b80, 0x00061df5, + 0x1b80, 0x00061df7, + 0x1b80, 0x77081e05, + 0x1b80, 0x77081e07, + 0x1b80, 0x00041e15, + 0x1b80, 0x00041e17, + 0x1b80, 0x49401e25, + 0x1b80, 0x49401e27, + 0x1b80, 0x4bb01e35, + 0x1b80, 0x4bb01e37, + 0x1b80, 0x00071e45, + 0x1b80, 0x00071e47, + 0x1b80, 0x54401e55, + 0x1b80, 0x54401e57, + 0x1b80, 0x00041e65, + 0x1b80, 0x00041e67, + 0x1b80, 0x40081e75, + 0x1b80, 0x40081e77, + 0x1b80, 0x00011e85, + 0x1b80, 0x00011e87, + 0x1b80, 0x00051e95, + 0x1b80, 0x00051e97, + 0x1b80, 0x5c5b1ea5, + 0x1b80, 0x5c5b1ea7, + 0x1b80, 0x5fb01eb5, + 0x1b80, 0x5fb01eb7, + 0x1b80, 0x5f301ec5, + 0x1b80, 0x5f301ec7, + 0x1b80, 0x5f001ed5, + 0x1b80, 0x5f001ed7, + 0x1b80, 0x00061ee5, + 0x1b80, 0x00061ee7, + 0x1b80, 0x77081ef5, + 0x1b80, 0x77081ef7, + 0x1b80, 0x00051f05, + 0x1b80, 0x00051f07, + 0x1b80, 0x61401f15, + 0x1b80, 0x61401f17, + 0x1b80, 0x63b01f25, + 0x1b80, 0x63b01f27, + 0x1b80, 0x00071f35, + 0x1b80, 0x00071f37, + 0x1b80, 0x54401f45, + 0x1b80, 0x54401f47, + 0x1b80, 0x00041f55, + 0x1b80, 0x00041f57, + 0x1b80, 0x40081f65, + 0x1b80, 0x40081f67, + 0x1b80, 0x00011f75, + 0x1b80, 0x00011f77, + 0x1b80, 0xe2571f85, + 0x1b80, 0xe2571f87, + 0x1b80, 0x74081f95, + 0x1b80, 0x74081f97, + 0x1b80, 0xe2a11fa5, + 0x1b80, 0xe2a11fa7, + 0x1b80, 0x00041fb5, + 0x1b80, 0x00041fb7, + 0x1b80, 0x40081fc5, + 0x1b80, 0x40081fc7, + 0x1b80, 0x00011fd5, + 0x1b80, 0x00011fd7, + 0x1b80, 0xe2571fe5, + 0x1b80, 0xe2571fe7, + 0x1b80, 0x74081ff5, + 0x1b80, 0x74081ff7, + 0x1b80, 0xe2b12005, + 0x1b80, 0xe2b12007, + 0x1b80, 0x00042015, + 0x1b80, 0x00042017, + 0x1b80, 0x40082025, + 0x1b80, 0x40082027, + 0x1b80, 0x00012035, + 0x1b80, 0x00012037, + 0x1b80, 0xe26d2045, + 0x1b80, 0xe26d2047, + 0x1b80, 0x74002055, + 0x1b80, 0x74002057, + 0x1b80, 0xe2a12065, + 0x1b80, 0xe2a12067, + 0x1b80, 0x00042075, + 0x1b80, 0x00042077, + 0x1b80, 0x40082085, + 0x1b80, 0x40082087, + 0x1b80, 0x00012095, + 0x1b80, 0x00012097, + 0x1b80, 0xe26d20a5, + 0x1b80, 0xe26d20a7, + 0x1b80, 0x740020b5, + 0x1b80, 0x740020b7, + 0x1b80, 0xe2b120c5, + 0x1b80, 0xe2b120c7, + 0x1b80, 0x000420d5, + 0x1b80, 0x000420d7, + 0x1b80, 0x400820e5, + 0x1b80, 0x400820e7, + 0x1b80, 0x000120f5, + 0x1b80, 0x000120f7, + 0x1b80, 0x00042105, + 0x1b80, 0x00042107, + 0x1b80, 0x49042115, + 0x1b80, 0x49042117, + 0x1b80, 0x4bb02125, + 0x1b80, 0x4bb02127, + 0x1b80, 0x00062135, + 0x1b80, 0x00062137, + 0x1b80, 0x75042145, + 0x1b80, 0x75042147, + 0x1b80, 0x77082155, + 0x1b80, 0x77082157, + 0x1b80, 0x00042165, + 0x1b80, 0x00042167, + 0x1b80, 0x44802175, + 0x1b80, 0x44802177, + 0x1b80, 0x45ff2185, + 0x1b80, 0x45ff2187, + 0x1b80, 0x463f2195, + 0x1b80, 0x463f2197, + 0x1b80, 0x473121a5, + 0x1b80, 0x473121a7, + 0x1b80, 0x400821b5, + 0x1b80, 0x400821b7, + 0x1b80, 0xe23e21c5, + 0x1b80, 0xe23e21c7, + 0x1b80, 0x000421d5, + 0x1b80, 0x000421d7, + 0x1b80, 0x400c21e5, + 0x1b80, 0x400c21e7, + 0x1b80, 0x000621f5, + 0x1b80, 0x000621f7, + 0x1b80, 0x75002205, + 0x1b80, 0x75002207, + 0x1b80, 0x00042215, + 0x1b80, 0x00042217, + 0x1b80, 0x445b2225, + 0x1b80, 0x445b2227, + 0x1b80, 0x47002235, + 0x1b80, 0x47002237, + 0x1b80, 0x40082245, + 0x1b80, 0x40082247, + 0x1b80, 0x00012255, + 0x1b80, 0x00012257, + 0x1b80, 0x00052265, + 0x1b80, 0x00052267, + 0x1b80, 0x61042275, + 0x1b80, 0x61042277, + 0x1b80, 0x63b02285, + 0x1b80, 0x63b02287, + 0x1b80, 0x00062295, + 0x1b80, 0x00062297, + 0x1b80, 0x750822a5, + 0x1b80, 0x750822a7, + 0x1b80, 0x770822b5, + 0x1b80, 0x770822b7, + 0x1b80, 0x000522c5, + 0x1b80, 0x000522c7, + 0x1b80, 0x5c8022d5, + 0x1b80, 0x5c8022d7, + 0x1b80, 0x5dff22e5, + 0x1b80, 0x5dff22e7, + 0x1b80, 0x5e3f22f5, + 0x1b80, 0x5e3f22f7, + 0x1b80, 0x5f312305, + 0x1b80, 0x5f312307, + 0x1b80, 0x00042315, + 0x1b80, 0x00042317, + 0x1b80, 0x400a2325, + 0x1b80, 0x400a2327, + 0x1b80, 0xe23e2335, + 0x1b80, 0xe23e2337, + 0x1b80, 0x00042345, + 0x1b80, 0x00042347, + 0x1b80, 0x400c2355, + 0x1b80, 0x400c2357, + 0x1b80, 0x00062365, + 0x1b80, 0x00062367, + 0x1b80, 0x75002375, + 0x1b80, 0x75002377, + 0x1b80, 0x00052385, + 0x1b80, 0x00052387, + 0x1b80, 0x5c5b2395, + 0x1b80, 0x5c5b2397, + 0x1b80, 0x5f0023a5, + 0x1b80, 0x5f0023a7, + 0x1b80, 0x000423b5, + 0x1b80, 0x000423b7, + 0x1b80, 0x400823c5, + 0x1b80, 0x400823c7, + 0x1b80, 0x000123d5, + 0x1b80, 0x000123d7, + 0x1b80, 0x000723e5, + 0x1b80, 0x000723e7, + 0x1b80, 0x4c1223f5, + 0x1b80, 0x4c1223f7, + 0x1b80, 0x4e202405, + 0x1b80, 0x4e202407, + 0x1b80, 0x00052415, + 0x1b80, 0x00052417, + 0x1b80, 0x598f2425, + 0x1b80, 0x598f2427, + 0x1b80, 0x40022435, + 0x1b80, 0x40022437, + 0x1b80, 0x4c012445, + 0x1b80, 0x4c012447, + 0x1b80, 0x4c002455, + 0x1b80, 0x4c002457, + 0x1b80, 0xab002465, + 0x1b80, 0xab002467, + 0x1b80, 0x40032475, + 0x1b80, 0x40032477, + 0x1b80, 0x49802485, + 0x1b80, 0x49802487, + 0x1b80, 0x56c02495, + 0x1b80, 0x56c02497, + 0x1b80, 0x540224a5, + 0x1b80, 0x540224a7, + 0x1b80, 0x4c0124b5, + 0x1b80, 0x4c0124b7, + 0x1b80, 0x4c0024c5, + 0x1b80, 0x4c0024c7, + 0x1b80, 0xab0024d5, + 0x1b80, 0xab0024d7, + 0x1b80, 0x540024e5, + 0x1b80, 0x540024e7, + 0x1b80, 0x000724f5, + 0x1b80, 0x000724f7, + 0x1b80, 0x4c002505, + 0x1b80, 0x4c002507, + 0x1b80, 0x4e002515, + 0x1b80, 0x4e002517, + 0x1b80, 0x00052525, + 0x1b80, 0x00052527, + 0x1b80, 0x40042535, + 0x1b80, 0x40042537, + 0x1b80, 0x4c012545, + 0x1b80, 0x4c012547, + 0x1b80, 0x4c002555, + 0x1b80, 0x4c002557, + 0x1b80, 0x00012565, + 0x1b80, 0x00012567, + 0x1b80, 0x00042575, + 0x1b80, 0x00042577, + 0x1b80, 0x44802585, + 0x1b80, 0x44802587, + 0x1b80, 0x4b002595, + 0x1b80, 0x4b002597, + 0x1b80, 0x000525a5, + 0x1b80, 0x000525a7, + 0x1b80, 0x5c8025b5, + 0x1b80, 0x5c8025b7, + 0x1b80, 0x630025c5, + 0x1b80, 0x630025c7, + 0x1b80, 0x000725d5, + 0x1b80, 0x000725d7, + 0x1b80, 0x780c25e5, + 0x1b80, 0x780c25e7, + 0x1b80, 0x791925f5, + 0x1b80, 0x791925f7, + 0x1b80, 0x7a002605, + 0x1b80, 0x7a002607, + 0x1b80, 0x7b822615, + 0x1b80, 0x7b822617, + 0x1b80, 0x7b022625, + 0x1b80, 0x7b022627, + 0x1b80, 0x78142635, + 0x1b80, 0x78142637, + 0x1b80, 0x79ee2645, + 0x1b80, 0x79ee2647, + 0x1b80, 0x7a012655, + 0x1b80, 0x7a012657, + 0x1b80, 0x7b832665, + 0x1b80, 0x7b832667, + 0x1b80, 0x7b032675, + 0x1b80, 0x7b032677, + 0x1b80, 0x78282685, + 0x1b80, 0x78282687, + 0x1b80, 0x79b42695, + 0x1b80, 0x79b42697, + 0x1b80, 0x7a0026a5, + 0x1b80, 0x7a0026a7, + 0x1b80, 0x7b0026b5, + 0x1b80, 0x7b0026b7, + 0x1b80, 0x000126c5, + 0x1b80, 0x000126c7, + 0x1b80, 0x000426d5, + 0x1b80, 0x000426d7, + 0x1b80, 0x448026e5, + 0x1b80, 0x448026e7, + 0x1b80, 0x4b0026f5, + 0x1b80, 0x4b0026f7, + 0x1b80, 0x00052705, + 0x1b80, 0x00052707, + 0x1b80, 0x5c802715, + 0x1b80, 0x5c802717, + 0x1b80, 0x63002725, + 0x1b80, 0x63002727, + 0x1b80, 0x00072735, + 0x1b80, 0x00072737, + 0x1b80, 0x78102745, + 0x1b80, 0x78102747, + 0x1b80, 0x79132755, + 0x1b80, 0x79132757, + 0x1b80, 0x7a002765, + 0x1b80, 0x7a002767, + 0x1b80, 0x7b802775, + 0x1b80, 0x7b802777, + 0x1b80, 0x7b002785, + 0x1b80, 0x7b002787, + 0x1b80, 0x78db2795, + 0x1b80, 0x78db2797, + 0x1b80, 0x790027a5, + 0x1b80, 0x790027a7, + 0x1b80, 0x7a0027b5, + 0x1b80, 0x7a0027b7, + 0x1b80, 0x7b8127c5, + 0x1b80, 0x7b8127c7, + 0x1b80, 0x7b0127d5, + 0x1b80, 0x7b0127d7, + 0x1b80, 0x782827e5, + 0x1b80, 0x782827e7, + 0x1b80, 0x79b427f5, + 0x1b80, 0x79b427f7, + 0x1b80, 0x7a002805, + 0x1b80, 0x7a002807, + 0x1b80, 0x7b002815, + 0x1b80, 0x7b002817, + 0x1b80, 0x00012825, + 0x1b80, 0x00012827, + 0x1b80, 0x00072835, + 0x1b80, 0x00072837, + 0x1b80, 0x783e2845, + 0x1b80, 0x783e2847, + 0x1b80, 0x79f92855, + 0x1b80, 0x79f92857, + 0x1b80, 0x7a012865, + 0x1b80, 0x7a012867, + 0x1b80, 0x7b822875, + 0x1b80, 0x7b822877, + 0x1b80, 0x7b022885, + 0x1b80, 0x7b022887, + 0x1b80, 0x78a92895, + 0x1b80, 0x78a92897, + 0x1b80, 0x79ed28a5, + 0x1b80, 0x79ed28a7, + 0x1b80, 0x7b8328b5, + 0x1b80, 0x7b8328b7, + 0x1b80, 0x7b0328c5, + 0x1b80, 0x7b0328c7, + 0x1b80, 0x782828d5, + 0x1b80, 0x782828d7, + 0x1b80, 0x79b428e5, + 0x1b80, 0x79b428e7, + 0x1b80, 0x7a0028f5, + 0x1b80, 0x7a0028f7, + 0x1b80, 0x7b002905, + 0x1b80, 0x7b002907, + 0x1b80, 0x00012915, + 0x1b80, 0x00012917, + 0x1b80, 0x00072925, + 0x1b80, 0x00072927, + 0x1b80, 0x78ae2935, + 0x1b80, 0x78ae2937, + 0x1b80, 0x79fa2945, + 0x1b80, 0x79fa2947, + 0x1b80, 0x7a012955, + 0x1b80, 0x7a012957, + 0x1b80, 0x7b802965, + 0x1b80, 0x7b802967, + 0x1b80, 0x7b002975, + 0x1b80, 0x7b002977, + 0x1b80, 0x787a2985, + 0x1b80, 0x787a2987, + 0x1b80, 0x79f12995, + 0x1b80, 0x79f12997, + 0x1b80, 0x7b8129a5, + 0x1b80, 0x7b8129a7, + 0x1b80, 0x7b0129b5, + 0x1b80, 0x7b0129b7, + 0x1b80, 0x782829c5, + 0x1b80, 0x782829c7, + 0x1b80, 0x79b429d5, + 0x1b80, 0x79b429d7, + 0x1b80, 0x7a0029e5, + 0x1b80, 0x7a0029e7, + 0x1b80, 0x7b0029f5, + 0x1b80, 0x7b0029f7, + 0x1b80, 0x00012a05, + 0x1b80, 0x00012a07, + 0x1b80, 0x00072a15, + 0x1b80, 0x00072a17, + 0x1b80, 0x75002a25, + 0x1b80, 0x75002a27, + 0x1b80, 0x76022a35, + 0x1b80, 0x76022a37, + 0x1b80, 0x77152a45, + 0x1b80, 0x77152a47, + 0x1b80, 0x00062a55, + 0x1b80, 0x00062a57, + 0x1b80, 0x74002a65, + 0x1b80, 0x74002a67, + 0x1b80, 0x76002a75, + 0x1b80, 0x76002a77, + 0x1b80, 0x77002a85, + 0x1b80, 0x77002a87, + 0x1b80, 0x75102a95, + 0x1b80, 0x75102a97, + 0x1b80, 0x75002aa5, + 0x1b80, 0x75002aa7, + 0x1b80, 0xb3002ab5, + 0x1b80, 0xb3002ab7, + 0x1b80, 0x93002ac5, + 0x1b80, 0x93002ac7, + 0x1b80, 0x00072ad5, + 0x1b80, 0x00072ad7, + 0x1b80, 0x76002ae5, + 0x1b80, 0x76002ae7, + 0x1b80, 0x77002af5, + 0x1b80, 0x77002af7, + 0x1b80, 0x00012b05, + 0x1b80, 0x00012b07, + 0x1b80, 0x00072b15, + 0x1b80, 0x00072b17, + 0x1b80, 0x75002b25, + 0x1b80, 0x75002b27, + 0x1b80, 0x76022b35, + 0x1b80, 0x76022b37, + 0x1b80, 0x77252b45, + 0x1b80, 0x77252b47, + 0x1b80, 0x00062b55, + 0x1b80, 0x00062b57, + 0x1b80, 0x74002b65, + 0x1b80, 0x74002b67, + 0x1b80, 0x76002b75, + 0x1b80, 0x76002b77, + 0x1b80, 0x77012b85, + 0x1b80, 0x77012b87, + 0x1b80, 0x75102b95, + 0x1b80, 0x75102b97, + 0x1b80, 0x75002ba5, + 0x1b80, 0x75002ba7, + 0x1b80, 0xb3002bb5, + 0x1b80, 0xb3002bb7, + 0x1b80, 0x93002bc5, + 0x1b80, 0x93002bc7, + 0x1b80, 0x00072bd5, + 0x1b80, 0x00072bd7, + 0x1b80, 0x76002be5, + 0x1b80, 0x76002be7, + 0x1b80, 0x77002bf5, + 0x1b80, 0x77002bf7, + 0x1b80, 0x00012c05, + 0x1b80, 0x00012c07, + 0x1b80, 0x00042c15, + 0x1b80, 0x00042c17, + 0x1b80, 0x44802c25, + 0x1b80, 0x44802c27, + 0x1b80, 0x47302c35, + 0x1b80, 0x47302c37, + 0x1b80, 0x00062c45, + 0x1b80, 0x00062c47, + 0x1b80, 0x776c2c55, + 0x1b80, 0x776c2c57, + 0x1b80, 0x00012c65, + 0x1b80, 0x00012c67, + 0x1b80, 0x00052c75, + 0x1b80, 0x00052c77, + 0x1b80, 0x5c802c85, + 0x1b80, 0x5c802c87, + 0x1b80, 0x5f302c95, + 0x1b80, 0x5f302c97, + 0x1b80, 0x00062ca5, + 0x1b80, 0x00062ca7, + 0x1b80, 0x776d2cb5, + 0x1b80, 0x776d2cb7, + 0x1b80, 0x00012cc5, + 0x1b80, 0x00012cc7, + 0x1b80, 0xb9002cd5, + 0x1b80, 0xb9002cd7, + 0x1b80, 0x99002ce5, + 0x1b80, 0x99002ce7, + 0x1b80, 0x00062cf5, + 0x1b80, 0x00062cf7, + 0x1b80, 0x77002d05, + 0x1b80, 0x77002d07, + 0x1b80, 0x98052d15, + 0x1b80, 0x98052d17, + 0x1b80, 0x00042d25, + 0x1b80, 0x00042d27, + 0x1b80, 0x40082d35, + 0x1b80, 0x40082d37, + 0x1b80, 0x4a022d45, + 0x1b80, 0x4a022d47, + 0x1b80, 0x30192d55, + 0x1b80, 0x30192d57, + 0x1b80, 0x00012d65, + 0x1b80, 0x00012d67, + 0x1b80, 0x7b482d75, + 0x1b80, 0x7b482d77, + 0x1b80, 0x7a902d85, + 0x1b80, 0x7a902d87, + 0x1b80, 0x79002d95, + 0x1b80, 0x79002d97, + 0x1b80, 0x55032da5, + 0x1b80, 0x55032da7, + 0x1b80, 0x32e32db5, + 0x1b80, 0x32e32db7, + 0x1b80, 0x7b382dc5, + 0x1b80, 0x7b382dc7, + 0x1b80, 0x7a802dd5, + 0x1b80, 0x7a802dd7, + 0x1b80, 0x550b2de5, + 0x1b80, 0x550b2de7, + 0x1b80, 0x32e32df5, + 0x1b80, 0x32e32df7, + 0x1b80, 0x7b402e05, + 0x1b80, 0x7b402e07, + 0x1b80, 0x7a002e15, + 0x1b80, 0x7a002e17, + 0x1b80, 0x55132e25, + 0x1b80, 0x55132e27, + 0x1b80, 0x74012e35, + 0x1b80, 0x74012e37, + 0x1b80, 0x74002e45, + 0x1b80, 0x74002e47, + 0x1b80, 0x8e002e55, + 0x1b80, 0x8e002e57, + 0x1b80, 0x00012e65, + 0x1b80, 0x00012e67, + 0x1b80, 0x57022e75, + 0x1b80, 0x57022e77, + 0x1b80, 0x57002e85, + 0x1b80, 0x57002e87, + 0x1b80, 0x97002e95, + 0x1b80, 0x97002e97, + 0x1b80, 0x00012ea5, + 0x1b80, 0x00012ea7, + 0x1b80, 0x4f782eb5, + 0x1b80, 0x4f782eb7, + 0x1b80, 0x53882ec5, + 0x1b80, 0x53882ec7, + 0x1b80, 0xe2f72ed5, + 0x1b80, 0xe2f72ed7, + 0x1b80, 0x54802ee5, + 0x1b80, 0x54802ee7, + 0x1b80, 0x54002ef5, + 0x1b80, 0x54002ef7, + 0x1b80, 0x54812f05, + 0x1b80, 0x54812f07, + 0x1b80, 0x54002f15, + 0x1b80, 0x54002f17, + 0x1b80, 0x54822f25, + 0x1b80, 0x54822f27, + 0x1b80, 0x54002f35, + 0x1b80, 0x54002f37, + 0x1b80, 0xe3022f45, + 0x1b80, 0xe3022f47, + 0x1b80, 0xbf1d2f55, + 0x1b80, 0xbf1d2f57, + 0x1b80, 0x30192f65, + 0x1b80, 0x30192f67, + 0x1b80, 0xe2d72f75, + 0x1b80, 0xe2d72f77, + 0x1b80, 0xe2dc2f85, + 0x1b80, 0xe2dc2f87, + 0x1b80, 0xe2e02f95, + 0x1b80, 0xe2e02f97, + 0x1b80, 0xe2e72fa5, + 0x1b80, 0xe2e72fa7, + 0x1b80, 0xe3412fb5, + 0x1b80, 0xe3412fb7, + 0x1b80, 0x55132fc5, + 0x1b80, 0x55132fc7, + 0x1b80, 0xe2e32fd5, + 0x1b80, 0xe2e32fd7, + 0x1b80, 0x55152fe5, + 0x1b80, 0x55152fe7, + 0x1b80, 0xe2e72ff5, + 0x1b80, 0xe2e72ff7, + 0x1b80, 0xe3413005, + 0x1b80, 0xe3413007, + 0x1b80, 0x00013015, + 0x1b80, 0x00013017, + 0x1b80, 0x54bf3025, + 0x1b80, 0x54bf3027, + 0x1b80, 0x54c03035, + 0x1b80, 0x54c03037, + 0x1b80, 0x54a33045, + 0x1b80, 0x54a33047, + 0x1b80, 0x54c13055, + 0x1b80, 0x54c13057, + 0x1b80, 0x54a43065, + 0x1b80, 0x54a43067, + 0x1b80, 0x4c183075, + 0x1b80, 0x4c183077, + 0x1b80, 0xbf073085, + 0x1b80, 0xbf073087, + 0x1b80, 0x54c23095, + 0x1b80, 0x54c23097, + 0x1b80, 0x54a430a5, + 0x1b80, 0x54a430a7, + 0x1b80, 0xbf0430b5, + 0x1b80, 0xbf0430b7, + 0x1b80, 0x54c130c5, + 0x1b80, 0x54c130c7, + 0x1b80, 0x54a330d5, + 0x1b80, 0x54a330d7, + 0x1b80, 0xbf0130e5, + 0x1b80, 0xbf0130e7, + 0x1b80, 0xe34f30f5, + 0x1b80, 0xe34f30f7, + 0x1b80, 0x54df3105, + 0x1b80, 0x54df3107, + 0x1b80, 0x00013115, + 0x1b80, 0x00013117, + 0x1b80, 0x54bf3125, + 0x1b80, 0x54bf3127, + 0x1b80, 0x54e53135, + 0x1b80, 0x54e53137, + 0x1b80, 0x050a3145, + 0x1b80, 0x050a3147, + 0x1b80, 0x54df3155, + 0x1b80, 0x54df3157, + 0x1b80, 0x00013165, + 0x1b80, 0x00013167, + 0x1b80, 0x7f403175, + 0x1b80, 0x7f403177, + 0x1b80, 0x7e003185, + 0x1b80, 0x7e003187, + 0x1b80, 0x7d003195, + 0x1b80, 0x7d003197, + 0x1b80, 0x550131a5, + 0x1b80, 0x550131a7, + 0x1b80, 0x5c3131b5, + 0x1b80, 0x5c3131b7, + 0x1b80, 0xe2e331c5, + 0x1b80, 0xe2e331c7, + 0x1b80, 0xe2e731d5, + 0x1b80, 0xe2e731d7, + 0x1b80, 0x548031e5, + 0x1b80, 0x548031e7, + 0x1b80, 0x540031f5, + 0x1b80, 0x540031f7, + 0x1b80, 0x54813205, + 0x1b80, 0x54813207, + 0x1b80, 0x54003215, + 0x1b80, 0x54003217, + 0x1b80, 0x54823225, + 0x1b80, 0x54823227, + 0x1b80, 0x54003235, + 0x1b80, 0x54003237, + 0x1b80, 0xe3023245, + 0x1b80, 0xe3023247, + 0x1b80, 0xbfed3255, + 0x1b80, 0xbfed3257, + 0x1b80, 0x30193265, + 0x1b80, 0x30193267, + 0x1b80, 0x74023275, + 0x1b80, 0x74023277, + 0x1b80, 0x003f3285, + 0x1b80, 0x003f3287, + 0x1b80, 0x74003295, + 0x1b80, 0x74003297, + 0x1b80, 0x000232a5, + 0x1b80, 0x000232a7, + 0x1b80, 0x000132b5, + 0x1b80, 0x000132b7, + 0x1b80, 0x000632c5, + 0x1b80, 0x000632c7, + 0x1b80, 0x5a8032d5, + 0x1b80, 0x5a8032d7, + 0x1b80, 0x5a0032e5, + 0x1b80, 0x5a0032e7, + 0x1b80, 0x920032f5, + 0x1b80, 0x920032f7, + 0x1b80, 0x00013305, + 0x1b80, 0x00013307, + 0x1b80, 0x5b8f3315, + 0x1b80, 0x5b8f3317, + 0x1b80, 0x5b0f3325, + 0x1b80, 0x5b0f3327, + 0x1b80, 0x91003335, + 0x1b80, 0x91003337, + 0x1b80, 0x00013345, + 0x1b80, 0x00013347, + 0x1b80, 0x00063355, + 0x1b80, 0x00063357, + 0x1b80, 0x5d803365, + 0x1b80, 0x5d803367, + 0x1b80, 0x5e563375, + 0x1b80, 0x5e563377, + 0x1b80, 0x00043385, + 0x1b80, 0x00043387, + 0x1b80, 0x4d083395, + 0x1b80, 0x4d083397, + 0x1b80, 0x571033a5, + 0x1b80, 0x571033a7, + 0x1b80, 0x570033b5, + 0x1b80, 0x570033b7, + 0x1b80, 0x4d0033c5, + 0x1b80, 0x4d0033c7, + 0x1b80, 0x000633d5, + 0x1b80, 0x000633d7, + 0x1b80, 0x5d0033e5, + 0x1b80, 0x5d0033e7, + 0x1b80, 0x000433f5, + 0x1b80, 0x000433f7, + 0x1b80, 0x00013405, + 0x1b80, 0x00013407, + 0x1b80, 0x549f3415, + 0x1b80, 0x549f3417, + 0x1b80, 0x54ff3425, + 0x1b80, 0x54ff3427, + 0x1b80, 0x54003435, + 0x1b80, 0x54003437, + 0x1b80, 0x00013445, + 0x1b80, 0x00013447, + 0x1b80, 0x5c313455, + 0x1b80, 0x5c313457, + 0x1b80, 0x07143465, + 0x1b80, 0x07143467, + 0x1b80, 0x54003475, + 0x1b80, 0x54003477, + 0x1b80, 0x5c323485, + 0x1b80, 0x5c323487, + 0x1b80, 0x00013495, + 0x1b80, 0x00013497, + 0x1b80, 0x5c3234a5, + 0x1b80, 0x5c3234a7, + 0x1b80, 0x071434b5, + 0x1b80, 0x071434b7, + 0x1b80, 0x540034c5, + 0x1b80, 0x540034c7, + 0x1b80, 0x5c3134d5, + 0x1b80, 0x5c3134d7, + 0x1b80, 0x000134e5, + 0x1b80, 0x000134e7, + 0x1b80, 0x4c9834f5, + 0x1b80, 0x4c9834f7, + 0x1b80, 0x4c183505, + 0x1b80, 0x4c183507, + 0x1b80, 0x00013515, + 0x1b80, 0x00013517, + 0x1b80, 0x5c323525, + 0x1b80, 0x5c323527, + 0x1b80, 0x62043535, + 0x1b80, 0x62043537, + 0x1b80, 0x63033545, + 0x1b80, 0x63033547, + 0x1b80, 0x66073555, + 0x1b80, 0x66073557, + 0x1b80, 0x7b403565, + 0x1b80, 0x7b403567, + 0x1b80, 0x7a003575, + 0x1b80, 0x7a003577, + 0x1b80, 0x79003585, + 0x1b80, 0x79003587, + 0x1b80, 0x7f403595, + 0x1b80, 0x7f403597, + 0x1b80, 0x7e0035a5, + 0x1b80, 0x7e0035a7, + 0x1b80, 0x7d0035b5, + 0x1b80, 0x7d0035b7, + 0x1b80, 0x090135c5, + 0x1b80, 0x090135c7, + 0x1b80, 0x0c0135d5, + 0x1b80, 0x0c0135d7, + 0x1b80, 0x0ba635e5, + 0x1b80, 0x0ba635e7, + 0x1b80, 0x000135f5, + 0x1b80, 0x000135f7, + 0x1b80, 0x00000006, + 0x1b80, 0x00000002, +}; + +RTW_DECL_TABLE_PHY_COND(rtw8822c_array_mp_cal_init, rtw_phy_cfg_bb); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c_table.h b/drivers/net/wireless/realtek/rtw88/rtw8822c_table.h new file mode 100644 index 000000000000..06e207dd8e5f --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c_table.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW8822C_TABLE_H__ +#define __RTW8822C_TABLE_H__ + +extern const struct rtw_table rtw8822c_mac_tbl; +extern const struct rtw_table rtw8822c_agc_tbl; +extern const struct rtw_table rtw8822c_bb_tbl; +extern const struct rtw_table rtw8822c_bb_pg_type0_tbl; +extern const struct rtw_table rtw8822c_rf_a_tbl; +extern const struct rtw_table rtw8822c_rf_b_tbl; +extern const struct rtw_table rtw8822c_txpwr_lmt_type0_tbl; +extern const struct rtw_table rtw8822c_array_mp_cal_init_tbl; + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/rx.c b/drivers/net/wireless/realtek/rtw88/rx.c new file mode 100644 index 000000000000..4d837f0c6d5f --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/rx.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "rx.h" +#include "ps.h" + +void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr; + struct rtw_vif *rtwvif; + + hdr = (struct ieee80211_hdr *)skb->data; + + if (!ieee80211_is_data(hdr->frame_control)) + return; + + if (!is_broadcast_ether_addr(hdr->addr1) && + !is_multicast_ether_addr(hdr->addr1)) { + rtwdev->stats.rx_unicast += skb->len; + rtwdev->stats.rx_cnt++; + if (vif) { + rtwvif = (struct rtw_vif *)vif->drv_priv; + rtwvif->stats.rx_unicast += skb->len; + rtwvif->stats.rx_cnt++; + if (rtwvif->stats.rx_cnt > RTW_LPS_THRESHOLD) + rtw_leave_lps_irqsafe(rtwdev, rtwvif); + } + } +} +EXPORT_SYMBOL(rtw_rx_stats); + +struct rtw_rx_addr_match_data { + struct rtw_dev *rtwdev; + struct ieee80211_hdr *hdr; + struct rtw_rx_pkt_stat *pkt_stat; + u8 *bssid; +}; + +static void rtw_rx_addr_match_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct rtw_rx_addr_match_data *iter_data = data; + struct ieee80211_sta *sta; + struct ieee80211_hdr *hdr = iter_data->hdr; + struct rtw_dev *rtwdev = iter_data->rtwdev; + struct rtw_sta_info *si; + struct rtw_rx_pkt_stat *pkt_stat = iter_data->pkt_stat; + u8 *bssid = iter_data->bssid; + + if (ether_addr_equal(vif->bss_conf.bssid, bssid) && + (ether_addr_equal(vif->addr, hdr->addr1) || + ieee80211_is_beacon(hdr->frame_control))) + sta = ieee80211_find_sta_by_ifaddr(rtwdev->hw, hdr->addr2, + vif->addr); + else + return; + + if (!sta) + return; + + si = (struct rtw_sta_info *)sta->drv_priv; + ewma_rssi_add(&si->avg_rssi, pkt_stat->rssi); +} + +static void rtw_rx_addr_match(struct rtw_dev *rtwdev, + struct rtw_rx_pkt_stat *pkt_stat, + struct ieee80211_hdr *hdr) +{ + struct rtw_rx_addr_match_data data = {}; + + if (pkt_stat->crc_err || pkt_stat->icv_err || !pkt_stat->phy_status || + ieee80211_is_ctl(hdr->frame_control)) + return; + + data.rtwdev = rtwdev; + data.hdr = hdr; + data.pkt_stat = pkt_stat; + data.bssid = get_hdr_bssid(hdr); + + rtw_iterate_vifs_atomic(rtwdev, rtw_rx_addr_match_iter, &data); +} + +void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, + struct rtw_rx_pkt_stat *pkt_stat, + struct ieee80211_hdr *hdr, + struct ieee80211_rx_status *rx_status, + u8 *phy_status) +{ + struct ieee80211_hw *hw = rtwdev->hw; + + memset(rx_status, 0, sizeof(*rx_status)); + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; + if (pkt_stat->crc_err) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + if (pkt_stat->decrypted) + rx_status->flag |= RX_FLAG_DECRYPTED; + + if (pkt_stat->rate >= DESC_RATEVHT1SS_MCS0) + rx_status->encoding = RX_ENC_VHT; + else if (pkt_stat->rate >= DESC_RATEMCS0) + rx_status->encoding = RX_ENC_HT; + + if (pkt_stat->rate >= DESC_RATEVHT1SS_MCS0 && + pkt_stat->rate <= DESC_RATEVHT1SS_MCS9) { + rx_status->nss = 1; + rx_status->rate_idx = pkt_stat->rate - DESC_RATEVHT1SS_MCS0; + } else if (pkt_stat->rate >= DESC_RATEVHT2SS_MCS0 && + pkt_stat->rate <= DESC_RATEVHT2SS_MCS9) { + rx_status->nss = 2; + rx_status->rate_idx = pkt_stat->rate - DESC_RATEVHT2SS_MCS0; + } else if (pkt_stat->rate >= DESC_RATEVHT3SS_MCS0 && + pkt_stat->rate <= DESC_RATEVHT3SS_MCS9) { + rx_status->nss = 3; + rx_status->rate_idx = pkt_stat->rate - DESC_RATEVHT3SS_MCS0; + } else if (pkt_stat->rate >= DESC_RATEVHT4SS_MCS0 && + pkt_stat->rate <= DESC_RATEVHT4SS_MCS9) { + rx_status->nss = 4; + rx_status->rate_idx = pkt_stat->rate - DESC_RATEVHT4SS_MCS0; + } else if (pkt_stat->rate >= DESC_RATEMCS0 && + pkt_stat->rate <= DESC_RATEMCS15) { + rx_status->rate_idx = pkt_stat->rate - DESC_RATEMCS0; + } else if (rx_status->band == NL80211_BAND_5GHZ && + pkt_stat->rate >= DESC_RATE6M && + pkt_stat->rate <= DESC_RATE54M) { + rx_status->rate_idx = pkt_stat->rate - DESC_RATE6M; + } else if (rx_status->band == NL80211_BAND_2GHZ && + pkt_stat->rate >= DESC_RATE1M && + pkt_stat->rate <= DESC_RATE54M) { + rx_status->rate_idx = pkt_stat->rate - DESC_RATE1M; + } else { + rx_status->rate_idx = 0; + } + + rx_status->flag |= RX_FLAG_MACTIME_START; + rx_status->mactime = pkt_stat->tsf_low; + + if (pkt_stat->bw == RTW_CHANNEL_WIDTH_80) + rx_status->bw = RATE_INFO_BW_80; + else if (pkt_stat->bw == RTW_CHANNEL_WIDTH_40) + rx_status->bw = RATE_INFO_BW_40; + else + rx_status->bw = RATE_INFO_BW_20; + + rx_status->signal = pkt_stat->signal_power; + + rtw_rx_addr_match(rtwdev, pkt_stat, hdr); +} diff --git a/drivers/net/wireless/realtek/rtw88/rx.h b/drivers/net/wireless/realtek/rtw88/rx.h new file mode 100644 index 000000000000..383f3b2babc1 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/rx.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW_RX_H_ +#define __RTW_RX_H_ + +#define GET_RX_DESC_PHYST(rxdesc) \ + le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(26)) +#define GET_RX_DESC_ICV_ERR(rxdesc) \ + le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(15)) +#define GET_RX_DESC_CRC32(rxdesc) \ + le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(14)) +#define GET_RX_DESC_SWDEC(rxdesc) \ + le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(27)) +#define GET_RX_DESC_C2H(rxdesc) \ + le32_get_bits(*((__le32 *)(rxdesc) + 0x02), BIT(28)) +#define GET_RX_DESC_PKT_LEN(rxdesc) \ + le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(13, 0)) +#define GET_RX_DESC_DRV_INFO_SIZE(rxdesc) \ + le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(19, 16)) +#define GET_RX_DESC_SHIFT(rxdesc) \ + le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(25, 24)) +#define GET_RX_DESC_RX_RATE(rxdesc) \ + le32_get_bits(*((__le32 *)(rxdesc) + 0x03), GENMASK(6, 0)) +#define GET_RX_DESC_MACID(rxdesc) \ + le32_get_bits(*((__le32 *)(rxdesc) + 0x01), GENMASK(6, 0)) +#define GET_RX_DESC_PPDU_CNT(rxdesc) \ + le32_get_bits(*((__le32 *)(rxdesc) + 0x02), GENMASK(30, 29)) +#define GET_RX_DESC_TSFL(rxdesc) \ + le32_get_bits(*((__le32 *)(rxdesc) + 0x05), GENMASK(31, 0)) + +void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + struct sk_buff *skb); +void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, + struct rtw_rx_pkt_stat *pkt_stat, + struct ieee80211_hdr *hdr, + struct ieee80211_rx_status *rx_status, + u8 *phy_status); + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/sec.c b/drivers/net/wireless/realtek/rtw88/sec.c new file mode 100644 index 000000000000..c594fc02804d --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/sec.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "sec.h" +#include "reg.h" + +int rtw_sec_get_free_cam(struct rtw_sec_desc *sec) +{ + /* if default key search is enabled, the first 4 cam entries + * are used to direct map to group key with its key->key_idx, so + * driver should use cam entries after 4 to install pairwise key + */ + if (sec->default_key_search) + return find_next_zero_bit(sec->cam_map, RTW_MAX_SEC_CAM_NUM, + RTW_SEC_DEFAULT_KEY_NUM); + + return find_first_zero_bit(sec->cam_map, RTW_MAX_SEC_CAM_NUM); +} + +void rtw_sec_write_cam(struct rtw_dev *rtwdev, + struct rtw_sec_desc *sec, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, + u8 hw_key_type, u8 hw_key_idx) +{ + struct rtw_cam_entry *cam = &sec->cam_table[hw_key_idx]; + u32 write_cmd; + u32 command; + u32 content; + u32 addr; + int i, j; + + set_bit(hw_key_idx, sec->cam_map); + cam->valid = true; + cam->group = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE); + cam->hw_key_type = hw_key_type; + cam->key = key; + if (sta) + ether_addr_copy(cam->addr, sta->addr); + else + eth_broadcast_addr(cam->addr); + + write_cmd = RTW_SEC_CMD_WRITE_ENABLE | RTW_SEC_CMD_POLLING; + addr = hw_key_idx << RTW_SEC_CAM_ENTRY_SHIFT; + for (i = 5; i >= 0; i--) { + switch (i) { + case 0: + content = ((key->keyidx & 0x3)) | + ((hw_key_type & 0x7) << 2) | + (cam->group << 6) | + (cam->valid << 15) | + (cam->addr[0] << 16) | + (cam->addr[1] << 24); + break; + case 1: + content = (cam->addr[2]) | + (cam->addr[3] << 8) | + (cam->addr[4] << 16) | + (cam->addr[5] << 24); + break; + default: + j = (i - 2) << 2; + content = (key->key[j]) | + (key->key[j + 1] << 8) | + (key->key[j + 2] << 16) | + (key->key[j + 3] << 24); + break; + } + + command = write_cmd | (addr + i); + rtw_write32(rtwdev, RTW_SEC_WRITE_REG, content); + rtw_write32(rtwdev, RTW_SEC_CMD_REG, command); + } +} + +void rtw_sec_clear_cam(struct rtw_dev *rtwdev, + struct rtw_sec_desc *sec, + u8 hw_key_idx) +{ + struct rtw_cam_entry *cam = &sec->cam_table[hw_key_idx]; + u32 write_cmd; + u32 command; + u32 addr; + + clear_bit(hw_key_idx, sec->cam_map); + cam->valid = false; + cam->key = NULL; + eth_zero_addr(cam->addr); + + write_cmd = RTW_SEC_CMD_WRITE_ENABLE | RTW_SEC_CMD_POLLING; + addr = hw_key_idx << RTW_SEC_CAM_ENTRY_SHIFT; + command = write_cmd | addr; + rtw_write32(rtwdev, RTW_SEC_WRITE_REG, 0); + rtw_write32(rtwdev, RTW_SEC_CMD_REG, command); +} + +void rtw_sec_enable_sec_engine(struct rtw_dev *rtwdev) +{ + struct rtw_sec_desc *sec = &rtwdev->sec; + u16 ctrl_reg; + u16 sec_config; + + /* default use default key search for now */ + sec->default_key_search = true; + + ctrl_reg = rtw_read16(rtwdev, REG_CR); + ctrl_reg |= RTW_SEC_ENGINE_EN; + rtw_write16(rtwdev, REG_CR, ctrl_reg); + + sec_config = rtw_read16(rtwdev, RTW_SEC_CONFIG); + + sec_config |= RTW_SEC_TX_DEC_EN | RTW_SEC_RX_DEC_EN; + if (sec->default_key_search) + sec_config |= RTW_SEC_TX_UNI_USE_DK | RTW_SEC_RX_UNI_USE_DK | + RTW_SEC_TX_BC_USE_DK | RTW_SEC_RX_BC_USE_DK; + + rtw_write16(rtwdev, RTW_SEC_CONFIG, sec_config); +} diff --git a/drivers/net/wireless/realtek/rtw88/sec.h b/drivers/net/wireless/realtek/rtw88/sec.h new file mode 100644 index 000000000000..8c50a895c797 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/sec.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW_SEC_H_ +#define __RTW_SEC_H_ + +#define RTW_SEC_CMD_REG 0x670 +#define RTW_SEC_WRITE_REG 0x674 +#define RTW_SEC_READ_REG 0x678 +#define RTW_SEC_CONFIG 0x680 + +#define RTW_SEC_CAM_ENTRY_SHIFT 3 +#define RTW_SEC_DEFAULT_KEY_NUM 4 +#define RTW_SEC_CMD_WRITE_ENABLE BIT(16) +#define RTW_SEC_CMD_CLEAR BIT(30) +#define RTW_SEC_CMD_POLLING BIT(31) + +#define RTW_SEC_TX_UNI_USE_DK BIT(0) +#define RTW_SEC_RX_UNI_USE_DK BIT(1) +#define RTW_SEC_TX_DEC_EN BIT(2) +#define RTW_SEC_RX_DEC_EN BIT(3) +#define RTW_SEC_TX_BC_USE_DK BIT(6) +#define RTW_SEC_RX_BC_USE_DK BIT(7) + +#define RTW_SEC_ENGINE_EN BIT(9) + +int rtw_sec_get_free_cam(struct rtw_sec_desc *sec); +void rtw_sec_write_cam(struct rtw_dev *rtwdev, + struct rtw_sec_desc *sec, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, + u8 hw_key_type, u8 hw_key_idx); +void rtw_sec_clear_cam(struct rtw_dev *rtwdev, + struct rtw_sec_desc *sec, + u8 hw_key_idx); +void rtw_sec_enable_sec_engine(struct rtw_dev *rtwdev); + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c new file mode 100644 index 000000000000..e32faf8bead9 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/tx.c @@ -0,0 +1,367 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "tx.h" +#include "fw.h" +#include "ps.h" + +static +void rtw_tx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr; + struct rtw_vif *rtwvif; + + hdr = (struct ieee80211_hdr *)skb->data; + + if (!ieee80211_is_data(hdr->frame_control)) + return; + + if (!is_broadcast_ether_addr(hdr->addr1) && + !is_multicast_ether_addr(hdr->addr1)) { + rtwdev->stats.tx_unicast += skb->len; + rtwdev->stats.tx_cnt++; + if (vif) { + rtwvif = (struct rtw_vif *)vif->drv_priv; + rtwvif->stats.tx_unicast += skb->len; + rtwvif->stats.tx_cnt++; + if (rtwvif->stats.tx_cnt > RTW_LPS_THRESHOLD) + rtw_leave_lps_irqsafe(rtwdev, rtwvif); + } + } +} + +void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb) +{ + __le32 *txdesc = (__le32 *)skb->data; + + SET_TX_DESC_TXPKTSIZE(txdesc, pkt_info->tx_pkt_size); + SET_TX_DESC_OFFSET(txdesc, pkt_info->offset); + SET_TX_DESC_PKT_OFFSET(txdesc, pkt_info->pkt_offset); + SET_TX_DESC_QSEL(txdesc, pkt_info->qsel); + SET_TX_DESC_BMC(txdesc, pkt_info->bmc); + SET_TX_DESC_RATE_ID(txdesc, pkt_info->rate_id); + SET_TX_DESC_DATARATE(txdesc, pkt_info->rate); + SET_TX_DESC_DISDATAFB(txdesc, pkt_info->dis_rate_fallback); + SET_TX_DESC_USE_RATE(txdesc, pkt_info->use_rate); + SET_TX_DESC_SEC_TYPE(txdesc, pkt_info->sec_type); + SET_TX_DESC_DATA_BW(txdesc, pkt_info->bw); + SET_TX_DESC_SW_SEQ(txdesc, pkt_info->seq); + SET_TX_DESC_MAX_AGG_NUM(txdesc, pkt_info->ampdu_factor); + SET_TX_DESC_AMPDU_DENSITY(txdesc, pkt_info->ampdu_density); + SET_TX_DESC_DATA_STBC(txdesc, pkt_info->stbc); + SET_TX_DESC_DATA_LDPC(txdesc, pkt_info->ldpc); + SET_TX_DESC_AGG_EN(txdesc, pkt_info->ampdu_en); + SET_TX_DESC_LS(txdesc, pkt_info->ls); + SET_TX_DESC_DATA_SHORT(txdesc, pkt_info->short_gi); + SET_TX_DESC_SPE_RPT(txdesc, pkt_info->report); + SET_TX_DESC_SW_DEFINE(txdesc, pkt_info->sn); +} +EXPORT_SYMBOL(rtw_tx_fill_tx_desc); + +static u8 get_tx_ampdu_factor(struct ieee80211_sta *sta) +{ + u8 exp = sta->ht_cap.ampdu_factor; + + /* the least ampdu factor is 8K, and the value in the tx desc is the + * max aggregation num, which represents val * 2 packets can be + * aggregated in an AMPDU, so here we should use 8/2=4 as the base + */ + return (BIT(2) << exp) - 1; +} + +static u8 get_tx_ampdu_density(struct ieee80211_sta *sta) +{ + return sta->ht_cap.ampdu_density; +} + +static u8 get_highest_ht_tx_rate(struct rtw_dev *rtwdev, + struct ieee80211_sta *sta) +{ + u8 rate; + + if (rtwdev->hal.rf_type == RF_2T2R && sta->ht_cap.mcs.rx_mask[1] != 0) + rate = DESC_RATEMCS15; + else + rate = DESC_RATEMCS7; + + return rate; +} + +static u8 get_highest_vht_tx_rate(struct rtw_dev *rtwdev, + struct ieee80211_sta *sta) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + u8 rate; + u16 tx_mcs_map; + + tx_mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.tx_mcs_map); + if (efuse->hw_cap.nss == 1) { + switch (tx_mcs_map & 0x3) { + case IEEE80211_VHT_MCS_SUPPORT_0_7: + rate = DESC_RATEVHT1SS_MCS7; + break; + case IEEE80211_VHT_MCS_SUPPORT_0_8: + rate = DESC_RATEVHT1SS_MCS8; + break; + default: + case IEEE80211_VHT_MCS_SUPPORT_0_9: + rate = DESC_RATEVHT1SS_MCS9; + break; + } + } else if (efuse->hw_cap.nss >= 2) { + switch ((tx_mcs_map & 0xc) >> 2) { + case IEEE80211_VHT_MCS_SUPPORT_0_7: + rate = DESC_RATEVHT2SS_MCS7; + break; + case IEEE80211_VHT_MCS_SUPPORT_0_8: + rate = DESC_RATEVHT2SS_MCS8; + break; + default: + case IEEE80211_VHT_MCS_SUPPORT_0_9: + rate = DESC_RATEVHT2SS_MCS9; + break; + } + } else { + rate = DESC_RATEVHT1SS_MCS9; + } + + return rate; +} + +static void rtw_tx_report_enable(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info) +{ + struct rtw_tx_report *tx_report = &rtwdev->tx_report; + + /* [11:8], reserved, fills with zero + * [7:2], tx report sequence number + * [1:0], firmware use, fills with zero + */ + pkt_info->sn = (atomic_inc_return(&tx_report->sn) << 2) & 0xfc; + pkt_info->report = true; +} + +void rtw_tx_report_purge_timer(struct timer_list *t) +{ + struct rtw_dev *rtwdev = from_timer(rtwdev, t, tx_report.purge_timer); + struct rtw_tx_report *tx_report = &rtwdev->tx_report; + unsigned long flags; + + if (skb_queue_len(&tx_report->queue) == 0) + return; + + WARN(1, "purge skb(s) not reported by firmware\n"); + + spin_lock_irqsave(&tx_report->q_lock, flags); + skb_queue_purge(&tx_report->queue); + spin_unlock_irqrestore(&tx_report->q_lock, flags); +} + +void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn) +{ + struct rtw_tx_report *tx_report = &rtwdev->tx_report; + unsigned long flags; + u8 *drv_data; + + /* pass sn to tx report handler through driver data */ + drv_data = (u8 *)IEEE80211_SKB_CB(skb)->status.status_driver_data; + *drv_data = sn; + + spin_lock_irqsave(&tx_report->q_lock, flags); + __skb_queue_tail(&tx_report->queue, skb); + spin_unlock_irqrestore(&tx_report->q_lock, flags); + + mod_timer(&tx_report->purge_timer, jiffies + RTW_TX_PROBE_TIMEOUT); +} +EXPORT_SYMBOL(rtw_tx_report_enqueue); + +static void rtw_tx_report_tx_status(struct rtw_dev *rtwdev, + struct sk_buff *skb, bool acked) +{ + struct ieee80211_tx_info *info; + + info = IEEE80211_SKB_CB(skb); + ieee80211_tx_info_clear_status(info); + if (acked) + info->flags |= IEEE80211_TX_STAT_ACK; + else + info->flags &= ~IEEE80211_TX_STAT_ACK; + + ieee80211_tx_status_irqsafe(rtwdev->hw, skb); +} + +void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) +{ + struct rtw_tx_report *tx_report = &rtwdev->tx_report; + struct rtw_c2h_cmd *c2h; + struct sk_buff *cur, *tmp; + unsigned long flags; + u8 sn, st; + u8 *n; + + c2h = get_c2h_from_skb(skb); + + sn = GET_CCX_REPORT_SEQNUM(c2h->payload); + st = GET_CCX_REPORT_STATUS(c2h->payload); + + spin_lock_irqsave(&tx_report->q_lock, flags); + skb_queue_walk_safe(&tx_report->queue, cur, tmp) { + n = (u8 *)IEEE80211_SKB_CB(cur)->status.status_driver_data; + if (*n == sn) { + __skb_unlink(cur, &tx_report->queue); + rtw_tx_report_tx_status(rtwdev, cur, st == 0); + break; + } + } + spin_unlock_irqrestore(&tx_report->q_lock, flags); +} + +static void rtw_tx_mgmt_pkt_info_update(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + pkt_info->use_rate = true; + pkt_info->rate_id = 6; + pkt_info->dis_rate_fallback = true; +} + +static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct ieee80211_sta *sta = control->sta; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct rtw_sta_info *si; + u16 seq; + u8 ampdu_factor = 0; + u8 ampdu_density = 0; + bool ampdu_en = false; + u8 rate = DESC_RATE6M; + u8 rate_id = 6; + u8 bw = RTW_CHANNEL_WIDTH_20; + bool stbc = false; + bool ldpc = false; + + seq = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; + + /* for broadcast/multicast, use default values */ + if (!sta) + goto out; + + if (info->flags & IEEE80211_TX_CTL_AMPDU) { + ampdu_en = true; + ampdu_factor = get_tx_ampdu_factor(sta); + ampdu_density = get_tx_ampdu_density(sta); + } + + if (sta->vht_cap.vht_supported) + rate = get_highest_vht_tx_rate(rtwdev, sta); + else if (sta->ht_cap.ht_supported) + rate = get_highest_ht_tx_rate(rtwdev, sta); + else if (sta->supp_rates[0] <= 0xf) + rate = DESC_RATE11M; + else + rate = DESC_RATE54M; + + si = (struct rtw_sta_info *)sta->drv_priv; + + bw = si->bw_mode; + rate_id = si->rate_id; + stbc = si->stbc_en; + ldpc = si->ldpc_en; + +out: + pkt_info->seq = seq; + pkt_info->ampdu_factor = ampdu_factor; + pkt_info->ampdu_density = ampdu_density; + pkt_info->ampdu_en = ampdu_en; + pkt_info->rate = rate; + pkt_info->rate_id = rate_id; + pkt_info->bw = bw; + pkt_info->stbc = stbc; + pkt_info->ldpc = ldpc; +} + +void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct rtw_sta_info *si; + struct ieee80211_vif *vif = NULL; + __le16 fc = hdr->frame_control; + u8 sec_type = 0; + bool bmc; + + if (control->sta) { + si = (struct rtw_sta_info *)control->sta->drv_priv; + vif = si->vif; + } + + if (ieee80211_is_mgmt(fc) || ieee80211_is_nullfunc(fc)) + rtw_tx_mgmt_pkt_info_update(rtwdev, pkt_info, control, skb); + else if (ieee80211_is_data(fc)) + rtw_tx_data_pkt_info_update(rtwdev, pkt_info, control, skb); + + if (info->control.hw_key) { + struct ieee80211_key_conf *key = info->control.hw_key; + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + sec_type = 0x01; + break; + case WLAN_CIPHER_SUITE_CCMP: + sec_type = 0x03; + break; + default: + break; + } + } + + bmc = is_broadcast_ether_addr(hdr->addr1) || + is_multicast_ether_addr(hdr->addr1); + + if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) + rtw_tx_report_enable(rtwdev, pkt_info); + + pkt_info->bmc = bmc; + pkt_info->sec_type = sec_type; + pkt_info->tx_pkt_size = skb->len; + pkt_info->offset = chip->tx_pkt_desc_sz; + pkt_info->qsel = skb->priority; + pkt_info->ls = true; + + /* maybe merge with tx status ? */ + rtw_tx_stats(rtwdev, vif, skb); +} + +void rtw_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct sk_buff *skb) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + bool bmc; + + bmc = is_broadcast_ether_addr(hdr->addr1) || + is_multicast_ether_addr(hdr->addr1); + pkt_info->use_rate = true; + pkt_info->rate_id = 6; + pkt_info->dis_rate_fallback = true; + pkt_info->bmc = bmc; + pkt_info->tx_pkt_size = skb->len; + pkt_info->offset = chip->tx_pkt_desc_sz; + pkt_info->qsel = skb->priority; + pkt_info->ls = true; +} diff --git a/drivers/net/wireless/realtek/rtw88/tx.h b/drivers/net/wireless/realtek/rtw88/tx.h new file mode 100644 index 000000000000..8338dbf55576 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/tx.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW_TX_H_ +#define __RTW_TX_H_ + +#define RTK_TX_MAX_AGG_NUM_MASK 0x1f + +#define RTW_TX_PROBE_TIMEOUT msecs_to_jiffies(500) + +#define SET_TX_DESC_TXPKTSIZE(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, GENMASK(15, 0)) +#define SET_TX_DESC_OFFSET(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, GENMASK(23, 16)) +#define SET_TX_DESC_PKT_OFFSET(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(28, 24)) +#define SET_TX_DESC_QSEL(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(12, 8)) +#define SET_TX_DESC_BMC(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(24)) +#define SET_TX_DESC_RATE_ID(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(20, 16)) +#define SET_TX_DESC_DATARATE(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x04, value, GENMASK(6, 0)) +#define SET_TX_DESC_DISDATAFB(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(10)) +#define SET_TX_DESC_USE_RATE(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(8)) +#define SET_TX_DESC_SEC_TYPE(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(23, 22)) +#define SET_TX_DESC_DATA_BW(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, GENMASK(6, 5)) +#define SET_TX_DESC_SW_SEQ(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x09, value, GENMASK(23, 12)) +#define SET_TX_DESC_MAX_AGG_NUM(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, GENMASK(21, 17)) +#define SET_TX_DESC_AMPDU_DENSITY(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, GENMASK(22, 20)) +#define SET_TX_DESC_DATA_STBC(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, GENMASK(9, 8)) +#define SET_TX_DESC_DATA_LDPC(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(7)) +#define SET_TX_DESC_AGG_EN(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(12)) +#define SET_TX_DESC_LS(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(26)) +#define SET_TX_DESC_DATA_SHORT(txdesc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(4)) +#define SET_TX_DESC_SPE_RPT(tx_desc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(19)) +#define SET_TX_DESC_SW_DEFINE(tx_desc, value) \ + le32p_replace_bits((__le32 *)(txdesc) + 0x06, value, GENMASK(11, 0)) + +enum rtw_tx_desc_queue_select { + TX_DESC_QSEL_TID0 = 0, + TX_DESC_QSEL_TID1 = 1, + TX_DESC_QSEL_TID2 = 2, + TX_DESC_QSEL_TID3 = 3, + TX_DESC_QSEL_TID4 = 4, + TX_DESC_QSEL_TID5 = 5, + TX_DESC_QSEL_TID6 = 6, + TX_DESC_QSEL_TID7 = 7, + TX_DESC_QSEL_TID8 = 8, + TX_DESC_QSEL_TID9 = 9, + TX_DESC_QSEL_TID10 = 10, + TX_DESC_QSEL_TID11 = 11, + TX_DESC_QSEL_TID12 = 12, + TX_DESC_QSEL_TID13 = 13, + TX_DESC_QSEL_TID14 = 14, + TX_DESC_QSEL_TID15 = 15, + TX_DESC_QSEL_BEACON = 16, + TX_DESC_QSEL_HIGH = 17, + TX_DESC_QSEL_MGMT = 18, + TX_DESC_QSEL_H2C = 19, +}; + +void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct ieee80211_tx_control *control, + struct sk_buff *skb); +void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb); +void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn); +void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb); +void rtw_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct sk_buff *skb); + +#endif diff --git a/drivers/net/wireless/realtek/rtw88/util.c b/drivers/net/wireless/realtek/rtw88/util.c new file mode 100644 index 000000000000..212070c2baa8 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/util.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "util.h" +#include "reg.h" + +bool check_hw_ready(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target) +{ + u32 cnt; + + for (cnt = 0; cnt < 1000; cnt++) { + if (rtw_read32_mask(rtwdev, addr, mask) == target) + return true; + + udelay(10); + } + + return false; +} + +bool ltecoex_read_reg(struct rtw_dev *rtwdev, u16 offset, u32 *val) +{ + if (!check_hw_ready(rtwdev, LTECOEX_ACCESS_CTRL, LTECOEX_READY, 1)) + return false; + + rtw_write32(rtwdev, LTECOEX_ACCESS_CTRL, 0x800F0000 | offset); + *val = rtw_read32(rtwdev, LTECOEX_READ_DATA); + + return true; +} + +bool ltecoex_reg_write(struct rtw_dev *rtwdev, u16 offset, u32 value) +{ + if (!check_hw_ready(rtwdev, LTECOEX_ACCESS_CTRL, LTECOEX_READY, 1)) + return false; + + rtw_write32(rtwdev, LTECOEX_WRITE_DATA, value); + rtw_write32(rtwdev, LTECOEX_ACCESS_CTRL, 0xC00F0000 | offset); + + return true; +} + +void rtw_restore_reg(struct rtw_dev *rtwdev, + struct rtw_backup_info *bckp, u32 num) +{ + u8 len; + u32 reg; + u32 val; + int i; + + for (i = 0; i < num; i++, bckp++) { + len = bckp->len; + reg = bckp->reg; + val = bckp->val; + + switch (len) { + case 1: + rtw_write8(rtwdev, reg, (u8)val); + break; + case 2: + rtw_write16(rtwdev, reg, (u16)val); + break; + case 4: + rtw_write32(rtwdev, reg, (u32)val); + break; + default: + break; + } + } +} diff --git a/drivers/net/wireless/realtek/rtw88/util.h b/drivers/net/wireless/realtek/rtw88/util.h new file mode 100644 index 000000000000..7bd2843b0bce --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/util.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW_UTIL_H__ +#define __RTW_UTIL_H__ + +struct rtw_dev; + +#define rtw_iterate_vifs(rtwdev, iterator, data) \ + ieee80211_iterate_active_interfaces(rtwdev->hw, \ + IEEE80211_IFACE_ITER_NORMAL, iterator, data) +#define rtw_iterate_vifs_atomic(rtwdev, iterator, data) \ + ieee80211_iterate_active_interfaces_atomic(rtwdev->hw, \ + IEEE80211_IFACE_ITER_NORMAL, iterator, data) +#define rtw_iterate_stas_atomic(rtwdev, iterator, data) \ + ieee80211_iterate_stations_atomic(rtwdev->hw, iterator, data) + +static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) +{ + __le16 fc = hdr->frame_control; + u8 *bssid; + + if (ieee80211_has_tods(fc)) + bssid = hdr->addr1; + else if (ieee80211_has_fromds(fc)) + bssid = hdr->addr2; + else + bssid = hdr->addr3; + + return bssid; +} + +#endif diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 51e4e92d95a0..e07a1152cec1 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1707,7 +1707,7 @@ static struct ndis_80211_pmkid *get_device_pmkids(struct usbnet *usbdev) int len, ret, max_pmkids; max_pmkids = priv->wdev.wiphy->max_num_pmkids; - len = sizeof(*pmkids) + max_pmkids * sizeof(pmkids->bssid_info[0]); + len = struct_size(pmkids, bssid_info, max_pmkids); pmkids = kzalloc(len, GFP_KERNEL); if (!pmkids) @@ -1740,7 +1740,7 @@ static int set_device_pmkids(struct usbnet *usbdev, int ret, len, num_pmkids; num_pmkids = le32_to_cpu(pmkids->bssid_info_count); - len = sizeof(*pmkids) + num_pmkids * sizeof(pmkids->bssid_info[0]); + len = struct_size(pmkids, bssid_info, num_pmkids); pmkids->length = cpu_to_le32(len); debug_print_pmkids(usbdev, pmkids, __func__); @@ -1761,7 +1761,7 @@ static struct ndis_80211_pmkid *remove_pmkid(struct usbnet *usbdev, struct cfg80211_pmksa *pmksa, int max_pmkids) { - int i, newlen, err; + int i, err; unsigned int count; count = le32_to_cpu(pmkids->bssid_info_count); @@ -1786,9 +1786,7 @@ static struct ndis_80211_pmkid *remove_pmkid(struct usbnet *usbdev, pmkids->bssid_info[i] = pmkids->bssid_info[i + 1]; count--; - newlen = sizeof(*pmkids) + count * sizeof(pmkids->bssid_info[0]); - - pmkids->length = cpu_to_le32(newlen); + pmkids->length = cpu_to_le32(struct_size(pmkids, bssid_info, count)); pmkids->bssid_info_count = cpu_to_le32(count); return pmkids; @@ -1831,7 +1829,7 @@ static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev, } /* add new pmkid */ - newlen = sizeof(*pmkids) + (count + 1) * sizeof(pmkids->bssid_info[0]); + newlen = struct_size(pmkids, bssid_info, count + 1); new_pmkids = krealloc(pmkids, newlen, GFP_KERNEL); if (!new_pmkids) { diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c index 1dbaab2a96b7..f84250bdb8cf 100644 --- a/drivers/net/wireless/rsi/rsi_91x_hal.c +++ b/drivers/net/wireless/rsi/rsi_91x_hal.c @@ -31,6 +31,13 @@ static struct ta_metadata metadata_flash_content[] = { }; +static struct ta_metadata metadata[] = {{"pmemdata_dummy", 0x00000000}, + {"rsi/rs9116_wlan.rps", 0x00000000}, + {"rsi/rs9116_wlan_bt_classic.rps", 0x00000000}, + {"rsi/pmemdata_dummy", 0x00000000}, + {"rsi/rs9116_wlan_bt_classic.rps", 0x00000000} +}; + int rsi_send_pkt_to_bus(struct rsi_common *common, struct sk_buff *skb) { struct rsi_hw *adapter = common->priv; @@ -829,21 +836,18 @@ static int auto_fw_upgrade(struct rsi_hw *adapter, u8 *flash_content, return 0; } -static int rsi_load_firmware(struct rsi_hw *adapter) +static int rsi_hal_prepare_fwload(struct rsi_hw *adapter) { - struct rsi_common *common = adapter->priv; struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops; - const struct firmware *fw_entry = NULL; - u32 regout_val = 0, content_size; - u16 tmp_regout_val = 0; - struct ta_metadata *metadata_p; + u32 regout_val = 0; int status; bl_start_cmd_timer(adapter, BL_CMD_TIMEOUT); while (!adapter->blcmd_timer_expired) { status = hif_ops->master_reg_read(adapter, SWBL_REGOUT, - ®out_val, 2); + ®out_val, + RSI_COMMON_REG_SIZE); if (status < 0) { rsi_dbg(ERR_ZONE, "%s: REGOUT read failed\n", __func__); @@ -865,13 +869,26 @@ static int rsi_load_firmware(struct rsi_hw *adapter) (regout_val & 0xff)); status = hif_ops->master_reg_write(adapter, SWBL_REGOUT, - (REGOUT_INVALID | REGOUT_INVALID << 8), - 2); - if (status < 0) { + (REGOUT_INVALID | + REGOUT_INVALID << 8), + RSI_COMMON_REG_SIZE); + if (status < 0) rsi_dbg(ERR_ZONE, "%s: REGOUT writing failed..\n", __func__); - return status; - } - mdelay(1); + else + rsi_dbg(INFO_ZONE, + "===> Device is ready to load firmware <===\n"); + + return status; +} + +static int rsi_load_9113_firmware(struct rsi_hw *adapter) +{ + struct rsi_common *common = adapter->priv; + const struct firmware *fw_entry = NULL; + u32 content_size; + u16 tmp_regout_val = 0; + struct ta_metadata *metadata_p; + int status; status = bl_cmd(adapter, CONFIG_AUTO_READ_MODE, CMD_PASS, "AUTO_READ_CMD"); @@ -902,13 +919,15 @@ static int rsi_load_firmware(struct rsi_hw *adapter) /* Get the firmware version */ common->lmac_ver.ver.info.fw_ver[0] = - fw_entry->data[LMAC_VER_OFFSET] & 0xFF; + fw_entry->data[LMAC_VER_OFFSET_9113] & 0xFF; common->lmac_ver.ver.info.fw_ver[1] = - fw_entry->data[LMAC_VER_OFFSET + 1] & 0xFF; - common->lmac_ver.major = fw_entry->data[LMAC_VER_OFFSET + 2] & 0xFF; + fw_entry->data[LMAC_VER_OFFSET_9113 + 1] & 0xFF; + common->lmac_ver.major = + fw_entry->data[LMAC_VER_OFFSET_9113 + 2] & 0xFF; common->lmac_ver.release_num = - fw_entry->data[LMAC_VER_OFFSET + 3] & 0xFF; - common->lmac_ver.minor = fw_entry->data[LMAC_VER_OFFSET + 4] & 0xFF; + fw_entry->data[LMAC_VER_OFFSET_9113 + 3] & 0xFF; + common->lmac_ver.minor = + fw_entry->data[LMAC_VER_OFFSET_9113 + 4] & 0xFF; common->lmac_ver.patch_num = 0; rsi_print_version(common); @@ -977,19 +996,161 @@ fail: return status; } +static int rsi_load_9116_firmware(struct rsi_hw *adapter) +{ + struct rsi_common *common = adapter->priv; + struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops; + const struct firmware *fw_entry; + struct ta_metadata *metadata_p; + u8 *ta_firmware, *fw_p; + struct bootload_ds bootload_ds; + u32 instructions_sz, base_address; + u16 block_size = adapter->block_size; + u32 dest, len; + int status, cnt; + + rsi_dbg(INIT_ZONE, "***** Load 9116 TA Instructions *****\n"); + + if (adapter->rsi_host_intf == RSI_HOST_INTF_USB) { + status = bl_cmd(adapter, POLLING_MODE, CMD_PASS, + "POLLING_MODE"); + if (status < 0) + return status; + } + + status = hif_ops->master_reg_write(adapter, MEM_ACCESS_CTRL_FROM_HOST, + RAM_384K_ACCESS_FROM_TA, + RSI_9116_REG_SIZE); + if (status < 0) { + rsi_dbg(ERR_ZONE, "%s: Unable to access full RAM memory\n", + __func__); + return status; + } + + metadata_p = &metadata[adapter->priv->coex_mode]; + rsi_dbg(INIT_ZONE, "%s: loading file %s\n", __func__, metadata_p->name); + status = request_firmware(&fw_entry, metadata_p->name, adapter->device); + if (status < 0) { + rsi_dbg(ERR_ZONE, "%s: Failed to open file %s\n", + __func__, metadata_p->name); + return status; + } + + ta_firmware = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL); + if (!ta_firmware) + goto fail_release_fw; + fw_p = ta_firmware; + instructions_sz = fw_entry->size; + rsi_dbg(INFO_ZONE, "FW Length = %d bytes\n", instructions_sz); + + common->lmac_ver.major = ta_firmware[LMAC_VER_OFFSET_9116]; + common->lmac_ver.minor = ta_firmware[LMAC_VER_OFFSET_9116 + 1]; + common->lmac_ver.release_num = ta_firmware[LMAC_VER_OFFSET_9116 + 2]; + common->lmac_ver.patch_num = ta_firmware[LMAC_VER_OFFSET_9116 + 3]; + common->lmac_ver.ver.info.fw_ver[0] = + ta_firmware[LMAC_VER_OFFSET_9116 + 4]; + + if (instructions_sz % FW_ALIGN_SIZE) + instructions_sz += + (FW_ALIGN_SIZE - (instructions_sz % FW_ALIGN_SIZE)); + rsi_dbg(INFO_ZONE, "instructions_sz : %d\n", instructions_sz); + + if (*(u16 *)fw_p == RSI_9116_FW_MAGIC_WORD) { + memcpy(&bootload_ds, fw_p, sizeof(struct bootload_ds)); + fw_p += le16_to_cpu(bootload_ds.offset); + rsi_dbg(INFO_ZONE, "FW start = %x\n", *(u32 *)fw_p); + + cnt = 0; + do { + rsi_dbg(ERR_ZONE, "%s: Loading chunk %d\n", + __func__, cnt); + + dest = le32_to_cpu(bootload_ds.bl_entry[cnt].dst_addr); + len = le32_to_cpu(bootload_ds.bl_entry[cnt].control) & + RSI_BL_CTRL_LEN_MASK; + rsi_dbg(INFO_ZONE, "length %d destination %x\n", + len, dest); + + status = hif_ops->load_data_master_write(adapter, dest, + len, + block_size, + fw_p); + if (status < 0) { + rsi_dbg(ERR_ZONE, + "Failed to load chunk %d\n", cnt); + break; + } + fw_p += len; + if (le32_to_cpu(bootload_ds.bl_entry[cnt].control) & + RSI_BL_CTRL_LAST_ENTRY) + break; + cnt++; + } while (1); + } else { + base_address = metadata_p->address; + status = hif_ops->load_data_master_write(adapter, + base_address, + instructions_sz, + block_size, + ta_firmware); + } + if (status) { + rsi_dbg(ERR_ZONE, + "%s: Unable to load %s blk\n", + __func__, metadata_p->name); + goto fail_free_fw; + } + + rsi_dbg(INIT_ZONE, "%s: Successfully loaded %s instructions\n", + __func__, metadata_p->name); + + if (adapter->rsi_host_intf == RSI_HOST_INTF_SDIO) { + if (hif_ops->ta_reset(adapter)) + rsi_dbg(ERR_ZONE, "Unable to put ta in reset\n"); + } else { + if (bl_cmd(adapter, JUMP_TO_ZERO_PC, + CMD_PASS, "JUMP_TO_ZERO") < 0) + rsi_dbg(INFO_ZONE, "Jump to zero command failed\n"); + else + rsi_dbg(INFO_ZONE, "Jump to zero command successful\n"); + } + +fail_free_fw: + kfree(ta_firmware); +fail_release_fw: + release_firmware(fw_entry); + + return status; +} + int rsi_hal_device_init(struct rsi_hw *adapter) { struct rsi_common *common = adapter->priv; + int status; switch (adapter->device_model) { case RSI_DEV_9113: - if (rsi_load_firmware(adapter)) { + status = rsi_hal_prepare_fwload(adapter); + if (status < 0) + return status; + if (rsi_load_9113_firmware(adapter)) { rsi_dbg(ERR_ZONE, "%s: Failed to load TA instructions\n", __func__); return -EINVAL; } break; + case RSI_DEV_9116: + status = rsi_hal_prepare_fwload(adapter); + if (status < 0) + return status; + if (rsi_load_9116_firmware(adapter)) { + rsi_dbg(ERR_ZONE, + "%s: Failed to load firmware to 9116 device\n", + __func__); + return -EINVAL; + } + break; default: return -EINVAL; } diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 831046e760f8..49df3bb08d41 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -188,27 +188,27 @@ bool rsi_is_cipher_wep(struct rsi_common *common) * @adapter: Pointer to the adapter structure. * @band: Operating band to be set. * - * Return: None. + * Return: int - 0 on success, negative error on failure. */ -static void rsi_register_rates_channels(struct rsi_hw *adapter, int band) +static int rsi_register_rates_channels(struct rsi_hw *adapter, int band) { struct ieee80211_supported_band *sbands = &adapter->sbands[band]; void *channels = NULL; if (band == NL80211_BAND_2GHZ) { - channels = kmalloc(sizeof(rsi_2ghz_channels), GFP_KERNEL); - memcpy(channels, - rsi_2ghz_channels, - sizeof(rsi_2ghz_channels)); + channels = kmemdup(rsi_2ghz_channels, sizeof(rsi_2ghz_channels), + GFP_KERNEL); + if (!channels) + return -ENOMEM; sbands->band = NL80211_BAND_2GHZ; sbands->n_channels = ARRAY_SIZE(rsi_2ghz_channels); sbands->bitrates = rsi_rates; sbands->n_bitrates = ARRAY_SIZE(rsi_rates); } else { - channels = kmalloc(sizeof(rsi_5ghz_channels), GFP_KERNEL); - memcpy(channels, - rsi_5ghz_channels, - sizeof(rsi_5ghz_channels)); + channels = kmemdup(rsi_5ghz_channels, sizeof(rsi_5ghz_channels), + GFP_KERNEL); + if (!channels) + return -ENOMEM; sbands->band = NL80211_BAND_5GHZ; sbands->n_channels = ARRAY_SIZE(rsi_5ghz_channels); sbands->bitrates = &rsi_rates[4]; @@ -227,6 +227,7 @@ static void rsi_register_rates_channels(struct rsi_hw *adapter, int band) sbands->ht_cap.mcs.rx_mask[0] = 0xff; sbands->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; /* sbands->ht_cap.mcs.rx_highest = 0x82; */ + return 0; } static int rsi_mac80211_hw_scan_start(struct ieee80211_hw *hw, @@ -2064,11 +2065,16 @@ int rsi_mac80211_attach(struct rsi_common *common) wiphy->available_antennas_rx = 1; wiphy->available_antennas_tx = 1; - rsi_register_rates_channels(adapter, NL80211_BAND_2GHZ); + status = rsi_register_rates_channels(adapter, NL80211_BAND_2GHZ); + if (status) + return status; wiphy->bands[NL80211_BAND_2GHZ] = &adapter->sbands[NL80211_BAND_2GHZ]; if (common->num_supp_bands > 1) { - rsi_register_rates_channels(adapter, NL80211_BAND_5GHZ); + status = rsi_register_rates_channels(adapter, + NL80211_BAND_5GHZ); + if (status) + return status; wiphy->bands[NL80211_BAND_5GHZ] = &adapter->sbands[NL80211_BAND_5GHZ]; } diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index 844f2fac298f..6c7f26ef6476 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c @@ -209,6 +209,59 @@ static struct bootup_params boot_params_40 = { .beacon_resedue_alg_en = 0, }; +static struct bootup_params_9116 boot_params_9116_20 = { + .magic_number = cpu_to_le16(LOADED_TOKEN), + .valid = cpu_to_le32(VALID_20), + .device_clk_info_9116 = {{ + .pll_config_9116_g = { + .pll_ctrl_set_reg = cpu_to_le16(0xd518), + .pll_ctrl_clr_reg = cpu_to_le16(0x2ae7), + .pll_modem_conig_reg = cpu_to_le16(0x2000), + .soc_clk_config_reg = cpu_to_le16(0x0c18), + .adc_dac_strm1_config_reg = cpu_to_le16(0x1100), + .adc_dac_strm2_config_reg = cpu_to_le16(0x6600), + }, + .switch_clk_9116_g = { + .switch_clk_info = + cpu_to_le32((RSI_SWITCH_TASS_CLK | + RSI_SWITCH_WLAN_BBP_LMAC_CLK_REG | + RSI_SWITCH_BBP_LMAC_CLK_REG)), + .tass_clock_reg = cpu_to_le32(0x083C0503), + .wlan_bbp_lmac_clk_reg_val = cpu_to_le32(0x01042001), + .zbbt_bbp_lmac_clk_reg_val = cpu_to_le32(0x02010001), + .bbp_lmac_clk_en_val = cpu_to_le32(0x0000003b), + } + }, + }, +}; + +static struct bootup_params_9116 boot_params_9116_40 = { + .magic_number = cpu_to_le16(LOADED_TOKEN), + .valid = cpu_to_le32(VALID_40), + .device_clk_info_9116 = {{ + .pll_config_9116_g = { + .pll_ctrl_set_reg = cpu_to_le16(0xd518), + .pll_ctrl_clr_reg = cpu_to_le16(0x2ae7), + .pll_modem_conig_reg = cpu_to_le16(0x3000), + .soc_clk_config_reg = cpu_to_le16(0x0c18), + .adc_dac_strm1_config_reg = cpu_to_le16(0x0000), + .adc_dac_strm2_config_reg = cpu_to_le16(0x6600), + }, + .switch_clk_9116_g = { + .switch_clk_info = + cpu_to_le32((RSI_SWITCH_TASS_CLK | + RSI_SWITCH_WLAN_BBP_LMAC_CLK_REG | + RSI_SWITCH_BBP_LMAC_CLK_REG | + RSI_MODEM_CLK_160MHZ)), + .tass_clock_reg = cpu_to_le32(0x083C0503), + .wlan_bbp_lmac_clk_reg_val = cpu_to_le32(0x01042002), + .zbbt_bbp_lmac_clk_reg_val = cpu_to_le32(0x04010002), + .bbp_lmac_clk_en_val = cpu_to_le32(0x0000003b), + } + }, + }, +}; + static u16 mcs[] = {13, 26, 39, 52, 78, 104, 117, 130}; /** @@ -235,6 +288,14 @@ static void rsi_set_default_parameters(struct rsi_common *common) common->obm_ant_sel_val = 2; common->beacon_interval = RSI_BEACON_INTERVAL; common->dtim_cnt = RSI_DTIM_COUNT; + common->w9116_features.pll_mode = 0x0; + common->w9116_features.rf_type = 1; + common->w9116_features.wireless_mode = 0; + common->w9116_features.enable_ppe = 0; + common->w9116_features.afe_type = 1; + common->w9116_features.dpd = 0; + common->w9116_features.sifs_tx_enable = 0; + common->w9116_features.ps_options = 0; } void init_bgscan_params(struct rsi_common *common) @@ -363,6 +424,10 @@ static int rsi_load_radio_caps(struct rsi_common *common) } radio_caps->radio_info |= radio_id; + if (adapter->device_model == RSI_DEV_9116 && + common->channel_width == BW_20MHZ) + radio_caps->radio_cfg_info &= ~0x3; + radio_caps->sifs_tx_11n = cpu_to_le16(SIFS_TX_11N_VALUE); radio_caps->sifs_tx_11b = cpu_to_le16(SIFS_TX_11B_VALUE); radio_caps->slot_rx_11n = cpu_to_le16(SHORT_SLOT_VALUE); @@ -378,14 +443,16 @@ static int rsi_load_radio_caps(struct rsi_common *common) } for (ii = 0; ii < NUM_EDCA_QUEUES; ii++) { - radio_caps->qos_params[ii].cont_win_min_q = - cpu_to_le16(common->edca_params[ii].cw_min); - radio_caps->qos_params[ii].cont_win_max_q = - cpu_to_le16(common->edca_params[ii].cw_max); - radio_caps->qos_params[ii].aifsn_val_q = - cpu_to_le16((common->edca_params[ii].aifs) << 8); - radio_caps->qos_params[ii].txop_q = - cpu_to_le16(common->edca_params[ii].txop); + if (common->edca_params[ii].cw_max > 0) { + radio_caps->qos_params[ii].cont_win_min_q = + cpu_to_le16(common->edca_params[ii].cw_min); + radio_caps->qos_params[ii].cont_win_max_q = + cpu_to_le16(common->edca_params[ii].cw_max); + radio_caps->qos_params[ii].aifsn_val_q = + cpu_to_le16(common->edca_params[ii].aifs << 8); + radio_caps->qos_params[ii].txop_q = + cpu_to_le16(common->edca_params[ii].txop); + } } radio_caps->qos_params[BROADCAST_HW_Q].txop_q = cpu_to_le16(0xffff); @@ -893,6 +960,50 @@ static int rsi_load_bootup_params(struct rsi_common *common) return rsi_send_internal_mgmt_frame(common, skb); } +static int rsi_load_9116_bootup_params(struct rsi_common *common) +{ + struct sk_buff *skb; + struct rsi_boot_params_9116 *boot_params; + + rsi_dbg(MGMT_TX_ZONE, "%s: Sending boot params frame\n", __func__); + + skb = dev_alloc_skb(sizeof(struct rsi_boot_params_9116)); + if (!skb) + return -ENOMEM; + memset(skb->data, 0, sizeof(struct rsi_boot_params)); + boot_params = (struct rsi_boot_params_9116 *)skb->data; + + if (common->channel_width == BW_40MHZ) { + memcpy(&boot_params->bootup_params, + &boot_params_9116_40, + sizeof(struct bootup_params_9116)); + rsi_dbg(MGMT_TX_ZONE, "%s: Packet 40MHZ <=== %d\n", __func__, + UMAC_CLK_40BW); + boot_params->umac_clk = cpu_to_le16(UMAC_CLK_40BW); + } else { + memcpy(&boot_params->bootup_params, + &boot_params_9116_20, + sizeof(struct bootup_params_9116)); + if (boot_params_20.valid != cpu_to_le32(VALID_20)) { + boot_params->umac_clk = cpu_to_le16(UMAC_CLK_20BW); + rsi_dbg(MGMT_TX_ZONE, + "%s: Packet 20MHZ <=== %d\n", __func__, + UMAC_CLK_20BW); + } else { + boot_params->umac_clk = cpu_to_le16(UMAC_CLK_40MHZ); + rsi_dbg(MGMT_TX_ZONE, + "%s: Packet 20MHZ <=== %d\n", __func__, + UMAC_CLK_40MHZ); + } + } + rsi_set_len_qno(&boot_params->desc_dword0.len_qno, + sizeof(struct bootup_params_9116), RSI_WIFI_MGMT_Q); + boot_params->desc_dword0.frame_type = BOOTUP_PARAMS_REQUEST; + skb_put(skb, sizeof(struct rsi_boot_params_9116)); + + return rsi_send_internal_mgmt_frame(common, skb); +} + /** * rsi_send_reset_mac() - This function prepares reset MAC request and sends an * internal management frame to indicate it to firmware. @@ -921,6 +1032,11 @@ static int rsi_send_reset_mac(struct rsi_common *common) mgmt_frame->desc_word[1] = cpu_to_le16(RESET_MAC_REQ); mgmt_frame->desc_word[4] = cpu_to_le16(RETRY_COUNT << 8); +#define RSI_9116_DEF_TA_AGGR 3 + if (common->priv->device_model == RSI_DEV_9116) + mgmt_frame->desc_word[3] |= + cpu_to_le16(RSI_9116_DEF_TA_AGGR << 8); + skb_put(skb, FRAME_DESC_SZ); return rsi_send_internal_mgmt_frame(common, skb); @@ -971,7 +1087,10 @@ int rsi_band_check(struct rsi_common *common, } if (common->channel_width != prev_bw) { - status = rsi_load_bootup_params(common); + if (adapter->device_model == RSI_DEV_9116) + status = rsi_load_9116_bootup_params(common); + else + status = rsi_load_bootup_params(common); if (status) return status; @@ -1546,6 +1665,47 @@ int rsi_send_ps_request(struct rsi_hw *adapter, bool enable, return rsi_send_internal_mgmt_frame(common, skb); } +static int rsi_send_w9116_features(struct rsi_common *common) +{ + struct rsi_wlan_9116_features *w9116_features; + u16 frame_len = sizeof(struct rsi_wlan_9116_features); + struct sk_buff *skb; + + rsi_dbg(MGMT_TX_ZONE, + "%s: Sending wlan 9116 features\n", __func__); + + skb = dev_alloc_skb(frame_len); + if (!skb) + return -ENOMEM; + memset(skb->data, 0, frame_len); + + w9116_features = (struct rsi_wlan_9116_features *)skb->data; + + w9116_features->pll_mode = common->w9116_features.pll_mode; + w9116_features->rf_type = common->w9116_features.rf_type; + w9116_features->wireless_mode = common->w9116_features.wireless_mode; + w9116_features->enable_ppe = common->w9116_features.enable_ppe; + w9116_features->afe_type = common->w9116_features.afe_type; + if (common->w9116_features.dpd) + w9116_features->feature_enable |= cpu_to_le32(RSI_DPD); + if (common->w9116_features.sifs_tx_enable) + w9116_features->feature_enable |= + cpu_to_le32(RSI_SIFS_TX_ENABLE); + if (common->w9116_features.ps_options & RSI_DUTY_CYCLING) + w9116_features->feature_enable |= cpu_to_le32(RSI_DUTY_CYCLING); + if (common->w9116_features.ps_options & RSI_END_OF_FRAME) + w9116_features->feature_enable |= cpu_to_le32(RSI_END_OF_FRAME); + w9116_features->feature_enable |= + cpu_to_le32((common->w9116_features.ps_options & ~0x3) << 2); + + rsi_set_len_qno(&w9116_features->desc.desc_dword0.len_qno, + frame_len - FRAME_DESC_SZ, RSI_WIFI_MGMT_Q); + w9116_features->desc.desc_dword0.frame_type = FEATURES_ENABLE; + skb_put(skb, frame_len); + + return rsi_send_internal_mgmt_frame(common, skb); +} + /** * rsi_set_antenna() - This function send antenna configuration request * to device @@ -1766,15 +1926,26 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common, rsi_dbg(FSM_ZONE, "%s: Boot up params confirm received\n", __func__); if (common->fsm_state == FSM_BOOT_PARAMS_SENT) { - adapter->eeprom.length = (IEEE80211_ADDR_LEN + - WLAN_MAC_MAGIC_WORD_LEN + - WLAN_HOST_MODE_LEN); - adapter->eeprom.offset = WLAN_MAC_EEPROM_ADDR; - if (rsi_eeprom_read(common)) { - common->fsm_state = FSM_CARD_NOT_READY; - goto out; + if (adapter->device_model == RSI_DEV_9116) { + common->band = NL80211_BAND_5GHZ; + common->num_supp_bands = 2; + + if (rsi_send_reset_mac(common)) + goto out; + else + common->fsm_state = FSM_RESET_MAC_SENT; + } else { + adapter->eeprom.length = + (IEEE80211_ADDR_LEN + + WLAN_MAC_MAGIC_WORD_LEN + + WLAN_HOST_MODE_LEN); + adapter->eeprom.offset = WLAN_MAC_EEPROM_ADDR; + if (rsi_eeprom_read(common)) { + common->fsm_state = FSM_CARD_NOT_READY; + goto out; + } + common->fsm_state = FSM_EEPROM_READ_MAC_ADDR; } - common->fsm_state = FSM_EEPROM_READ_MAC_ADDR; } else { rsi_dbg(INFO_ZONE, "%s: Received bootup params cfm in %d state\n", @@ -1853,6 +2024,12 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common, case RADIO_CAPABILITIES: if (common->fsm_state == FSM_RADIO_CAPS_SENT) { common->rf_reset = 1; + if (adapter->device_model == RSI_DEV_9116 && + rsi_send_w9116_features(common)) { + rsi_dbg(ERR_ZONE, + "Failed to send 9116 features\n"); + goto out; + } if (rsi_program_bb_rf(common)) { goto out; } else { @@ -1925,6 +2102,8 @@ out: int rsi_handle_card_ready(struct rsi_common *common, u8 *msg) { + int status; + switch (common->fsm_state) { case FSM_CARD_NOT_READY: rsi_dbg(INIT_ZONE, "Card ready indication from Common HAL\n"); @@ -1936,14 +2115,29 @@ int rsi_handle_card_ready(struct rsi_common *common, u8 *msg) case FSM_COMMON_DEV_PARAMS_SENT: rsi_dbg(INIT_ZONE, "Card ready indication from WLAN HAL\n"); + if (common->priv->device_model == RSI_DEV_9116) { + if (msg[16] != MAGIC_WORD) { + rsi_dbg(FSM_ZONE, + "%s: [EEPROM_READ] Invalid token\n", + __func__); + common->fsm_state = FSM_CARD_NOT_READY; + return -EINVAL; + } + memcpy(common->mac_addr, &msg[20], ETH_ALEN); + rsi_dbg(INIT_ZONE, "MAC Addr %pM", common->mac_addr); + } /* Get usb buffer status register address */ common->priv->usb_buffer_status_reg = *(u32 *)&msg[8]; rsi_dbg(INFO_ZONE, "USB buffer status register = %x\n", common->priv->usb_buffer_status_reg); - if (rsi_load_bootup_params(common)) { + if (common->priv->device_model == RSI_DEV_9116) + status = rsi_load_9116_bootup_params(common); + else + status = rsi_load_bootup_params(common); + if (status < 0) { common->fsm_state = FSM_CARD_NOT_READY; - return -EINVAL; + return status; } common->fsm_state = FSM_BOOT_PARAMS_SENT; break; diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index 3430d7a0899e..f9c67ed473d1 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -923,6 +923,70 @@ static int rsi_sdio_reinit_device(struct rsi_hw *adapter) return 0; } +static int rsi_sdio_ta_reset(struct rsi_hw *adapter) +{ + int status; + u32 addr; + u8 *data; + + status = rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR); + if (status < 0) { + rsi_dbg(ERR_ZONE, + "Unable to set ms word to common reg\n"); + return status; + } + + rsi_dbg(INIT_ZONE, "%s: Bring TA out of reset\n", __func__); + put_unaligned_le32(TA_HOLD_THREAD_VALUE, data); + addr = TA_HOLD_THREAD_REG | RSI_SD_REQUEST_MASTER; + status = rsi_sdio_write_register_multiple(adapter, addr, + (u8 *)&data, + RSI_9116_REG_SIZE); + if (status < 0) { + rsi_dbg(ERR_ZONE, "Unable to hold TA threads\n"); + return status; + } + + put_unaligned_le32(TA_SOFT_RST_CLR, data); + addr = TA_SOFT_RESET_REG | RSI_SD_REQUEST_MASTER; + status = rsi_sdio_write_register_multiple(adapter, addr, + (u8 *)&data, + RSI_9116_REG_SIZE); + if (status < 0) { + rsi_dbg(ERR_ZONE, "Unable to get TA out of reset\n"); + return status; + } + + put_unaligned_le32(TA_PC_ZERO, data); + addr = TA_TH0_PC_REG | RSI_SD_REQUEST_MASTER; + status = rsi_sdio_write_register_multiple(adapter, addr, + (u8 *)&data, + RSI_9116_REG_SIZE); + if (status < 0) { + rsi_dbg(ERR_ZONE, "Unable to Reset TA PC value\n"); + return -EINVAL; + } + + put_unaligned_le32(TA_RELEASE_THREAD_VALUE, data); + addr = TA_RELEASE_THREAD_REG | RSI_SD_REQUEST_MASTER; + status = rsi_sdio_write_register_multiple(adapter, addr, + (u8 *)&data, + RSI_9116_REG_SIZE); + if (status < 0) { + rsi_dbg(ERR_ZONE, "Unable to release TA threads\n"); + return status; + } + + status = rsi_sdio_master_access_msword(adapter, MISC_CFG_BASE_ADDR); + if (status < 0) { + rsi_dbg(ERR_ZONE, "Unable to set ms word to common reg\n"); + return status; + } + rsi_dbg(INIT_ZONE, "***** TA Reset done *****\n"); + + return 0; +} + static struct rsi_host_intf_ops sdio_host_intf_ops = { .write_pkt = rsi_sdio_host_intf_write_pkt, .read_pkt = rsi_sdio_host_intf_read_pkt, @@ -933,6 +997,7 @@ static struct rsi_host_intf_ops sdio_host_intf_ops = { .master_reg_write = rsi_sdio_master_reg_write, .load_data_master_write = rsi_sdio_load_data_master_write, .reinit_device = rsi_sdio_reinit_device, + .ta_reset = rsi_sdio_ta_reset, }; /** @@ -949,7 +1014,7 @@ static int rsi_probe(struct sdio_func *pfunction, { struct rsi_hw *adapter; struct rsi_91x_sdiodev *sdev; - int status; + int status = -EINVAL; rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__); @@ -968,6 +1033,20 @@ static int rsi_probe(struct sdio_func *pfunction, status = -EIO; goto fail_free_adapter; } + + if (pfunction->device == RSI_SDIO_PID_9113) { + rsi_dbg(ERR_ZONE, "%s: 9113 module detected\n", __func__); + adapter->device_model = RSI_DEV_9113; + } else if (pfunction->device == RSI_SDIO_PID_9116) { + rsi_dbg(ERR_ZONE, "%s: 9116 module detected\n", __func__); + adapter->device_model = RSI_DEV_9116; + } else { + rsi_dbg(ERR_ZONE, + "%s: Unsupported RSI device id 0x%x\n", __func__, + pfunction->device); + goto fail_free_adapter; + } + sdev = (struct rsi_91x_sdiodev *)adapter->rsi_dev; rsi_init_event(&sdev->rx_thread.event); status = rsi_create_kthread(adapter->priv, &sdev->rx_thread, @@ -1088,16 +1167,41 @@ static void rsi_reset_chip(struct rsi_hw *adapter) * and any pending dma transfers to rf spi in device to finish. */ msleep(100); - - ulp_read_write(adapter, RSI_ULP_RESET_REG, RSI_ULP_WRITE_0, 32); - ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_1, RSI_ULP_WRITE_2, 32); - ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_2, RSI_ULP_WRITE_0, 32); - ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_1, RSI_ULP_WRITE_50, - 32); - ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_2, RSI_ULP_WRITE_0, - 32); - ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_ENABLE, - RSI_ULP_TIMER_ENABLE, 32); + if (adapter->device_model != RSI_DEV_9116) { + ulp_read_write(adapter, RSI_ULP_RESET_REG, RSI_ULP_WRITE_0, 32); + ulp_read_write(adapter, + RSI_WATCH_DOG_TIMER_1, RSI_ULP_WRITE_2, 32); + ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_2, RSI_ULP_WRITE_0, + 32); + ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_1, + RSI_ULP_WRITE_50, 32); + ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_2, + RSI_ULP_WRITE_0, 32); + ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_ENABLE, + RSI_ULP_TIMER_ENABLE, 32); + } else { + if ((rsi_sdio_master_reg_write(adapter, + NWP_WWD_INTERRUPT_TIMER, + NWP_WWD_INT_TIMER_CLKS, + RSI_9116_REG_SIZE)) < 0) { + rsi_dbg(ERR_ZONE, "Failed to write to intr timer\n"); + } + if ((rsi_sdio_master_reg_write(adapter, + NWP_WWD_SYSTEM_RESET_TIMER, + NWP_WWD_SYS_RESET_TIMER_CLKS, + RSI_9116_REG_SIZE)) < 0) { + rsi_dbg(ERR_ZONE, + "Failed to write to system reset timer\n"); + } + if ((rsi_sdio_master_reg_write(adapter, + NWP_WWD_MODE_AND_RSTART, + NWP_WWD_TIMER_DISABLE, + RSI_9116_REG_SIZE)) < 0) { + rsi_dbg(ERR_ZONE, + "Failed to write to mode and restart\n"); + } + rsi_dbg(ERR_ZONE, "***** Watch Dog Reset Successful *****\n"); + } /* This msleep will be sufficient for the ulp * read write operations to complete for chip reset. */ @@ -1415,7 +1519,8 @@ static const struct dev_pm_ops rsi_pm_ops = { #endif static const struct sdio_device_id rsi_dev_table[] = { - { SDIO_DEVICE(RSI_SDIO_VID_9113, RSI_SDIO_PID_9113) }, + { SDIO_DEVICE(RSI_SDIO_VENDOR_ID, RSI_SDIO_PID_9113) }, + { SDIO_DEVICE(RSI_SDIO_VENDOR_ID, RSI_SDIO_PID_9116) }, { /* Blank */}, }; diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c index ac0ef5ea6ffb..f5048d4b8cb6 100644 --- a/drivers/net/wireless/rsi/rsi_91x_usb.c +++ b/drivers/net/wireless/rsi/rsi_91x_usb.c @@ -213,7 +213,7 @@ static int rsi_usb_reg_read(struct usb_device *usbdev, */ static int rsi_usb_reg_write(struct usb_device *usbdev, u32 reg, - u16 value, + u32 value, u16 len) { u8 *usb_reg_buf; @@ -226,17 +226,17 @@ static int rsi_usb_reg_write(struct usb_device *usbdev, if (!usb_reg_buf) return status; - usb_reg_buf[0] = (value & 0x00ff); - usb_reg_buf[1] = (value & 0xff00) >> 8; - usb_reg_buf[2] = 0x0; - usb_reg_buf[3] = 0x0; + usb_reg_buf[0] = (cpu_to_le32(value) & 0x00ff); + usb_reg_buf[1] = (cpu_to_le32(value) & 0xff00) >> 8; + usb_reg_buf[2] = (cpu_to_le32(value) & 0x00ff0000) >> 16; + usb_reg_buf[3] = (cpu_to_le32(value) & 0xff000000) >> 24; status = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), USB_VENDOR_REGISTER_WRITE, RSI_USB_REQ_OUT, - ((reg & 0xffff0000) >> 16), - (reg & 0xffff), + ((cpu_to_le32(reg) & 0xffff0000) >> 16), + (cpu_to_le32(reg) & 0xffff), (void *)usb_reg_buf, len, USB_CTRL_SET_TIMEOUT); @@ -263,8 +263,10 @@ static void rsi_rx_done_handler(struct urb *urb) struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)rx_cb->data; int status = -EINVAL; - if (urb->status) - goto out; + if (urb->status) { + dev_kfree_skb(rx_cb->rx_skb); + return; + } if (urb->actual_length <= 0 || urb->actual_length > rx_cb->rx_skb->len) { @@ -698,26 +700,47 @@ static int rsi_reset_card(struct rsi_hw *adapter) goto fail; } - ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_1, - RSI_ULP_WRITE_2, 32); - if (ret < 0) - goto fail; - ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_2, - RSI_ULP_WRITE_0, 32); - if (ret < 0) - goto fail; - ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_1, - RSI_ULP_WRITE_50, 32); - if (ret < 0) - goto fail; - ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_2, - RSI_ULP_WRITE_0, 32); - if (ret < 0) - goto fail; - ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_ENABLE, - RSI_ULP_TIMER_ENABLE, 32); - if (ret < 0) - goto fail; + if (adapter->device_model != RSI_DEV_9116) { + ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_1, + RSI_ULP_WRITE_2, 32); + if (ret < 0) + goto fail; + ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_2, + RSI_ULP_WRITE_0, 32); + if (ret < 0) + goto fail; + ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_1, + RSI_ULP_WRITE_50, 32); + if (ret < 0) + goto fail; + ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_DELAY_TIMER_2, + RSI_ULP_WRITE_0, 32); + if (ret < 0) + goto fail; + ret = usb_ulp_read_write(adapter, RSI_WATCH_DOG_TIMER_ENABLE, + RSI_ULP_TIMER_ENABLE, 32); + if (ret < 0) + goto fail; + } else { + if ((rsi_usb_master_reg_write(adapter, + NWP_WWD_INTERRUPT_TIMER, + NWP_WWD_INT_TIMER_CLKS, + RSI_9116_REG_SIZE)) < 0) { + goto fail; + } + if ((rsi_usb_master_reg_write(adapter, + NWP_WWD_SYSTEM_RESET_TIMER, + NWP_WWD_SYS_RESET_TIMER_CLKS, + RSI_9116_REG_SIZE)) < 0) { + goto fail; + } + if ((rsi_usb_master_reg_write(adapter, + NWP_WWD_MODE_AND_RSTART, + NWP_WWD_TIMER_DISABLE, + RSI_9116_REG_SIZE)) < 0) { + goto fail; + } + } rsi_dbg(INFO_ZONE, "Reset card done\n"); return ret; @@ -763,6 +786,18 @@ static int rsi_probe(struct usb_interface *pfunction, rsi_dbg(ERR_ZONE, "%s: Initialized os intf ops\n", __func__); + if (id && id->idProduct == RSI_USB_PID_9113) { + rsi_dbg(INIT_ZONE, "%s: 9113 module detected\n", __func__); + adapter->device_model = RSI_DEV_9113; + } else if (id && id->idProduct == RSI_USB_PID_9116) { + rsi_dbg(INIT_ZONE, "%s: 9116 module detected\n", __func__); + adapter->device_model = RSI_DEV_9116; + } else { + rsi_dbg(ERR_ZONE, "%s: Unsupported RSI device id 0x%x\n", + __func__, id->idProduct); + goto err1; + } + dev = (struct rsi_91x_usbdev *)adapter->rsi_dev; status = rsi_usb_reg_read(dev->usbdev, FW_STATUS_REG, &fw_status, 2); @@ -845,7 +880,8 @@ static int rsi_resume(struct usb_interface *intf) #endif static const struct usb_device_id rsi_dev_table[] = { - { USB_DEVICE(RSI_USB_VID_9113, RSI_USB_PID_9113) }, + { USB_DEVICE(RSI_USB_VENDOR_ID, RSI_USB_PID_9113) }, + { USB_DEVICE(RSI_USB_VENDOR_ID, RSI_USB_PID_9116) }, { /* Blank */}, }; diff --git a/drivers/net/wireless/rsi/rsi_boot_params.h b/drivers/net/wireless/rsi/rsi_boot_params.h index ad903b22440e..c1cf19d1e376 100644 --- a/drivers/net/wireless/rsi/rsi_boot_params.h +++ b/drivers/net/wireless/rsi/rsi_boot_params.h @@ -80,6 +80,15 @@ struct pll_config { struct afepll_info afepll_info_g; } __packed; +struct pll_config_9116 { + __le16 pll_ctrl_set_reg; + __le16 pll_ctrl_clr_reg; + __le16 pll_modem_conig_reg; + __le16 soc_clk_config_reg; + __le16 adc_dac_strm1_config_reg; + __le16 adc_dac_strm2_config_reg; +} __packed; + /* structure to store configs related to UMAC clk programming */ struct switch_clk { __le16 switch_clk_info; @@ -93,11 +102,32 @@ struct switch_clk { __le16 qspi_uart_clock_reg_config; } __packed; +#define RSI_SWITCH_TASS_CLK BIT(0) +#define RSI_SWITCH_QSPI_CLK BIT(1) +#define RSI_SWITCH_SLP_CLK_2_32 BIT(2) +#define RSI_SWITCH_WLAN_BBP_LMAC_CLK_REG BIT(3) +#define RSI_SWITCH_ZBBT_BBP_LMAC_CLK_REG BIT(4) +#define RSI_SWITCH_BBP_LMAC_CLK_REG BIT(5) +#define RSI_MODEM_CLK_160MHZ BIT(6) + +struct switch_clk_9116 { + __le32 switch_clk_info; + __le32 tass_clock_reg; + __le32 wlan_bbp_lmac_clk_reg_val; + __le32 zbbt_bbp_lmac_clk_reg_val; + __le32 bbp_lmac_clk_en_val; +} __packed; + struct device_clk_info { struct pll_config pll_config_g; struct switch_clk switch_clk_g; } __packed; +struct device_clk_info_9116 { + struct pll_config_9116 pll_config_9116_g; + struct switch_clk_9116 switch_clk_9116_g; +} __packed; + struct bootup_params { __le16 magic_number; __le16 crystal_good_time; @@ -127,4 +157,37 @@ struct bootup_params { __le32 max_threshold_to_avoid_sleep; u8 beacon_resedue_alg_en; } __packed; + +struct bootup_params_9116 { + __le16 magic_number; +#define LOADED_TOKEN 0x5AA5 /* Bootup params are installed by host + * or OTP/FLASH (Bootloader) + */ +#define ROM_TOKEN 0x55AA /* Bootup params are taken from ROM + * itself in MCU mode. + */ + __le16 crystal_good_time; + __le32 valid; + __le32 reserved_for_valids; + __le16 bootup_mode_info; +#define BT_COEXIST BIT(0) +#define BOOTUP_MODE (BIT(2) | BIT(1)) +#define CUR_DEV_MODE_9116 (bootup_params_9116.bootup_mode_info >> 1) + __le16 digital_loop_back_params; + __le16 rtls_timestamp_en; + __le16 host_spi_intr_cfg; + struct device_clk_info_9116 device_clk_info_9116[1]; + __le32 buckboost_wakeup_cnt; + __le16 pmu_wakeup_wait; + u8 shutdown_wait_time; + u8 pmu_slp_clkout_sel; + __le32 wdt_prog_value; + __le32 wdt_soc_rst_delay; + __le32 dcdc_operation_mode; + __le32 soc_reset_wait_cnt; + __le32 waiting_time_at_fresh_sleep; + __le32 max_threshold_to_avoid_sleep; + u8 beacon_resedue_alg_en; +} __packed; + #endif diff --git a/drivers/net/wireless/rsi/rsi_hal.h b/drivers/net/wireless/rsi/rsi_hal.h index 327638cdd30b..46e36df9e8e3 100644 --- a/drivers/net/wireless/rsi/rsi_hal.h +++ b/drivers/net/wireless/rsi/rsi_hal.h @@ -70,6 +70,21 @@ #define RSI_WATCH_DOG_DELAY_TIMER_2 0x16f #define RSI_WATCH_DOG_TIMER_ENABLE 0x170 +/* Watchdog timer addresses for 9116 */ +#define NWP_AHB_BASE_ADDR 0x41300000 +#define NWP_WWD_INTERRUPT_TIMER (NWP_AHB_BASE_ADDR + 0x300) +#define NWP_WWD_SYSTEM_RESET_TIMER (NWP_AHB_BASE_ADDR + 0x304) +#define NWP_WWD_WINDOW_TIMER (NWP_AHB_BASE_ADDR + 0x308) +#define NWP_WWD_TIMER_SETTINGS (NWP_AHB_BASE_ADDR + 0x30C) +#define NWP_WWD_MODE_AND_RSTART (NWP_AHB_BASE_ADDR + 0x310) +#define NWP_WWD_RESET_BYPASS (NWP_AHB_BASE_ADDR + 0x314) +#define NWP_FSM_INTR_MASK_REG (NWP_AHB_BASE_ADDR + 0x104) + +/* Watchdog timer values */ +#define NWP_WWD_INT_TIMER_CLKS 5 +#define NWP_WWD_SYS_RESET_TIMER_CLKS 4 +#define NWP_WWD_TIMER_DISABLE 0xAA0001 + #define RSI_ULP_WRITE_0 00 #define RSI_ULP_WRITE_2 02 #define RSI_ULP_WRITE_50 50 @@ -113,9 +128,18 @@ #define BBP_INFO_40MHZ 0x6 #define FW_FLASH_OFFSET 0x820 -#define LMAC_VER_OFFSET (FW_FLASH_OFFSET + 0x200) +#define LMAC_VER_OFFSET_9113 (FW_FLASH_OFFSET + 0x200) +#define LMAC_VER_OFFSET_9116 0x22C2 #define MAX_DWORD_ALIGN_BYTES 64 #define RSI_COMMON_REG_SIZE 2 +#define RSI_9116_REG_SIZE 4 +#define FW_ALIGN_SIZE 4 +#define RSI_9116_FW_MAGIC_WORD 0x5aa5 + +#define MEM_ACCESS_CTRL_FROM_HOST 0x41300000 +#define RAM_384K_ACCESS_FROM_TA (BIT(2) | BIT(3) | BIT(4) | BIT(5) | \ + BIT(20) | BIT(21) | BIT(22) | \ + BIT(23) | BIT(24) | BIT(25)) struct bl_header { __le32 flags; @@ -130,6 +154,24 @@ struct ta_metadata { unsigned int address; }; +#define RSI_BL_CTRL_LEN_MASK 0xFFFFFF +#define RSI_BL_CTRL_SPI_32BIT_MODE BIT(27) +#define RSI_BL_CTRL_REL_TA_SOFTRESET BIT(28) +#define RSI_BL_CTRL_START_FROM_ROM_PC BIT(29) +#define RSI_BL_CTRL_SPI_8BIT_MODE BIT(30) +#define RSI_BL_CTRL_LAST_ENTRY BIT(31) +struct bootload_entry { + __le32 control; + __le32 dst_addr; +} __packed; + +struct bootload_ds { + __le16 fixed_pattern; + __le16 offset; + __le32 reserved; + struct bootload_entry bl_entry[7]; +} __packed; + struct rsi_mgmt_desc { __le16 len_qno; u8 frame_type; diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h index 35d13f35e9b0..73a19e43106b 100644 --- a/drivers/net/wireless/rsi/rsi_main.h +++ b/drivers/net/wireless/rsi/rsi_main.h @@ -111,9 +111,13 @@ extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...); #define RSI_WOW_ENABLED BIT(0) #define RSI_WOW_NO_CONNECTION BIT(1) -#define RSI_DEV_9113 1 #define RSI_MAX_RX_PKTS 64 +enum rsi_dev_model { + RSI_DEV_9113 = 0, + RSI_DEV_9116 +}; + struct version_info { u16 major; u16 minor; @@ -215,6 +219,17 @@ enum rsi_dfs_regions { RSI_REGION_WORLD }; +struct rsi_9116_features { + u8 pll_mode; + u8 rf_type; + u8 wireless_mode; + u8 afe_type; + u8 enable_ppe; + u8 dpd; + u32 sifs_tx_enable; + u32 ps_options; +}; + struct rsi_common { struct rsi_hw *priv; struct vif_priv vif_info[RSI_MAX_VIFS]; @@ -310,6 +325,7 @@ struct rsi_common { struct cfg80211_scan_request *hwscan; struct rsi_bgscan_params bgscan; + struct rsi_9116_features w9116_features; u8 bgscan_en; u8 mac_ops_resumed; }; @@ -329,7 +345,7 @@ struct eeprom_read { struct rsi_hw { struct rsi_common *priv; - u8 device_model; + enum rsi_dev_model device_model; struct ieee80211_hw *hw; struct ieee80211_vif *vifs[RSI_MAX_VIFS]; struct ieee80211_tx_queue_params edca_params[NUM_EDCA_QUEUES]; @@ -381,6 +397,7 @@ struct rsi_host_intf_ops { u32 instructions_size, u16 block_size, u8 *fw); int (*reinit_device)(struct rsi_hw *adapter); + int (*ta_reset)(struct rsi_hw *adapter); }; enum rsi_host_intf rsi_get_host_intf(void *priv); diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h index ea83faa15c7e..2ce2dcf57441 100644 --- a/drivers/net/wireless/rsi/rsi_mgmt.h +++ b/drivers/net/wireless/rsi/rsi_mgmt.h @@ -294,6 +294,7 @@ enum cmd_frame_type { COMMON_DEV_CONFIG = 0x28, RADIO_PARAMS_UPDATE = 0x29, WOWLAN_CONFIG_PARAMS = 0x2B, + FEATURES_ENABLE = 0x33, WOWLAN_WAKEUP_REASON = 0xc5 }; @@ -351,6 +352,15 @@ struct rsi_boot_params { struct bootup_params bootup_params; } __packed; +struct rsi_boot_params_9116 { + struct rsi_cmd_desc_dword0 desc_dword0; + struct rsi_cmd_desc_dword1 desc_dword1; + struct rsi_cmd_desc_dword2 desc_dword2; + __le16 reserved; + __le16 umac_clk; + struct bootup_params_9116 bootup_params; +} __packed; + struct rsi_peer_notify { struct rsi_cmd_desc desc; u8 mac_addr[6]; @@ -654,6 +664,22 @@ struct rsi_bgscan_probe { __le16 probe_req_length; } __packed; +#define RSI_DUTY_CYCLING BIT(0) +#define RSI_END_OF_FRAME BIT(1) +#define RSI_SIFS_TX_ENABLE BIT(2) +#define RSI_DPD BIT(3) +struct rsi_wlan_9116_features { + struct rsi_cmd_desc desc; + u8 pll_mode; + u8 rf_type; + u8 wireless_mode; + u8 enable_ppe; + u8 afe_type; + u8 reserved1; + __le16 reserved2; + __le32 feature_enable; +}; + static inline u32 rsi_get_queueno(u8 *addr, u16 offset) { return (le16_to_cpu(*(__le16 *)&addr[offset]) & 0x7000) >> 12; diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h index 66dcd2ec9051..c5cfb6238f73 100644 --- a/drivers/net/wireless/rsi/rsi_sdio.h +++ b/drivers/net/wireless/rsi/rsi_sdio.h @@ -28,8 +28,9 @@ #include <linux/mmc/sdio_ids.h> #include "rsi_main.h" -#define RSI_SDIO_VID_9113 0x041B +#define RSI_SDIO_VENDOR_ID 0x041B #define RSI_SDIO_PID_9113 0x9330 +#define RSI_SDIO_PID_9116 0x9116 enum sdio_interrupt_type { BUFFER_FULL = 0x0, @@ -91,7 +92,7 @@ enum sdio_interrupt_type { #define TA_SOFT_RST_SET BIT(0) #define TA_PC_ZERO 0 #define TA_HOLD_THREAD_VALUE 0xF -#define TA_RELEASE_THREAD_VALUE cpu_to_le32(0xF) +#define TA_RELEASE_THREAD_VALUE 0xF #define TA_BASE_ADDR 0x2200 #define MISC_CFG_BASE_ADDR 0x4105 diff --git a/drivers/net/wireless/rsi/rsi_usb.h b/drivers/net/wireless/rsi/rsi_usb.h index 5b2eddd1a2ee..8702f434b569 100644 --- a/drivers/net/wireless/rsi/rsi_usb.h +++ b/drivers/net/wireless/rsi/rsi_usb.h @@ -22,8 +22,9 @@ #include "rsi_main.h" #include "rsi_common.h" -#define RSI_USB_VID_9113 0x1618 +#define RSI_USB_VENDOR_ID 0x1618 #define RSI_USB_PID_9113 0x9113 +#define RSI_USB_PID_9116 0x9116 #define USB_INTERNAL_REG_1 0x25000 #define RSI_USB_READY_MAGIC_NUM 0xab diff --git a/drivers/net/wireless/st/cw1200/main.c b/drivers/net/wireless/st/cw1200/main.c index 90dc979f260b..c1608f0bf6d0 100644 --- a/drivers/net/wireless/st/cw1200/main.c +++ b/drivers/net/wireless/st/cw1200/main.c @@ -345,6 +345,11 @@ static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr, mutex_init(&priv->wsm_cmd_mux); mutex_init(&priv->conf_mutex); priv->workqueue = create_singlethread_workqueue("cw1200_wq"); + if (!priv->workqueue) { + ieee80211_free_hw(hw); + return NULL; + } + sema_init(&priv->scan.lock, 1); INIT_WORK(&priv->scan.work, cw1200_scan_work); INIT_DELAYED_WORK(&priv->scan.probe_work, cw1200_probe_work); diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 348be0aed97e..0415a064f6e2 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -1700,14 +1700,14 @@ void wlcore_set_pending_regdomain_ch(struct wl1271 *wl, u16 channel, ch_bit_idx = wlcore_get_reg_conf_ch_idx(band, channel); if (ch_bit_idx >= 0 && ch_bit_idx <= WL1271_MAX_CHANNELS) - set_bit(ch_bit_idx, (long *)wl->reg_ch_conf_pending); + __set_bit_le(ch_bit_idx, (long *)wl->reg_ch_conf_pending); } int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl) { struct wl12xx_cmd_regdomain_dfs_config *cmd = NULL; int ret = 0, i, b, ch_bit_idx; - u32 tmp_ch_bitmap[2]; + __le32 tmp_ch_bitmap[2] __aligned(sizeof(unsigned long)); struct wiphy *wiphy = wl->hw->wiphy; struct ieee80211_supported_band *band; bool timeout = false; @@ -1717,7 +1717,7 @@ int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl) wl1271_debug(DEBUG_CMD, "cmd reg domain config"); - memset(tmp_ch_bitmap, 0, sizeof(tmp_ch_bitmap)); + memcpy(tmp_ch_bitmap, wl->reg_ch_conf_pending, sizeof(tmp_ch_bitmap)); for (b = NL80211_BAND_2GHZ; b <= NL80211_BAND_5GHZ; b++) { band = wiphy->bands[b]; @@ -1738,13 +1738,10 @@ int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl) if (ch_bit_idx < 0) continue; - set_bit(ch_bit_idx, (long *)tmp_ch_bitmap); + __set_bit_le(ch_bit_idx, (long *)tmp_ch_bitmap); } } - tmp_ch_bitmap[0] |= wl->reg_ch_conf_pending[0]; - tmp_ch_bitmap[1] |= wl->reg_ch_conf_pending[1]; - if (!memcmp(tmp_ch_bitmap, wl->reg_ch_conf_last, sizeof(tmp_ch_bitmap))) goto out; @@ -1754,8 +1751,8 @@ int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl) goto out; } - cmd->ch_bit_map1 = cpu_to_le32(tmp_ch_bitmap[0]); - cmd->ch_bit_map2 = cpu_to_le32(tmp_ch_bitmap[1]); + cmd->ch_bit_map1 = tmp_ch_bitmap[0]; + cmd->ch_bit_map2 = tmp_ch_bitmap[1]; cmd->dfs_region = wl->dfs_region; wl1271_debug(DEBUG_CMD, diff --git a/drivers/net/wireless/ti/wlcore/testmode.c b/drivers/net/wireless/ti/wlcore/testmode.c index dcb2c8b0feb6..affefaaea1ea 100644 --- a/drivers/net/wireless/ti/wlcore/testmode.c +++ b/drivers/net/wireless/ti/wlcore/testmode.c @@ -372,8 +372,8 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 nla_cmd; int err; - err = nla_parse(tb, WL1271_TM_ATTR_MAX, data, len, wl1271_tm_policy, - NULL); + err = nla_parse_deprecated(tb, WL1271_TM_ATTR_MAX, data, len, + wl1271_tm_policy, NULL); if (err) return err; diff --git a/drivers/net/wireless/ti/wlcore/vendor_cmd.c b/drivers/net/wireless/ti/wlcore/vendor_cmd.c index 7f34ec077ee5..75756fb8e7b0 100644 --- a/drivers/net/wireless/ti/wlcore/vendor_cmd.c +++ b/drivers/net/wireless/ti/wlcore/vendor_cmd.c @@ -41,8 +41,8 @@ wlcore_vendor_cmd_smart_config_start(struct wiphy *wiphy, if (!data) return -EINVAL; - ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len, - wlcore_vendor_attr_policy, NULL); + ret = nla_parse_deprecated(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len, + wlcore_vendor_attr_policy, NULL); if (ret) return ret; @@ -122,8 +122,8 @@ wlcore_vendor_cmd_smart_config_set_group_key(struct wiphy *wiphy, if (!data) return -EINVAL; - ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len, - wlcore_vendor_attr_policy, NULL); + ret = nla_parse_deprecated(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len, + wlcore_vendor_attr_policy, NULL); if (ret) return ret; diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index dd14850b0603..870eea3e7a27 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -320,9 +320,9 @@ struct wl1271 { bool watchdog_recovery; /* Reg domain last configuration */ - u32 reg_ch_conf_last[2] __aligned(8); + DECLARE_BITMAP(reg_ch_conf_last, 64); /* Reg domain pending configuration */ - u32 reg_ch_conf_pending[2]; + DECLARE_BITMAP(reg_ch_conf_pending, 64); /* Pointer that holds DMA-friendly block for the mailbox */ void *mbox; diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_usb.c b/drivers/net/wireless/zydas/zd1211rw/zd_usb.c index c2cda3acd4af..a094d5b3383c 100644 --- a/drivers/net/wireless/zydas/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zydas/zd1211rw/zd_usb.c @@ -1917,8 +1917,7 @@ int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, if (!urb) return -ENOMEM; - req_len = sizeof(struct usb_req_write_regs) + - count * sizeof(struct reg_data); + req_len = struct_size(req, reg_writes, count); req = kmalloc(req_len, GFP_KERNEL); if (!req) { r = -ENOMEM; |