This message generated a parse failure. Raw output follows here. Please use 'back' to navigate. From devnull@lkml.org Wed Apr 24 16:27:24 2024 >From mailfetcher Fri Jul 23 02:43:52 2021 Envelope-to: lkml@grols.ch Delivery-date: Fri, 23 Jul 2021 02:43:51 +0200 Received: from stout.grols.ch [195.201.141.146] by 72459556e3a9 with IMAP (fetchmail-6.3.26) for (single-drop); Fri, 23 Jul 2021 02:43:52 +0200 (CEST) Received: from vger.kernel.org ([23.128.96.18]) by stout.grols.ch with esmtp (Exim 4.92) (envelope-from ) id 1m6jHb-00042d-JS for lkml@grols.ch; Fri, 23 Jul 2021 02:43:51 +0200 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232870AbhGWACi (ORCPT ); Thu, 22 Jul 2021 20:02:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44922 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232907AbhGWACG (ORCPT ); Thu, 22 Jul 2021 20 Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 01FC3C061757 for ; Thu, 22 Jul 2021 17:42:32 -0700 (PDT) Received: by mail-wr1-x436.google.com with SMTP id g15so566592wrd.3 for ; Thu, 22 Jul 2021 17:42:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=philpotter-co-uk.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=LadHOtSAbdVxx2C35VUW5poqhz8m X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=LadHOtSAbdVxx2C35VUW5poqhz8mp6QdcghEEKn X-Gm-Message-State: AOAM532y5nmz/z7NpERe3BXrZOkAVqVHbKCHi3s84AZl4lXXm+nzQa+3 +IRTh0KK4ow+S3R+3WED6STQFw== X-Google-Smtp-Source: ABdhPJyeDii2EtwsHavfhvK91pp7wjfqTiM156RMvExl5r/cyREHO5UeNSNe06HHkYQePhDn++F+0g== X-Received: by 2002:a5d:59ae:: with SMTP id p14mr2526180wrr.148.1627000950382; Thu, 22 Jul 2021 17:42:30 -0700 (PDT) Received: from localhost.localdomain (2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.a.1.e.e.d.f.d.0.b.8.0.1.0.0.2.ip6.arpa. [2001:8b0:dfde:e1a0::2]) by smtp.gmail.com with ESMTPSA id m4sm31630498wrs.14.2021.07.22.17.42.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_S From: Phillip Potter To: gregkh@linuxfoundation.org Cc: Larry.Finger@lwfinger.net, dan.carpenter@oracle.com, linux-kernel@vger.kernel.org, linux-staging@lists.linux.dev, fabioaiuto83@gmail.com Subject: [PATCH 3/7] staging: rtl8188eu: introduce new hal dir for RTL8188eu driver Date: Fri, 23 Jul 2021 01:42:10 +0100 Message-Id: <20210723004214.912295-4-phil@philpotter.co.uk> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210723004214.912295-1-phil@philpotter.co.uk> References: <20210723004214.912295-1-phil@philpotter.co.uk> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-Id: X-Mailing-List: linux-kernel@vger.kernel.org Received-SPF: pass client-ip=23.128.96.18; envelope-from=linux-kernel-owner@vger.kernel.org; helo=vger.kernel.org X-Spam-Score: -2.4 X-Spam-Score-Bar: -- X-Spam-Action: no action X-Spam-Report: Action: no action Symbol: ARC_NA(0.00) Symbol: RCVD_VIA_SMTP_AUTH(0.00) Symbol: R_DKIM_ALLOW(-0.20) Symbol: RCVD_COUNT_FIVE(0.00) Symbol: FROM_HAS_DN(0.00) Symbol: R_SPF_ALLOW(-0.20) Symbol: PRECEDENCE_BULK(0.00) Symbol: MIME_GOOD(-0.10) Symbol: PREVIOUS This patchset is split in order to keep the file sizes down. This hal directory is part of the newer/better driver from GitHub modified by Larry Finger. Import this as the basis for all future work going forward. Suggested-by: Larry Finger Signed-off-by: Phillip Potter --- .../staging/rtl8188eu/hal/Hal8188EPwrSeq.c | 71 + .../rtl8188eu/hal/HalEfuseMask8188E_USB.c | 84 + .../rtl8188eu/hal/HalEfuseMask8188E_USB.h | 23 + drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c | 145 + .../staging/rtl8188eu/hal/btc/halbtcoutsrc.h | 997 ++ .../staging/rtl8188eu/hal/btc/mp_precomp.h | 49 + drivers/staging/rtl8188eu/hal/efuse_mask.h | 2 + drivers/staging/rtl8188eu/hal/hal8188e_s_fw.c | 7283 +++++++++++ drivers/staging/rtl8188eu/hal/hal8188e_s_fw.h | 26 + drivers/staging/rtl8188eu/hal/hal8188e_t_fw.c | 7730 ++++++++++++ drivers/staging/rtl8188eu/hal/hal8188e_t_fw.h | 25 + .../rtl8188eu/hal/hal8188erateadaptive.c | 1022 ++ .../rtl8188eu/hal/hal8188erateadaptive.h | 65 + drivers/staging/rtl8188eu/hal/hal8188ereg.h | 48 + drivers/staging/rtl8188eu/hal/hal_btcoex.c | 3786 ++++++ .../rtl8188eu/hal/hal_btcoex_wifionly.c | 131 + drivers/staging/rtl8188eu/hal/hal_com.c | 10540 ++++++++++++++++ drivers/staging/rtl8188eu/hal/hal_com_c2h.h | 103 + .../staging/rtl8188eu/hal/hal_com_phycfg.c | 5150 ++++++++ drivers/staging/rtl8188eu/hal/hal_dm.c | 186 + drivers/staging/rtl8188eu/hal/hal_dm.h | 9 + drivers/staging/rtl8188eu/hal/hal_intf.c | 1279 ++ drivers/staging/rtl8188eu/hal/hal_mcc.c | 1862 +++ drivers/staging/rtl8188eu/hal/hal_mp.c | 883 ++ drivers/staging/rtl8188eu/hal/hal_phy.c | 244 + drivers/staging/rtl8188eu/hal/hal_usb.c | 452 + drivers/staging/rtl8188eu/hal/hal_usb_led.c | 4235 +++++++ drivers/staging/rtl8188eu/hal/halcomtxbf.h | 135 + drivers/staging/rtl8188eu/hal/halhwimg.h | 78 + .../staging/rtl8188eu/hal/halhwimg8188e_bb.c | 1730 +++ .../staging/rtl8188eu/hal/halhwimg8188e_bb.h | 42 + .../staging/rtl8188eu/hal/halhwimg8188e_mac.c | 272 + .../staging/rtl8188eu/hal/halhwimg8188e_mac.h | 22 + .../staging/rtl8188eu/hal/halhwimg8188e_rf.c | 2183 ++++ .../staging/rtl8188eu/hal/halhwimg8188e_rf.h | 112 + .../staging/rtl8188eu/hal/halphyrf_8188e_ce.c | 1973 +++ .../staging/rtl8188eu/hal/halphyrf_8188e_ce.h | 92 + drivers/staging/rtl8188eu/hal/halphyrf_ap.h | 76 + drivers/staging/rtl8188eu/hal/halphyrf_ce.c | 635 + drivers/staging/rtl8188eu/hal/halphyrf_ce.h | 81 + .../staging/rtl8188eu/hal/haltxbfinterface.h | 14 + drivers/staging/rtl8188eu/hal/haltxbfjaguar.h | 74 + drivers/staging/rtl8188eu/hal/mp_precomp.h | 3 + drivers/staging/rtl8188eu/hal/phydm.c | 2341 ++++ drivers/staging/rtl8188eu/hal/phydm.h | 1069 ++ drivers/staging/rtl8188eu/hal/phydm_acs.c | 167 + drivers/staging/rtl8188eu/hal/phydm_acs.h | 50 + .../staging/rtl8188eu/hal/phydm_adaptivity.c | 823 ++ .../staging/rtl8188eu/hal/phydm_adaptivity.h | 159 + .../rtl8188eu/hal/phydm_adc_sampling.c | 594 + .../rtl8188eu/hal/phydm_adc_sampling.h | 123 + drivers/staging/rtl8188eu/hal/phydm_antdect.c | 847 ++ drivers/staging/rtl8188eu/hal/phydm_antdect.h | 78 + drivers/staging/rtl8188eu/hal/phydm_antdiv.c | 3194 +++++ drivers/staging/rtl8188eu/hal/phydm_antdiv.h | 516 + .../staging/rtl8188eu/hal/phydm_beamforming.h | 27 + drivers/staging/rtl8188eu/hal/phydm_ccx.c | 389 + drivers/staging/rtl8188eu/hal/phydm_ccx.h | 102 + .../staging/rtl8188eu/hal/phydm_cfotracking.c | 297 + .../staging/rtl8188eu/hal/phydm_cfotracking.h | 53 + drivers/staging/rtl8188eu/hal/phydm_debug.c | 2357 ++++ drivers/staging/rtl8188eu/hal/phydm_debug.h | 294 + drivers/staging/rtl8188eu/hal/phydm_dfs.c | 241 + drivers/staging/rtl8188eu/hal/phydm_dfs.h | 59 + drivers/staging/rtl8188eu/hal/phydm_dig.c | 1305 ++ drivers/staging/rtl8188eu/hal/phydm_dig.h | 292 + .../rtl8188eu/hal/phydm_dynamic_rx_path.c | 271 + .../rtl8188eu/hal/phydm_dynamic_rx_path.h | 93 + .../hal/phydm_dynamicbbpowersaving.c | 90 + .../hal/phydm_dynamicbbpowersaving.h | 41 + .../rtl8188eu/hal/phydm_dynamictxpower.c | 132 + .../rtl8188eu/hal/phydm_dynamictxpower.h | 69 + .../rtl8188eu/hal/phydm_edcaturbocheck.c | 192 + .../rtl8188eu/hal/phydm_edcaturbocheck.h | 49 + .../staging/rtl8188eu/hal/phydm_features.h | 38 + .../rtl8188eu/hal/phydm_hal_txbf_api.c | 72 + .../rtl8188eu/hal/phydm_hal_txbf_api.h | 28 + .../staging/rtl8188eu/hal/phydm_hwconfig.c | 2102 +++ .../staging/rtl8188eu/hal/phydm_hwconfig.h | 547 + .../staging/rtl8188eu/hal/phydm_interface.c | 451 + .../staging/rtl8188eu/hal/phydm_interface.h | 351 + drivers/staging/rtl8188eu/hal/phydm_iqk.h | 49 + drivers/staging/rtl8188eu/hal/phydm_kfree.c | 164 + drivers/staging/rtl8188eu/hal/phydm_kfree.h | 29 + .../rtl8188eu/hal/phydm_noisemonitor.c | 270 + .../rtl8188eu/hal/phydm_noisemonitor.h | 31 + drivers/staging/rtl8188eu/hal/phydm_pathdiv.c | 95 + drivers/staging/rtl8188eu/hal/phydm_pathdiv.h | 136 + .../rtl8188eu/hal/phydm_powertracking_ce.c | 646 + .../rtl8188eu/hal/phydm_powertracking_ce.h | 285 + .../staging/rtl8188eu/hal/phydm_pre_define.h | 578 + drivers/staging/rtl8188eu/hal/phydm_precomp.h | 60 + drivers/staging/rtl8188eu/hal/phydm_rainfo.c | 2198 ++++ drivers/staging/rtl8188eu/hal/phydm_rainfo.h | 484 + drivers/staging/rtl8188eu/hal/phydm_reg.h | 116 + .../rtl8188eu/hal/phydm_regconfig8188e.c | 184 + .../rtl8188eu/hal/phydm_regconfig8188e.h | 79 + .../rtl8188eu/hal/phydm_regdefine11ac.h | 77 + .../rtl8188eu/hal/phydm_regdefine11n.h | 196 + .../staging/rtl8188eu/hal/phydm_rtl8188e.c | 56 + .../staging/rtl8188eu/hal/phydm_rtl8188e.h | 51 + drivers/staging/rtl8188eu/hal/phydm_types.h | 142 + drivers/staging/rtl8188eu/hal/rtchnlplan.c | 287 + drivers/staging/rtl8188eu/hal/rtchnlplan.h | 615 + drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c | 790 ++ drivers/staging/rtl8188eu/hal/rtl8188e_dm.c | 275 + .../staging/rtl8188eu/hal/rtl8188e_hal_init.c | 4629 +++++++ .../staging/rtl8188eu/hal/rtl8188e_phycfg.c | 1713 +++ .../staging/rtl8188eu/hal/rtl8188e_rf6052.c | 245 + .../staging/rtl8188eu/hal/rtl8188e_rxdesc.c | 76 + .../staging/rtl8188eu/hal/rtl8188e_sreset.c | 84 + drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c | 290 + drivers/staging/rtl8188eu/hal/rtl8188eu_led.c | 144 + .../staging/rtl8188eu/hal/rtl8188eu_recv.c | 17 + .../staging/rtl8188eu/hal/rtl8188eu_xmit.c | 1261 ++ drivers/staging/rtl8188eu/hal/usb_halinit.c | 2135 ++++ drivers/staging/rtl8188eu/hal/usb_ops_linux.c | 246 + .../staging/rtl8188eu/hal/version_rtl8188e.h | 10 + 118 files changed, 92598 insertions(+) create mode 100644 drivers/staging/rtl8188eu/hal/Hal8188EPwrSeq.c create mode 100644 drivers/staging/rtl8188eu/hal/HalEfuseMask8188E_USB.c create mode 100644 drivers/staging/rtl8188eu/hal/HalEfuseMask8188E_USB.h create mode 100644 drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c create mode 100644 drivers/staging/rtl8188eu/hal/btc/halbtcoutsrc.h create mode 100644 drivers/staging/rtl8188eu/hal/btc/mp_precomp.h create mode 100644 drivers/staging/rtl8188eu/hal/efuse_mask.h create mode 100644 drivers/staging/rtl8188eu/hal/hal8188e_s_fw.c create mode 100644 drivers/staging/rtl8188eu/hal/hal8188e_s_fw.h create mode 100644 drivers/staging/rtl8188eu/hal/hal8188e_t_fw.c create mode 100644 drivers/staging/rtl8188eu/hal/hal8188e_t_fw.h create mode 100644 drivers/staging/rtl8188eu/hal/hal8188erateadaptive.c create mode 100644 drivers/staging/rtl8188eu/hal/hal8188erateadaptive.h create mode 100644 drivers/staging/rtl8188eu/hal/hal8188ereg.h create mode 100644 drivers/staging/rtl8188eu/hal/hal_btcoex.c create mode 100644 drivers/staging/rtl8188eu/hal/hal_btcoex_wifionly.c create mode 100644 drivers/staging/rtl8188eu/hal/hal_com.c create mode 100644 drivers/staging/rtl8188eu/hal/hal_com_c2h.h create mode 100644 drivers/staging/rtl8188eu/hal/hal_com_phycfg.c create mode 100644 drivers/staging/rtl8188eu/hal/hal_dm.c create mode 100644 drivers/staging/rtl8188eu/hal/hal_dm.h create mode 100644 drivers/staging/rtl8188eu/hal/hal_intf.c create mode 100644 drivers/staging/rtl8188eu/hal/hal_mcc.c create mode 100644 drivers/staging/rtl8188eu/hal/hal_mp.c create mode 100644 drivers/staging/rtl8188eu/hal/hal_phy.c create mode 100644 drivers/staging/rtl8188eu/hal/hal_usb.c create mode 100644 drivers/staging/rtl8188eu/hal/hal_usb_led.c create mode 100644 drivers/staging/rtl8188eu/hal/halcomtxbf.h create mode 100644 drivers/staging/rtl8188eu/hal/halhwimg.h create mode 100644 drivers/staging/rtl8188eu/hal/halhwimg8188e_bb.c create mode 100644 drivers/staging/rtl8188eu/hal/halhwimg8188e_bb.h create mode 100644 drivers/staging/rtl8188eu/hal/halhwimg8188e_mac.c create mode 100644 drivers/staging/rtl8188eu/hal/halhwimg8188e_mac.h create mode 100644 drivers/staging/rtl8188eu/hal/halhwimg8188e_rf.c create mode 100644 drivers/staging/rtl8188eu/hal/halhwimg8188e_rf.h create mode 100644 drivers/staging/rtl8188eu/hal/halphyrf_8188e_ce.c create mode 100644 drivers/staging/rtl8188eu/hal/halphyrf_8188e_ce.h create mode 100644 drivers/staging/rtl8188eu/hal/halphyrf_ap.h create mode 100644 drivers/staging/rtl8188eu/hal/halphyrf_ce.c create mode 100644 drivers/staging/rtl8188eu/hal/halphyrf_ce.h create mode 100644 drivers/staging/rtl8188eu/hal/haltxbfinterface.h create mode 100644 drivers/staging/rtl8188eu/hal/haltxbfjaguar.h create mode 100644 drivers/staging/rtl8188eu/hal/mp_precomp.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_acs.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_acs.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_adaptivity.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_adaptivity.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_adc_sampling.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_adc_sampling.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_antdect.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_antdect.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_antdiv.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_antdiv.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_beamforming.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_ccx.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_ccx.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_cfotracking.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_cfotracking.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_debug.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_debug.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_dfs.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_dfs.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_dig.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_dig.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_dynamic_rx_path.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_dynamic_rx_path.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_dynamicbbpowersaving.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_dynamicbbpowersaving.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_dynamictxpower.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_dynamictxpower.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_edcaturbocheck.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_edcaturbocheck.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_features.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_hal_txbf_api.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_hal_txbf_api.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_hwconfig.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_hwconfig.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_interface.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_interface.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_iqk.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_kfree.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_kfree.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_noisemonitor.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_noisemonitor.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_pathdiv.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_pathdiv.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_powertracking_ce.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_powertracking_ce.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_pre_define.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_precomp.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_rainfo.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_rainfo.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_reg.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_regconfig8188e.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_regconfig8188e.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_regdefine11ac.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_regdefine11n.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_rtl8188e.c create mode 100644 drivers/staging/rtl8188eu/hal/phydm_rtl8188e.h create mode 100644 drivers/staging/rtl8188eu/hal/phydm_types.h create mode 100644 drivers/staging/rtl8188eu/hal/rtchnlplan.c create mode 100644 drivers/staging/rtl8188eu/hal/rtchnlplan.h create mode 100644 drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c create mode 100644 drivers/staging/rtl8188eu/hal/rtl8188e_dm.c create mode 100644 drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c create mode 100644 drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c create mode 100644 drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c create mode 100644 drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c create mode 100644 drivers/staging/rtl8188eu/hal/rtl8188e_sreset.c create mode 100644 drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c create mode 100644 drivers/staging/rtl8188eu/hal/rtl8188eu_led.c create mode 100644 drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c create mode 100644 drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c create mode 100644 drivers/staging/rtl8188eu/hal/usb_halinit.c create mode 100644 drivers/staging/rtl8188eu/hal/usb_ops_linux.c create mode 100644 drivers/staging/rtl8188eu/hal/version_rtl8188e.h diff --git a/drivers/staging/rtl8188eu/hal/Hal8188EPwrSeq.c b/drivers/staging/rtl8188eu/hal/Hal8188EPwrSeq.c new file mode 100644 index 000000000000..38ca0bc5458b --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/Hal8188EPwrSeq.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#include "Hal8188EPwrSeq.h" +#include + +/* + drivers should parse below arrays and do the corresponding actions +*/ +/* 3 Power on Array */ +WLAN_PWR_CFG rtl8188E_power_on_flow[RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS + RTL8188E_TRANS_END_STEPS] = { + RTL8188E_TRANS_CARDEMU_TO_ACT + RTL8188E_TRANS_END +}; + +/* 3Radio off Array */ +WLAN_PWR_CFG rtl8188E_radio_off_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_END_STEPS] = { + RTL8188E_TRANS_ACT_TO_CARDEMU + RTL8188E_TRANS_END +}; + +/* 3Card Disable Array */ +WLAN_PWR_CFG rtl8188E_card_disable_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + RTL8188E_TRANS_END_STEPS] = { + RTL8188E_TRANS_ACT_TO_CARDEMU + RTL8188E_TRANS_CARDEMU_TO_CARDDIS + RTL8188E_TRANS_END +}; + +/* 3 Card Enable Array */ +WLAN_PWR_CFG rtl8188E_card_enable_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + RTL8188E_TRANS_END_STEPS] = { + RTL8188E_TRANS_CARDDIS_TO_CARDEMU + RTL8188E_TRANS_CARDEMU_TO_ACT + RTL8188E_TRANS_END +}; + +/* 3Suspend Array */ +WLAN_PWR_CFG rtl8188E_suspend_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS + RTL8188E_TRANS_END_STEPS] = { + RTL8188E_TRANS_ACT_TO_CARDEMU + RTL8188E_TRANS_CARDEMU_TO_SUS + RTL8188E_TRANS_END +}; + +/* 3 Resume Array */ +WLAN_PWR_CFG rtl8188E_resume_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS + RTL8188E_TRANS_END_STEPS] = { + RTL8188E_TRANS_SUS_TO_CARDEMU + RTL8188E_TRANS_CARDEMU_TO_ACT + RTL8188E_TRANS_END +}; + + +/* 3HWPDN Array */ +WLAN_PWR_CFG rtl8188E_hwpdn_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + RTL8188E_TRANS_END_STEPS] = { + RTL8188E_TRANS_ACT_TO_CARDEMU + RTL8188E_TRANS_CARDEMU_TO_PDN + RTL8188E_TRANS_END +}; + +/* 3 Enter LPS */ +WLAN_PWR_CFG rtl8188E_enter_lps_flow[RTL8188E_TRANS_ACT_TO_LPS_STEPS + RTL8188E_TRANS_END_STEPS] = { + /* FW behavior */ + RTL8188E_TRANS_ACT_TO_LPS + RTL8188E_TRANS_END +}; + +/* 3 Leave LPS */ +WLAN_PWR_CFG rtl8188E_leave_lps_flow[RTL8188E_TRANS_LPS_TO_ACT_STEPS + RTL8188E_TRANS_END_STEPS] = { + /* FW behavior */ + RTL8188E_TRANS_LPS_TO_ACT + RTL8188E_TRANS_END +}; diff --git a/drivers/staging/rtl8188eu/hal/HalEfuseMask8188E_USB.c b/drivers/staging/rtl8188eu/hal/HalEfuseMask8188E_USB.c new file mode 100644 index 000000000000..a86c83a656a7 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/HalEfuseMask8188E_USB.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* #include "Mp_Precomp.h" */ +/* #include "../odm_precomp.h" */ + +#include + +#include "HalEfuseMask8188E_USB.h" + + +/****************************************************************************** +* MUSB.TXT +******************************************************************************/ + +static u8 Array_MP_8188E_MUSB[] = { + 0xFF, + 0xF3, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x0F, + 0xF1, + 0xFF, + 0xFF, + 0xFF, + 0x00, + 0x00, + 0x00, + 0xF7, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + +}; + +u16 +EFUSE_GetArrayLen_MP_8188E_MUSB(void) +{ + return sizeof(Array_MP_8188E_MUSB) / sizeof(u8); +} + +void +EFUSE_GetMaskArray_MP_8188E_MUSB( + u8 * Array +) +{ + u16 len = EFUSE_GetArrayLen_MP_8188E_MUSB(), i = 0; + + for (i = 0; i < len; ++i) + Array[i] = Array_MP_8188E_MUSB[i]; +} +bool +EFUSE_IsAddressMasked_MP_8188E_MUSB( + u16 Offset +) +{ + int r = Offset / 16; + int c = (Offset % 16) / 2; + int result = 0; + + if (c < 4) /* Upper double word */ + result = (Array_MP_8188E_MUSB[r] & (0x10 << c)); + else + result = (Array_MP_8188E_MUSB[r] & (0x01 << (c - 4))); + + return (result > 0) ? 0 : 1; +} diff --git a/drivers/staging/rtl8188eu/hal/HalEfuseMask8188E_USB.h b/drivers/staging/rtl8188eu/hal/HalEfuseMask8188E_USB.h new file mode 100644 index 000000000000..700d5d88107b --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/HalEfuseMask8188E_USB.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + + + +/****************************************************************************** +* MUSB.TXT +******************************************************************************/ + + +u16 +EFUSE_GetArrayLen_MP_8188E_MUSB(void); + +void +EFUSE_GetMaskArray_MP_8188E_MUSB( + u8 * Array +); + +bool +EFUSE_IsAddressMasked_MP_8188E_MUSB(/* TC: Test Chip, MP: MP Chip */ + u16 Offset +); diff --git a/drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c b/drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c new file mode 100644 index 000000000000..c42e44e79ef2 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +/*++ +Copyright (c) Realtek Semiconductor Corp. All rights reserved. + +Module Name: + HalPwrSeqCmd.c + +Abstract: + Implement HW Power sequence configuration CMD handling routine for Realtek devices. + +Major Change History: + When Who What + ---------- --------------- ------------------------------- + 2011-10-26 Lucas Modify to be compatible with SD4-CE driver. + 2011-07-07 Roger Create. + +--*/ +#include + + +/* + * Description: + * This routine deal with the Power Configuration CMDs parsing for RTL8723/RTL8188E Series IC. + * + * Assumption: + * We should follow specific format which was released from HW SD. + * + * 2011.07.07, added by Roger. + * */ +u8 HalPwrSeqCmdParsing( + PADAPTER padapter, + u8 CutVersion, + u8 FabVersion, + u8 InterfaceType, + WLAN_PWR_CFG PwrSeqCmd[]) +{ + WLAN_PWR_CFG PwrCfgCmd = {0}; + u8 bPollingBit = false; + u32 AryIdx = 0; + u8 value = 0; + u32 offset = 0; + u32 pollingCount = 0; /* polling autoload done. */ + u32 maxPollingCnt = 5000; + + do { + PwrCfgCmd = PwrSeqCmd[AryIdx]; + + + /* 2 Only Handle the command whose FAB, CUT, and Interface are matched */ + if ((GET_PWR_CFG_FAB_MASK(PwrCfgCmd) & FabVersion) && + (GET_PWR_CFG_CUT_MASK(PwrCfgCmd) & CutVersion) && + (GET_PWR_CFG_INTF_MASK(PwrCfgCmd) & InterfaceType)) { + switch (GET_PWR_CFG_CMD(PwrCfgCmd)) { + case PWR_CMD_READ: + break; + + case PWR_CMD_WRITE: + offset = GET_PWR_CFG_OFFSET(PwrCfgCmd); + +#ifdef CONFIG_SDIO_HCI + /* */ + /* We should deal with interface specific address mapping for some interfaces, e.g., SDIO interface */ + /* 2011.07.07. */ + /* */ + if (GET_PWR_CFG_BASE(PwrCfgCmd) == PWR_BASEADDR_SDIO) { + /* Read Back SDIO Local value */ + value = SdioLocalCmd52Read1Byte(padapter, offset); + + value &= ~(GET_PWR_CFG_MASK(PwrCfgCmd)); + value |= (GET_PWR_CFG_VALUE(PwrCfgCmd) & GET_PWR_CFG_MASK(PwrCfgCmd)); + + /* Write Back SDIO Local value */ + SdioLocalCmd52Write1Byte(padapter, offset, value); + } else +#endif + { +#ifdef CONFIG_GSPI_HCI + if (GET_PWR_CFG_BASE(PwrCfgCmd) == PWR_BASEADDR_SDIO) + offset = SPI_LOCAL_OFFSET | offset; +#endif + /* Read the value from system register */ + value = rtw_read8(padapter, offset); + + value = value & (~(GET_PWR_CFG_MASK(PwrCfgCmd))); + value = value | (GET_PWR_CFG_VALUE(PwrCfgCmd) & GET_PWR_CFG_MASK(PwrCfgCmd)); + + /* Write the value back to sytem register */ + rtw_write8(padapter, offset, value); + } + break; + + case PWR_CMD_POLLING: + + bPollingBit = false; + offset = GET_PWR_CFG_OFFSET(PwrCfgCmd); +#ifdef CONFIG_GSPI_HCI + if (GET_PWR_CFG_BASE(PwrCfgCmd) == PWR_BASEADDR_SDIO) + offset = SPI_LOCAL_OFFSET | offset; +#endif + do { +#ifdef CONFIG_SDIO_HCI + if (GET_PWR_CFG_BASE(PwrCfgCmd) == PWR_BASEADDR_SDIO) + value = SdioLocalCmd52Read1Byte(padapter, offset); + else +#endif + value = rtw_read8(padapter, offset); + + value = value & GET_PWR_CFG_MASK(PwrCfgCmd); + if (value == (GET_PWR_CFG_VALUE(PwrCfgCmd) & GET_PWR_CFG_MASK(PwrCfgCmd))) + bPollingBit = true; + else + rtw_udelay_os(10); + + if (pollingCount++ > maxPollingCnt) { + RTW_ERR("HalPwrSeqCmdParsing: Fail to polling Offset[%#x]=%02x\n", offset, value); + return false; + } + } while (!bPollingBit); + + break; + + case PWR_CMD_DELAY: + if (GET_PWR_CFG_VALUE(PwrCfgCmd) == PWRSEQ_DELAY_US) + rtw_udelay_os(GET_PWR_CFG_OFFSET(PwrCfgCmd)); + else + rtw_udelay_os(GET_PWR_CFG_OFFSET(PwrCfgCmd) * 1000); + break; + + case PWR_CMD_END: + /* When this command is parsed, end the process */ + return true; + break; + + default: + break; + } + } + + AryIdx++;/* Add Array Index */ + } while (1); + + return true; +} diff --git a/drivers/staging/rtl8188eu/hal/btc/halbtcoutsrc.h b/drivers/staging/rtl8188eu/hal/btc/halbtcoutsrc.h new file mode 100644 index 000000000000..0f25098cdda4 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/btc/halbtcoutsrc.h @@ -0,0 +1,997 @@ +#ifndef __HALBTC_OUT_SRC_H__ +#define __HALBTC_OUT_SRC_H__ + + +#define BTC_COEX_OFFLOAD 0 +#define BTC_TMP_BUF_SHORT 20 + +extern u8 gl_btc_trace_buf[]; +#define BTC_SPRINTF rsprintf +#define BTC_TRACE(_MSG_)\ +do {\ + if (GLBtcDbgType[COMP_COEX] & BIT(DBG_LOUD)) {\ + RTW_INFO("%s", _MSG_);\ + } \ +} while (0) +#define BT_PrintData(adapter, _MSG_, len, data) RTW_DBG_DUMP((_MSG_), data, len) + + +#define NORMAL_EXEC FALSE +#define FORCE_EXEC TRUE + +#define BTC_RF_OFF 0x0 +#define BTC_RF_ON 0x1 + +#define BTC_RF_A 0x0 +#define BTC_RF_B 0x1 +#define BTC_RF_C 0x2 +#define BTC_RF_D 0x3 + +#define BTC_SMSP SINGLEMAC_SINGLEPHY +#define BTC_DMDP DUALMAC_DUALPHY +#define BTC_DMSP DUALMAC_SINGLEPHY +#define BTC_MP_UNKNOWN 0xff + +#define BT_COEX_ANT_TYPE_PG 0 +#define BT_COEX_ANT_TYPE_ANTDIV 1 +#define BT_COEX_ANT_TYPE_DETECTED 2 + +#define BTC_MIMO_PS_STATIC 0 /* 1ss */ +#define BTC_MIMO_PS_DYNAMIC 1 /* 2ss */ + +#define BTC_RATE_DISABLE 0 +#define BTC_RATE_ENABLE 1 + +/* single Antenna definition */ +#define BTC_ANT_PATH_WIFI 0 +#define BTC_ANT_PATH_BT 1 +#define BTC_ANT_PATH_PTA 2 +#define BTC_ANT_PATH_WIFI5G 3 +#define BTC_ANT_PATH_AUTO 4 +/* dual Antenna definition */ +#define BTC_ANT_WIFI_AT_MA 0 +#define BTC_ANT_WIFI_AT_AUX 1 +#define BTC_ANT_WIFI_AT_DIVERSITY 2 +/* coupler Antenna definition */ +#define BTC_ANT_WIFI_AT_CPL_MA0 +#define BTC_ANT_WIFI_AT_CPL_AUX 1 + +typedef enum _BTC_POWERSAVE_TYPE { + BTC_PS_WIFI_NATIVE = 0, /* wifi original power save behavior */ + BTC_PS_LPS_ON = 1, + BTC_PS_LPS_OFF = 2, + BTC_PS_MAX +} BTC_POWERSAVE_TYPE, *PBTC_POWERSAVE_TYPE; + +typedef enum _BTC_BT_REG_TYPE { + BTC_BT_REG_RF = 0, + BTC_BT_REG_MODEM = 1, + BTC_BT_REG_BLUEWIZE = 2, + BTC_BT_REG_VENDOR = 3, + BTC_BT_REG_LE = 4, + BTC_BT_REG_MAX +} BTC_BT_REG_TYPE, *PBTC_BT_REG_TYPE; + +typedef enum _BTC_CHIP_INTERFACE { + BTC_INTF_UNKNOWN = 0, + BTC_INTF_PCI = 1, + BTC_INTF_USB = 2, + BTC_INTF_SDIO = 3, + BTC_INTF_MAX +} BTC_CHIP_INTERFACE, *PBTC_CHIP_INTERFACE; + +typedef enum _BTC_CHIP_TYPE { + BTC_CHIP_UNDEF = 0, + BTC_CHIP_CSR_BC4 = 1, + BTC_CHIP_CSR_BC8 = 2, + BTC_CHIP_RTL8723A = 3, + BTC_CHIP_RTL8821 = 4, + BTC_CHIP_RTL8723B = 5, + BTC_CHIP_MAX +} BTC_CHIP_TYPE, *PBTC_CHIP_TYPE; + +/* following is for wifi link status */ +#define WIFI_STA_CONNECTED BIT0 +#define WIFI_AP_CONNECTED BIT1 +#define WIFI_HS_CONNECTED BIT2 +#define WIFI_P2P_GO_CONNECTED BIT3 +#define WIFI_P2P_GC_CONNECTED BIT4 + +/* following is for command line utility */ +#define CL_SPRINTF rsprintf +#define CL_PRINTF DCMD_Printf + +struct btc_board_info { + /* The following is some board information */ + u8 bt_chip_type; + u8 pg_ant_num; /* pg ant number */ + u8 btdm_ant_num; /* ant number for btdm */ + u8 btdm_ant_num_by_ant_det; /* ant number for btdm after antenna detection */ + u8 btdm_ant_pos; /* Bryant Add to indicate Antenna Position for (pg_ant_num = 2) && (btdm_ant_num =1) (DPDT+1Ant case) */ + u8 single_ant_path; /* current used for 8723b only, 1=>s0, 0=>s1 */ + bool tfbga_package; /* for Antenna detect threshold */ + bool btdm_ant_det_finish; + bool btdm_ant_det_already_init_phydm; + u8 ant_type; + u8 rfe_type; + u8 ant_div_cfg; + bool btdm_ant_det_complete_fail; + u8 ant_det_result; + bool ant_det_result_five_complete; + u32 antdetval; +}; + +typedef enum _BTC_DBG_OPCODE { + BTC_DBG_SET_COEX_NORMAL = 0x0, + BTC_DBG_SET_COEX_WIFI_ONLY = 0x1, + BTC_DBG_SET_COEX_BT_ONLY = 0x2, + BTC_DBG_SET_COEX_DEC_BT_PWR = 0x3, + BTC_DBG_SET_COEX_BT_AFH_MAP = 0x4, + BTC_DBG_SET_COEX_BT_IGNORE_WLAN_ACT = 0x5, + BTC_DBG_SET_COEX_MANUAL_CTRL = 0x6, + BTC_DBG_MAX +} BTC_DBG_OPCODE, *PBTC_DBG_OPCODE; + +typedef enum _BTC_RSSI_STATE { + BTC_RSSI_STATE_HIGH = 0x0, + BTC_RSSI_STATE_MEDIUM = 0x1, + BTC_RSSI_STATE_LOW = 0x2, + BTC_RSSI_STATE_STAY_HIGH = 0x3, + BTC_RSSI_STATE_STAY_MEDIUM = 0x4, + BTC_RSSI_STATE_STAY_LOW = 0x5, + BTC_RSSI_MAX +} BTC_RSSI_STATE, *PBTC_RSSI_STATE; +#define BTC_RSSI_HIGH(_rssi_) ((_rssi_ == BTC_RSSI_STATE_HIGH || _rssi_ == BTC_RSSI_STATE_STAY_HIGH) ? TRUE:FALSE) +#define BTC_RSSI_MEDIUM(_rssi_) ((_rssi_ == BTC_RSSI_STATE_MEDIUM || _rssi_ == BTC_RSSI_STATE_STAY_MEDIUM) ? TRUE:FALSE) +#define BTC_RSSI_LOW(_rssi_) ((_rssi_ == BTC_RSSI_STATE_LOW || _rssi_ == BTC_RSSI_STATE_STAY_LOW) ? TRUE:FALSE) + +typedef enum _BTC_WIFI_ROLE { + BTC_ROLE_STATION = 0x0, + BTC_ROLE_AP = 0x1, + BTC_ROLE_IBSS = 0x2, + BTC_ROLE_HS_MODE = 0x3, + BTC_ROLE_MAX +} BTC_WIFI_ROLE, *PBTC_WIFI_ROLE; + +typedef enum _BTC_WIRELESS_FREQ { + BTC_FREQ_2_4G = 0x0, + BTC_FREQ_5G = 0x1, + BTC_FREQ_MAX +} BTC_WIRELESS_FREQ, *PBTC_WIRELESS_FREQ; + +typedef enum _BTC_WIFI_BW_MODE { + BTC_WIFI_BW_LEGACY = 0x0, + BTC_WIFI_BW_HT20 = 0x1, + BTC_WIFI_BW_HT40 = 0x2, + BTC_WIFI_BW_HT80 = 0x3, + BTC_WIFI_BW_HT160 = 0x4, + BTC_WIFI_BW_MAX +} BTC_WIFI_BW_MODE, *PBTC_WIFI_BW_MODE; + +typedef enum _BTC_WIFI_TRAFFIC_DIR { + BTC_WIFI_TRAFFIC_TX = 0x0, + BTC_WIFI_TRAFFIC_RX = 0x1, + BTC_WIFI_TRAFFIC_MAX +} BTC_WIFI_TRAFFIC_DIR, *PBTC_WIFI_TRAFFIC_DIR; + +typedef enum _BTC_WIFI_PNP { + BTC_WIFI_PNP_WAKE_UP = 0x0, + BTC_WIFI_PNP_SLEEP = 0x1, + BTC_WIFI_PNP_SLEEP_KEEP_ANT = 0x2, + BTC_WIFI_PNP_MAX +} BTC_WIFI_PNP, *PBTC_WIFI_PNP; + +typedef enum _BTC_IOT_PEER { + BTC_IOT_PEER_UNKNOWN = 0, + BTC_IOT_PEER_REALTEK = 1, + BTC_IOT_PEER_REALTEK_92SE = 2, + BTC_IOT_PEER_BROADCOM = 3, + BTC_IOT_PEER_RALINK = 4, + BTC_IOT_PEER_ATHEROS = 5, + BTC_IOT_PEER_CISCO = 6, + BTC_IOT_PEER_MERU = 7, + BTC_IOT_PEER_MARVELL = 8, + BTC_IOT_PEER_REALTEK_SOFTAP = 9, /* peer is RealTek SOFT_AP, by Bohn, 2009.12.17 */ + BTC_IOT_PEER_SELF_SOFTAP = 10, /* Self is SoftAP */ + BTC_IOT_PEER_AIRGO = 11, + BTC_IOT_PEER_INTEL = 12, + BTC_IOT_PEER_RTK_APCLIENT = 13, + BTC_IOT_PEER_REALTEK_81XX = 14, + BTC_IOT_PEER_REALTEK_WOW = 15, + BTC_IOT_PEER_REALTEK_JAGUAR_BCUTAP = 16, + BTC_IOT_PEER_REALTEK_JAGUAR_CCUTAP = 17, + BTC_IOT_PEER_MAX, +} BTC_IOT_PEER, *PBTC_IOT_PEER; + +/* for 8723b-d cut large current issue */ +typedef enum _BTC_WIFI_COEX_STATE { + BTC_WIFI_STAT_INIT, + BTC_WIFI_STAT_IQK, + BTC_WIFI_STAT_NORMAL_OFF, + BTC_WIFI_STAT_MP_OFF, + BTC_WIFI_STAT_NORMAL, + BTC_WIFI_STAT_ANT_DIV, + BTC_WIFI_STAT_MAX +} BTC_WIFI_COEX_STATE, *PBTC_WIFI_COEX_STATE; + +typedef enum _BTC_ANT_TYPE { + BTC_ANT_TYPE_0, + BTC_ANT_TYPE_1, + BTC_ANT_TYPE_2, + BTC_ANT_TYPE_3, + BTC_ANT_TYPE_4, + BTC_ANT_TYPE_MAX +} BTC_ANT_TYPE, *PBTC_ANT_TYPE; + +typedef enum _BTC_VENDOR { + BTC_VENDOR_LENOVO, + BTC_VENDOR_ASUS, + BTC_VENDOR_OTHER +} BTC_VENDOR, *PBTC_VENDOR; + + +/* defined for BFP_BTC_GET */ +typedef enum _BTC_GET_TYPE { + /* type bool */ + BTC_GET_BL_HS_OPERATION, + BTC_GET_BL_HS_CONNECTING, + BTC_GET_BL_WIFI_FW_READY, + BTC_GET_BL_WIFI_CONNECTED, + BTC_GET_BL_WIFI_BUSY, + BTC_GET_BL_WIFI_SCAN, + BTC_GET_BL_WIFI_LINK, + BTC_GET_BL_WIFI_ROAM, + BTC_GET_BL_WIFI_4_WAY_PROGRESS, + BTC_GET_BL_WIFI_UNDER_5G, + BTC_GET_BL_WIFI_AP_MODE_ENABLE, + BTC_GET_BL_WIFI_ENABLE_ENCRYPTION, + BTC_GET_BL_WIFI_UNDER_B_MODE, + BTC_GET_BL_EXT_SWITCH, + BTC_GET_BL_WIFI_IS_IN_MP_MODE, + BTC_GET_BL_IS_ASUS_8723B, + + /* type s4Byte */ + BTC_GET_S4_WIFI_RSSI, + BTC_GET_S4_HS_RSSI, + + /* type u32 */ + BTC_GET_U4_WIFI_BW, + BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, + BTC_GET_U4_WIFI_FW_VER, + BTC_GET_U4_WIFI_LINK_STATUS, + BTC_GET_U4_BT_PATCH_VER, + BTC_GET_U4_VENDOR, + BTC_GET_U4_SUPPORTED_VERSION, + BTC_GET_U4_SUPPORTED_FEATURE, + BTC_GET_U4_WIFI_IQK_TOTAL, + BTC_GET_U4_WIFI_IQK_OK, + BTC_GET_U4_WIFI_IQK_FAIL, + + /* type u8 */ + BTC_GET_U1_WIFI_DOT11_CHNL, + BTC_GET_U1_WIFI_CENTRAL_CHNL, + BTC_GET_U1_WIFI_HS_CHNL, + BTC_GET_U1_WIFI_P2P_CHNL, + BTC_GET_U1_MAC_PHY_MODE, + BTC_GET_U1_AP_NUM, + BTC_GET_U1_ANT_TYPE, + BTC_GET_U1_IOT_PEER, + + /*===== for 1Ant ======*/ + BTC_GET_U1_LPS_MODE, + + BTC_GET_MAX +} BTC_GET_TYPE, *PBTC_GET_TYPE; + +/* defined for BFP_BTC_SET */ +typedef enum _BTC_SET_TYPE { + /* type bool */ + BTC_SET_BL_BT_DISABLE, + BTC_SET_BL_BT_ENABLE_DISABLE_CHANGE, + BTC_SET_BL_BT_TRAFFIC_BUSY, + BTC_SET_BL_BT_LIMITED_DIG, + BTC_SET_BL_FORCE_TO_ROAM, + BTC_SET_BL_TO_REJ_AP_AGG_PKT, + BTC_SET_BL_BT_CTRL_AGG_SIZE, + BTC_SET_BL_INC_SCAN_DEV_NUM, + BTC_SET_BL_BT_TX_RX_MASK, + BTC_SET_BL_MIRACAST_PLUS_BT, + + /* type u8 */ + BTC_SET_U1_RSSI_ADJ_VAL_FOR_AGC_TABLE_ON, + BTC_SET_U1_AGG_BUF_SIZE, + + /* type trigger some action */ + BTC_SET_ACT_GET_BT_RSSI, + BTC_SET_ACT_AGGREGATE_CTRL, + BTC_SET_ACT_ANTPOSREGRISTRY_CTRL, + /*===== for 1Ant ======*/ + /* type bool */ + + /* type u8 */ + BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE, + BTC_SET_U1_LPS_VAL, + BTC_SET_U1_RPWM_VAL, + /* type trigger some action */ + BTC_SET_ACT_LEAVE_LPS, + BTC_SET_ACT_ENTER_LPS, + BTC_SET_ACT_NORMAL_LPS, + BTC_SET_ACT_DISABLE_LOW_POWER, + BTC_SET_ACT_UPDATE_RAMASK, + BTC_SET_ACT_SEND_MIMO_PS, + /* BT Coex related */ + BTC_SET_ACT_CTRL_BT_INFO, + BTC_SET_ACT_CTRL_BT_COEX, + BTC_SET_ACT_CTRL_8723B_ANT, + /*=================*/ + BTC_SET_MAX +} BTC_SET_TYPE, *PBTC_SET_TYPE; + +typedef enum _BTC_DBG_DISP_TYPE { + BTC_DBG_DISP_COEX_STATISTICS = 0x0, + BTC_DBG_DISP_BT_LINK_INFO = 0x1, + BTC_DBG_DISP_WIFI_STATUS = 0x2, + BTC_DBG_DISP_MAX +} BTC_DBG_DISP_TYPE, *PBTC_DBG_DISP_TYPE; + +typedef enum _BTC_NOTIFY_TYPE_IPS { + BTC_IPS_LEAVE = 0x0, + BTC_IPS_ENTER = 0x1, + BTC_IPS_MAX +} BTC_NOTIFY_TYPE_IPS, *PBTC_NOTIFY_TYPE_IPS; +typedef enum _BTC_NOTIFY_TYPE_LPS { + BTC_LPS_DISABLE = 0x0, + BTC_LPS_ENABLE = 0x1, + BTC_LPS_MAX +} BTC_NOTIFY_TYPE_LPS, *PBTC_NOTIFY_TYPE_LPS; +typedef enum _BTC_NOTIFY_TYPE_SCAN { + BTC_SCAN_FINISH = 0x0, + BTC_SCAN_START = 0x1, + BTC_SCAN_START_2G = 0x2, + BTC_SCAN_MAX +} BTC_NOTIFY_TYPE_SCAN, *PBTC_NOTIFY_TYPE_SCAN; +typedef enum _BTC_NOTIFY_TYPE_SWITCHBAND { + BTC_NOT_SWITCH = 0x0, + BTC_SWITCH_TO_24G = 0x1, + BTC_SWITCH_TO_5G = 0x2, + BTC_SWITCH_TO_24G_NOFORSCAN = 0x3, + BTC_SWITCH_MAX +} BTC_NOTIFY_TYPE_SWITCHBAND, *PBTC_NOTIFY_TYPE_SWITCHBAND; +typedef enum _BTC_NOTIFY_TYPE_ASSOCIATE { + BTC_ASSOCIATE_FINISH = 0x0, + BTC_ASSOCIATE_START = 0x1, + BTC_ASSOCIATE_5G_FINISH = 0x2, + BTC_ASSOCIATE_5G_START = 0x3, + BTC_ASSOCIATE_MAX +} BTC_NOTIFY_TYPE_ASSOCIATE, *PBTC_NOTIFY_TYPE_ASSOCIATE; +typedef enum _BTC_NOTIFY_TYPE_MEDIA_STATUS { + BTC_MEDIA_DISCONNECT = 0x0, + BTC_MEDIA_CONNECT = 0x1, + BTC_MEDIA_MAX +} BTC_NOTIFY_TYPE_MEDIA_STATUS, *PBTC_NOTIFY_TYPE_MEDIA_STATUS; +typedef enum _BTC_NOTIFY_TYPE_SPECIFIC_PACKET { + BTC_PACKET_UNKNOWN = 0x0, + BTC_PACKET_DHCP = 0x1, + BTC_PACKET_ARP = 0x2, + BTC_PACKET_EAPOL = 0x3, + BTC_PACKET_MAX +} BTC_NOTIFY_TYPE_SPECIFIC_PACKET, *PBTC_NOTIFY_TYPE_SPECIFIC_PACKET; +typedef enum _BTC_NOTIFY_TYPE_STACK_OPERATION { + BTC_STACK_OP_NONE = 0x0, + BTC_STACK_OP_INQ_PAGE_PAIR_START = 0x1, + BTC_STACK_OP_INQ_PAGE_PAIR_FINISH = 0x2, + BTC_STACK_OP_MAX +} BTC_NOTIFY_TYPE_STACK_OPERATION, *PBTC_NOTIFY_TYPE_STACK_OPERATION; + +/* Bryant Add */ +typedef enum _BTC_ANTENNA_POS { + BTC_ANTENNA_AT_MAIN_PORT = 0x1, + BTC_ANTENNA_AT_AUX_PORT = 0x2, +} BTC_ANTENNA_POS, *PBTC_ANTENNA_POS; + +/* Bryant Add */ +typedef enum _BTC_BT_OFFON { + BTC_BT_OFF = 0x0, + BTC_BT_ON = 0x1, +} BTC_BTOFFON, *PBTC_BT_OFFON; + +/*================================================== +For following block is for coex offload +==================================================*/ +typedef struct _COL_H2C { + u8 opcode; + u8 opcode_ver:4; + u8 req_num:4; + u8 buf[1]; +} COL_H2C, *PCOL_H2C; + +#define COL_C2H_ACK_HDR_LEN 3 +typedef struct _COL_C2H_ACK { + u8 status; + u8 opcode_ver:4; + u8 req_num:4; + u8 ret_len; + u8 buf[1]; +} COL_C2H_ACK, *PCOL_C2H_ACK; + +#define COL_C2H_IND_HDR_LEN 3 +typedef struct _COL_C2H_IND { + u8 type; + u8 version; + u8 length; + u8 data[1]; +} COL_C2H_IND, *PCOL_C2H_IND; + +/*============================================ +NOTE: for debug message, the following define should match +the strings in coexH2cResultString. +============================================*/ +typedef enum _COL_H2C_STATUS { + /* c2h status */ + COL_STATUS_C2H_OK = 0x00, /* Wifi received H2C request and check content ok. */ + COL_STATUS_C2H_UNKNOWN = 0x01, /* Not handled routine */ + COL_STATUS_C2H_UNKNOWN_OPCODE = 0x02, /* Invalid OP code, It means that wifi firmware received an undefiend OP code. */ + COL_STATUS_C2H_OPCODE_VER_MISMATCH = 0x03, /* Wifi firmware and wifi driver mismatch, need to update wifi driver or wifi or. */ + COL_STATUS_C2H_PARAMETER_ERROR = 0x04, /* Error paraneter.(ex: parameters = NULL but it should have values) */ + COL_STATUS_C2H_PARAMETER_OUT_OF_RANGE = 0x05, /* Wifi firmware needs to check the parameters from H2C request and return the status.(ex: ch = 500, it's wrong) */ + /* other COL status start from here */ + COL_STATUS_C2H_REQ_NUM_MISMATCH , /* c2h req_num mismatch, means this c2h is not we expected. */ + COL_STATUS_H2C_HALMAC_FAIL , /* HALMAC return fail. */ + COL_STATUS_H2C_TIMT , /* not received the c2h response from fw */ + COL_STATUS_INVALID_C2H_LEN , /* invalid coex offload c2h ack length, must >= 3 */ + COL_STATUS_COEX_DATA_OVERFLOW , /* coex returned length over the c2h ack length. */ + COL_STATUS_MAX +} COL_H2C_STATUS, *PCOL_H2C_STATUS; + +#define COL_MAX_H2C_REQ_NUM 16 + +#define COL_H2C_BUF_LEN 20 +typedef enum _COL_OPCODE { + COL_OP_WIFI_STATUS_NOTIFY = 0x0, + COL_OP_WIFI_PROGRESS_NOTIFY = 0x1, + COL_OP_WIFI_INFO_NOTIFY = 0x2, + COL_OP_WIFI_POWER_STATE_NOTIFY = 0x3, + COL_OP_SET_CONTROL = 0x4, + COL_OP_GET_CONTROL = 0x5, + COL_OP_WIFI_OPCODE_MAX +} COL_OPCODE, *PCOL_OPCODE; + +typedef enum _COL_IND_TYPE { + COL_IND_BT_INFO = 0x0, + COL_IND_PSTDMA = 0x1, + COL_IND_LIMITED_TX_RX = 0x2, + COL_IND_COEX_TABLE = 0x3, + COL_IND_REQ = 0x4, + COL_IND_MAX +} COL_IND_TYPE, *PCOL_IND_TYPE; + +typedef struct _COL_SINGLE_H2C_RECORD { + u8 h2c_buf[COL_H2C_BUF_LEN]; /* the latest sent h2c buffer */ + u32 h2c_len; + u8 c2h_ack_buf[COL_H2C_BUF_LEN]; /* the latest received c2h buffer */ + u32 c2h_ack_len; + u32 count; /* the total number of the sent h2c command */ + u32 status[COL_STATUS_MAX]; /* the c2h status for the sent h2c command */ +} COL_SINGLE_H2C_RECORD, *PCOL_SINGLE_H2C_RECORD; + +typedef struct _COL_SINGLE_C2H_IND_RECORD { + u8 ind_buf[COL_H2C_BUF_LEN]; /* the latest received c2h indication buffer */ + u32 ind_len; + u32 count; /* the total number of the rcvd c2h indication */ + u32 status[COL_STATUS_MAX]; /* the c2h indication verified status */ +} COL_SINGLE_C2H_IND_RECORD, *PCOL_SINGLE_C2H_IND_RECORD; + +typedef struct _BTC_OFFLOAD { + /* H2C command related */ + u8 h2c_req_num; + u32 cnt_h2c_sent; + COL_SINGLE_H2C_RECORD h2c_record[COL_OP_WIFI_OPCODE_MAX]; + + /* C2H Ack related */ + u32 cnt_c2h_ack; + u32 status[COL_STATUS_MAX]; + struct completion c2h_event[COL_MAX_H2C_REQ_NUM]; /* for req_num = 1~COL_MAX_H2C_REQ_NUM */ + u8 c2h_ack_buf[COL_MAX_H2C_REQ_NUM][COL_H2C_BUF_LEN]; + u8 c2h_ack_len[COL_MAX_H2C_REQ_NUM]; + + /* C2H Indication related */ + u32 cnt_c2h_ind; + COL_SINGLE_C2H_IND_RECORD c2h_ind_record[COL_IND_MAX]; + u32 c2h_ind_status[COL_STATUS_MAX]; + u8 c2h_ind_buf[COL_H2C_BUF_LEN]; + u8 c2h_ind_len; +} BTC_OFFLOAD, *PBTC_OFFLOAD; +extern BTC_OFFLOAD gl_coex_offload; +/*==================================================*/ + +typedef u8 +(*BFP_BTC_R1)( + void * pBtcContext, + u32 RegAddr + ); +typedef u16 +(*BFP_BTC_R2)( + void * pBtcContext, + u32 RegAddr + ); +typedef u32 +(*BFP_BTC_R4)( + void * pBtcContext, + u32 RegAddr + ); +typedef void +(*BFP_BTC_W1)( + void * pBtcContext, + u32 RegAddr, + u8 Data + ); +typedef void +(*BFP_BTC_W1_BIT_MASK)( + void * pBtcContext, + u32 regAddr, + u8 bitMask, + u8 data1b + ); +typedef void +(*BFP_BTC_W2)( + void * pBtcContext, + u32 RegAddr, + u16 Data + ); +typedef void +(*BFP_BTC_W4)( + void * pBtcContext, + u32 RegAddr, + u32 Data + ); +typedef void +(*BFP_BTC_LOCAL_REG_W1)( + void * pBtcContext, + u32 RegAddr, + u8 Data + ); +typedef void +(*BFP_BTC_SET_BB_REG)( + void * pBtcContext, + u32 RegAddr, + u32 BitMask, + u32 Data + ); +typedef u32 +(*BFP_BTC_GET_BB_REG)( + void * pBtcContext, + u32 RegAddr, + u32 BitMask + ); +typedef void +(*BFP_BTC_SET_RF_REG)( + void * pBtcContext, + u8 eRFPath, + u32 RegAddr, + u32 BitMask, + u32 Data + ); +typedef u32 +(*BFP_BTC_GET_RF_REG)( + void * pBtcContext, + u8 eRFPath, + u32 RegAddr, + u32 BitMask + ); +typedef void +(*BFP_BTC_FILL_H2C)( + void * pBtcContext, + u8 elementId, + u32 cmdLen, + u8 * pCmdBuffer + ); + +typedef bool +(*BFP_BTC_GET)( + void * pBtCoexist, + u8 getType, + void * pOutBuf + ); + +typedef bool +(*BFP_BTC_SET)( + void * pBtCoexist, + u8 setType, + void * pInBuf + ); +typedef u16 +(*BFP_BTC_SET_BT_REG)( + void * pBtcContext, + u8 regType, + u32 offset, + u32 value + ); +typedef bool +(*BFP_BTC_SET_BT_ANT_DETECTION)( + void * pBtcContext, + u8 txTime, + u8 btChnl + ); + +typedef bool +(*BFP_BTC_SET_BT_TRX_MASK)( + void * pBtcContext, + u8 bt_trx_mask + ); + +typedef u32 +(*BFP_BTC_GET_BT_REG)( + void * pBtcContext, + u8 regType, + u32 offset + ); +typedef void +(*BFP_BTC_DISP_DBG_MSG)( + void * pBtCoexist, + u8 dispType + ); + +typedef COL_H2C_STATUS +(*BFP_BTC_COEX_H2C_PROCESS)( + void * pBtCoexist, + u8 opcode, + u8 opcode_ver, + u8 * ph2c_par, + u8 h2c_par_len + ); + +typedef u32 +(*BFP_BTC_GET_BT_COEX_SUPPORTED_FEATURE)( + void * pBtcContext + ); + +typedef u32 +(*BFP_BTC_GET_BT_COEX_SUPPORTED_VERSION)( + void * pBtcContext + ); + +typedef u32 +(*BFP_BTC_GET_PHYDM_VERSION)( + void * pBtcContext + ); + +typedef void +(*BTC_PHYDM_MODIFY_RA_PCR_THRESHLOD)( + void * pDM_Odm, + u8 RA_offset_direction, + u8 RA_threshold_offset + ); + +typedef u32 +(*BTC_PHYDM_CMNINFOQUERY)( + void * pDM_Odm, + u8 info_type + ); + +typedef u8 +(*BFP_BTC_GET_ANT_DET_VAL_FROM_BT)( + + void * pBtcContext + ); + +typedef u8 +(*BFP_BTC_GET_BLE_SCAN_TYPE_FROM_BT)( + void * pBtcContext + ); + +typedef u32 +(*BFP_BTC_GET_BLE_SCAN_PARA_FROM_BT)( + void * pBtcContext, + u8 scanType + ); + +typedef bool +(*BFP_BTC_GET_BT_AFH_MAP_FROM_BT)( + void * pBtcContext, + u8 mapType, + u8 * afhMap + ); + +struct btc_bt_info { + bool bt_disabled; + bool bt_enable_disable_change; + u8 rssi_adjust_for_agc_table_on; + u8 rssi_adjust_for_1ant_coex_type; + bool pre_bt_ctrl_agg_buf_size; + bool bt_ctrl_agg_buf_size; + bool pre_reject_agg_pkt; + bool reject_agg_pkt; + bool increase_scan_dev_num; + bool bt_tx_rx_mask; + u8 pre_agg_buf_size; + u8 agg_buf_size; + bool bt_busy; + bool limited_dig; + u16 bt_hci_ver; + u16 bt_real_fw_ver; + u8 bt_fw_ver; + u32 get_bt_fw_ver_cnt; + u32 bt_get_fw_ver; + bool miracast_plus_bt; + + bool bt_disable_low_pwr; + + bool bt_ctrl_lps; + bool bt_lps_on; + bool force_to_roam; /* for 1Ant solution */ + u8 lps_val; + u8 rpwm_val; + u32 ra_mask; +}; + +struct btc_stack_info { + bool profile_notified; + u16 hci_version; /* stack hci version */ + u8 num_of_link; + bool bt_link_exist; + bool sco_exist; + bool acl_exist; + bool a2dp_exist; + bool hid_exist; + u8 num_of_hid; + bool pan_exist; + bool unknown_acl_exist; + s8 min_bt_rssi; +}; + +struct btc_bt_link_info { + bool bt_link_exist; + bool bt_hi_pri_link_exist; + bool sco_exist; + bool sco_only; + bool a2dp_exist; + bool a2dp_only; + bool hid_exist; + bool hid_only; + bool pan_exist; + bool pan_only; + bool slave_role; + bool acl_busy; +}; + +struct btc_statistics { + u32 cnt_bind; + u32 cnt_power_on; + u32 cnt_pre_load_firmware; + u32 cnt_init_hw_config; + u32 cnt_init_coex_dm; + u32 cnt_ips_notify; + u32 cnt_lps_notify; + u32 cnt_scan_notify; + u32 cnt_connect_notify; + u32 cnt_media_status_notify; + u32 cnt_specific_packet_notify; + u32 cnt_bt_info_notify; + u32 cnt_rf_status_notify; + u32 cnt_periodical; + u32 cnt_coex_dm_switch; + u32 cnt_stack_operation_notify; + u32 cnt_dbg_ctrl; +}; + +struct btc_coexist { + bool bBinded; /*make sure only one adapter can bind the data context*/ + void * Adapter; /*default adapter*/ + struct btc_board_info board_info; + struct btc_bt_info bt_info; /*some bt info referenced by non-bt module*/ + struct btc_stack_info stack_info; + struct btc_bt_link_info bt_link_info; + BTC_CHIP_INTERFACE chip_interface; + void * odm_priv; + + bool initilized; + bool stop_coex_dm; + bool manual_control; + bool bdontenterLPS; + u8 * cli_buf; + struct btc_statistics statistics; + u8 pwrModeVal[10]; + + /* function pointers */ + /* io related */ + BFP_BTC_R1 btc_read_1byte; + BFP_BTC_W1 btc_write_1byte; + BFP_BTC_W1_BIT_MASK btc_write_1byte_bitmask; + BFP_BTC_R2 btc_read_2byte; + BFP_BTC_W2 btc_write_2byte; + BFP_BTC_R4 btc_read_4byte; + BFP_BTC_W4 btc_write_4byte; + BFP_BTC_LOCAL_REG_W1 btc_write_local_reg_1byte; + /* read/write bb related */ + BFP_BTC_SET_BB_REG btc_set_bb_reg; + BFP_BTC_GET_BB_REG btc_get_bb_reg; + + /* read/write rf related */ + BFP_BTC_SET_RF_REG btc_set_rf_reg; + BFP_BTC_GET_RF_REG btc_get_rf_reg; + + /* fill h2c related */ + BFP_BTC_FILL_H2C btc_fill_h2c; + /* other */ + BFP_BTC_DISP_DBG_MSG btc_disp_dbg_msg; + /* normal get/set related */ + BFP_BTC_GET btc_get; + BFP_BTC_SET btc_set; + + BFP_BTC_GET_BT_REG btc_get_bt_reg; + BFP_BTC_SET_BT_REG btc_set_bt_reg; + + BFP_BTC_SET_BT_ANT_DETECTION btc_set_bt_ant_detection; + + BFP_BTC_COEX_H2C_PROCESS btc_coex_h2c_process; + BFP_BTC_SET_BT_TRX_MASK btc_set_bt_trx_mask; + BFP_BTC_GET_BT_COEX_SUPPORTED_FEATURE btc_get_bt_coex_supported_feature; + BFP_BTC_GET_BT_COEX_SUPPORTED_VERSION btc_get_bt_coex_supported_version; + BFP_BTC_GET_PHYDM_VERSION btc_get_bt_phydm_version; + BTC_PHYDM_MODIFY_RA_PCR_THRESHLOD btc_phydm_modify_RA_PCR_threshold; + BTC_PHYDM_CMNINFOQUERY btc_phydm_query_PHY_counter; + BFP_BTC_GET_ANT_DET_VAL_FROM_BT btc_get_ant_det_val_from_bt; + BFP_BTC_GET_BLE_SCAN_TYPE_FROM_BT btc_get_ble_scan_type_from_bt; + BFP_BTC_GET_BLE_SCAN_PARA_FROM_BT btc_get_ble_scan_para_from_bt; + BFP_BTC_GET_BT_AFH_MAP_FROM_BT btc_get_bt_afh_map_from_bt; +}; +typedef struct btc_coexist *PBTC_COEXIST; + +extern struct btc_coexist GLBtCoexist; + +bool +EXhalbtcoutsrc_InitlizeVariables( + void * Adapter + ); +void +EXhalbtcoutsrc_PowerOnSetting( + PBTC_COEXIST pBtCoexist + ); +void +EXhalbtcoutsrc_PreLoadFirmware( + PBTC_COEXIST pBtCoexist + ); +void +EXhalbtcoutsrc_InitHwConfig( + PBTC_COEXIST pBtCoexist, + bool bWifiOnly + ); +void +EXhalbtcoutsrc_InitCoexDm( + PBTC_COEXIST pBtCoexist + ); +void +EXhalbtcoutsrc_IpsNotify( + PBTC_COEXIST pBtCoexist, + u8 type + ); +void +EXhalbtcoutsrc_LpsNotify( + PBTC_COEXIST pBtCoexist, + u8 type + ); +void +EXhalbtcoutsrc_ScanNotify( + PBTC_COEXIST pBtCoexist, + u8 type + ); +void +EXhalbtcoutsrc_SetAntennaPathNotify( + PBTC_COEXIST pBtCoexist, + u8 type + ); +void +EXhalbtcoutsrc_ConnectNotify( + PBTC_COEXIST pBtCoexist, + u8 action + ); +void +EXhalbtcoutsrc_MediaStatusNotify( + PBTC_COEXIST pBtCoexist, + RT_MEDIA_STATUS mediaStatus + ); +void +EXhalbtcoutsrc_SpecificPacketNotify( + PBTC_COEXIST pBtCoexist, + u8 pktType + ); +void +EXhalbtcoutsrc_BtInfoNotify( + PBTC_COEXIST pBtCoexist, + u8 * tmpBuf, + u8 length + ); +void +EXhalbtcoutsrc_RfStatusNotify( + PBTC_COEXIST pBtCoexist, + u8 type + ); +void +EXhalbtcoutsrc_StackOperationNotify( + PBTC_COEXIST pBtCoexist, + u8 type + ); +void +EXhalbtcoutsrc_HaltNotify( + PBTC_COEXIST pBtCoexist + ); +void +EXhalbtcoutsrc_PnpNotify( + PBTC_COEXIST pBtCoexist, + u8 pnpState + ); +void +EXhalbtcoutsrc_CoexDmSwitch( + PBTC_COEXIST pBtCoexist + ); +void +EXhalbtcoutsrc_Periodical( + PBTC_COEXIST pBtCoexist + ); +void +EXhalbtcoutsrc_DbgControl( + PBTC_COEXIST pBtCoexist, + u8 opCode, + u8 opLen, + u8 * pData + ); +void +EXhalbtcoutsrc_AntennaDetection( + PBTC_COEXIST pBtCoexist, + u32 centFreq, + u32 offset, + u32 span, + u32 seconds + ); +void +EXhalbtcoutsrc_StackUpdateProfileInfo( + void + ); +void +EXhalbtcoutsrc_SetHciVersion( + u16 hciVersion + ); +void +EXhalbtcoutsrc_SetBtPatchVersion( + u16 btHciVersion, + u16 btPatchVersion + ); +void +EXhalbtcoutsrc_UpdateMinBtRssi( + s8 btRssi + ); +void +EXhalbtcoutsrc_SetChipType( + u8 chipType + ); +void +EXhalbtcoutsrc_SetAntNum( + u8 type, + u8 antNum + ); +void +EXhalbtcoutsrc_SetSingleAntPath( + u8 singleAntPath + ); +void +EXhalbtcoutsrc_DisplayBtCoexInfo( + PBTC_COEXIST pBtCoexist + ); +void +EXhalbtcoutsrc_DisplayAntDetection( + PBTC_COEXIST pBtCoexist + ); + +#define MASKBYTE0 0xff +#define MASKBYTE1 0xff00 +#define MASKBYTE2 0xff0000 +#define MASKBYTE3 0xff000000 +#define MASKHWORD 0xffff0000 +#define MASKLWORD 0x0000ffff +#define MASKDWORD 0xffffffff +#define MASK12BITS 0xfff +#define MASKH4BITS 0xf0000000 +#define MASKOFDM_D 0xffc00000 +#define MASKCCK 0x3f3f3f3f + +#endif diff --git a/drivers/staging/rtl8188eu/hal/btc/mp_precomp.h b/drivers/staging/rtl8188eu/hal/btc/mp_precomp.h new file mode 100644 index 000000000000..17412fd54810 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/btc/mp_precomp.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#ifndef __MP_PRECOMP_H__ +#define __MP_PRECOMP_H__ + +#include +#include + +#define BT_TMP_BUF_SIZE 100 + +#define rsprintf snprintf + +#define DCMD_Printf DBG_BT_INFO + +#define delay_ms(ms) rtw_mdelay_os(ms) + +#ifdef bEnable +#undef bEnable +#endif + +#define WPP_SOFTWARE_TRACE 0 + +typedef enum _BTC_MSG_COMP_TYPE { + COMP_COEX = 0, + COMP_MAX +} BTC_MSG_COMP_TYPE; +extern u32 GLBtcDbgType[]; + +#define DBG_OFF 0 +#define DBG_SEC 1 +#define DBG_SERIOUS 2 +#define DBG_WARNING 3 +#define DBG_LOUD 4 +#define DBG_TRACE 5 + +#ifdef CONFIG_BT_COEXIST +#define BT_SUPPORT 1 +#define COEX_SUPPORT 1 +#define HS_SUPPORT 1 +#else +#define BT_SUPPORT 0 +#define COEX_SUPPORT 0 +#define HS_SUPPORT 0 +#endif + +#include "halbtcoutsrc.h" + +#endif /* __MP_PRECOMP_H__ */ diff --git a/drivers/staging/rtl8188eu/hal/efuse_mask.h b/drivers/staging/rtl8188eu/hal/efuse_mask.h new file mode 100644 index 000000000000..0669c2ef1b64 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/efuse_mask.h @@ -0,0 +1,2 @@ + + #include "HalEfuseMask8188E_USB.h" diff --git a/drivers/staging/rtl8188eu/hal/hal8188e_s_fw.c b/drivers/staging/rtl8188eu/hal/hal8188e_s_fw.c new file mode 100644 index 000000000000..23930e112b82 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal8188e_s_fw.c @@ -0,0 +1,7283 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#include "drv_types.h" + +#ifdef CONFIG_SFW_SUPPORTED + +#ifdef LOAD_FW_HEADER_FROM_DRIVER + +#if (defined(CONFIG_AP_WOWLAN)) + +u8 array_mp_8188e_s_fw_ap[] = { +0xE3, 0x88, 0x20, 0x00, 0x1C, 0x00, 0x00, 0x00, +0x05, 0x04, 0x22, 0x24, 0x96, 0x3E, 0x02, 0x00, +0xA5, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x02, 0x47, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x02, 0x48, 0x84, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x02, 0x57, 0xFA, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xE1, 0xFB, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x02, 0x4F, 0xF7, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xC2, 0xAF, 0x80, 0xFE, 0x32, 0x12, 0x43, 0x04, +0x85, 0xD0, 0x0B, 0x75, 0xD0, 0x08, 0xAA, 0xE0, +0xC2, 0x8C, 0xE5, 0x8A, 0x24, 0x67, 0xF5, 0x8A, +0xE5, 0x8C, 0x34, 0x79, 0xF5, 0x8C, 0xD2, 0x8C, +0xEC, 0x24, 0x87, 0xF8, 0xE6, 0xBC, 0x02, 0x02, +0x74, 0xFF, 0xC3, 0x95, 0x81, 0xB4, 0x40, 0x00, +0x40, 0xCE, 0x79, 0x03, 0x78, 0x80, 0x16, 0xE6, +0x08, 0x70, 0x0B, 0xC2, 0xAF, 0xE6, 0x30, 0xE1, +0x03, 0x44, 0x18, 0xF6, 0xD2, 0xAF, 0x08, 0xD9, +0xED, 0xEA, 0x8B, 0xD0, 0x22, 0xE5, 0x0C, 0xFF, +0x23, 0x24, 0x81, 0xF8, 0x0F, 0x08, 0x08, 0xBF, +0x03, 0x04, 0x7F, 0x00, 0x78, 0x81, 0xE6, 0x30, +0xE4, 0xF2, 0x00, 0xE5, 0x0C, 0xC3, 0x9F, 0x50, +0x20, 0x05, 0x0C, 0x74, 0x86, 0x25, 0x0C, 0xF8, +0xE6, 0xFD, 0xA6, 0x81, 0x08, 0xE6, 0xAE, 0x0C, +0xBE, 0x02, 0x02, 0x74, 0xFF, 0xCD, 0xF8, 0xE8, +0x6D, 0x60, 0xE0, 0x08, 0xE6, 0xC0, 0xE0, 0x80, +0xF6, 0xE5, 0x0C, 0xD3, 0x9F, 0x40, 0x27, 0xE5, +0x0C, 0x24, 0x87, 0xF8, 0xE6, 0xAE, 0x0C, 0xBE, +0x02, 0x02, 0x74, 0xFF, 0xFD, 0x18, 0xE6, 0xCD, +0xF8, 0xE5, 0x81, 0x6D, 0x60, 0x06, 0xD0, 0xE0, +0xF6, 0x18, 0x80, 0xF5, 0xE5, 0x0C, 0x24, 0x86, +0xC8, 0xF6, 0x15, 0x0C, 0x80, 0xD3, 0xE5, 0x0C, +0x23, 0x24, 0x81, 0xF8, 0x7F, 0x04, 0xC2, 0xAF, +0xE6, 0x30, 0xE0, 0x03, 0x10, 0xE2, 0x0C, 0x7F, +0x00, 0x30, 0xE1, 0x07, 0x30, 0xE3, 0x04, 0x7F, +0x08, 0x54, 0xF4, 0x54, 0x7C, 0xC6, 0xD2, 0xAF, +0x54, 0x80, 0x42, 0x07, 0x22, 0x78, 0x86, 0xA6, +0x81, 0x74, 0x02, 0x60, 0x06, 0xFF, 0x08, 0x76, +0xFF, 0xDF, 0xFB, 0x7F, 0x03, 0xE4, 0x78, 0x80, +0xF6, 0x08, 0xF6, 0x08, 0xDF, 0xFA, 0x78, 0x81, +0x76, 0x30, 0x90, 0x47, 0xF5, 0x74, 0x01, 0x93, +0xC0, 0xE0, 0xE4, 0x93, 0xC0, 0xE0, 0x43, 0x89, +0x01, 0x75, 0x8A, 0x60, 0x75, 0x8C, 0x79, 0xD2, +0x8C, 0xD2, 0xAF, 0x22, 0x02, 0xEF, 0xD3, 0x94, +0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, 0x74, 0x81, +0x2F, 0x2F, 0xF8, 0xE6, 0x20, 0xE5, 0xF4, 0xC2, +0xAF, 0xE6, 0x44, 0x30, 0xF6, 0xD2, 0xAF, 0xAE, +0x0C, 0xEE, 0xC3, 0x9F, 0x50, 0x21, 0x0E, 0x74, +0x86, 0x2E, 0xF8, 0xE6, 0xF9, 0x08, 0xE6, 0x18, +0xBE, 0x02, 0x02, 0x74, 0xFF, 0xFD, 0xED, 0x69, +0x60, 0x09, 0x09, 0xE7, 0x19, 0x19, 0xF7, 0x09, +0x09, 0x80, 0xF3, 0x16, 0x16, 0x80, 0xDA, 0xEE, +0xD3, 0x9F, 0x40, 0x04, 0x05, 0x81, 0x05, 0x81, +0xEE, 0xD3, 0x9F, 0x40, 0x22, 0x74, 0x86, 0x2E, +0xF8, 0x08, 0xE6, 0xF9, 0xEE, 0xB5, 0x0C, 0x02, +0xA9, 0x81, 0x18, 0x06, 0x06, 0xE6, 0xFD, 0xED, +0x69, 0x60, 0x09, 0x19, 0x19, 0xE7, 0x09, 0x09, +0xF7, 0x19, 0x80, 0xF3, 0x1E, 0x80, 0xD9, 0xEF, +0x24, 0x86, 0xF8, 0xE6, 0x04, 0xF8, 0xEF, 0x2F, +0x04, 0x90, 0x47, 0xF5, 0x93, 0xF6, 0x08, 0xEF, +0x2F, 0x93, 0xF6, 0x7F, 0x00, 0x22, 0xEF, 0xD3, +0x94, 0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, 0xEF, +0x23, 0x24, 0x81, 0xF8, 0xE6, 0x30, 0xE5, 0xF4, +0xC2, 0xAF, 0xE6, 0x54, 0x8C, 0xF6, 0xD2, 0xAF, +0xE5, 0x0C, 0xB5, 0x07, 0x0A, 0x74, 0x86, 0x2F, +0xF8, 0xE6, 0xF5, 0x81, 0x02, 0x43, 0x4D, 0x50, +0x2E, 0x74, 0x87, 0x2F, 0xF8, 0xE6, 0xBF, 0x02, +0x02, 0x74, 0xFF, 0xFD, 0x18, 0xE6, 0xF9, 0x74, +0x86, 0x2F, 0xF8, 0xFB, 0xE6, 0xFC, 0xE9, 0x6C, +0x60, 0x08, 0xA8, 0x05, 0xE7, 0xF6, 0x1D, 0x19, +0x80, 0xF4, 0xA8, 0x03, 0xA6, 0x05, 0x1F, 0xE5, +0x0C, 0xB5, 0x07, 0xE3, 0x7F, 0x00, 0x22, 0x74, +0x87, 0x2F, 0xF8, 0xE6, 0xFD, 0x18, 0x86, 0x01, +0x0F, 0x74, 0x86, 0x2F, 0xF8, 0xA6, 0x01, 0x08, +0x86, 0x04, 0xE5, 0x0C, 0xB5, 0x07, 0x02, 0xAC, +0x81, 0xED, 0x6C, 0x60, 0x08, 0x0D, 0x09, 0xA8, +0x05, 0xE6, 0xF7, 0x80, 0xF4, 0xE5, 0x0C, 0xB5, +0x07, 0xDE, 0x89, 0x81, 0x7F, 0x00, 0x22, 0xEF, +0xD3, 0x94, 0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, +0xEF, 0x23, 0x24, 0x81, 0xF8, 0xC2, 0xAF, 0xE6, +0x30, 0xE5, 0x05, 0x30, 0xE0, 0x02, 0xD2, 0xE4, +0xD2, 0xE2, 0xC6, 0xD2, 0xAF, 0x7F, 0x00, 0x30, +0xE2, 0x01, 0x0F, 0x02, 0x43, 0x4C, 0x8F, 0xF0, +0xE4, 0xFF, 0xFE, 0xE5, 0x0C, 0x23, 0x24, 0x80, +0xF8, 0xC2, 0xA9, 0x30, 0xF7, 0x0D, 0x7F, 0x08, +0xE6, 0x60, 0x0B, 0x2D, 0xF6, 0x60, 0x30, 0x50, +0x2E, 0x80, 0x07, 0x30, 0xF1, 0x06, 0xED, 0xF6, +0x60, 0x25, 0x7E, 0x02, 0x08, 0x30, 0xF0, 0x10, +0xC2, 0xAF, 0xE6, 0x10, 0xE7, 0x23, 0x0E, 0x30, +0xE2, 0x0C, 0xD2, 0xAF, 0x7F, 0x04, 0x80, 0x12, +0xC2, 0xAF, 0xE6, 0x10, 0xE7, 0x13, 0x54, 0xEC, +0x4E, 0xF6, 0xD2, 0xAF, 0x02, 0x43, 0x4D, 0x7F, +0x08, 0x08, 0xEF, 0x44, 0x83, 0xF4, 0xC2, 0xAF, +0x56, 0xC6, 0xD2, 0xAF, 0x54, 0x80, 0x4F, 0xFF, +0x22, 0xE7, 0x09, 0xF6, 0x08, 0xDF, 0xFA, 0x80, +0x46, 0xE7, 0x09, 0xF2, 0x08, 0xDF, 0xFA, 0x80, +0x3E, 0x88, 0x82, 0x8C, 0x83, 0xE7, 0x09, 0xF0, +0xA3, 0xDF, 0xFA, 0x80, 0x32, 0xE3, 0x09, 0xF6, +0x08, 0xDF, 0xFA, 0x80, 0x78, 0xE3, 0x09, 0xF2, +0x08, 0xDF, 0xFA, 0x80, 0x70, 0x88, 0x82, 0x8C, +0x83, 0xE3, 0x09, 0xF0, 0xA3, 0xDF, 0xFA, 0x80, +0x64, 0x89, 0x82, 0x8A, 0x83, 0xE0, 0xA3, 0xF6, +0x08, 0xDF, 0xFA, 0x80, 0x58, 0x89, 0x82, 0x8A, +0x83, 0xE0, 0xA3, 0xF2, 0x08, 0xDF, 0xFA, 0x80, +0x4C, 0x80, 0xD2, 0x80, 0xFA, 0x80, 0xC6, 0x80, +0xD4, 0x80, 0x69, 0x80, 0xF2, 0x80, 0x33, 0x80, +0x10, 0x80, 0xA6, 0x80, 0xEA, 0x80, 0x9A, 0x80, +0xA8, 0x80, 0xDA, 0x80, 0xE2, 0x80, 0xCA, 0x80, +0x33, 0x89, 0x82, 0x8A, 0x83, 0xEC, 0xFA, 0xE4, +0x93, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, 0xC5, +0x83, 0xCC, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, +0xCC, 0xC5, 0x83, 0xCC, 0xDF, 0xE9, 0xDE, 0xE7, +0x80, 0x0D, 0x89, 0x82, 0x8A, 0x83, 0xE4, 0x93, +0xA3, 0xF6, 0x08, 0xDF, 0xF9, 0xEC, 0xFA, 0xA9, +0xF0, 0xED, 0xFB, 0x22, 0x89, 0x82, 0x8A, 0x83, +0xEC, 0xFA, 0xE0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, +0xCC, 0xC5, 0x83, 0xCC, 0xF0, 0xA3, 0xC8, 0xC5, +0x82, 0xC8, 0xCC, 0xC5, 0x83, 0xCC, 0xDF, 0xEA, +0xDE, 0xE8, 0x80, 0xDB, 0x89, 0x82, 0x8A, 0x83, +0xE4, 0x93, 0xA3, 0xF2, 0x08, 0xDF, 0xF9, 0x80, +0xCC, 0x88, 0xF0, 0xEF, 0x60, 0x01, 0x0E, 0x4E, +0x60, 0xC3, 0x88, 0xF0, 0xED, 0x24, 0x02, 0xB4, +0x04, 0x00, 0x50, 0xB9, 0xF5, 0x82, 0xEB, 0x24, +0x02, 0xB4, 0x04, 0x00, 0x50, 0xAF, 0x23, 0x23, +0x45, 0x82, 0x23, 0x90, 0x45, 0xF9, 0x73, 0xC5, +0xF0, 0xF8, 0xA3, 0xE0, 0x28, 0xF0, 0xC5, 0xF0, +0xF8, 0xE5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, +0x83, 0xE0, 0x38, 0xF0, 0x22, 0xEF, 0x4B, 0xFF, +0xEE, 0x4A, 0xFE, 0xED, 0x49, 0xFD, 0xEC, 0x48, +0xFC, 0x22, 0xEB, 0x9F, 0xF5, 0xF0, 0xEA, 0x9E, +0x42, 0xF0, 0xE9, 0x9D, 0x42, 0xF0, 0xE8, 0x9C, +0x45, 0xF0, 0x22, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, +0xA3, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x22, 0xA4, +0x25, 0x82, 0xF5, 0x82, 0xE5, 0xF0, 0x35, 0x83, +0xF5, 0x83, 0x22, 0xE0, 0xFB, 0xA3, 0xE0, 0xFA, +0xA3, 0xE0, 0xF9, 0x22, 0xEB, 0xF0, 0xA3, 0xEA, +0xF0, 0xA3, 0xE9, 0xF0, 0x22, 0xD0, 0x83, 0xD0, +0x82, 0xF8, 0xE4, 0x93, 0x70, 0x12, 0x74, 0x01, +0x93, 0x70, 0x0D, 0xA3, 0xA3, 0x93, 0xF8, 0x74, +0x01, 0x93, 0xF5, 0x82, 0x88, 0x83, 0xE4, 0x73, +0x74, 0x02, 0x93, 0x68, 0x60, 0xEF, 0xA3, 0xA3, +0xA3, 0x80, 0xDF, 0xEF, 0x4E, 0x60, 0x12, 0xEF, +0x60, 0x01, 0x0E, 0xED, 0xBB, 0x01, 0x0B, 0x89, +0x82, 0x8A, 0x83, 0xF0, 0xA3, 0xDF, 0xFC, 0xDE, +0xFA, 0x22, 0x89, 0xF0, 0x50, 0x07, 0xF7, 0x09, +0xDF, 0xFC, 0xA9, 0xF0, 0x22, 0xBB, 0xFE, 0xFC, +0xF3, 0x09, 0xDF, 0xFC, 0xA9, 0xF0, 0x22, 0x02, +0x47, 0x8D, 0x02, 0x43, 0xDD, 0xE4, 0x93, 0xA3, +0xF8, 0xE4, 0x93, 0xA3, 0x40, 0x03, 0xF6, 0x80, +0x01, 0xF2, 0x08, 0xDF, 0xF4, 0x80, 0x29, 0xE4, +0x93, 0xA3, 0xF8, 0x54, 0x07, 0x24, 0x0C, 0xC8, +0xC3, 0x33, 0xC4, 0x54, 0x0F, 0x44, 0x20, 0xC8, +0x83, 0x40, 0x04, 0xF4, 0x56, 0x80, 0x01, 0x46, +0xF6, 0xDF, 0xE4, 0x80, 0x0B, 0x01, 0x02, 0x04, +0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x47, 0xD2, +0xE4, 0x7E, 0x01, 0x93, 0x60, 0xBC, 0xA3, 0xFF, +0x54, 0x3F, 0x30, 0xE5, 0x09, 0x54, 0x1F, 0xFE, +0xE4, 0x93, 0xA3, 0x60, 0x01, 0x0E, 0xCF, 0x54, +0xC0, 0x25, 0xE0, 0x60, 0xA8, 0x40, 0xB8, 0xE4, +0x93, 0xA3, 0xFA, 0xE4, 0x93, 0xA3, 0xF8, 0xE4, +0x93, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCA, 0xC5, +0x83, 0xCA, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, +0xCA, 0xC5, 0x83, 0xCA, 0xDF, 0xE9, 0xDE, 0xE7, +0x80, 0xBE, 0x41, 0x83, 0x27, 0x00, 0x41, 0x83, +0x28, 0x00, 0x41, 0x83, 0x35, 0x00, 0x41, 0x83, +0x38, 0x00, 0x44, 0x82, 0xF9, 0x41, 0x4E, 0x59, +0x00, 0x44, 0x82, 0xF5, 0x61, 0x6E, 0x79, 0x00, +0x41, 0x83, 0x39, 0x00, 0x00, 0x60, 0x03, 0x61, +0x0A, 0x66, 0x68, 0xC0, 0xE0, 0xC0, 0xF0, 0xC0, +0x83, 0xC0, 0x82, 0xC0, 0xD0, 0x75, 0xD0, 0x00, +0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x02, 0xC0, 0x03, +0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, +0x90, 0x01, 0xC4, 0x74, 0xFB, 0xF0, 0x74, 0x47, +0xA3, 0xF0, 0x11, 0x4A, 0x74, 0xFB, 0x04, 0x90, +0x01, 0xC4, 0xF0, 0x74, 0x47, 0xA3, 0xF0, 0xD0, +0x07, 0xD0, 0x06, 0xD0, 0x05, 0xD0, 0x04, 0xD0, +0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0xD0, +0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0, +0xE0, 0x32, 0x90, 0x00, 0x54, 0xE0, 0x55, 0x35, +0xF5, 0x39, 0xA3, 0xE0, 0x55, 0x36, 0xF5, 0x3A, +0xA3, 0xE0, 0x55, 0x37, 0xF5, 0x3B, 0xA3, 0xE0, +0x55, 0x38, 0xF5, 0x3C, 0xAD, 0x39, 0x7F, 0x54, +0x12, 0x32, 0x1E, 0xAD, 0x3A, 0x7F, 0x55, 0x12, +0x32, 0x1E, 0xAD, 0x3B, 0x7F, 0x56, 0x12, 0x32, +0x1E, 0xAD, 0x3C, 0x7F, 0x57, 0x12, 0x32, 0x1E, +0x53, 0x91, 0xEF, 0x22, 0xC0, 0xE0, 0xC0, 0xF0, +0xC0, 0x83, 0xC0, 0x82, 0xC0, 0xD0, 0x75, 0xD0, +0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x02, 0xC0, +0x03, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, +0x07, 0x90, 0x01, 0xC4, 0x74, 0x84, 0xF0, 0x74, +0x48, 0xA3, 0xF0, 0x12, 0x71, 0x3D, 0xE5, 0x41, +0x30, 0xE3, 0x03, 0x12, 0x71, 0x9A, 0xE5, 0x41, +0x30, 0xE4, 0x02, 0x31, 0x31, 0xE5, 0x43, 0x30, +0xE0, 0x02, 0xF1, 0x81, 0xE5, 0x43, 0x30, 0xE1, +0x03, 0x12, 0x71, 0xE3, 0xE5, 0x43, 0x30, 0xE2, +0x03, 0x12, 0x73, 0x19, 0xE5, 0x43, 0x30, 0xE3, +0x02, 0x91, 0xA4, 0xE5, 0x43, 0x30, 0xE4, 0x03, +0x12, 0x62, 0x8A, 0xE5, 0x43, 0x30, 0xE5, 0x03, +0x12, 0x62, 0x1B, 0xE5, 0x43, 0x30, 0xE6, 0x03, +0x12, 0x61, 0x56, 0xE5, 0x43, 0x30, 0xE7, 0x03, +0x12, 0x72, 0xBC, 0xE5, 0x44, 0x30, 0xE0, 0x03, +0x12, 0x72, 0xB4, 0xE5, 0x44, 0x30, 0xE1, 0x03, +0x12, 0x67, 0xD1, 0x74, 0x84, 0x04, 0x90, 0x01, +0xC4, 0xF0, 0x74, 0x48, 0xA3, 0xF0, 0xD0, 0x07, +0xD0, 0x06, 0xD0, 0x05, 0xD0, 0x04, 0xD0, 0x03, +0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0xD0, 0xD0, +0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0, 0xE0, +0x32, 0x31, 0x44, 0x7F, 0x02, 0x8F, 0x0F, 0x7F, +0x02, 0x12, 0x45, 0x27, 0x90, 0x80, 0x01, 0xE0, +0x45, 0x0F, 0xF0, 0x22, 0x90, 0x01, 0xCC, 0xE0, +0x54, 0x0F, 0x90, 0x83, 0x29, 0xF0, 0x90, 0x83, +0x29, 0xE0, 0xFD, 0x70, 0x02, 0x41, 0x3E, 0x90, +0x80, 0x60, 0xE0, 0xFF, 0x70, 0x06, 0xA3, 0xE0, +0x64, 0x09, 0x60, 0x0A, 0xEF, 0x14, 0xFF, 0x90, +0x80, 0x61, 0xE0, 0xB5, 0x07, 0x04, 0x7F, 0x01, +0x80, 0x02, 0x7F, 0x00, 0xEF, 0x60, 0x08, 0x90, +0x01, 0xC1, 0xE0, 0x44, 0x01, 0xF0, 0x22, 0x90, +0x83, 0x27, 0x12, 0x70, 0xCE, 0x80, 0x05, 0xC3, +0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, 0xEF, +0x5D, 0x70, 0x02, 0x41, 0x20, 0xE4, 0x90, 0x83, +0x2A, 0xF0, 0x90, 0x83, 0x2A, 0xE0, 0xF9, 0xC3, +0x94, 0x04, 0x50, 0x31, 0x71, 0x18, 0xA4, 0xFF, +0xE9, 0xFD, 0x7C, 0x00, 0x2F, 0xFF, 0xEC, 0x35, +0xF0, 0xFE, 0x74, 0xD0, 0x71, 0xF6, 0x90, 0x80, +0x10, 0x71, 0xD5, 0x71, 0x18, 0xA4, 0x2D, 0xFF, +0xEC, 0x35, 0xF0, 0xFE, 0x74, 0xF0, 0x71, 0xF6, +0x90, 0x80, 0x14, 0x71, 0xD5, 0x90, 0x83, 0x2A, +0xE0, 0x04, 0xF0, 0x80, 0xC5, 0x90, 0x83, 0x29, +0xE0, 0xFF, 0x90, 0x83, 0x27, 0xE0, 0xFE, 0x74, +0x01, 0xA8, 0x06, 0x08, 0x80, 0x02, 0xC3, 0x33, +0xD8, 0xFC, 0xF4, 0x5F, 0x90, 0x83, 0x29, 0xF0, +0x90, 0x83, 0x27, 0x51, 0x45, 0x80, 0x02, 0xC3, +0x33, 0xD8, 0xFC, 0x90, 0x01, 0xCC, 0xF0, 0x90, +0x83, 0x27, 0xE0, 0x04, 0xF0, 0xE0, 0x54, 0x03, +0xF0, 0x90, 0x80, 0x61, 0x12, 0x66, 0x61, 0xB4, +0x0A, 0x02, 0x7F, 0x01, 0xEF, 0x70, 0x02, 0x21, +0x4E, 0xE4, 0x90, 0x80, 0x61, 0xF0, 0x21, 0x4E, +0x90, 0x01, 0xC0, 0xE0, 0x44, 0x02, 0xF0, 0x90, +0x83, 0x27, 0xE0, 0x44, 0x80, 0x90, 0x00, 0x8A, +0xF0, 0x71, 0x18, 0x90, 0x01, 0xD0, 0x12, 0x46, +0xDF, 0xE0, 0x90, 0x01, 0xC3, 0xF0, 0x22, 0x12, +0x32, 0x1E, 0x90, 0x83, 0x2B, 0xE0, 0xFF, 0x74, +0x01, 0xA8, 0x07, 0x08, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x83, 0x2C, 0xED, +0xF0, 0x90, 0x83, 0x2B, 0xEF, 0xF0, 0xD3, 0x94, +0x07, 0x50, 0x4B, 0x51, 0x45, 0x80, 0x02, 0xC3, +0x33, 0xD8, 0xFC, 0xF4, 0xFF, 0x90, 0x00, 0x47, +0xE0, 0x5F, 0xFD, 0x7F, 0x47, 0x51, 0x3F, 0x80, +0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xFF, 0x90, 0x00, +0x46, 0xE0, 0x4F, 0xFD, 0x7F, 0x46, 0x71, 0xC1, +0x60, 0x10, 0x51, 0x42, 0x80, 0x02, 0xC3, 0x33, +0xD8, 0xFC, 0xFF, 0x90, 0x00, 0x45, 0xE0, 0x4F, +0x80, 0x0F, 0x51, 0x42, 0x80, 0x02, 0xC3, 0x33, +0xD8, 0xFC, 0xF4, 0xFF, 0x90, 0x00, 0x45, 0xE0, +0x5F, 0xFD, 0x7F, 0x45, 0x80, 0x62, 0x90, 0x83, +0x2B, 0xE0, 0x24, 0xF8, 0xF0, 0xE0, 0x24, 0x04, +0x51, 0x46, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, +0xF4, 0xFF, 0x90, 0x00, 0x43, 0xE0, 0x5F, 0xFD, +0x7F, 0x43, 0x51, 0x3F, 0x80, 0x02, 0xC3, 0x33, +0xD8, 0xFC, 0xFF, 0x90, 0x00, 0x43, 0xE0, 0x4F, +0xFD, 0x7F, 0x43, 0x71, 0xC1, 0x60, 0x19, 0x90, +0x83, 0x2B, 0xE0, 0x24, 0x04, 0x51, 0x46, 0x80, +0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xFF, 0x90, 0x00, +0x42, 0xE0, 0x4F, 0xFD, 0x7F, 0x42, 0x80, 0x18, +0x90, 0x83, 0x2B, 0xE0, 0x24, 0x04, 0x51, 0x46, +0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xF4, 0xFF, +0x90, 0x00, 0x42, 0xE0, 0x5F, 0xFD, 0x7F, 0x42, +0x12, 0x32, 0x1E, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x90, 0x83, 0x27, 0xE0, 0x75, 0xF0, 0x04, 0x22, +0xAD, 0x07, 0x90, 0x82, 0x21, 0xE0, 0x75, 0xF0, +0x20, 0xA4, 0xFF, 0x90, 0x83, 0x09, 0xE5, 0xF0, +0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x82, 0x22, 0xE0, +0x75, 0xF0, 0x08, 0xA4, 0xAE, 0xF0, 0x90, 0x83, +0x0B, 0xF0, 0xEE, 0xA3, 0xF0, 0x71, 0xB9, 0x90, +0x83, 0x0D, 0xF0, 0xEE, 0xA3, 0xF0, 0xED, 0x64, +0x01, 0x60, 0x5E, 0x90, 0x82, 0x1F, 0xE0, 0xFE, +0xF1, 0xF0, 0x30, 0xE0, 0x54, 0xEE, 0x71, 0xEA, +0x20, 0xE0, 0x02, 0x7D, 0x01, 0x71, 0xB2, 0xFE, +0x54, 0x0F, 0xFF, 0xEE, 0xC4, 0x13, 0x13, 0x54, +0x01, 0xFD, 0x71, 0xB2, 0xC4, 0x13, 0x54, 0x07, +0x30, 0xE0, 0x21, 0xA3, 0xE0, 0x30, 0xE0, 0x0D, +0x90, 0x83, 0x0E, 0xE0, 0xF5, 0x1D, 0x90, 0x83, +0x0D, 0x71, 0xC9, 0x80, 0x0F, 0x71, 0xB9, 0xFF, +0x12, 0x32, 0xAA, 0x71, 0xE5, 0x20, 0xE0, 0x02, +0x7D, 0x01, 0x51, 0x4D, 0x90, 0x82, 0x1F, 0xE0, +0xC4, 0x54, 0x0F, 0x30, 0xE0, 0x0B, 0x90, 0x83, +0x0C, 0xE0, 0xF5, 0x1D, 0x90, 0x83, 0x0B, 0x71, +0xC9, 0x22, 0x51, 0x4D, 0x90, 0x82, 0x1F, 0xE0, +0x22, 0x90, 0x83, 0x09, 0xE0, 0xFE, 0xA3, 0xE0, +0x22, 0x12, 0x32, 0x1E, 0x90, 0x83, 0x2C, 0xE0, +0x22, 0xE0, 0xF5, 0x1E, 0xE4, 0xFB, 0xFD, 0x7F, +0x58, 0x7E, 0x01, 0x80, 0x67, 0x12, 0x46, 0xDF, +0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE4, 0x35, 0x83, +0xF5, 0x83, 0xEF, 0xF0, 0x22, 0x90, 0x82, 0x1F, +0xE0, 0xFE, 0x54, 0x0F, 0xFF, 0xEE, 0xC4, 0x13, +0x13, 0x54, 0x03, 0x7D, 0x00, 0x22, 0x2F, 0xF5, +0x82, 0x74, 0x01, 0x3E, 0xF5, 0x83, 0xE0, 0xFF, +0x90, 0x80, 0x61, 0xE0, 0x75, 0xF0, 0x08, 0x22, +0x90, 0x82, 0x1F, 0xF1, 0xEE, 0x30, 0xE0, 0x1A, +0xEF, 0xC4, 0x54, 0x0F, 0x30, 0xE0, 0x03, 0x12, +0x65, 0x1F, 0x90, 0x82, 0x20, 0xE0, 0x30, 0xE0, +0x09, 0x71, 0xE5, 0x20, 0xE0, 0x02, 0x7D, 0x01, +0x51, 0x4D, 0x22, 0xF0, 0xE4, 0xF5, 0x1D, 0x90, +0x82, 0x03, 0xE0, 0xF5, 0x1E, 0xE4, 0xFB, 0xFD, +0x7F, 0x54, 0x7E, 0x01, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x8E, 0x19, 0x8F, 0x1A, 0xE5, +0x1E, 0x54, 0x07, 0xC4, 0x33, 0x54, 0xE0, 0x85, +0x19, 0x83, 0x85, 0x1A, 0x82, 0xF0, 0xE5, 0x1D, +0x91, 0x9C, 0xE5, 0x1E, 0x13, 0x13, 0x13, 0x54, +0x1F, 0x4F, 0xA3, 0xF0, 0xEB, 0x91, 0x9C, 0xE5, +0x1D, 0x13, 0x13, 0x13, 0x54, 0x1F, 0x4F, 0x91, +0x93, 0xF0, 0xBD, 0x01, 0x0D, 0x85, 0x1A, 0x82, +0x8E, 0x83, 0xA3, 0xA3, 0xA3, 0x74, 0x03, 0xF0, +0x80, 0x06, 0x91, 0x93, 0xA3, 0x74, 0x01, 0xF0, +0x91, 0x93, 0xA3, 0x74, 0x05, 0xF0, 0xD0, 0xD0, +0x92, 0xAF, 0x22, 0x85, 0x1A, 0x82, 0x85, 0x19, +0x83, 0xA3, 0xA3, 0x22, 0x54, 0x07, 0xC4, 0x33, +0x54, 0xE0, 0xFF, 0x22, 0xF1, 0xC8, 0x70, 0x12, +0x90, 0x81, 0x30, 0xE0, 0x60, 0x0C, 0x90, 0x81, +0x34, 0xE0, 0x20, 0xE4, 0x05, 0x12, 0x7D, 0xFD, +0x91, 0x2B, 0x22, 0x90, 0x81, 0x34, 0xE0, 0x44, +0x10, 0xF0, 0x90, 0x81, 0x39, 0xE0, 0x60, 0x04, +0x64, 0x01, 0x70, 0x15, 0xE4, 0xF5, 0x1D, 0x90, +0x81, 0x39, 0xE0, 0xFF, 0x90, 0x81, 0x38, 0xE0, +0x2F, 0x91, 0x33, 0x90, 0x81, 0x39, 0xE0, 0x80, +0x0F, 0xE4, 0xF5, 0x1D, 0x91, 0xFB, 0xFF, 0x90, +0x81, 0x38, 0xE0, 0x2F, 0x91, 0x33, 0x91, 0xFB, +0xFF, 0x90, 0x81, 0x38, 0xE0, 0x2F, 0x90, 0x81, +0x49, 0xF0, 0x22, 0x90, 0x81, 0x39, 0xE0, 0x75, +0xF0, 0x03, 0xA4, 0x24, 0xFE, 0x22, 0x90, 0x82, +0x09, 0xE0, 0x30, 0xE0, 0x49, 0xC4, 0x54, 0x0F, +0x20, 0xE0, 0x17, 0xE4, 0xF5, 0x1D, 0x90, 0x82, +0x0B, 0x91, 0x32, 0xD1, 0x90, 0xF1, 0xD1, 0x30, +0xE0, 0x06, 0x7D, 0x0C, 0x7F, 0x01, 0xB1, 0x57, +0xE1, 0xDE, 0x90, 0x82, 0x09, 0xE0, 0xC4, 0x54, +0x0F, 0x30, 0xE0, 0x22, 0xE4, 0xF5, 0x1D, 0x90, +0x82, 0x0C, 0x91, 0x32, 0x90, 0x82, 0x09, 0xE0, +0x54, 0xEF, 0xF0, 0xE0, 0xC3, 0x13, 0x30, 0xE0, +0x06, 0x7D, 0x04, 0x7F, 0x01, 0x80, 0x08, 0x7B, +0x31, 0xF1, 0xD8, 0x12, 0x69, 0x66, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xAC, 0x07, +0xEF, 0x14, 0x60, 0x15, 0x14, 0x60, 0x19, 0x24, +0x02, 0x70, 0x1A, 0xED, 0x54, 0x01, 0xFE, 0x90, +0x81, 0x2B, 0xE0, 0x54, 0xFE, 0x4E, 0xF0, 0x80, +0x0C, 0x90, 0x81, 0x33, 0xED, 0xF0, 0x80, 0x05, +0x90, 0x81, 0x32, 0xED, 0xF0, 0x90, 0x00, 0x8F, +0xE0, 0x30, 0xE4, 0x2E, 0xEC, 0x14, 0x60, 0x07, +0x14, 0x60, 0x1D, 0x24, 0x02, 0x70, 0x23, 0x90, +0x81, 0x2B, 0xE0, 0x54, 0x01, 0xC4, 0x33, 0x33, +0x33, 0x54, 0x80, 0xFF, 0x90, 0x81, 0x33, 0xE0, +0x54, 0x7F, 0x4F, 0xFD, 0x7F, 0x88, 0x80, 0x07, +0x90, 0x81, 0x32, 0xE0, 0xFD, 0x7F, 0x89, 0x12, +0x32, 0x1E, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x7E, +0x00, 0x7F, 0xD7, 0x7D, 0x00, 0x7B, 0x01, 0x7A, +0x81, 0x79, 0x2B, 0x12, 0x47, 0x23, 0x90, 0x81, +0x2F, 0x74, 0x02, 0xF0, 0x90, 0x81, 0x36, 0x14, +0xF0, 0xA3, 0xF0, 0xA3, 0x74, 0x10, 0xF0, 0x90, +0x81, 0x3C, 0xE4, 0xF0, 0xA3, 0x74, 0x05, 0xD1, +0x6B, 0xE4, 0xFD, 0xFF, 0xB1, 0x57, 0x7D, 0x0C, +0x7F, 0x02, 0xB1, 0x57, 0x7D, 0x0C, 0x7F, 0x01, +0xB1, 0x57, 0x90, 0x80, 0x07, 0xE0, 0xFF, 0xB4, +0x01, 0x08, 0x90, 0x81, 0x3B, 0x74, 0x99, 0xF0, +0x80, 0x29, 0xEF, 0xB4, 0x03, 0x08, 0x90, 0x81, +0x3B, 0x74, 0x90, 0xF0, 0x80, 0x1D, 0x90, 0x81, +0x3B, 0x74, 0x40, 0xF0, 0x90, 0x00, 0x2C, 0xE0, +0x54, 0x0F, 0xFF, 0xBF, 0x05, 0x08, 0x90, 0x81, +0x4D, 0x74, 0x02, 0xF0, 0x80, 0x05, 0xE4, 0x90, +0x81, 0x4D, 0xF0, 0x90, 0x82, 0x02, 0x74, 0x02, +0xF0, 0xA3, 0x74, 0x0F, 0xF0, 0xA3, 0xE0, 0x54, +0x01, 0x44, 0x28, 0xF0, 0xA3, 0x74, 0x07, 0xD1, +0x6B, 0x7E, 0x00, 0x7F, 0x02, 0x7D, 0x00, 0x7B, +0x01, 0x7A, 0x82, 0x79, 0x06, 0x12, 0x47, 0x23, +0xF1, 0xE6, 0x12, 0x7E, 0x8C, 0x7B, 0x56, 0xE4, +0xFD, 0x7F, 0xFF, 0xD1, 0x97, 0xE4, 0x90, 0x82, +0x08, 0xF0, 0x22, 0xF0, 0x90, 0x81, 0x4D, 0xE0, +0x24, 0x05, 0x90, 0x81, 0x48, 0xF0, 0xA3, 0x74, +0x10, 0xF0, 0x22, 0x90, 0x83, 0x33, 0xEF, 0xF0, +0xD1, 0xED, 0x90, 0x83, 0x33, 0xE0, 0x60, 0x02, +0xD1, 0x92, 0x7D, 0x04, 0x7F, 0x01, 0xA1, 0x57, +0xD1, 0xED, 0xE4, 0xFB, 0xFD, 0x7F, 0xFF, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x05, +0x22, 0xED, 0xF0, 0x90, 0x80, 0x05, 0xEB, 0xF0, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x81, 0x2C, +0xE0, 0xC3, 0x13, 0x20, 0xE0, 0x04, 0x7D, 0x0C, +0x80, 0x05, 0x12, 0x75, 0x72, 0x7D, 0x04, 0x7F, +0x01, 0xB1, 0x57, 0xE4, 0xFB, 0xFD, 0x7F, 0xFF, +0x80, 0xCD, 0x90, 0x81, 0x2C, 0xE0, 0x90, 0x06, +0x04, 0x20, 0xE0, 0x08, 0xE0, 0x44, 0x40, 0xF0, +0x7D, 0x04, 0x80, 0x06, 0xE0, 0x54, 0x7F, 0xF0, +0x7D, 0x0C, 0x7F, 0x01, 0xB1, 0x57, 0xE4, 0xFB, +0xFD, 0x7F, 0xFF, 0x80, 0xAA, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x01, 0x01, 0xE0, +0x44, 0x02, 0xF0, 0x90, 0x01, 0x00, 0x74, 0xFF, +0xF0, 0x90, 0x06, 0xB7, 0x74, 0x09, 0xF0, 0x90, +0x06, 0xB4, 0x74, 0x86, 0xF0, 0x12, 0x6A, 0xA3, +0x54, 0x7F, 0xFC, 0x90, 0x83, 0x1C, 0x12, 0x20, +0xCE, 0x90, 0x83, 0x1C, 0x12, 0x68, 0xD5, 0x7F, +0x7C, 0xF1, 0x6E, 0x12, 0x20, 0xDA, 0xCC, 0xC0, +0x00, 0xC0, 0xF1, 0x6C, 0x12, 0x20, 0xDA, 0x00, +0xC0, 0x00, 0x14, 0x12, 0x6A, 0xAC, 0x12, 0x20, +0xDA, 0x00, 0x03, 0x3E, 0x60, 0xE4, 0xFD, 0xFF, +0x12, 0x6A, 0x10, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x90, 0x82, 0x09, 0xE0, 0x30, 0xE0, 0x14, 0x90, +0x01, 0x57, 0xE4, 0xF0, 0xD1, 0x90, 0xF1, 0xD1, +0x30, 0xE0, 0x06, 0x7D, 0x0C, 0x7F, 0x01, 0xB1, +0x57, 0xF1, 0xDE, 0x22, 0xD1, 0x90, 0x7D, 0x0C, +0x7F, 0x01, 0xA1, 0x57, 0x7F, 0x8C, 0x7E, 0x08, +0x12, 0x2E, 0xA2, 0x90, 0x85, 0xBB, 0x22, 0xF1, +0xE6, 0xD1, 0x92, 0x7D, 0x0C, 0x7F, 0x01, 0xA1, +0x57, 0x12, 0x72, 0xCD, 0xF1, 0x97, 0xE4, 0xFF, +0x12, 0x50, 0x9C, 0x90, 0x80, 0xFC, 0xE0, 0x30, +0xE0, 0x03, 0x12, 0x5C, 0x41, 0x80, 0xB1, 0xE4, +0xF5, 0x51, 0x90, 0x81, 0x30, 0xE0, 0x60, 0x27, +0xF1, 0xC8, 0x70, 0x23, 0x12, 0x55, 0x27, 0x60, +0x0C, 0x90, 0x81, 0x2C, 0xE0, 0xC4, 0x13, 0x13, +0x54, 0x03, 0x20, 0xE0, 0x03, 0x75, 0x51, 0x01, +0xE5, 0x51, 0x60, 0x0B, 0x12, 0x7E, 0x18, 0x20, +0xE2, 0x03, 0x12, 0x51, 0x4D, 0x91, 0xBB, 0x22, +0xE4, 0xFF, 0x12, 0x53, 0x4B, 0xEF, 0x64, 0x01, +0x22, 0x90, 0x82, 0x09, 0xE0, 0xC3, 0x13, 0x22, +0x7D, 0xFF, 0x7F, 0xFF, 0xC1, 0x97, 0x90, 0x82, +0x09, 0xE0, 0x44, 0x10, 0xF0, 0x22, 0x90, 0x06, +0x04, 0xE0, 0x54, 0x7F, 0xF0, 0x22, 0xE0, 0xFF, +0xC4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x22, 0xC0, +0xE0, 0xC0, 0xF0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, +0xD0, 0x75, 0xD0, 0x00, 0xC0, 0x00, 0xC0, 0x01, +0xC0, 0x02, 0xC0, 0x03, 0xC0, 0x04, 0xC0, 0x05, +0xC0, 0x06, 0xC0, 0x07, 0x90, 0x01, 0xC4, 0x74, +0xF7, 0xF0, 0x74, 0x4F, 0xA3, 0xF0, 0x12, 0x71, +0x6A, 0xE5, 0x49, 0x30, 0xE1, 0x02, 0x11, 0xD1, +0xE5, 0x49, 0x30, 0xE2, 0x03, 0x12, 0x61, 0xD7, +0xE5, 0x49, 0x30, 0xE3, 0x03, 0x12, 0x6E, 0xBB, +0xE5, 0x49, 0x30, 0xE4, 0x02, 0xB1, 0xB7, 0xE5, +0x4A, 0x30, 0xE0, 0x03, 0x12, 0x6D, 0x0E, 0xE5, +0x4B, 0x30, 0xE5, 0x03, 0x12, 0x6F, 0x22, 0xE5, +0x4C, 0x30, 0xE1, 0x05, 0x7F, 0x04, 0x12, 0x49, +0x35, 0xE5, 0x4C, 0x30, 0xE4, 0x02, 0x11, 0x96, +0xE5, 0x4C, 0x30, 0xE5, 0x03, 0x12, 0x62, 0xAC, +0xE5, 0x4C, 0x30, 0xE6, 0x03, 0x12, 0x62, 0xD6, +0x74, 0xF7, 0x04, 0x90, 0x01, 0xC4, 0xF0, 0x74, +0x4F, 0xA3, 0xF0, 0xD0, 0x07, 0xD0, 0x06, 0xD0, +0x05, 0xD0, 0x04, 0xD0, 0x03, 0xD0, 0x02, 0xD0, +0x01, 0xD0, 0x00, 0xD0, 0xD0, 0xD0, 0x82, 0xD0, +0x83, 0xD0, 0xF0, 0xD0, 0xE0, 0x32, 0x71, 0x76, +0x11, 0xE2, 0x7F, 0x01, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x90, 0x81, 0x2D, 0xE0, 0xFE, +0xC3, 0x13, 0x30, 0xE0, 0x1F, 0x90, 0x82, 0xDC, +0x74, 0x1E, 0xF0, 0x90, 0x82, 0xEA, 0x74, 0x01, +0xF0, 0x90, 0x82, 0xDE, 0xEF, 0xF0, 0x7B, 0x01, +0x7A, 0x82, 0x79, 0xDC, 0x12, 0x65, 0x3B, 0x7F, +0x04, 0x12, 0x49, 0x35, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x90, 0x81, 0x30, 0xE0, 0x60, 0x02, 0x91, +0xB3, 0x02, 0x4D, 0x06, 0x7D, 0x01, 0x7F, 0x02, +0x11, 0xE6, 0x7D, 0x02, 0x7F, 0x02, 0x74, 0x3D, +0x2F, 0xF8, 0xE6, 0x4D, 0xFE, 0xF6, 0x74, 0x30, +0x81, 0x9A, 0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFB, +0xF0, 0xE4, 0x90, 0x81, 0x39, 0xF0, 0xA3, 0xF0, +0x90, 0x81, 0x34, 0xF0, 0x90, 0x81, 0x2C, 0xE0, +0x54, 0xF7, 0xF0, 0x54, 0xBF, 0xF0, 0x11, 0xDC, +0x7D, 0x10, 0x7F, 0x03, 0x81, 0x92, 0x90, 0x01, +0x36, 0x74, 0x78, 0xF0, 0xA3, 0x74, 0x02, 0xF0, +0x7D, 0x78, 0xFF, 0x11, 0xE6, 0x7D, 0x02, 0x7F, +0x03, 0x11, 0xE6, 0x90, 0x06, 0x0A, 0xE0, 0x44, +0x07, 0x12, 0x7E, 0x2E, 0xE4, 0xFF, 0x71, 0x4B, +0xBF, 0x01, 0x0F, 0xB1, 0x1F, 0x90, 0x81, 0x33, +0xE0, 0x20, 0xE2, 0x08, 0x7D, 0x01, 0x7F, 0x04, +0x80, 0x07, 0xF1, 0xDA, 0x22, 0x7D, 0x01, 0x7F, +0x04, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x90, 0x83, 0x34, 0xED, 0xF0, 0x90, 0x81, 0x2B, +0xE0, 0xFE, 0xC4, 0x13, 0x13, 0x54, 0x03, 0x30, +0xE0, 0x02, 0x41, 0xA4, 0xEE, 0x12, 0x4F, 0xF0, +0x30, 0xE0, 0x02, 0x41, 0xA4, 0x90, 0x81, 0x33, +0xE0, 0xFE, 0x6F, 0x70, 0x02, 0x41, 0xA4, 0xEF, +0x70, 0x02, 0x41, 0x15, 0x24, 0xFE, 0x70, 0x02, +0x41, 0x50, 0x24, 0xFE, 0x60, 0x4C, 0x24, 0xFC, +0x70, 0x02, 0x41, 0x8E, 0x24, 0xFC, 0x60, 0x02, +0x41, 0x9D, 0xEE, 0xB4, 0x0E, 0x03, 0x12, 0x4E, +0xAD, 0x90, 0x81, 0x33, 0xE0, 0x70, 0x05, 0x7F, +0x01, 0x12, 0x4E, 0x7B, 0x90, 0x81, 0x33, 0xE0, +0xB4, 0x06, 0x03, 0x12, 0x4E, 0xCA, 0x90, 0x81, +0x33, 0xE0, 0xB4, 0x04, 0x0E, 0x90, 0x83, 0x34, +0xE0, 0xFF, 0x60, 0x04, 0xB1, 0x7E, 0x80, 0x03, +0x12, 0x4F, 0x77, 0x90, 0x81, 0x33, 0xE0, 0x64, +0x08, 0x60, 0x02, 0x41, 0x9D, 0x12, 0x4F, 0x64, +0x41, 0x9D, 0x90, 0x81, 0x33, 0xE0, 0x70, 0x05, +0x7F, 0x01, 0x12, 0x4E, 0x7B, 0x90, 0x81, 0x33, +0xE0, 0xB4, 0x06, 0x03, 0x12, 0x4E, 0xCA, 0x90, +0x81, 0x33, 0xE0, 0xB4, 0x0E, 0x08, 0x51, 0xA9, +0xBF, 0x01, 0x03, 0x12, 0x4E, 0xAD, 0x90, 0x81, +0x33, 0xE0, 0x64, 0x0C, 0x60, 0x02, 0x41, 0x9D, +0x51, 0xA9, 0xEF, 0x64, 0x01, 0x60, 0x02, 0x41, +0x9D, 0x71, 0x00, 0x41, 0x9D, 0x90, 0x81, 0x33, +0xE0, 0xB4, 0x0E, 0x08, 0x51, 0xA9, 0xBF, 0x01, +0x03, 0x12, 0x4E, 0xAD, 0x90, 0x81, 0x33, 0xE0, +0xB4, 0x06, 0x03, 0x12, 0x4E, 0xCA, 0x90, 0x81, +0x33, 0xE0, 0xB4, 0x0C, 0x07, 0x51, 0xA9, 0xBF, +0x01, 0x02, 0x71, 0x00, 0x90, 0x81, 0x33, 0xE0, +0x64, 0x04, 0x70, 0x59, 0x12, 0x73, 0xE4, 0xEF, +0x64, 0x01, 0x70, 0x51, 0x71, 0x2E, 0x80, 0x4D, +0x90, 0x81, 0x33, 0xE0, 0xB4, 0x0E, 0x08, 0x51, +0xA9, 0xBF, 0x01, 0x03, 0x12, 0x4E, 0xAD, 0x90, +0x81, 0x33, 0xE0, 0xB4, 0x06, 0x03, 0x12, 0x4E, +0xCA, 0x90, 0x81, 0x33, 0xE0, 0xB4, 0x0C, 0x07, +0x51, 0xA9, 0xBF, 0x01, 0x02, 0x71, 0x00, 0x90, +0x81, 0x33, 0xE0, 0x70, 0x05, 0x7F, 0x01, 0x12, +0x4E, 0x7B, 0x90, 0x81, 0x33, 0xE0, 0xB4, 0x04, +0x14, 0x12, 0x74, 0xE4, 0x80, 0x0F, 0x90, 0x81, +0x33, 0xE0, 0xB4, 0x0C, 0x08, 0xB1, 0x37, 0x30, +0xE0, 0x03, 0x12, 0x6A, 0xB7, 0x90, 0x81, 0x33, +0x12, 0x7E, 0x54, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x12, 0x73, 0xCB, 0xEF, 0x64, 0x01, 0x60, 0x05, +0x75, 0x1F, 0x01, 0x80, 0x30, 0x12, 0x67, 0xDA, +0x30, 0xE0, 0x05, 0x75, 0x1F, 0x02, 0x80, 0x25, +0x90, 0x81, 0x32, 0xE0, 0xD3, 0x94, 0x04, 0x40, +0x05, 0x75, 0x1F, 0x08, 0x80, 0x17, 0x90, 0x82, +0x09, 0xE0, 0x30, 0xE0, 0x0B, 0xC4, 0x54, 0x0F, +0x30, 0xE0, 0x05, 0x75, 0x1F, 0x11, 0x80, 0x05, +0x12, 0x74, 0x4B, 0x80, 0x0E, 0x90, 0x01, 0xB9, +0x74, 0x02, 0xF0, 0x90, 0x01, 0xB8, 0xE5, 0x1F, +0xF0, 0x7F, 0x00, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x12, 0x4F, 0xC8, 0x70, 0x28, 0x90, 0x81, 0x2C, +0xE0, 0x54, 0xFD, 0xF0, 0x7B, 0x2C, 0x12, 0x74, +0xEF, 0x7D, 0x08, 0x7F, 0x01, 0xD1, 0x0B, 0xBF, +0x01, 0x0E, 0x90, 0x81, 0x2B, 0xE0, 0x44, 0x80, +0xF0, 0x7D, 0x0E, 0x7F, 0x01, 0x02, 0x4D, 0x57, +0x12, 0x63, 0x0B, 0x04, 0xF0, 0x22, 0x7B, 0x2D, +0x12, 0x4F, 0xD8, 0x12, 0x6A, 0x32, 0x90, 0x01, +0x37, 0x74, 0x02, 0xF0, 0xFD, 0x7F, 0x03, 0x11, +0xE6, 0x12, 0x69, 0x66, 0xE4, 0xFD, 0x7F, 0x01, +0x02, 0x4D, 0x57, 0x12, 0x6D, 0xE8, 0xFE, 0xEF, +0x54, 0x07, 0xFF, 0x74, 0x22, 0x2E, 0x12, 0x70, +0xC5, 0xFD, 0x7C, 0x00, 0x12, 0x70, 0xD0, 0x80, +0x05, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, +0xFF, 0xEE, 0x5C, 0xFE, 0xEF, 0x5D, 0x4E, 0x7F, +0x00, 0x60, 0x02, 0x7F, 0x01, 0x22, 0xE4, 0x90, +0x82, 0x27, 0xF0, 0x90, 0x81, 0x30, 0xE0, 0x60, +0x21, 0x12, 0x4F, 0xC8, 0x70, 0x1C, 0xF1, 0xEA, +0xF0, 0x90, 0x82, 0x27, 0x74, 0x01, 0xF0, 0xE4, +0x90, 0x81, 0x37, 0xF0, 0x04, 0x60, 0x0B, 0x12, +0x7E, 0x18, 0x20, 0xE2, 0x02, 0x31, 0x4D, 0x12, +0x4C, 0xBB, 0x22, 0xEF, 0x70, 0x37, 0x7D, 0x78, +0x7F, 0x02, 0x91, 0xA9, 0x7D, 0x02, 0x7F, 0x03, +0x91, 0xA9, 0x7D, 0xC8, 0x7F, 0x02, 0x91, 0x92, +0x12, 0x7D, 0xFD, 0xF0, 0xE4, 0xFF, 0x71, 0x4B, +0xEF, 0x70, 0x0E, 0x12, 0x4E, 0xED, 0x12, 0x4F, +0x77, 0x12, 0x75, 0x6A, 0x54, 0x7F, 0xF0, 0x80, +0x06, 0x7D, 0x01, 0x7F, 0x0C, 0x31, 0x51, 0x12, +0x67, 0x98, 0x02, 0x7E, 0x8C, 0x21, 0x16, 0x12, +0x4F, 0xC8, 0x60, 0x02, 0x81, 0x8D, 0x90, 0x81, +0x30, 0xE0, 0x70, 0x02, 0x81, 0x8D, 0x90, 0x06, +0xA9, 0xE0, 0xFF, 0x12, 0x7D, 0xFD, 0xF0, 0x90, +0x81, 0x34, 0xE0, 0x54, 0xED, 0xF0, 0x12, 0x61, +0x75, 0xB1, 0x27, 0x64, 0x01, 0x70, 0x27, 0x90, +0x06, 0xAB, 0xE0, 0x90, 0x81, 0x37, 0xF0, 0x90, +0x06, 0xAA, 0xE0, 0x60, 0x05, 0xE0, 0x90, 0x81, +0x36, 0xF0, 0x90, 0x81, 0x37, 0xE0, 0xFF, 0x70, +0x08, 0x90, 0x81, 0x36, 0xE0, 0xFE, 0xFF, 0x80, +0x00, 0x90, 0x81, 0x37, 0xEF, 0xF0, 0xE4, 0x90, +0x81, 0x39, 0xF0, 0xA3, 0x12, 0x7E, 0x2E, 0x90, +0x81, 0x2C, 0x12, 0x6F, 0xE3, 0x30, 0xE0, 0x4B, +0xEF, 0xC4, 0x13, 0x13, 0x54, 0x03, 0x20, 0xE0, +0x1F, 0xB1, 0x2F, 0x6F, 0x70, 0x3D, 0x90, 0x81, +0x2C, 0xE0, 0x44, 0x40, 0xF0, 0xF1, 0xEA, 0xB1, +0x41, 0x12, 0x73, 0xA5, 0xF1, 0xD4, 0x91, 0xA5, +0x90, 0x81, 0x37, 0xE0, 0x14, 0xF0, 0x80, 0x23, +0xB1, 0x27, 0x64, 0x01, 0x70, 0x1D, 0xB1, 0x2F, +0xFE, 0x6F, 0x60, 0x17, 0x90, 0x05, 0x73, 0xE0, +0xFF, 0xEE, 0x6F, 0x60, 0x0E, 0xB1, 0x37, 0x30, +0xE0, 0x09, 0xEF, 0x54, 0xBF, 0xB1, 0x41, 0x91, +0x92, 0x11, 0xDC, 0xF1, 0xDA, 0x22, 0x7D, 0x10, +0xE4, 0xFF, 0x74, 0x45, 0xF1, 0xF2, 0xFE, 0xF6, +0x74, 0x38, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x01, +0xF5, 0x83, 0xEE, 0xF0, 0x22, 0x7D, 0x02, 0x7F, +0x02, 0x74, 0x3D, 0xF1, 0xF2, 0xFE, 0xF6, 0x74, +0x30, 0x80, 0xE7, 0x90, 0x81, 0x2C, 0x12, 0x6F, +0xE3, 0x30, 0xE0, 0x0B, 0xEF, 0xC4, 0x13, 0x13, +0x54, 0x03, 0x30, 0xE0, 0x02, 0x91, 0xA5, 0x90, +0x81, 0x2B, 0xB1, 0x3A, 0x30, 0xE0, 0x08, 0xEF, +0x12, 0x7E, 0x47, 0x70, 0x49, 0x80, 0x44, 0x90, +0x81, 0x39, 0xE0, 0x04, 0xF0, 0x90, 0x81, 0x34, +0xE0, 0x54, 0xEF, 0xF0, 0x90, 0x82, 0x02, 0xE0, +0xFF, 0x90, 0x81, 0x39, 0xE0, 0xD3, 0x9F, 0x40, +0x2A, 0x12, 0x4F, 0xC8, 0x70, 0x28, 0x12, 0x62, +0x5F, 0x70, 0x02, 0x80, 0x22, 0x90, 0x81, 0x3A, +0xE0, 0x04, 0xF0, 0xE0, 0xD3, 0x94, 0x02, 0x40, +0x09, 0xB1, 0x1F, 0xE4, 0x90, 0x81, 0x3A, 0xF0, +0x80, 0x03, 0x12, 0x61, 0xC4, 0xE4, 0x90, 0x81, +0x39, 0xF0, 0x22, 0x12, 0x61, 0x4C, 0x22, 0x90, +0x81, 0x2C, 0xE0, 0x54, 0xFB, 0xF0, 0x22, 0x90, +0x81, 0x2E, 0xE0, 0xC4, 0x54, 0x0F, 0x22, 0x90, +0x81, 0x36, 0xE0, 0xFF, 0xA3, 0xE0, 0x22, 0x90, +0x81, 0x2C, 0xE0, 0xFF, 0x13, 0x13, 0x54, 0x3F, +0x22, 0xF0, 0x90, 0x01, 0x3F, 0x74, 0x10, 0xF0, +0xFD, 0x7F, 0x03, 0x22, 0x90, 0x82, 0x46, 0x12, +0x46, 0xF4, 0x11, 0xF2, 0x90, 0x81, 0x30, 0xE0, +0xFF, 0x71, 0xA3, 0x90, 0x81, 0x30, 0xE0, 0x60, +0x1C, 0x90, 0x82, 0x46, 0x12, 0x5F, 0x27, 0x54, +0x0F, 0xFF, 0x12, 0x5F, 0xD4, 0xFD, 0x12, 0x74, +0xB7, 0x12, 0x6D, 0x9E, 0x90, 0x83, 0x23, 0x74, +0x01, 0xF0, 0x12, 0x6C, 0x2E, 0x22, 0xEF, 0x60, +0x35, 0x12, 0x4F, 0xC8, 0x70, 0x30, 0x90, 0x81, +0x2C, 0xE0, 0x54, 0xFE, 0xF0, 0x7B, 0x2B, 0x7D, +0x0F, 0x7F, 0xFF, 0x12, 0x4E, 0x97, 0x90, 0x06, +0x04, 0xE0, 0x54, 0xBF, 0xF0, 0xD1, 0x07, 0xBF, +0x01, 0x0E, 0x90, 0x81, 0x2B, 0xE0, 0x44, 0x40, +0xF0, 0x7D, 0x06, 0x7F, 0x01, 0x02, 0x4D, 0x57, +0x12, 0x63, 0x0B, 0x74, 0x08, 0xF0, 0x22, 0x12, +0x4F, 0xD1, 0x30, 0xE0, 0x0A, 0x30, 0xE0, 0x46, +0x90, 0x81, 0x2B, 0xE0, 0x30, 0xE0, 0x3F, 0x90, +0x81, 0x1E, 0xE0, 0x60, 0x2F, 0x90, 0x01, 0x63, +0xE4, 0xF0, 0x90, 0x81, 0x1F, 0xE0, 0x60, 0x08, +0xF5, 0x2D, 0xE4, 0xF5, 0x2E, 0xFB, 0x80, 0x11, +0x90, 0x81, 0x20, 0xE0, 0xFB, 0x60, 0x07, 0xE4, +0xF5, 0x2D, 0xF5, 0x2E, 0x80, 0x03, 0x12, 0x7D, +0xB8, 0x7D, 0x01, 0x7F, 0x60, 0x7E, 0x01, 0x12, +0x31, 0x21, 0x80, 0x07, 0x91, 0x8E, 0x90, 0x01, +0x63, 0xE4, 0xF0, 0x12, 0x6E, 0x74, 0x22, 0x7D, +0x08, 0xE4, 0xFF, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x83, 0x0F, 0xEF, 0xF0, 0xA3, +0xED, 0xF0, 0x90, 0x80, 0x03, 0xE0, 0x04, 0xF0, +0x90, 0x04, 0x1D, 0xE0, 0x60, 0x28, 0x90, 0x05, +0x22, 0xE0, 0x90, 0x83, 0x13, 0xF0, 0x7B, 0x26, +0x12, 0x6A, 0x9C, 0x12, 0x6A, 0x32, 0xEF, 0x64, +0x01, 0x70, 0x02, 0xD1, 0x87, 0x90, 0x83, 0x13, +0xE0, 0xFD, 0x7B, 0x27, 0xE4, 0xFF, 0x12, 0x4E, +0x97, 0x12, 0x75, 0x07, 0x80, 0x05, 0x12, 0x75, +0x07, 0xD1, 0x87, 0x12, 0x62, 0x57, 0x7F, 0x01, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xF1, 0xBD, 0x54, +0x3F, 0xF0, 0xBF, 0x01, 0x02, 0x80, 0x16, 0xEF, +0x70, 0x02, 0x80, 0x07, 0x90, 0x81, 0x33, 0xE0, +0x30, 0xE3, 0x0A, 0xF1, 0xB0, 0x54, 0xEF, 0xF1, +0xBC, 0x44, 0x40, 0xF0, 0x22, 0xF1, 0xB0, 0x44, +0x10, 0xF1, 0xBC, 0x44, 0x80, 0xF0, 0x22, 0x90, +0x80, 0x0B, 0xE0, 0xFF, 0x90, 0x83, 0x10, 0xE0, +0xFB, 0x90, 0x83, 0x1B, 0x74, 0x0A, 0xF0, 0x7D, +0x01, 0xF1, 0x19, 0x90, 0x83, 0x11, 0xEE, 0xF0, +0xFC, 0xA3, 0xEF, 0xF0, 0xFD, 0x90, 0x83, 0x0F, +0xE0, 0xFF, 0xD1, 0x5D, 0x90, 0x83, 0x11, 0xE0, +0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x04, 0x80, 0xE0, +0x54, 0x0F, 0xFD, 0xAC, 0x07, 0x12, 0x7E, 0x6E, +0x44, 0x01, 0xF0, 0x12, 0x7E, 0x6E, 0x54, 0xFB, +0xF0, 0xAC, 0x07, 0x74, 0x16, 0x2C, 0xF1, 0xCC, +0xE0, 0x44, 0xFA, 0xF0, 0x74, 0x15, 0x2C, 0xF5, +0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x44, +0x1F, 0xF0, 0xAC, 0x07, 0x74, 0x06, 0x2C, 0xF5, +0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x44, +0x0F, 0xF0, 0x90, 0x04, 0x53, 0xE4, 0xF0, 0x90, +0x04, 0x52, 0xF0, 0x90, 0x04, 0x51, 0x74, 0xFF, +0xF0, 0x90, 0x04, 0x50, 0x74, 0xFD, 0xF0, 0x74, +0x14, 0x2C, 0xF1, 0xE2, 0xE0, 0x54, 0xC0, 0x4D, +0xFD, 0x74, 0x14, 0x2F, 0xF1, 0xE2, 0xED, 0xF0, +0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x90, 0x83, 0x19, 0xED, 0xF0, 0xA3, 0xEB, 0xF0, +0x90, 0x83, 0x18, 0xEF, 0xF0, 0xE4, 0xFD, 0xFC, +0x12, 0x75, 0x8A, 0x7C, 0x00, 0xAD, 0x07, 0x90, +0x83, 0x18, 0xE0, 0x90, 0x04, 0x25, 0xF0, 0x90, +0x83, 0x19, 0xE0, 0x60, 0x0E, 0x74, 0x0F, 0x2F, +0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, +0x44, 0x80, 0xF0, 0xAF, 0x05, 0x74, 0x08, 0x2F, +0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE4, +0xF0, 0x74, 0x09, 0x2F, 0xF5, 0x82, 0xE4, 0x34, +0xFC, 0xF5, 0x83, 0xE0, 0x54, 0xF0, 0xF0, 0xAF, +0x05, 0xF1, 0xC9, 0xE0, 0x20, 0xE1, 0x15, 0x54, +0x01, 0xFE, 0x90, 0x83, 0x1A, 0xE0, 0x25, 0xE0, +0x25, 0xE0, 0xFB, 0xEE, 0x44, 0x02, 0x4B, 0xFE, +0xF1, 0xC9, 0xEE, 0xF0, 0x90, 0x83, 0x1B, 0xE0, +0xFF, 0xAE, 0x05, 0x74, 0x1E, 0x2E, 0xF5, 0x82, +0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xEF, 0xF0, 0x74, +0x21, 0x2E, 0xF1, 0xB3, 0x54, 0xF7, 0xF0, 0xAE, +0x04, 0xAF, 0x05, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x74, 0x21, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0xFC, +0xF5, 0x83, 0xE0, 0x22, 0xF0, 0x74, 0x1F, 0x2D, +0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, +0x22, 0x74, 0x16, 0x2F, 0xF5, 0x82, 0xE4, 0x34, +0xFC, 0xF5, 0x83, 0x22, 0x7D, 0x01, 0x7F, 0x02, +0x81, 0xA9, 0x90, 0x81, 0x2C, 0xE0, 0x44, 0x04, +0xF0, 0x22, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, +0x83, 0x22, 0x90, 0x81, 0x36, 0xE0, 0x90, 0x05, +0x73, 0x22, 0x2F, 0xF8, 0xE6, 0xFE, 0xED, 0xF4, +0x5E, 0x22, 0xC0, 0xE0, 0xC0, 0x83, 0xC0, 0x82, +0xC0, 0xD0, 0x75, 0xD0, 0x00, 0xC0, 0x05, 0xC0, +0x07, 0x7D, 0xFA, 0x90, 0x01, 0xC4, 0xED, 0xF0, +0x74, 0x57, 0xFF, 0xA3, 0xF0, 0xED, 0x04, 0x90, +0x01, 0xC4, 0xF0, 0xA3, 0xEF, 0xF0, 0xD0, 0x07, +0xD0, 0x05, 0xD0, 0xD0, 0xD0, 0x82, 0xD0, 0x83, +0xD0, 0xE0, 0x32, 0x90, 0x00, 0xF7, 0xE0, 0x20, +0xE7, 0x09, 0xE0, 0x7F, 0x01, 0x20, 0xE6, 0x0C, +0x7F, 0x02, 0x22, 0x90, 0x00, 0xF7, 0xE0, 0x30, +0xE6, 0x02, 0x7F, 0x03, 0x22, 0x11, 0x2B, 0x90, +0x80, 0x07, 0xEF, 0xF0, 0x11, 0x65, 0x90, 0x01, +0x64, 0x74, 0x01, 0xF0, 0x90, 0x00, 0x12, 0xE0, +0x54, 0xC7, 0x44, 0x20, 0xFD, 0x7F, 0x12, 0x12, +0x32, 0x1E, 0x02, 0x2D, 0xA7, 0x90, 0x00, 0x08, +0xE0, 0x54, 0xEF, 0xF0, 0x11, 0x9E, 0x11, 0xD6, +0x12, 0x70, 0xD8, 0x12, 0x70, 0xF7, 0xE4, 0xF5, +0x35, 0xF5, 0x37, 0xF5, 0x36, 0xF5, 0x37, 0x75, +0x38, 0x80, 0xAD, 0x35, 0x7F, 0x50, 0x12, 0x32, +0x1E, 0xAD, 0x36, 0x7F, 0x51, 0x12, 0x32, 0x1E, +0xAD, 0x37, 0x7F, 0x52, 0x12, 0x32, 0x1E, 0xAD, +0x38, 0x7F, 0x53, 0x02, 0x32, 0x1E, 0x90, 0x01, +0x30, 0xE4, 0x11, 0xCE, 0x90, 0x01, 0x38, 0x11, +0xCE, 0xFD, 0x7F, 0x50, 0x12, 0x32, 0x1E, 0xE4, +0xFD, 0x7F, 0x51, 0x12, 0x32, 0x1E, 0xE4, 0xFD, +0x7F, 0x52, 0x12, 0x32, 0x1E, 0xE4, 0xFD, 0x7F, +0x53, 0x02, 0x32, 0x1E, 0xE4, 0x90, 0x82, 0x4B, +0xF0, 0x90, 0x82, 0xB6, 0xF0, 0xA3, 0xF0, 0xA3, +0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0x22, 0x90, 0x01, +0x34, 0x74, 0xFF, 0x11, 0xCE, 0x90, 0x01, 0x3C, +0x11, 0xCE, 0xFD, 0x7F, 0x54, 0x12, 0x32, 0x1E, +0x7D, 0xFF, 0x7F, 0x55, 0x12, 0x32, 0x1E, 0x7D, +0xFF, 0x7F, 0x56, 0x12, 0x32, 0x1E, 0x7D, 0xFF, +0x7F, 0x57, 0x02, 0x32, 0x1E, 0x90, 0x80, 0xFC, +0xE0, 0x54, 0xFE, 0x71, 0x9A, 0x90, 0x80, 0xFC, +0xE0, 0x54, 0xFD, 0xF0, 0x54, 0xFB, 0xF0, 0x54, +0xF7, 0xF0, 0x54, 0xEF, 0xF0, 0xE4, 0x90, 0x80, +0xFF, 0x11, 0xCC, 0x11, 0xCF, 0x90, 0x81, 0x1E, +0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0x22, 0x90, 0x82, +0xC6, 0x51, 0xF7, 0xE4, 0x11, 0xCF, 0xFC, 0xA3, +0xF0, 0x31, 0xD3, 0x90, 0x82, 0xCB, 0xEF, 0xF0, +0x51, 0xAE, 0xA3, 0xE0, 0x04, 0xFD, 0x31, 0xD3, +0xAC, 0x07, 0x90, 0x82, 0xCB, 0xE0, 0x30, 0xE7, +0x08, 0x90, 0x82, 0xC9, 0x74, 0x02, 0xF0, 0x80, +0x05, 0xE4, 0x90, 0x82, 0xC9, 0xF0, 0xEC, 0x30, +0xE6, 0x34, 0x51, 0xAE, 0x7D, 0x02, 0x31, 0xD3, +0xEF, 0x54, 0x70, 0xC4, 0x54, 0x0F, 0x90, 0x82, +0xCC, 0xF0, 0x14, 0x60, 0x11, 0x14, 0x60, 0x16, +0x24, 0xFE, 0x60, 0x12, 0x14, 0x60, 0x07, 0x14, +0x60, 0x04, 0x24, 0x06, 0x80, 0x10, 0x90, 0x82, +0xCA, 0x74, 0x04, 0xF0, 0x80, 0x0D, 0x90, 0x82, +0xCA, 0x74, 0x08, 0xF0, 0x80, 0x05, 0xE4, 0x90, +0x82, 0xCA, 0xF0, 0x90, 0x82, 0xC9, 0xE0, 0x24, +0x18, 0xFF, 0xA3, 0xE0, 0x2F, 0xFF, 0x22, 0x90, +0x82, 0xC2, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xA3, +0xED, 0xF0, 0x31, 0x26, 0x90, 0x82, 0xC5, 0xEF, +0xF0, 0x90, 0x82, 0xC4, 0xE0, 0xFD, 0x90, 0x82, +0xC3, 0xE0, 0x2D, 0xFD, 0x90, 0x82, 0xC2, 0xE0, +0x34, 0x00, 0xFC, 0x7E, 0x00, 0xED, 0x2F, 0xFF, +0xEE, 0x3C, 0xCF, 0x24, 0x06, 0xCF, 0x34, 0x00, +0xFE, 0xE4, 0xFD, 0xAB, 0x07, 0xAA, 0x06, 0xED, +0x2B, 0xFB, 0xE4, 0x3A, 0xFA, 0xC3, 0x90, 0x80, +0xFB, 0xE0, 0x9B, 0x90, 0x80, 0xFA, 0xE0, 0x9A, +0x50, 0x0A, 0xA3, 0x12, 0x7D, 0xC8, 0xEB, 0x9F, +0xFB, 0xEA, 0x9E, 0xFA, 0xEA, 0x90, 0xFD, 0x11, +0xF0, 0xAF, 0x03, 0x74, 0x00, 0x2F, 0x12, 0x7E, +0x7A, 0xFF, 0x22, 0x31, 0x9F, 0xEF, 0x64, 0x08, +0x70, 0x34, 0x51, 0x41, 0x24, 0x07, 0x31, 0xCD, +0xEF, 0x70, 0x2B, 0x51, 0x41, 0x24, 0x1D, 0x31, +0xCD, 0xBF, 0x44, 0x0B, 0x51, 0x41, 0x24, 0x1F, +0x31, 0xCD, 0xEF, 0x64, 0x43, 0x60, 0x14, 0x51, +0x41, 0x24, 0x1D, 0x31, 0xCD, 0xEF, 0x64, 0x43, +0x70, 0x0C, 0x51, 0x41, 0x24, 0x1F, 0x31, 0xCD, +0xBF, 0x44, 0x03, 0x7F, 0x01, 0x22, 0x7F, 0x00, +0x22, 0x90, 0x82, 0xC4, 0xE0, 0xFF, 0x90, 0x82, +0xC3, 0xE0, 0x2F, 0xFF, 0x90, 0x82, 0xC2, 0xE0, +0x34, 0x00, 0xFE, 0x90, 0x82, 0xC5, 0xE0, 0x7C, +0x00, 0x2F, 0xFF, 0xEC, 0x3E, 0xCF, 0x22, 0x31, +0x9F, 0xEF, 0x64, 0x08, 0x70, 0x20, 0x51, 0x41, +0x24, 0x07, 0x31, 0xCD, 0xEF, 0x64, 0x06, 0x70, +0x15, 0x51, 0x41, 0x24, 0x0E, 0x31, 0xCD, 0xEF, +0x70, 0x0C, 0x51, 0x41, 0x24, 0x0F, 0x31, 0xCD, +0xBF, 0x01, 0x03, 0x7F, 0x01, 0x22, 0x7F, 0x00, +0x22, 0x24, 0x0A, 0xFC, 0xED, 0x2C, 0xFD, 0x31, +0xD3, 0x90, 0x82, 0x43, 0xA3, 0xE0, 0xFE, 0x90, +0x82, 0x49, 0xE0, 0x2E, 0x24, 0x24, 0xF5, 0x82, +0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xEF, 0xF0, 0x90, +0x82, 0x49, 0xE0, 0x04, 0xF0, 0x22, 0x90, 0x82, +0xC6, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x22, 0x90, +0x82, 0xC2, 0x51, 0xF7, 0x31, 0xD3, 0xEF, 0x54, +0x0C, 0x64, 0x08, 0x70, 0x2F, 0x90, 0x82, 0xC5, +0xF0, 0x90, 0x82, 0xC5, 0xE0, 0xFD, 0xC3, 0x94, +0x06, 0x50, 0x21, 0x90, 0x82, 0xC2, 0xE0, 0xFE, +0xA3, 0xE0, 0xFF, 0xA3, 0xE0, 0x24, 0x10, 0xFC, +0xED, 0x2C, 0xFD, 0x31, 0xD3, 0xEF, 0xF4, 0x60, +0x03, 0x7F, 0x01, 0x22, 0x90, 0x82, 0xC5, 0xE0, +0x04, 0xF0, 0x80, 0xD5, 0x7F, 0x00, 0x22, 0xEE, +0xF0, 0xA3, 0xEF, 0xF0, 0xA3, 0xED, 0xF0, 0x22, +0xFD, 0x31, 0xD3, 0x90, 0x82, 0x4A, 0xE0, 0x22, +0x24, 0x1A, 0xFC, 0xED, 0x2C, 0xFD, 0x31, 0xD3, +0x90, 0x82, 0x49, 0xE0, 0x24, 0x61, 0xF5, 0x82, +0xE4, 0x34, 0x82, 0x22, 0x71, 0x38, 0x12, 0x70, +0x00, 0x12, 0x4D, 0xBF, 0x12, 0x74, 0xF6, 0x71, +0x8A, 0x12, 0x75, 0xD6, 0x11, 0xFD, 0x12, 0x73, +0xAE, 0x90, 0x82, 0x1E, 0x74, 0x01, 0xF0, 0x22, +0xE4, 0xFD, 0xFF, 0x12, 0x6D, 0xE8, 0xFE, 0xEF, +0x54, 0x07, 0xFF, 0xED, 0x70, 0x14, 0x71, 0x81, +0xF5, 0x83, 0xC0, 0x83, 0xC0, 0x82, 0x71, 0x79, +0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xF4, 0x5E, +0x80, 0x11, 0x71, 0x81, 0xF5, 0x83, 0xC0, 0x83, +0xC0, 0x82, 0x71, 0x79, 0x80, 0x02, 0xC3, 0x33, +0xD8, 0xFC, 0x4E, 0xD0, 0x82, 0xD0, 0x83, 0xF0, +0x12, 0x70, 0x72, 0x90, 0x81, 0x2A, 0xEF, 0xF0, +0x22, 0xE0, 0xFE, 0x74, 0x01, 0xA8, 0x07, 0x08, +0x22, 0x74, 0x22, 0x2E, 0xF5, 0x82, 0xE4, 0x34, +0x81, 0x22, 0x90, 0x82, 0x12, 0xE0, 0x54, 0xFE, +0xF0, 0x54, 0x7F, 0xF0, 0x54, 0xFB, 0xF0, 0xA3, +0x74, 0x0A, 0xF0, 0xE4, 0xA3, 0xF0, 0xA3, 0xF0, +0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x90, 0x83, 0x14, 0xEE, 0xF0, 0xA3, 0xEF, 0x71, +0x9A, 0x90, 0x83, 0x14, 0xE0, 0xFE, 0xA3, 0xE0, +0xF5, 0x82, 0x8E, 0x83, 0xE0, 0x60, 0x23, 0xC3, +0x90, 0x83, 0x17, 0xE0, 0x94, 0xE8, 0x90, 0x83, +0x16, 0xE0, 0x94, 0x03, 0x40, 0x0B, 0x90, 0x01, +0xC0, 0xE0, 0x44, 0x80, 0xF0, 0x7F, 0x00, 0x80, +0x0B, 0x90, 0x83, 0x16, 0x91, 0x3A, 0xF1, 0x20, +0x80, 0xCF, 0x7F, 0x01, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x90, 0x82, 0x3B, 0xEF, 0x71, 0x9A, 0x90, +0x01, 0x09, 0xE0, 0x7F, 0x00, 0x30, 0xE7, 0x02, +0x7F, 0x01, 0x90, 0x82, 0x3B, 0xE0, 0x6F, 0x60, +0x35, 0xC3, 0x90, 0x82, 0x3D, 0xE0, 0x94, 0x88, +0x90, 0x82, 0x3C, 0xE0, 0x94, 0x13, 0x40, 0x08, +0x90, 0x01, 0xC0, 0xE0, 0x44, 0x10, 0xF0, 0x22, +0x90, 0x82, 0x3C, 0x91, 0x3A, 0x12, 0x60, 0xBC, +0xD3, 0x90, 0x82, 0x3D, 0xE0, 0x94, 0x32, 0x90, +0x82, 0x3C, 0xE0, 0x94, 0x00, 0x40, 0xC0, 0x90, +0x01, 0xC6, 0xE0, 0x30, 0xE0, 0xB9, 0x22, 0x90, +0x82, 0xC0, 0xE4, 0x75, 0xF0, 0x01, 0x02, 0x46, +0x9F, 0xE4, 0xFD, 0xFB, 0xFA, 0xF1, 0x19, 0x30, +0xE0, 0x73, 0x90, 0x00, 0xB6, 0xE0, 0xFC, 0x90, +0x00, 0xBF, 0xE0, 0xFE, 0x90, 0x00, 0xBE, 0xE0, +0x24, 0x00, 0xFB, 0xEA, 0x3E, 0xFA, 0xC4, 0xF8, +0x54, 0xF0, 0xC8, 0xEB, 0xC4, 0x54, 0x0F, 0x48, +0x54, 0x1E, 0xFF, 0xEC, 0xC4, 0x54, 0x01, 0x4F, +0x90, 0x82, 0x25, 0xF0, 0xF1, 0xEB, 0xEC, 0x30, +0xE4, 0x0A, 0x90, 0x81, 0x14, 0xE0, 0xFD, 0x12, +0x6F, 0x0A, 0x80, 0x35, 0xEB, 0x30, 0xE5, 0x09, +0x90, 0x81, 0x15, 0xB1, 0x0A, 0x04, 0xF0, 0x80, +0x28, 0xEB, 0x30, 0xE6, 0x0A, 0x90, 0x81, 0x16, +0xB1, 0x0A, 0x74, 0x02, 0xF0, 0x80, 0x1A, 0xEB, +0x30, 0xE7, 0x0A, 0x90, 0x81, 0x17, 0xB1, 0x0A, +0x74, 0x03, 0xF0, 0x80, 0x0C, 0xEA, 0x30, 0xE0, +0x08, 0x90, 0x81, 0x18, 0xB1, 0x0A, 0x74, 0x04, +0xF0, 0xAF, 0x05, 0x80, 0x56, 0x90, 0x81, 0x07, +0xE0, 0xFD, 0x7C, 0x00, 0xA3, 0xE0, 0xFE, 0xA3, +0xE0, 0xFF, 0x12, 0x20, 0x30, 0xED, 0x4C, 0x70, +0x05, 0x90, 0x81, 0x14, 0x80, 0x2A, 0xED, 0x64, +0x01, 0x4C, 0x70, 0x05, 0x90, 0x81, 0x15, 0x80, +0x1F, 0xED, 0x64, 0x02, 0x4C, 0x70, 0x05, 0x90, +0x81, 0x16, 0x80, 0x14, 0xED, 0x64, 0x03, 0x4C, +0x70, 0x05, 0x90, 0x81, 0x17, 0x80, 0x09, 0xED, +0x64, 0x04, 0x4C, 0x70, 0x0C, 0x90, 0x81, 0x18, +0xE0, 0xFF, 0xB1, 0x13, 0x90, 0x81, 0x08, 0x91, +0x3A, 0x22, 0xE0, 0xFD, 0x90, 0x81, 0x08, 0xE4, +0xF0, 0xA3, 0x22, 0x90, 0x04, 0x24, 0xEF, 0xF0, +0x22, 0x12, 0x73, 0x2B, 0x90, 0x81, 0x3B, 0xE0, +0x20, 0xE0, 0x0C, 0x90, 0x00, 0x26, 0xE0, 0x54, +0x7F, 0xFD, 0x7F, 0x26, 0x12, 0x32, 0x1E, 0x90, +0x00, 0x08, 0xE0, 0x54, 0xEF, 0xFD, 0x7F, 0x08, +0x12, 0x32, 0x1E, 0xE4, 0xFF, 0x61, 0xE9, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x73, +0x48, 0xB1, 0x19, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x90, 0x81, 0x33, 0xE0, 0xFF, 0x60, 0x03, 0xB4, +0x08, 0x0E, 0x12, 0x74, 0x71, 0xBF, 0x01, 0x08, +0xB1, 0x3F, 0x90, 0x01, 0xE5, 0xE0, 0x04, 0xF0, +0x22, 0xE4, 0x90, 0x83, 0x2D, 0xF0, 0xA3, 0xF0, +0x90, 0x02, 0x86, 0xE0, 0x20, 0xE1, 0x22, 0xC3, +0x90, 0x83, 0x2E, 0xE0, 0x94, 0xD0, 0x90, 0x83, +0x2D, 0xE0, 0x94, 0x07, 0x40, 0x0A, 0x90, 0x01, +0xC1, 0xE0, 0x44, 0x04, 0xF0, 0x7F, 0x00, 0x22, +0x90, 0x83, 0x2D, 0x91, 0x3A, 0xF1, 0x20, 0x80, +0xD7, 0x7F, 0x01, 0x22, 0x90, 0x01, 0x17, 0xE0, +0xFE, 0x90, 0x01, 0x16, 0x12, 0x7E, 0x83, 0x90, +0x80, 0xFA, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x02, +0x86, 0xE0, 0x44, 0x04, 0xF1, 0xE2, 0x30, 0xE0, +0x2B, 0x90, 0x01, 0xC7, 0xE4, 0xF0, 0xB1, 0x69, +0x90, 0x80, 0xFC, 0xE0, 0xBF, 0x01, 0x05, 0x54, +0xEF, 0xF0, 0x80, 0x03, 0x44, 0x10, 0xF0, 0x90, +0x80, 0xFF, 0xE0, 0xFF, 0x60, 0x0E, 0xE4, 0xF5, +0x1D, 0x8F, 0x1E, 0xFB, 0xFD, 0x7F, 0x5C, 0x7E, +0x01, 0x12, 0x4C, 0x3C, 0x90, 0x80, 0xFC, 0xE0, +0x44, 0x01, 0xF0, 0x7D, 0x08, 0xE4, 0xFF, 0x12, +0x50, 0xE6, 0x90, 0x05, 0x52, 0xE0, 0x54, 0x07, +0x04, 0x90, 0x81, 0x07, 0x71, 0x9A, 0x90, 0x04, +0x22, 0xE0, 0x54, 0xEF, 0xF0, 0xF1, 0x19, 0x30, +0xE0, 0x02, 0xF1, 0xEB, 0x22, 0x12, 0x67, 0xC8, +0xFC, 0x54, 0x02, 0xFE, 0x90, 0x80, 0xFC, 0xE0, +0x54, 0xFD, 0x4E, 0xF0, 0xE0, 0xFF, 0xC3, 0x13, +0x30, 0xE0, 0x08, 0xF1, 0x13, 0xF1, 0x75, 0x90, +0x80, 0xFF, 0xF0, 0xEC, 0x30, 0xE0, 0x18, 0xB1, +0x9C, 0x90, 0x01, 0xC7, 0xE4, 0xF0, 0x90, 0x80, +0x07, 0xE0, 0x64, 0x01, 0x70, 0x2E, 0x90, 0xFE, +0x10, 0xE0, 0x44, 0x04, 0xF0, 0x80, 0x25, 0x12, +0x54, 0x8E, 0x90, 0x01, 0x3C, 0xE0, 0x30, 0xE4, +0x03, 0x74, 0x10, 0xF0, 0x90, 0x01, 0x63, 0xE4, +0xF0, 0x12, 0x6E, 0xD6, 0xF1, 0x19, 0x30, 0xE0, +0x0B, 0x90, 0x02, 0x86, 0xE0, 0x30, 0xE2, 0x04, +0xE0, 0x54, 0xFB, 0xF0, 0x90, 0x82, 0x43, 0xF1, +0x27, 0x90, 0x80, 0xFD, 0xF1, 0xD3, 0x90, 0x80, +0xFE, 0xF1, 0xE2, 0x30, 0xE0, 0x2A, 0xF1, 0x13, +0x12, 0x7E, 0x61, 0x90, 0x80, 0xFC, 0x12, 0x6F, +0xD7, 0x4E, 0x12, 0x65, 0xFA, 0x90, 0x81, 0x00, +0xF0, 0x70, 0x03, 0x74, 0x14, 0xF0, 0xF1, 0x13, +0x90, 0x00, 0x05, 0x12, 0x1F, 0xBD, 0x90, 0x81, +0x01, 0x12, 0x67, 0xA1, 0x90, 0x81, 0x02, 0xF0, +0x90, 0x80, 0xFD, 0xE0, 0x54, 0x01, 0x90, 0x81, +0x0A, 0xF0, 0x90, 0x80, 0xFD, 0xE0, 0x54, 0x02, +0x90, 0x81, 0x0B, 0xF0, 0x90, 0x80, 0xFD, 0xE0, +0x54, 0x04, 0x90, 0x81, 0x0C, 0xF0, 0x90, 0x80, +0xFD, 0xE0, 0x54, 0x08, 0x90, 0x81, 0x0D, 0xF0, +0x90, 0x80, 0xFD, 0xE0, 0x54, 0x10, 0x90, 0x81, +0x0E, 0xF0, 0x90, 0x80, 0xFE, 0xE0, 0x54, 0x01, +0x90, 0x81, 0x0F, 0xF0, 0x90, 0x80, 0xFE, 0xE0, +0x54, 0x02, 0x90, 0x81, 0x10, 0xF0, 0x90, 0x80, +0xFE, 0xE0, 0x54, 0x04, 0x90, 0x81, 0x11, 0xF0, +0x90, 0x80, 0xFE, 0xE0, 0x54, 0x08, 0x90, 0x81, +0x12, 0xF0, 0x90, 0x80, 0xFE, 0xE0, 0x54, 0x10, +0x90, 0x81, 0x13, 0xF0, 0x22, 0x90, 0x82, 0x43, +0x12, 0x46, 0xF4, 0x90, 0x82, 0x43, 0x02, 0x46, +0xEB, 0x90, 0x80, 0xFC, 0xE0, 0xC3, 0x13, 0x22, +0x7F, 0x0A, 0x7E, 0x00, 0x02, 0x32, 0xAA, 0x12, +0x46, 0xEB, 0x90, 0x00, 0x01, 0x02, 0x1F, 0xBD, +0x90, 0x82, 0x43, 0x12, 0x46, 0xF4, 0x12, 0x75, +0xD6, 0xF1, 0x13, 0x12, 0x67, 0xB8, 0xF1, 0x7B, +0x4E, 0xF0, 0xEF, 0xC3, 0x13, 0x30, 0xE0, 0x2B, +0xF1, 0x2A, 0x90, 0x82, 0x17, 0xF1, 0xD3, 0x90, +0x82, 0x18, 0xF0, 0x12, 0x1F, 0xA4, 0xFF, 0x54, +0x04, 0xFE, 0x90, 0x82, 0x16, 0xE0, 0x54, 0xFB, +0x4E, 0xF1, 0x74, 0x90, 0x82, 0x19, 0xF0, 0xEF, +0x54, 0x08, 0xFF, 0x90, 0x82, 0x16, 0xE0, 0x54, +0xF7, 0x4F, 0xF0, 0x22, 0xF0, 0x90, 0x00, 0x03, +0x02, 0x1F, 0xBD, 0x90, 0x82, 0x16, 0xE0, 0x54, +0xFE, 0x22, 0x90, 0x82, 0x16, 0xE0, 0xFD, 0x30, +0xE0, 0x47, 0x90, 0x82, 0x1B, 0xE0, 0xFC, 0x60, +0x40, 0x12, 0x70, 0xD0, 0x80, 0x05, 0xC3, 0x33, +0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, 0x90, 0x04, +0xE0, 0xE0, 0xFB, 0xEF, 0x5B, 0x60, 0x0B, 0xE4, +0x90, 0x82, 0x1B, 0xF0, 0x90, 0x82, 0x1D, 0x04, +0xF0, 0x22, 0x90, 0x82, 0x18, 0xE0, 0xD3, 0x9C, +0x50, 0x14, 0xED, 0x13, 0x13, 0x13, 0x54, 0x1F, +0x30, 0xE0, 0x04, 0xF1, 0xDA, 0x80, 0x03, 0x12, +0x6E, 0x68, 0xF1, 0x7B, 0xF0, 0x22, 0x12, 0x7E, +0x39, 0x22, 0x4F, 0xF0, 0x90, 0x00, 0x02, 0x02, +0x1F, 0xBD, 0xE4, 0xFD, 0xFF, 0x71, 0x3B, 0xE4, +0xFF, 0x22, 0xF0, 0x90, 0x80, 0xFC, 0xE0, 0xFF, +0xC3, 0x13, 0x22, 0x90, 0x00, 0xB6, 0x74, 0x10, +0xF0, 0x90, 0x00, 0xBE, 0x74, 0xE0, 0xF0, 0xA3, +0x74, 0x01, 0xF0, 0x22, 0x75, 0xE8, 0x03, 0x75, +0xA8, 0x84, 0x22, 0x90, 0x00, 0x80, 0xE0, 0x44, +0x80, 0xFD, 0x7F, 0x80, 0x12, 0x32, 0x1E, 0x90, +0xFD, 0x00, 0xE0, 0x54, 0xBF, 0xF0, 0x11, 0xCD, +0x12, 0x32, 0x77, 0x11, 0xDA, 0x11, 0xB5, 0x7F, +0x01, 0x12, 0x44, 0x15, 0x90, 0x82, 0x11, 0x74, +0x02, 0xF0, 0xFF, 0x12, 0x44, 0x15, 0x90, 0x82, +0x11, 0xE0, 0x04, 0xF0, 0x12, 0x58, 0x45, 0x12, +0x5B, 0x1C, 0x90, 0x01, 0xCC, 0x74, 0x0F, 0xF0, +0x90, 0x00, 0x80, 0xE0, 0x44, 0x40, 0xFD, 0x7F, +0x80, 0x12, 0x32, 0x1E, 0x75, 0x20, 0xFF, 0x12, +0x5F, 0xFC, 0x11, 0x5B, 0x11, 0xC3, 0xE4, 0xFF, +0x02, 0x44, 0x9E, 0xE4, 0x90, 0x82, 0x36, 0xF0, +0xA3, 0xF0, 0x90, 0x01, 0x98, 0xE0, 0x7F, 0x00, +0x30, 0xE4, 0x02, 0x7F, 0x01, 0xEF, 0x64, 0x01, +0x60, 0x3C, 0xC3, 0x90, 0x82, 0x37, 0xE0, 0x94, +0x88, 0x90, 0x82, 0x36, 0xE0, 0x94, 0x13, 0x40, +0x0F, 0x90, 0x01, 0xC1, 0xE0, 0x44, 0x10, 0xF0, +0x90, 0x01, 0xC7, 0x74, 0xFD, 0xF0, 0x80, 0x1E, +0x90, 0x82, 0x36, 0x12, 0x5C, 0x3A, 0x11, 0xBC, +0xD3, 0x90, 0x82, 0x37, 0xE0, 0x94, 0x32, 0x90, +0x82, 0x36, 0xE0, 0x94, 0x00, 0x40, 0xBB, 0x90, +0x01, 0xC6, 0xE0, 0x30, 0xE3, 0xB4, 0x90, 0x01, +0xC7, 0x74, 0xFE, 0xF0, 0x22, 0xE4, 0x90, 0x80, +0x01, 0x02, 0x58, 0xCC, 0x7F, 0x14, 0x7E, 0x00, +0x02, 0x32, 0xAA, 0x90, 0x01, 0xE4, 0x74, 0x1C, +0xF0, 0xA3, 0xE4, 0xF0, 0x22, 0x90, 0x01, 0x94, +0xE0, 0x44, 0x01, 0xF0, 0x90, 0x01, 0xC7, 0xE4, +0xF0, 0x22, 0x90, 0x01, 0x01, 0xE0, 0x44, 0x04, +0xF0, 0x90, 0x01, 0x9C, 0x74, 0x7E, 0xF0, 0xA3, +0x74, 0x92, 0xF0, 0xA3, 0x74, 0xA0, 0xF0, 0xA3, +0x74, 0x24, 0xF0, 0x90, 0x01, 0x9B, 0x74, 0x49, +0xF0, 0x90, 0x01, 0x9A, 0x74, 0xE0, 0xF0, 0x90, +0x01, 0x99, 0xE4, 0xF0, 0x90, 0x01, 0x98, 0x04, +0xF0, 0x22, 0xE4, 0x90, 0x82, 0x38, 0xF0, 0xA3, +0xF0, 0xA3, 0xF0, 0x90, 0x82, 0x38, 0xE0, 0x64, +0x01, 0xF0, 0x24, 0x0A, 0x90, 0x01, 0xC4, 0xF0, +0x74, 0x61, 0xA3, 0xF0, 0x90, 0x81, 0x30, 0xE0, +0x60, 0x0E, 0x90, 0x81, 0x33, 0xE0, 0xFF, 0x90, +0x81, 0x32, 0xE0, 0x6F, 0x60, 0x02, 0x31, 0x4C, +0xC2, 0xAF, 0x12, 0x71, 0x16, 0xBF, 0x01, 0x02, +0xF1, 0xE4, 0xD2, 0xAF, 0x31, 0x4B, 0x12, 0x43, +0x4D, 0x80, 0xC8, 0x22, 0x90, 0x81, 0x32, 0xE0, +0xFF, 0x7D, 0x01, 0x02, 0x51, 0x51, 0xE4, 0xFF, +0x12, 0x53, 0x4B, 0xBF, 0x01, 0x0E, 0x90, 0x81, +0x30, 0xE0, 0x60, 0x08, 0x31, 0x6D, 0x54, 0x07, +0x70, 0x02, 0x31, 0x4C, 0x22, 0x90, 0x81, 0x34, +0xE0, 0x54, 0xFE, 0xF0, 0x22, 0x90, 0x06, 0xA9, +0xE0, 0xF5, 0x4E, 0x54, 0xC0, 0x70, 0x07, 0x31, +0x6D, 0x54, 0xFD, 0xF0, 0x80, 0xC6, 0xE5, 0x4E, +0x30, 0xE6, 0x1C, 0x90, 0x81, 0x30, 0xE0, 0x64, +0x01, 0x70, 0x16, 0x90, 0x81, 0x34, 0xE0, 0x44, +0x01, 0x51, 0x5E, 0x64, 0x02, 0x60, 0x04, 0x51, +0x34, 0x80, 0x06, 0x31, 0xC4, 0x80, 0x02, 0x31, +0x6D, 0xE5, 0x4E, 0x90, 0x81, 0x34, 0x30, 0xE7, +0x0E, 0xE0, 0x44, 0x02, 0x12, 0x4C, 0x2B, 0x90, +0x81, 0x2B, 0xE0, 0x44, 0x04, 0xF0, 0x22, 0xE0, +0x54, 0xFD, 0xF0, 0x22, 0x31, 0xEF, 0x90, 0x81, +0x33, 0xE0, 0x64, 0x0C, 0x60, 0x08, 0x51, 0x83, +0x12, 0x4E, 0x92, 0x12, 0x56, 0x07, 0x22, 0x90, +0x81, 0x30, 0xE0, 0x60, 0x0F, 0x90, 0x06, 0x92, +0xE0, 0x30, 0xE1, 0x04, 0x31, 0xEF, 0x80, 0x04, +0xF1, 0x98, 0x31, 0x4C, 0x02, 0x4C, 0x08, 0xF1, +0xDA, 0x30, 0xE0, 0x05, 0x90, 0x01, 0x5B, 0xE4, +0xF0, 0x90, 0x06, 0x92, 0x74, 0x02, 0xF0, 0x90, +0x01, 0x3C, 0x74, 0x04, 0xF0, 0xE4, 0xF5, 0x1D, +0x90, 0x82, 0x04, 0xE0, 0xC3, 0x13, 0x54, 0x7F, +0x12, 0x4B, 0xCA, 0x90, 0x81, 0x2B, 0xE0, 0x44, +0x08, 0xF0, 0x22, 0xE4, 0xFF, 0x12, 0x53, 0x4B, +0xBF, 0x01, 0x10, 0x90, 0x81, 0x30, 0xE0, 0x60, +0x0A, 0x51, 0x5F, 0x64, 0x02, 0x60, 0x02, 0x80, +0x03, 0x31, 0xC4, 0x22, 0x90, 0x04, 0x1D, 0xE0, +0x70, 0x1C, 0x90, 0x80, 0x0A, 0xE0, 0xFF, 0x90, +0x83, 0x1B, 0x74, 0x09, 0xF0, 0x7B, 0x18, 0xE4, +0xFD, 0x12, 0x57, 0x19, 0x90, 0x82, 0x25, 0xEE, +0xF0, 0xA3, 0xEF, 0xF0, 0x51, 0x57, 0x22, 0x90, +0x04, 0x1F, 0x74, 0x20, 0xF0, 0x22, 0xF0, 0x90, +0x81, 0x2E, 0xE0, 0x54, 0x0F, 0x22, 0x90, 0x81, +0x30, 0xE0, 0x64, 0x01, 0x70, 0x14, 0x51, 0x5F, +0x60, 0x07, 0x51, 0x83, 0x12, 0x4E, 0x92, 0x21, +0xEF, 0x90, 0x81, 0x33, 0xE0, 0x70, 0x03, 0x12, +0x51, 0x4D, 0x22, 0xE4, 0xFD, 0x7F, 0x0C, 0x02, +0x51, 0x51, 0x12, 0x4F, 0xC8, 0x70, 0x1C, 0x90, +0x81, 0x30, 0xE0, 0x60, 0x16, 0x90, 0x81, 0x34, +0xE0, 0x20, 0xE4, 0x0F, 0x12, 0x7D, 0xFD, 0xF0, +0x90, 0x81, 0x2B, 0xE0, 0x12, 0x7E, 0x47, 0x70, +0x02, 0x31, 0x4C, 0x22, 0x90, 0x81, 0x2B, 0xE0, +0xFF, 0xC4, 0x13, 0x13, 0x54, 0x03, 0x30, 0xE0, +0x18, 0xEF, 0x54, 0xBF, 0x71, 0x01, 0x30, 0xE0, +0x06, 0xE0, 0x44, 0x01, 0xF0, 0x80, 0x08, 0xE0, +0x54, 0xFE, 0x71, 0x0A, 0x74, 0x04, 0xF0, 0x31, +0x4C, 0xE4, 0xFF, 0x02, 0x5F, 0x82, 0x90, 0x81, +0x2B, 0x12, 0x4F, 0xEE, 0x30, 0xE0, 0x1D, 0xEF, +0x54, 0x7F, 0x71, 0x01, 0x30, 0xE1, 0x06, 0xE0, +0x44, 0x02, 0xF0, 0x80, 0x07, 0xE0, 0x54, 0xFD, +0x71, 0x0A, 0x04, 0xF0, 0x90, 0x81, 0x30, 0xE0, +0x60, 0x02, 0x31, 0x4C, 0x7F, 0x01, 0x02, 0x5F, +0x82, 0xF0, 0x90, 0x04, 0xE0, 0xE0, 0x90, 0x81, +0x2C, 0x22, 0xF0, 0x90, 0x01, 0xB9, 0x74, 0x01, +0xF0, 0x90, 0x01, 0xB8, 0x22, 0xF1, 0xC8, 0xFF, +0x54, 0x7F, 0x90, 0x81, 0x30, 0xF0, 0xEF, 0x12, +0x4F, 0xF0, 0xA3, 0xF0, 0x12, 0x5F, 0x2A, 0xFD, +0x54, 0xF0, 0xC4, 0x54, 0x0F, 0xFF, 0x90, 0x81, +0x2E, 0xE0, 0x54, 0xF0, 0x4F, 0x12, 0x5F, 0x74, +0xFC, 0x54, 0x01, 0x25, 0xE0, 0xFF, 0x90, 0x81, +0x2B, 0xE0, 0x54, 0xFD, 0x4F, 0xF0, 0xEC, 0x54, +0x04, 0xC3, 0x13, 0xFF, 0x90, 0x81, 0x2D, 0xE0, +0x54, 0xFD, 0x4F, 0xF0, 0xED, 0x54, 0x0F, 0xC4, +0x54, 0xF0, 0xFF, 0xA3, 0xE0, 0x54, 0x0F, 0x12, +0x5F, 0xD2, 0x90, 0x81, 0x2F, 0xB1, 0xFA, 0xFD, +0x7F, 0x02, 0x12, 0x4D, 0x57, 0x12, 0x5F, 0x13, +0x12, 0x55, 0x4C, 0x71, 0x0B, 0xF0, 0x90, 0x81, +0x30, 0x12, 0x7E, 0x54, 0x51, 0x5E, 0x90, 0x01, +0xBE, 0xF0, 0x22, 0x90, 0x82, 0x40, 0x12, 0x46, +0xF4, 0x90, 0x82, 0x3F, 0xEF, 0xF0, 0x12, 0x46, +0xFD, 0x63, 0xC2, 0x00, 0x63, 0xC6, 0x01, 0x63, +0xCA, 0x03, 0x63, 0xCE, 0x04, 0x63, 0xD3, 0x08, +0x63, 0xD8, 0x09, 0x63, 0xDC, 0x0A, 0x63, 0xE0, +0x12, 0x63, 0xE4, 0x13, 0x63, 0xE9, 0x14, 0x63, +0xEE, 0x20, 0x63, 0xF2, 0x25, 0x63, 0xF6, 0x26, +0x63, 0xFB, 0xC2, 0x63, 0xFF, 0xC4, 0x00, 0x00, +0x64, 0x04, 0x91, 0x14, 0xA1, 0xB7, 0x91, 0x14, +0xE1, 0x30, 0x91, 0x14, 0xA1, 0x98, 0x91, 0x14, +0x02, 0x5F, 0x30, 0x91, 0x14, 0x02, 0x5E, 0x0D, +0x91, 0x14, 0x80, 0x3E, 0x91, 0x14, 0x80, 0x46, +0x91, 0x14, 0x80, 0x5A, 0x91, 0x14, 0x02, 0x6A, +0xD4, 0x91, 0x14, 0x02, 0x6B, 0x4E, 0x91, 0x14, +0x61, 0x15, 0x91, 0x14, 0xE1, 0xA8, 0x91, 0x14, +0x02, 0x6B, 0x5D, 0x91, 0x14, 0xE1, 0xB0, 0x91, +0x14, 0x02, 0x6F, 0xEB, 0x90, 0x01, 0xC0, 0xE0, +0x44, 0x01, 0xF0, 0x90, 0x82, 0x3F, 0xE0, 0x90, +0x01, 0xC2, 0xF0, 0x22, 0x90, 0x82, 0x40, 0x02, +0x46, 0xEB, 0x12, 0x5F, 0x0D, 0x91, 0x32, 0x7A, +0x81, 0x79, 0x14, 0x02, 0x2B, 0xED, 0x12, 0x5F, +0x0D, 0x91, 0x32, 0x7A, 0x81, 0x79, 0x19, 0x02, +0x2B, 0xED, 0x8B, 0x13, 0x8A, 0x14, 0x89, 0x15, +0x75, 0x16, 0x05, 0x7B, 0x01, 0x22, 0x12, 0x1F, +0xA4, 0xFF, 0x90, 0x81, 0x21, 0xF0, 0xBF, 0x01, +0x07, 0x91, 0x51, 0xE4, 0x90, 0x81, 0x21, 0xF0, +0x22, 0xB1, 0x18, 0x7F, 0xF5, 0x7E, 0x00, 0x12, +0x2B, 0x27, 0xBF, 0x01, 0x06, 0x90, 0x82, 0x43, +0xE0, 0xA3, 0xF0, 0xB1, 0x18, 0x7F, 0xF6, 0x7E, +0x00, 0x12, 0x2B, 0x27, 0xBF, 0x01, 0x08, 0x90, +0x82, 0x43, 0xE0, 0x90, 0x82, 0x45, 0xF0, 0xB1, +0x18, 0x7F, 0xF4, 0x7E, 0x00, 0x12, 0x2B, 0x27, +0xBF, 0x01, 0x08, 0x90, 0x82, 0x43, 0xE0, 0x90, +0x82, 0x46, 0xF0, 0xB1, 0x18, 0x7F, 0xF3, 0x7E, +0x00, 0x12, 0x2B, 0x27, 0xBF, 0x01, 0x08, 0x90, +0x82, 0x43, 0xE0, 0x90, 0x82, 0x47, 0xF0, 0xB1, +0x18, 0x7F, 0xF2, 0x7E, 0x00, 0x12, 0x2B, 0x27, +0xBF, 0x01, 0x08, 0x90, 0x82, 0x43, 0xE0, 0x90, +0x82, 0x48, 0xF0, 0x90, 0x82, 0x44, 0xE0, 0xFF, +0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFB, 0xA3, 0xE0, +0x90, 0x82, 0x4C, 0xF0, 0x90, 0x82, 0x48, 0xE0, +0x90, 0x82, 0x4D, 0xF0, 0x90, 0x82, 0x4E, 0x74, +0x12, 0xF0, 0x90, 0x82, 0x5C, 0x74, 0x05, 0xF0, +0x90, 0x82, 0x50, 0xEF, 0xF0, 0xA3, 0xED, 0xF0, +0xA3, 0xEB, 0xF0, 0x90, 0x82, 0x4C, 0xE0, 0x90, +0x82, 0x53, 0xF0, 0x90, 0x82, 0x4D, 0xE0, 0x90, +0x82, 0x54, 0xF0, 0x7B, 0x01, 0x7A, 0x82, 0x79, +0x4E, 0xB1, 0x3B, 0x7F, 0x04, 0x90, 0x83, 0x2F, +0xEF, 0xF0, 0x7F, 0x02, 0x12, 0x45, 0x27, 0x90, +0x80, 0x01, 0xE0, 0xFF, 0x90, 0x83, 0x2F, 0xE0, +0xFE, 0xEF, 0x4E, 0x90, 0x80, 0x01, 0xF0, 0x22, +0x7B, 0x01, 0x7A, 0x82, 0x79, 0x43, 0x22, 0xE4, +0x90, 0x82, 0x29, 0xF0, 0x90, 0x82, 0x27, 0x74, +0x14, 0xF0, 0x90, 0x82, 0x35, 0x74, 0x01, 0xF0, +0xFB, 0x7A, 0x82, 0x79, 0x27, 0xB1, 0x3B, 0x7F, +0x04, 0x80, 0xC2, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x80, 0xF8, 0xE0, 0xFF, 0x70, +0x06, 0xA3, 0xE0, 0x64, 0x09, 0x60, 0x0A, 0xEF, +0x14, 0xFF, 0x90, 0x80, 0xF9, 0xE0, 0xB5, 0x07, +0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xEF, +0x60, 0x09, 0x90, 0x01, 0xC1, 0xE0, 0x44, 0x02, +0xF0, 0x80, 0x28, 0xC0, 0x01, 0x90, 0x80, 0xF9, +0xE0, 0xF1, 0x24, 0xA8, 0x01, 0xFC, 0x7D, 0x01, +0xD0, 0x01, 0x7E, 0x00, 0x7F, 0x0F, 0x12, 0x46, +0x79, 0x90, 0x80, 0xF9, 0xD1, 0x61, 0xB4, 0x0A, +0x02, 0x7F, 0x01, 0xEF, 0x60, 0x05, 0xE4, 0x90, +0x80, 0xF9, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0xF1, 0xB8, 0x90, 0x82, 0x12, 0xF1, 0xC0, 0x54, +0x04, 0xFF, 0xEE, 0x54, 0xFB, 0x4F, 0xF0, 0x12, +0x1F, 0xA4, 0xC3, 0x13, 0x30, 0xE0, 0x07, 0x12, +0x5F, 0x2A, 0x90, 0x82, 0x13, 0xF0, 0x22, 0x90, +0x02, 0x09, 0xE0, 0xF5, 0x55, 0x12, 0x1F, 0xA4, +0x25, 0x55, 0x90, 0x80, 0x09, 0xF0, 0x12, 0x5F, +0x2A, 0x25, 0x55, 0x90, 0x80, 0x0A, 0x12, 0x5F, +0xD3, 0x25, 0x55, 0x90, 0x80, 0x0B, 0x12, 0x5F, +0x74, 0x25, 0x55, 0x90, 0x80, 0x0C, 0xB1, 0xFA, +0x25, 0x55, 0x90, 0x80, 0x0D, 0xF0, 0x90, 0x00, +0x05, 0x12, 0x1F, 0xBD, 0x25, 0x55, 0x90, 0x80, +0x0E, 0xF1, 0xA1, 0x25, 0x55, 0x90, 0x80, 0x0F, +0xF0, 0x22, 0xF0, 0x90, 0x00, 0x04, 0x02, 0x1F, +0xBD, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x90, 0x80, 0x61, 0xE0, 0xFF, 0x90, 0x80, 0x60, +0xE0, 0xB5, 0x07, 0x04, 0x7F, 0x01, 0x80, 0x02, +0x7F, 0x00, 0xEF, 0x70, 0x3F, 0x90, 0x80, 0x60, +0xE0, 0xFE, 0x75, 0xF0, 0x08, 0x90, 0x80, 0x10, +0x12, 0x46, 0xDF, 0xE0, 0xFD, 0xEE, 0x75, 0xF0, +0x08, 0xA4, 0x24, 0x11, 0xF9, 0x74, 0x80, 0x35, +0xF0, 0xFA, 0x7B, 0x01, 0xAF, 0x05, 0x71, 0x83, +0x90, 0x80, 0x60, 0xD1, 0x61, 0xB4, 0x0A, 0x02, +0x7F, 0x01, 0xEF, 0x60, 0x05, 0xE4, 0x90, 0x80, +0x60, 0xF0, 0x12, 0x49, 0x44, 0x90, 0x80, 0x01, +0xE0, 0x44, 0x02, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0xE0, 0x04, 0xF0, 0xE0, 0x7F, 0x00, 0x22, +0xE4, 0xFB, 0xFA, 0xFD, 0x7F, 0x01, 0x12, 0x45, +0x4E, 0x90, 0x82, 0x3E, 0xEF, 0xF0, 0x60, 0xF0, +0x90, 0x80, 0x01, 0xE0, 0xFF, 0x70, 0x04, 0xA3, +0xE0, 0x60, 0xE5, 0xC2, 0xAF, 0xEF, 0x30, 0xE1, +0x09, 0x90, 0x80, 0x01, 0xE0, 0x54, 0xFD, 0xF0, +0xD1, 0x01, 0xD1, 0xB3, 0xFF, 0x30, 0xE2, 0x05, +0x54, 0xFB, 0xF0, 0xD1, 0xBC, 0xD1, 0xB3, 0xFF, +0x30, 0xE5, 0x0C, 0x54, 0xDF, 0xF0, 0x12, 0x5D, +0x69, 0xBF, 0x01, 0x03, 0x12, 0x76, 0x55, 0xD2, +0xAF, 0x80, 0xC5, 0xD2, 0xAF, 0xC2, 0xAF, 0x90, +0x80, 0x01, 0xE0, 0x22, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0xE4, 0xFF, 0x90, 0x80, 0xF9, +0xE0, 0xFE, 0x90, 0x80, 0xF8, 0xE0, 0xFD, 0xB5, +0x06, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, +0xEE, 0x64, 0x01, 0x60, 0x42, 0x90, 0x01, 0xAF, +0xE0, 0x70, 0x0B, 0xED, 0xF1, 0x24, 0xFA, 0x7B, +0x01, 0x12, 0x70, 0x0E, 0x7F, 0x01, 0xEF, 0x60, +0x2E, 0x90, 0x80, 0xF8, 0xD1, 0x61, 0xB4, 0x0A, +0x02, 0x7F, 0x01, 0xEF, 0x60, 0x05, 0xE4, 0x90, +0x80, 0xF8, 0xF0, 0x90, 0x80, 0xF9, 0xE0, 0xFF, +0x90, 0x80, 0xF8, 0xE0, 0xB5, 0x07, 0x04, 0x7F, +0x01, 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x70, 0x07, +0x90, 0x80, 0x01, 0xE0, 0x44, 0x04, 0xF0, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x75, 0xF0, 0x0F, 0xA4, +0x24, 0x62, 0xF9, 0x74, 0x80, 0x35, 0xF0, 0x22, +0x8B, 0x55, 0x8A, 0x56, 0x89, 0x57, 0x12, 0x5F, +0x2A, 0xFF, 0xF5, 0x59, 0x12, 0x1F, 0xA4, 0xFE, +0xC3, 0x13, 0x30, 0xE0, 0x07, 0x12, 0x5F, 0xD4, +0xF5, 0x5A, 0x80, 0x02, 0x8F, 0x5A, 0x85, 0x59, +0x58, 0xE5, 0x58, 0xD3, 0x95, 0x5A, 0x50, 0x26, +0xAB, 0x55, 0xAA, 0x56, 0xA9, 0x57, 0x12, 0x1F, +0xA4, 0x54, 0x01, 0xFD, 0xAF, 0x58, 0x12, 0x5B, +0x3B, 0xAF, 0x58, 0x12, 0x53, 0x4B, 0xEF, 0xAF, +0x58, 0x70, 0x05, 0x12, 0x5F, 0xE1, 0x80, 0x02, +0xF1, 0xA0, 0x05, 0x58, 0x80, 0xD3, 0xE5, 0x59, +0x70, 0x15, 0xFF, 0x12, 0x53, 0x4B, 0xEF, 0x70, +0x0E, 0x12, 0x4E, 0xED, 0x12, 0x4F, 0x77, 0xF1, +0x98, 0x54, 0xBF, 0xF0, 0x54, 0x7F, 0xF0, 0x22, +0x90, 0x81, 0x2B, 0xE0, 0x54, 0xF7, 0xF0, 0x22, +0x22, 0xF0, 0x90, 0x00, 0x06, 0x02, 0x1F, 0xBD, +0x12, 0x1F, 0xA4, 0x90, 0x82, 0x08, 0xF0, 0x22, +0x12, 0x1F, 0xA4, 0x90, 0x82, 0x1E, 0xF0, 0x22, +0x12, 0x1F, 0xA4, 0xFF, 0x54, 0x01, 0xFE, 0x22, +0xE0, 0x54, 0xFE, 0x4E, 0xFE, 0xF0, 0xEF, 0x22, +0x90, 0x82, 0x43, 0x12, 0x46, 0xF4, 0x02, 0x1F, +0xA4, 0x90, 0x81, 0x30, 0xE0, 0x60, 0x02, 0x51, +0x66, 0x22, 0x90, 0x81, 0x2B, 0xE0, 0x13, 0x13, +0x13, 0x54, 0x1F, 0x22, 0x90, 0x81, 0x2B, 0xE0, +0x30, 0xE0, 0x03, 0x12, 0x5D, 0x50, 0x22, 0x90, +0x82, 0xCD, 0xEF, 0xF0, 0xA3, 0xED, 0xF0, 0xA3, +0x12, 0x20, 0xDA, 0x00, 0x00, 0x00, 0x00, 0xE4, +0x90, 0x82, 0xDB, 0xF0, 0x7F, 0x24, 0x7E, 0x08, +0x12, 0x2D, 0x5C, 0x90, 0x82, 0xD3, 0x12, 0x20, +0xCE, 0x90, 0x82, 0xCD, 0xE0, 0xFB, 0x70, 0x08, +0x90, 0x82, 0xD3, 0x12, 0x46, 0xD3, 0x80, 0x06, +0xEB, 0x11, 0xDE, 0x12, 0x2D, 0x5C, 0x90, 0x82, +0xD7, 0x12, 0x20, 0xCE, 0x90, 0x82, 0xCE, 0xE0, +0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x17, 0x31, +0x5A, 0x90, 0x82, 0xD7, 0x12, 0x46, 0xD3, 0xED, +0x54, 0x7F, 0xFD, 0xEC, 0x54, 0x80, 0xFC, 0x12, +0x46, 0xB5, 0xEC, 0x44, 0x80, 0xFC, 0x90, 0x82, +0xD7, 0x12, 0x20, 0xCE, 0x11, 0xF1, 0x54, 0x7F, +0xFC, 0x11, 0xD8, 0x11, 0xF9, 0x11, 0xDE, 0xC0, +0x06, 0xC0, 0x07, 0x90, 0x82, 0xD7, 0x11, 0xD5, +0xD0, 0x07, 0xD0, 0x06, 0x12, 0x2E, 0xA2, 0x11, +0xF1, 0x44, 0x80, 0xFC, 0x11, 0xD8, 0x11, 0xF9, +0x70, 0x04, 0x7F, 0x20, 0x80, 0x09, 0x90, 0x82, +0xCD, 0xE0, 0xB4, 0x01, 0x16, 0x7F, 0x28, 0x7E, +0x08, 0x12, 0x2D, 0x5C, 0x78, 0x08, 0x12, 0x20, +0xA8, 0xEF, 0x54, 0x01, 0xFF, 0xE4, 0x90, 0x82, +0xDB, 0xEF, 0xF0, 0x90, 0x82, 0xDB, 0xE0, 0x90, +0x82, 0xCD, 0x60, 0x0E, 0xE0, 0x75, 0xF0, 0x08, +0xA4, 0x24, 0x66, 0xF5, 0x82, 0xE4, 0x34, 0x87, +0x80, 0x0C, 0xE0, 0x75, 0xF0, 0x08, 0xA4, 0x24, +0x64, 0xF5, 0x82, 0xE4, 0x34, 0x87, 0x11, 0xE9, +0x12, 0x2D, 0x5C, 0xED, 0x54, 0x0F, 0xFD, 0xE4, +0xFC, 0x90, 0x82, 0xCF, 0x12, 0x20, 0xCE, 0x90, +0x82, 0xCF, 0x02, 0x46, 0xD3, 0x12, 0x46, 0xD3, +0x90, 0x85, 0xBB, 0x02, 0x20, 0xCE, 0x75, 0xF0, +0x08, 0xA4, 0x24, 0x62, 0xF5, 0x82, 0xE4, 0x34, +0x87, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, +0x22, 0x90, 0x82, 0xD3, 0x12, 0x46, 0xD3, 0xEC, +0x22, 0x7F, 0x24, 0x7E, 0x08, 0x12, 0x2E, 0xA2, +0x90, 0x82, 0xCD, 0xE0, 0x22, 0x90, 0x82, 0xEB, +0xEF, 0xF0, 0xAB, 0x05, 0x90, 0x82, 0xF1, 0x12, +0x20, 0xDA, 0x00, 0x00, 0x00, 0x00, 0xAF, 0x03, +0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x14, 0x31, 0x5A, +0x90, 0x82, 0xED, 0x12, 0x46, 0xD3, 0xED, 0x54, +0x0F, 0xFD, 0xE4, 0xFC, 0x12, 0x46, 0xB5, 0xEC, +0x54, 0x0F, 0xFC, 0x90, 0x82, 0xF1, 0x12, 0x20, +0xCE, 0x90, 0x82, 0xEB, 0xE0, 0x75, 0xF0, 0x08, +0xA4, 0x24, 0x60, 0xF5, 0x82, 0xE4, 0x34, 0x87, +0x11, 0xE9, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x82, +0xF1, 0x11, 0xD5, 0xD0, 0x07, 0xD0, 0x06, 0x02, +0x2E, 0xA2, 0x12, 0x20, 0xBB, 0xA8, 0x04, 0xA9, +0x05, 0xAA, 0x06, 0xAB, 0x07, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xE4, 0x90, 0x83, +0x03, 0xF0, 0xA3, 0xF0, 0x51, 0x32, 0x90, 0x85, +0xBB, 0x12, 0x20, 0xDA, 0xCC, 0xF0, 0x00, 0xC0, +0x12, 0x4F, 0x6C, 0x12, 0x20, 0xDA, 0x00, 0x00, +0x00, 0x14, 0x51, 0xAC, 0x12, 0x20, 0xDA, 0x00, +0x00, 0x00, 0x00, 0xE4, 0xFD, 0xFF, 0x51, 0x10, +0x7F, 0xE8, 0x7E, 0x08, 0x12, 0x2D, 0x5C, 0xEF, +0x54, 0x0E, 0xFF, 0xE4, 0xFE, 0xED, 0x54, 0xF4, +0xFD, 0xEC, 0x54, 0x03, 0xFC, 0xE4, 0xFB, 0xFA, +0xF9, 0xF8, 0xC3, 0x12, 0x46, 0xC2, 0x60, 0x18, +0xD3, 0x51, 0x03, 0x40, 0x09, 0x90, 0x01, 0xC3, +0xE0, 0x44, 0x02, 0xF0, 0x80, 0x0A, 0x51, 0x95, +0x90, 0x83, 0x03, 0x12, 0x5C, 0x3A, 0x80, 0xC8, +0xC3, 0x51, 0x03, 0x50, 0x17, 0x51, 0xA3, 0x44, +0x80, 0xFC, 0x90, 0x83, 0x05, 0x12, 0x20, 0xCE, +0x90, 0x83, 0x05, 0x11, 0xD5, 0x7F, 0x7C, 0x7E, +0x08, 0x12, 0x2E, 0xA2, 0x90, 0x01, 0x00, 0x74, +0x3F, 0xF0, 0xA3, 0xE0, 0x54, 0xFD, 0xF0, 0x90, +0x05, 0x53, 0xE0, 0x44, 0x20, 0xF0, 0xD0, 0xD0, +0x92, 0xAF, 0x22, 0x90, 0x83, 0x04, 0xE0, 0x94, +0xE8, 0x90, 0x83, 0x03, 0xE0, 0x94, 0x03, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xC0, +0x07, 0xC0, 0x05, 0x90, 0x82, 0xFF, 0x12, 0x46, +0xD3, 0x90, 0x82, 0xED, 0x12, 0x20, 0xCE, 0xD0, +0x05, 0xD0, 0x07, 0x31, 0x05, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0xE4, 0x90, 0x83, 0x24, 0xF0, 0xA3, +0xF0, 0x90, 0x05, 0x22, 0xE0, 0x90, 0x83, 0x26, +0xF0, 0x7B, 0x47, 0x51, 0x9C, 0x90, 0x05, 0xF8, +0xE0, 0x70, 0x1B, 0xA3, 0xE0, 0x70, 0x17, 0xA3, +0xE0, 0x70, 0x13, 0xA3, 0xE0, 0x70, 0x0F, 0x90, +0x83, 0x26, 0xE0, 0xFD, 0x7B, 0x48, 0xE4, 0xFF, +0x12, 0x4E, 0x97, 0x7F, 0x01, 0x22, 0xD3, 0x90, +0x83, 0x25, 0xE0, 0x94, 0xE8, 0x90, 0x83, 0x24, +0xE0, 0x94, 0x03, 0x40, 0x16, 0x90, 0x01, 0xC0, +0xE0, 0x44, 0x20, 0xF0, 0x90, 0x83, 0x26, 0xE0, +0xFD, 0x7B, 0x5B, 0xE4, 0xFF, 0x12, 0x4E, 0x97, +0x7F, 0x00, 0x22, 0x51, 0x95, 0x90, 0x83, 0x24, +0x12, 0x5C, 0x3A, 0x80, 0xB0, 0x7F, 0x32, 0x7E, +0x00, 0x02, 0x32, 0xAA, 0x7D, 0xFF, 0xE4, 0xFF, +0x02, 0x4E, 0x97, 0x7F, 0x7C, 0x7E, 0x08, 0x12, +0x2D, 0x5C, 0xEC, 0x22, 0x7F, 0x70, 0x7E, 0x0E, +0x12, 0x2E, 0xA2, 0x90, 0x82, 0xFF, 0x22, 0x7B, +0x2F, 0x12, 0x4F, 0xD8, 0x31, 0x66, 0x7D, 0x08, +0x7F, 0x01, 0x02, 0x4D, 0x57, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x67, 0xEF, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x12, 0x1F, 0xA4, 0xFF, +0x54, 0x80, 0xFE, 0x90, 0x82, 0x1F, 0xE0, 0x54, +0x7F, 0x4E, 0xFE, 0xF0, 0xEF, 0x54, 0x40, 0xFF, +0xEE, 0x54, 0xBF, 0x4F, 0xFF, 0xF0, 0x12, 0x1F, +0xA4, 0xFE, 0x54, 0x20, 0xFD, 0xEF, 0x54, 0xDF, +0x4D, 0xFF, 0x90, 0x82, 0x1F, 0xF0, 0xEE, 0x54, +0x10, 0xFE, 0xEF, 0x54, 0xEF, 0x4E, 0xFF, 0xF0, +0x12, 0x1F, 0xA4, 0x54, 0x0F, 0xFE, 0xEF, 0x54, +0xF0, 0x4E, 0x90, 0x82, 0x1F, 0xF0, 0x12, 0x5F, +0x2A, 0xFF, 0x54, 0x7F, 0x90, 0x82, 0x21, 0xF0, +0xEF, 0x54, 0x80, 0x12, 0x4F, 0xF0, 0xFF, 0x90, +0x82, 0x20, 0xE0, 0x54, 0xFE, 0x12, 0x5F, 0xD2, +0x90, 0x82, 0x22, 0x12, 0x5F, 0x74, 0x54, 0x01, +0x25, 0xE0, 0xFF, 0x90, 0x82, 0x20, 0xE0, 0x54, +0xFD, 0x4F, 0xF0, 0x12, 0x4B, 0xE5, 0x20, 0xE0, +0x02, 0x7D, 0x01, 0x02, 0x4A, 0x4D, 0x12, 0x1F, +0xA4, 0x54, 0x01, 0xFF, 0x90, 0x82, 0x24, 0xE0, +0x54, 0xFE, 0x4F, 0xF0, 0x22, 0x12, 0x67, 0xC8, +0xFF, 0x54, 0x01, 0xFE, 0x90, 0x82, 0x09, 0x12, +0x67, 0xC0, 0x54, 0x02, 0xFF, 0xEE, 0x54, 0xFD, +0x4F, 0xFF, 0xF0, 0x12, 0x7E, 0x61, 0x90, 0x82, +0x09, 0xF1, 0xD7, 0x4E, 0xFF, 0xF0, 0x12, 0x1F, +0xA4, 0x54, 0x10, 0x25, 0xE0, 0x25, 0xE0, 0xFE, +0xEF, 0x54, 0xBF, 0x4E, 0x90, 0x82, 0x09, 0xF0, +0x90, 0x05, 0x52, 0xE0, 0x54, 0x07, 0xFF, 0x90, +0x82, 0x43, 0x60, 0x13, 0x12, 0x5F, 0x27, 0xFD, +0x90, 0x05, 0x56, 0xE0, 0xC3, 0x9D, 0x90, 0x82, +0x0B, 0xF0, 0xA3, 0xED, 0xF0, 0x80, 0x23, 0x12, +0x5F, 0x27, 0xFB, 0xFF, 0x90, 0x05, 0x54, 0xE0, +0xC3, 0x9F, 0xFF, 0xE4, 0x94, 0x00, 0xFE, 0x7C, +0x00, 0x7D, 0x05, 0x12, 0x20, 0x30, 0x90, 0x82, +0x0B, 0xEF, 0xF0, 0xEB, 0x75, 0xF0, 0x05, 0x84, +0xA3, 0xF0, 0x12, 0x5F, 0x13, 0x12, 0x1F, 0xA4, +0x20, 0xE0, 0x0A, 0x12, 0x4E, 0x90, 0x90, 0x01, +0x57, 0xE4, 0xF0, 0x80, 0x0A, 0x7D, 0x0C, 0x7F, +0x01, 0x12, 0x4D, 0x57, 0x12, 0x4F, 0xDE, 0xF1, +0xE0, 0x20, 0xE0, 0x04, 0xEF, 0x44, 0x20, 0xF0, +0x12, 0x4F, 0xD1, 0x30, 0xE0, 0x18, 0x90, 0x81, +0x30, 0x74, 0x01, 0xF0, 0xE4, 0x90, 0x81, 0x32, +0xF0, 0x12, 0x57, 0xDA, 0xB1, 0x9E, 0x90, 0x83, +0x23, 0x74, 0x06, 0xF0, 0x80, 0x18, 0xE4, 0x90, +0x81, 0x30, 0xF0, 0x90, 0x81, 0x32, 0x74, 0x0C, +0xF0, 0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFE, 0xF0, +0xA3, 0xE0, 0x54, 0xFB, 0xF0, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xAC, 0x07, 0x90, +0x81, 0x2C, 0xE0, 0x12, 0x4F, 0xF0, 0x30, 0xE0, +0x02, 0x81, 0xEE, 0x90, 0x81, 0x2B, 0xE0, 0x30, +0xE0, 0x16, 0x90, 0x81, 0x4D, 0xE0, 0x24, 0x05, +0x90, 0x81, 0x45, 0xF0, 0x90, 0x81, 0x4D, 0xE0, +0x24, 0x03, 0x90, 0x81, 0x44, 0xF0, 0x80, 0x0E, +0x90, 0x81, 0x45, 0x74, 0x05, 0xF0, 0x90, 0x81, +0x44, 0x14, 0xF0, 0x04, 0x2B, 0xFB, 0x90, 0x81, +0x44, 0xE0, 0xFA, 0x90, 0x81, 0x43, 0xE0, 0xD3, +0x9A, 0x50, 0x12, 0x90, 0x81, 0x38, 0xEB, 0xF0, +0x90, 0x81, 0x45, 0xE0, 0xC3, 0x9D, 0x2C, 0x90, +0x81, 0x48, 0xF0, 0x80, 0x1C, 0xC3, 0xED, 0x9A, +0x2B, 0x90, 0x81, 0x38, 0xF0, 0x90, 0x81, 0x44, +0xE0, 0xFF, 0xA3, 0xE0, 0xC3, 0x9F, 0x90, 0x81, +0x48, 0xF0, 0xE4, 0x90, 0x81, 0xEE, 0xF0, 0xA3, +0xF0, 0x90, 0x81, 0x45, 0x91, 0xFA, 0x90, 0x81, +0x48, 0xB1, 0x03, 0x40, 0x04, 0xEF, 0x24, 0x0A, +0xF0, 0x90, 0x81, 0x48, 0x91, 0xFA, 0x90, 0x81, +0x38, 0xB1, 0x03, 0x40, 0x04, 0xEF, 0x24, 0x0A, +0xF0, 0x90, 0x81, 0x48, 0xE0, 0xFF, 0x7E, 0x00, +0x90, 0x81, 0x3C, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, +0x90, 0x05, 0x58, 0xE0, 0x6F, 0x70, 0x01, 0xE4, +0x60, 0x03, 0x12, 0x7E, 0x2F, 0x90, 0x81, 0x2D, +0xE0, 0x54, 0xFE, 0xF0, 0x80, 0x07, 0x90, 0x81, +0x2D, 0xE0, 0x44, 0x01, 0xF0, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0xE0, 0xFF, 0x24, 0x0A, 0xFD, 0xE4, +0x33, 0xFC, 0x22, 0xE0, 0xD3, 0x9D, 0xEC, 0x64, +0x80, 0xF8, 0x74, 0x80, 0x98, 0x22, 0xB1, 0xAC, +0x90, 0x82, 0x27, 0xEF, 0xF0, 0x30, 0xE0, 0x05, +0x7D, 0x01, 0xE4, 0x80, 0x02, 0xE4, 0xFD, 0xFF, +0x12, 0x4D, 0x57, 0x90, 0x82, 0x27, 0xE0, 0x30, +0xE6, 0x11, 0x90, 0x01, 0x2F, 0xE0, 0x30, 0xE7, +0x04, 0xE4, 0xF0, 0x80, 0x06, 0x90, 0x01, 0x2F, +0x74, 0x80, 0xF0, 0x90, 0x81, 0x2B, 0xE0, 0x30, +0xE0, 0x2E, 0xB1, 0x96, 0x30, 0xE1, 0x0D, 0xE0, +0x44, 0x04, 0xF0, 0x90, 0x04, 0xEC, 0xE0, 0x54, +0xFD, 0xF0, 0x80, 0x04, 0xE0, 0x54, 0xFB, 0xF0, +0xB1, 0x96, 0x30, 0xE5, 0x0D, 0xE0, 0x44, 0x08, +0xF0, 0x90, 0x04, 0xEC, 0xE0, 0x54, 0xDF, 0xF0, +0x80, 0x22, 0xE0, 0x54, 0xF7, 0xF0, 0x80, 0x1C, +0x90, 0x81, 0x2D, 0x12, 0x55, 0x3A, 0x30, 0xE0, +0x07, 0x90, 0x04, 0xEC, 0xE0, 0x44, 0x02, 0xF0, +0xB1, 0xE8, 0x30, 0xE0, 0x07, 0x90, 0x04, 0xEC, +0xE0, 0x44, 0x20, 0xF0, 0xB1, 0x9E, 0x90, 0x83, +0x23, 0x74, 0x02, 0xF0, 0x81, 0x2E, 0x90, 0x04, +0xEC, 0xE0, 0x90, 0x81, 0x2D, 0x22, 0x90, 0x81, +0x42, 0xE0, 0xFF, 0xA3, 0xE0, 0xFD, 0x90, 0x81, +0x49, 0xE0, 0xFB, 0x22, 0xE4, 0x90, 0x82, 0x29, +0xF0, 0xA3, 0xF0, 0x90, 0x00, 0x83, 0xE0, 0x90, +0x82, 0x28, 0xF0, 0x90, 0x00, 0x83, 0xE0, 0xFE, +0x90, 0x82, 0x28, 0xE0, 0xFF, 0xB5, 0x06, 0x01, +0x22, 0xC3, 0x90, 0x82, 0x2A, 0xE0, 0x94, 0x64, +0x90, 0x82, 0x29, 0xE0, 0x94, 0x00, 0x40, 0x08, +0xF1, 0xCF, 0x90, 0x82, 0x28, 0xE0, 0xFF, 0x22, +0x90, 0x82, 0x29, 0x12, 0x5C, 0x3A, 0x80, 0xCB, +0xEF, 0x13, 0x13, 0x13, 0x54, 0x1F, 0x22, 0x90, +0x82, 0x16, 0xE0, 0x30, 0xE0, 0x71, 0x90, 0x82, +0x1A, 0xE0, 0x04, 0xF0, 0x90, 0x82, 0x1D, 0xE0, +0x64, 0x01, 0x70, 0x2F, 0x90, 0x82, 0x16, 0x12, +0x55, 0x3A, 0x30, 0xE0, 0x26, 0x90, 0x82, 0x1C, +0xE0, 0x70, 0x20, 0x90, 0x82, 0x19, 0xE0, 0xFE, +0xA3, 0xE0, 0xC3, 0x9E, 0x40, 0x15, 0xB1, 0xE8, +0x30, 0xE0, 0x09, 0x12, 0x5F, 0xDA, 0x12, 0x5F, +0x7B, 0xF0, 0x80, 0x07, 0xD1, 0x68, 0x12, 0x5F, +0x7B, 0xF0, 0x22, 0x90, 0x82, 0x1A, 0xE0, 0xFF, +0x90, 0x82, 0x17, 0xE0, 0xD3, 0x9F, 0x50, 0x27, +0x90, 0x06, 0x92, 0xE0, 0x20, 0xE2, 0x11, 0x90, +0x82, 0x1C, 0xE0, 0x70, 0x0B, 0x12, 0x7E, 0x39, +0x90, 0x82, 0x15, 0xE0, 0x04, 0xF0, 0x80, 0x06, +0x90, 0x06, 0x92, 0x74, 0x04, 0xF0, 0xE4, 0x90, +0x82, 0x1A, 0xF0, 0x90, 0x82, 0x1C, 0xF0, 0x22, +0x90, 0x01, 0xC7, 0x74, 0x10, 0xF0, 0x7F, 0x01, +0x80, 0x0A, 0xD1, 0xD6, 0x90, 0x01, 0xC7, 0x74, +0x66, 0xF0, 0xE4, 0xFF, 0x90, 0x83, 0x37, 0xEF, +0xF0, 0x90, 0x80, 0x07, 0xE0, 0xB4, 0x02, 0x12, +0x90, 0x83, 0x37, 0xE0, 0xFF, 0x64, 0x01, 0x60, +0x25, 0x90, 0x01, 0x4D, 0xE0, 0x64, 0x80, 0xF0, +0x80, 0x19, 0x90, 0x01, 0x00, 0x74, 0xFF, 0xF0, +0x7F, 0x64, 0x7E, 0x00, 0x12, 0x32, 0xAA, 0x90, +0x06, 0x90, 0xE0, 0x44, 0x01, 0xF0, 0x90, 0x83, +0x37, 0xE0, 0xFF, 0x12, 0x4B, 0x20, 0x12, 0x5F, +0x7B, 0xF0, 0x22, 0x12, 0x5F, 0xE3, 0x30, 0xE0, +0x14, 0xE4, 0x90, 0x80, 0xFF, 0xF0, 0x90, 0x80, +0xFC, 0xE0, 0x30, 0xE0, 0x08, 0xC4, 0x54, 0x0F, +0x30, 0xE0, 0x02, 0xD1, 0x72, 0x22, 0xE4, 0x90, +0x82, 0xC2, 0xF0, 0x90, 0x80, 0xFC, 0xE0, 0xFE, +0x54, 0x01, 0x90, 0x82, 0xC2, 0xF0, 0xEE, 0x54, +0xFE, 0x90, 0x80, 0xFC, 0xF0, 0x7D, 0x08, 0xE4, +0xFF, 0x12, 0x54, 0xA9, 0x90, 0x82, 0xC2, 0xE0, +0x60, 0x10, 0x90, 0x02, 0x09, 0xE0, 0x90, 0x04, +0x24, 0xF0, 0x90, 0x02, 0x09, 0xE0, 0x90, 0x04, +0x25, 0xF0, 0xE4, 0x90, 0x81, 0x08, 0xF0, 0xA3, +0xF0, 0x22, 0x90, 0x80, 0xFF, 0xE0, 0x60, 0x08, +0x90, 0x80, 0xFC, 0xE0, 0x44, 0x10, 0xF0, 0x22, +0xC1, 0x72, 0xF1, 0x71, 0x90, 0x82, 0x27, 0xEE, +0xF0, 0xA3, 0xEF, 0x12, 0x5F, 0xE2, 0x30, 0xE0, +0x14, 0x90, 0x82, 0x28, 0xE0, 0x20, 0xE0, 0x0D, +0xD1, 0xD6, 0x90, 0x02, 0x86, 0xE0, 0x30, 0xE2, +0x04, 0xE0, 0x54, 0xFB, 0xF0, 0x22, 0x12, 0x5F, +0xE3, 0x30, 0xE0, 0x24, 0xEF, 0x30, 0xE0, 0x20, +0x13, 0x13, 0x13, 0x54, 0x1F, 0x30, 0xE0, 0x18, +0x90, 0x81, 0x00, 0xE0, 0x70, 0x0C, 0xD1, 0xD6, +0x90, 0x01, 0xC7, 0x74, 0x66, 0xF0, 0xE4, 0xFF, +0xC1, 0x7C, 0x90, 0x81, 0x00, 0xE0, 0x14, 0xF0, +0x22, 0xE4, 0x90, 0x82, 0x2B, 0xF0, 0xA3, 0xF0, +0x90, 0x00, 0x9E, 0xE0, 0x90, 0x82, 0x2D, 0xF0, +0x90, 0x00, 0x9F, 0xE0, 0x90, 0x82, 0x2E, 0xF0, +0xE0, 0xFD, 0xFE, 0x90, 0x82, 0x2D, 0xE0, 0xFC, +0xFB, 0xEB, 0xFF, 0x90, 0x82, 0x29, 0xEE, 0xF0, +0xA3, 0xEF, 0xF0, 0x90, 0x00, 0x9E, 0xE0, 0xFF, +0xEC, 0xB5, 0x07, 0x09, 0xA3, 0xE0, 0xFF, 0xED, +0xB5, 0x07, 0x02, 0x80, 0x11, 0xC3, 0x90, 0x82, +0x2C, 0xE0, 0x94, 0x64, 0x90, 0x82, 0x2B, 0xE0, +0x94, 0x00, 0x40, 0x0B, 0xF1, 0xCF, 0x90, 0x82, +0x29, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x22, 0x90, +0x82, 0x2B, 0x12, 0x5C, 0x3A, 0x80, 0xA9, 0x90, +0x01, 0xC0, 0xE0, 0x44, 0x40, 0xF0, 0x22, 0xF0, +0xEE, 0x54, 0x08, 0xFE, 0xEF, 0x54, 0xF7, 0x22, +0x90, 0x82, 0x09, 0xE0, 0xFF, 0x13, 0x13, 0x13, +0x54, 0x1F, 0x22, 0x12, 0x1F, 0xA4, 0x90, 0x81, +0x1E, 0xF0, 0x12, 0x5F, 0x2A, 0x90, 0x81, 0x1F, +0x12, 0x5F, 0xD3, 0x90, 0x81, 0x20, 0xF0, 0x22, +0xE4, 0x90, 0x80, 0xF8, 0xF0, 0xA3, 0xF0, 0x90, +0x80, 0x60, 0xF0, 0xA3, 0xF0, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x82, 0x3F, +0x12, 0x46, 0xF4, 0x90, 0x83, 0x28, 0xE0, 0xFF, +0x04, 0xF0, 0x90, 0x00, 0x01, 0xEF, 0x12, 0x1F, +0xFC, 0x7F, 0xAF, 0x7E, 0x01, 0x12, 0x5B, 0xA1, +0xEF, 0x60, 0x3A, 0x90, 0x82, 0x3F, 0x12, 0x46, +0xEB, 0x8B, 0x13, 0x8A, 0x14, 0x89, 0x15, 0x90, +0x00, 0x0E, 0x12, 0x1F, 0xBD, 0x24, 0x02, 0xF5, +0x16, 0x7B, 0x01, 0x7A, 0x01, 0x79, 0xA0, 0x12, +0x2B, 0xED, 0x90, 0x82, 0x3F, 0x12, 0x46, 0xEB, +0x90, 0x00, 0x0E, 0x12, 0x1F, 0xBD, 0x90, 0x01, +0xAE, 0xF0, 0xA3, 0x74, 0xFF, 0xF0, 0x90, 0x01, +0xCB, 0xE0, 0x64, 0x80, 0xF0, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x7D, 0x08, 0xED, 0x14, 0xF9, 0x24, 0x22, +0x11, 0xC5, 0x60, 0x38, 0x7C, 0x08, 0xEC, 0x14, +0x90, 0x83, 0x30, 0xF0, 0x74, 0x22, 0x29, 0x11, +0xC5, 0xFB, 0x7A, 0x00, 0x90, 0x83, 0x30, 0x11, +0xCE, 0x80, 0x05, 0xC3, 0x33, 0xCE, 0x33, 0xCE, +0xD8, 0xF9, 0xFF, 0xEE, 0x5A, 0xFE, 0xEF, 0x5B, +0x4E, 0x60, 0x0F, 0xE9, 0x75, 0xF0, 0x08, 0xA4, +0xFF, 0x90, 0x83, 0x30, 0xE0, 0x2F, 0x04, 0xFF, +0x80, 0x06, 0xDC, 0xCA, 0xDD, 0xBD, 0x7F, 0x00, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xF5, 0x82, 0xE4, +0x34, 0x81, 0xF5, 0x83, 0xE0, 0x22, 0xE0, 0xFF, +0x74, 0x01, 0x7E, 0x00, 0xA8, 0x07, 0x08, 0x22, +0x75, 0x3D, 0x10, 0xE4, 0xF5, 0x3E, 0x75, 0x3F, +0x87, 0x75, 0x40, 0x03, 0x90, 0x01, 0x30, 0xE5, +0x3D, 0xF0, 0xA3, 0xE5, 0x3E, 0xF0, 0xA3, 0xE5, +0x3F, 0xF0, 0xA3, 0xE5, 0x40, 0xF0, 0x22, 0x75, +0x45, 0x0F, 0x75, 0x46, 0x01, 0x75, 0x47, 0x23, +0x75, 0x48, 0x62, 0x90, 0x01, 0x38, 0xE5, 0x45, +0xF0, 0xA3, 0xE5, 0x46, 0xF0, 0xA3, 0xE5, 0x47, +0xF0, 0xA3, 0xE5, 0x48, 0xF0, 0x22, 0x7F, 0x02, +0x90, 0x82, 0x11, 0xE0, 0xFE, 0xEF, 0xC3, 0x9E, +0x50, 0x18, 0xEF, 0x25, 0xE0, 0x24, 0x81, 0xF8, +0xE6, 0x30, 0xE4, 0x0B, 0x90, 0x01, 0xB8, 0x74, +0x08, 0xF0, 0xA3, 0xF0, 0x7F, 0x00, 0x22, 0x0F, +0x80, 0xDE, 0x7F, 0x01, 0x22, 0x90, 0x01, 0x34, +0xE0, 0x55, 0x3D, 0xF5, 0x41, 0xA3, 0xE0, 0x55, +0x3E, 0xF5, 0x42, 0xA3, 0xE0, 0x55, 0x3F, 0xF5, +0x43, 0xA3, 0xE0, 0x55, 0x40, 0xF5, 0x44, 0x90, +0x01, 0x34, 0xE5, 0x41, 0xF0, 0xA3, 0xE5, 0x42, +0xF0, 0xA3, 0xE5, 0x43, 0xF0, 0xA3, 0xE5, 0x44, +0xF0, 0x22, 0x90, 0x01, 0x3C, 0xE0, 0x55, 0x45, +0xF5, 0x49, 0xA3, 0xE0, 0x55, 0x46, 0xF5, 0x4A, +0xA3, 0xE0, 0x55, 0x47, 0xF5, 0x4B, 0xA3, 0xE0, +0x55, 0x48, 0xF5, 0x4C, 0x90, 0x01, 0x3C, 0xE5, +0x49, 0xF0, 0xA3, 0xE5, 0x4A, 0xF0, 0xA3, 0xE5, +0x4B, 0xF0, 0xA3, 0xE5, 0x4C, 0xF0, 0x53, 0x91, +0xDF, 0x22, 0x90, 0x80, 0xFC, 0xE0, 0x30, 0xE0, +0x05, 0x7F, 0x20, 0x12, 0x49, 0x35, 0x22, 0x90, +0x01, 0xCF, 0xE0, 0x90, 0x83, 0x32, 0xF0, 0xE0, +0xFF, 0x30, 0xE0, 0x07, 0x90, 0x01, 0xCF, 0xE0, +0x54, 0xFE, 0xF0, 0xEF, 0x30, 0xE5, 0x23, 0x90, +0x01, 0xCF, 0xE0, 0x54, 0xDF, 0xF0, 0x90, 0x01, +0x34, 0x74, 0x20, 0xF0, 0xE4, 0xF5, 0xA8, 0xF5, +0xE8, 0x12, 0x58, 0x9E, 0x90, 0x00, 0x03, 0xE0, +0x54, 0xFB, 0xFD, 0x7F, 0x03, 0x12, 0x32, 0x1E, +0x80, 0xFE, 0x22, 0x51, 0xCD, 0x90, 0x81, 0x30, +0xE0, 0x60, 0x2D, 0x90, 0x81, 0x2C, 0x12, 0x67, +0xDD, 0x30, 0xE0, 0x0D, 0x90, 0x01, 0x3B, 0xE0, +0x30, 0xE4, 0x06, 0x12, 0x54, 0xA5, 0x12, 0x57, +0xD4, 0x90, 0x83, 0x31, 0xE0, 0x04, 0xF0, 0xE0, +0xC3, 0x94, 0x80, 0x40, 0x0B, 0x90, 0x01, 0x98, +0xE0, 0x54, 0xFE, 0xF0, 0xE0, 0x44, 0x01, 0xF0, +0x51, 0xAC, 0xBF, 0x03, 0x14, 0x90, 0x82, 0x1E, +0xE0, 0xB4, 0x01, 0x0D, 0x90, 0x01, 0xB8, 0xE0, +0x04, 0xF0, 0x90, 0x05, 0x21, 0xE0, 0x44, 0x80, +0xF0, 0x12, 0x6D, 0xEF, 0x51, 0x69, 0xE4, 0x90, +0x82, 0x15, 0xF0, 0x12, 0x6F, 0x46, 0x90, 0x82, +0x09, 0xE0, 0x30, 0xE0, 0x0C, 0xE4, 0xF5, 0x1D, +0x90, 0x82, 0x0B, 0x12, 0x4C, 0x32, 0x12, 0x4F, +0xDE, 0x90, 0x80, 0x07, 0xE0, 0xB4, 0x01, 0x10, +0x12, 0x6F, 0xE0, 0x20, 0xE0, 0x0A, 0xEF, 0xC4, +0x13, 0x54, 0x07, 0x30, 0xE0, 0x02, 0x51, 0xDD, +0x22, 0x90, 0x82, 0x12, 0xE0, 0x30, 0xE0, 0x34, +0x12, 0x4F, 0xC8, 0x70, 0x2F, 0x90, 0x83, 0x38, +0xE0, 0x04, 0xF0, 0xE0, 0xB4, 0x0A, 0x0B, 0x90, +0x82, 0x14, 0xE0, 0x04, 0xF0, 0xE4, 0x90, 0x83, +0x38, 0xF0, 0x90, 0x82, 0x14, 0xE0, 0xFF, 0x90, +0x82, 0x13, 0xE0, 0xD3, 0x9F, 0x50, 0x0D, 0x90, +0x82, 0x15, 0xE0, 0x70, 0x07, 0xE4, 0x90, 0x82, +0x14, 0xF0, 0x51, 0xA5, 0x22, 0x7D, 0x08, 0x7F, +0x02, 0x02, 0x56, 0x0B, 0x90, 0x01, 0x02, 0xE0, +0x54, 0x03, 0xFF, 0x22, 0x51, 0xAC, 0xBF, 0x03, +0x02, 0x51, 0xD5, 0x22, 0x51, 0xCD, 0x90, 0x05, +0x50, 0xE0, 0x44, 0x01, 0xF0, 0x51, 0xAC, 0xBF, +0x03, 0x02, 0x51, 0xD5, 0x22, 0xE4, 0xF5, 0x4E, +0xF5, 0x4F, 0xF5, 0x50, 0x22, 0x90, 0x05, 0x21, +0xE0, 0x54, 0x7F, 0xF0, 0x22, 0x90, 0x82, 0x09, +0xE0, 0x30, 0xE0, 0x34, 0xC4, 0x13, 0x54, 0x07, +0x30, 0xE0, 0x2D, 0x90, 0x83, 0x35, 0xE0, 0x04, +0xF0, 0xE0, 0xD3, 0x94, 0xC8, 0x40, 0x21, 0x90, +0x82, 0x09, 0xE0, 0x54, 0xDF, 0xF0, 0xE4, 0x90, +0x83, 0x35, 0xF0, 0x90, 0x82, 0x09, 0xE0, 0x13, +0x30, 0xE0, 0x0D, 0x90, 0x81, 0x2B, 0xE0, 0x44, +0x01, 0xF0, 0x90, 0x81, 0x3B, 0x74, 0xD0, 0xF0, +0x22, 0x90, 0x82, 0x1C, 0xE0, 0x04, 0xF0, 0x90, +0x81, 0x33, 0xE0, 0x64, 0x02, 0x60, 0x03, 0x12, +0x53, 0xDF, 0x22, 0x90, 0x01, 0xC4, 0x74, 0x2B, +0xF0, 0x74, 0x73, 0xA3, 0xF0, 0x90, 0x00, 0x90, +0xE0, 0x20, 0xE0, 0xF9, 0x74, 0x2B, 0x04, 0x90, +0x01, 0xC4, 0xF0, 0x74, 0x73, 0xA3, 0xF0, 0x22, +0x90, 0x81, 0x3B, 0xE0, 0xFD, 0x7F, 0x93, 0x12, +0x32, 0x1E, 0x90, 0x81, 0x31, 0xE0, 0x60, 0x12, +0x90, 0x01, 0x2F, 0xE0, 0x30, 0xE7, 0x05, 0x74, +0x10, 0xF0, 0x80, 0x06, 0x90, 0x01, 0x2F, 0x74, +0x90, 0xF0, 0x90, 0x00, 0x08, 0xE0, 0x44, 0x10, +0xFD, 0x7F, 0x08, 0x12, 0x32, 0x1E, 0x7F, 0x01, +0x12, 0x5B, 0xE9, 0x90, 0x81, 0x3B, 0xE0, 0x20, +0xE0, 0x0C, 0x90, 0x00, 0x26, 0xE0, 0x44, 0x80, +0xFD, 0x7F, 0x26, 0x12, 0x32, 0x1E, 0x90, 0x00, +0x90, 0xE0, 0x44, 0x01, 0xFD, 0x7F, 0x90, 0x12, +0x32, 0x1E, 0x7F, 0x14, 0x7E, 0x00, 0x02, 0x32, +0xAA, 0x7D, 0x10, 0xE4, 0xFF, 0x74, 0x45, 0x2F, +0xF8, 0xE6, 0x4D, 0x02, 0x54, 0x96, 0x90, 0x82, +0x1F, 0xE0, 0x54, 0x7F, 0xF0, 0x54, 0xBF, 0xF0, +0x54, 0xDF, 0xF0, 0x54, 0xF0, 0xF0, 0xE4, 0x90, +0x82, 0x21, 0xF0, 0x90, 0x82, 0x1F, 0xE0, 0x54, +0xEF, 0xF0, 0x22, 0x90, 0x04, 0x1A, 0xE0, 0xF4, +0x60, 0x03, 0x7F, 0x00, 0x22, 0x90, 0x04, 0x1B, +0xE0, 0x54, 0x07, 0x64, 0x07, 0x7F, 0x01, 0x60, +0x02, 0x7F, 0x00, 0x22, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x71, 0xCB, 0xEF, 0x64, 0x01, +0x60, 0x05, 0x75, 0x0D, 0x01, 0x80, 0x41, 0x90, +0x81, 0x34, 0xE0, 0xFF, 0x54, 0x03, 0x60, 0x05, +0x75, 0x0D, 0x02, 0x80, 0x33, 0xEF, 0x30, 0xE2, +0x05, 0x75, 0x0D, 0x08, 0x80, 0x2A, 0x90, 0x81, +0x34, 0xE0, 0x30, 0xE4, 0x05, 0x75, 0x0D, 0x10, +0x80, 0x1E, 0x12, 0x55, 0x37, 0x20, 0xE0, 0x05, +0x75, 0x0D, 0x20, 0x80, 0x13, 0x91, 0x53, 0x8F, +0x0E, 0xE5, 0x0E, 0x64, 0x01, 0x60, 0x05, 0x85, +0x0E, 0x0D, 0x80, 0x04, 0x91, 0x4B, 0x80, 0x0E, +0x90, 0x01, 0xB9, 0x74, 0x04, 0xF0, 0x90, 0x01, +0xB8, 0xE5, 0x0D, 0xF0, 0x7F, 0x00, 0xD0, 0xD0, +0x92, 0xAF, 0x22, 0x90, 0x01, 0xB8, 0xE4, 0xF0, +0x7F, 0x01, 0x22, 0x90, 0x81, 0x32, 0xE0, 0xD3, +0x94, 0x00, 0x40, 0x06, 0x75, 0x55, 0x04, 0x7F, +0xFF, 0x22, 0x90, 0x82, 0x08, 0xE0, 0x60, 0x06, +0x75, 0x55, 0x80, 0x7F, 0xFF, 0x22, 0x7F, 0x01, +0x22, 0x90, 0x02, 0x87, 0xE0, 0x60, 0x02, 0x80, +0x08, 0x90, 0x01, 0x00, 0xE0, 0x64, 0x3F, 0x60, +0x05, 0x75, 0x54, 0x01, 0x80, 0x22, 0x90, 0x02, +0x96, 0xE0, 0x60, 0x05, 0x75, 0x54, 0x10, 0x80, +0x17, 0x90, 0x02, 0x86, 0xE0, 0x20, 0xE1, 0x02, +0x80, 0x07, 0x90, 0x02, 0x86, 0xE0, 0x30, 0xE3, +0x05, 0x75, 0x54, 0x04, 0x80, 0x02, 0x80, 0xA3, +0x90, 0x01, 0xB9, 0x74, 0x08, 0xF0, 0x90, 0x01, +0xB8, 0xE5, 0x54, 0xF0, 0x7F, 0x00, 0x22, 0xEF, +0x24, 0xFE, 0x60, 0x0B, 0x04, 0x70, 0x24, 0x90, +0x81, 0x36, 0x74, 0x02, 0xF0, 0x80, 0x13, 0xED, +0x70, 0x06, 0x90, 0x82, 0x05, 0xE0, 0x80, 0x02, +0xED, 0x14, 0x90, 0x81, 0x36, 0xF0, 0x90, 0x81, +0x36, 0xE0, 0xA3, 0xF0, 0x90, 0x81, 0x2C, 0xE0, +0x44, 0x08, 0xF0, 0x22, 0x7B, 0x2E, 0x91, 0xEF, +0x7D, 0x02, 0x7F, 0x01, 0x02, 0x4D, 0x57, 0x7D, +0x6F, 0x7F, 0xFF, 0x02, 0x4E, 0x97, 0x90, 0x82, +0x09, 0xE0, 0x54, 0xFE, 0xF0, 0x54, 0xFD, 0xF0, +0x54, 0xEF, 0xF0, 0x44, 0x08, 0xF0, 0x22, 0x90, +0x83, 0x0F, 0xE0, 0xFF, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x90, 0x83, 0x36, 0xEF, 0xF0, +0xC3, 0x94, 0x02, 0x50, 0x48, 0x90, 0x80, 0x0B, +0xE0, 0xFF, 0x90, 0x04, 0x1C, 0xE0, 0x6F, 0x70, +0x3C, 0x90, 0x81, 0x33, 0xE0, 0x64, 0x0E, 0x70, +0x19, 0x90, 0x83, 0x36, 0xE0, 0x70, 0x2E, 0x90, +0x81, 0x2B, 0xE0, 0x54, 0x7F, 0xF0, 0x12, 0x4F, +0xE6, 0x7D, 0x0C, 0x7F, 0x01, 0x12, 0x4D, 0x57, +0x80, 0x18, 0x90, 0x81, 0x33, 0xE0, 0x64, 0x06, +0x70, 0x13, 0x90, 0x83, 0x36, 0xE0, 0x60, 0x0D, +0xB1, 0x6A, 0xB1, 0x72, 0x90, 0x81, 0x33, 0x74, +0x04, 0xF0, 0x12, 0x4E, 0x92, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0x90, 0x81, 0x2B, 0xE0, 0x54, 0xBF, +0xF0, 0x22, 0x90, 0x06, 0x04, 0xE0, 0x44, 0x40, +0xF0, 0xE0, 0x44, 0x80, 0xF0, 0x22, 0x74, 0xA2, +0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x82, 0xF5, 0x83, +0xE0, 0xFF, 0xE4, 0xFE, 0xEF, 0xC3, 0x13, 0xFD, +0xEF, 0x30, 0xE0, 0x02, 0x7E, 0x80, 0x90, 0xFD, +0x10, 0xED, 0xF0, 0xAF, 0x06, 0x22, 0x90, 0x82, +0x3F, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x02, +0x84, 0xEF, 0xF0, 0xEE, 0xA3, 0xF0, 0xA3, 0xE0, +0x44, 0x01, 0xF0, 0x22, 0x7D, 0x7F, 0xEF, 0x5D, +0xC3, 0x60, 0x0A, 0xB1, 0xC9, 0x24, 0x80, 0xFF, +0xE4, 0x3E, 0xFE, 0x80, 0x03, 0xB1, 0xC9, 0xFF, +0x22, 0x74, 0xFF, 0x9D, 0xFD, 0x74, 0xFF, 0x94, +0x00, 0x5E, 0xFE, 0xED, 0x5F, 0x22, 0x7E, 0x00, +0x7F, 0x08, 0x7D, 0x00, 0x7B, 0x01, 0x7A, 0x82, +0x79, 0x16, 0x12, 0x47, 0x23, 0x90, 0x82, 0x17, +0x74, 0x08, 0xF0, 0xA3, 0x74, 0x03, 0xF0, 0x22, +0x90, 0x82, 0xC2, 0x12, 0x46, 0xF4, 0xE4, 0xFF, +0x90, 0x82, 0xC8, 0xE0, 0xFE, 0xEF, 0xC3, 0x9E, +0x50, 0x1E, 0x90, 0x82, 0xC5, 0x12, 0x46, 0xEB, +0x8F, 0x82, 0xD1, 0x39, 0xFE, 0x90, 0x82, 0xC2, +0x12, 0x46, 0xEB, 0x8F, 0x82, 0xD1, 0x39, 0x6E, +0x60, 0x03, 0x7F, 0x00, 0x22, 0x0F, 0x80, 0xD8, +0x7F, 0x01, 0x22, 0x75, 0xF0, 0x03, 0xA4, 0x24, +0x93, 0xF5, 0x82, 0xE4, 0x34, 0x82, 0xF5, 0x83, +0x12, 0x46, 0xEB, 0x90, 0x82, 0x49, 0xE0, 0xF5, +0x82, 0x75, 0x83, 0x00, 0x02, 0x1F, 0xBD, 0x74, +0x03, 0xF0, 0x7A, 0x82, 0x79, 0xF9, 0xB1, 0xF0, +0xEF, 0x22, 0x74, 0x03, 0xF0, 0x7A, 0x82, 0x79, +0xF5, 0xB1, 0xF0, 0xEF, 0x22, 0x12, 0x5F, 0x19, +0x30, 0xE0, 0x0A, 0xE0, 0xC4, 0x54, 0x0F, 0x30, +0xE0, 0x03, 0x02, 0x7C, 0xE4, 0x90, 0x81, 0x19, +0xE0, 0x90, 0x82, 0xA2, 0xF0, 0x90, 0x81, 0x1A, +0xE0, 0x90, 0x82, 0xA3, 0xF0, 0x90, 0x81, 0x1B, +0xE0, 0x90, 0x82, 0xA4, 0xF0, 0x90, 0x81, 0x1C, +0xE0, 0x90, 0x82, 0xA5, 0xF0, 0x90, 0x81, 0x1D, +0xE0, 0x90, 0x82, 0xA6, 0xF0, 0x90, 0x81, 0x0A, +0xE0, 0x90, 0x82, 0xA7, 0xF0, 0x90, 0x81, 0x0B, +0xE0, 0x90, 0x82, 0xA8, 0xF0, 0x90, 0x81, 0x0C, +0xE0, 0x90, 0x82, 0xA9, 0xF0, 0x90, 0x81, 0x0D, +0xE0, 0x90, 0x82, 0xAA, 0xF0, 0x90, 0x81, 0x0E, +0xE0, 0x90, 0x82, 0xAB, 0xF0, 0x90, 0x81, 0x0F, +0xE0, 0x90, 0x82, 0xAC, 0xF0, 0x90, 0x81, 0x10, +0xE0, 0x90, 0x82, 0xAD, 0xF0, 0x90, 0x81, 0x11, +0xE0, 0x90, 0x82, 0xAE, 0xF0, 0x90, 0x81, 0x12, +0xE0, 0x90, 0x82, 0xAF, 0xF0, 0x90, 0x81, 0x13, +0xE0, 0x90, 0x82, 0xB0, 0xF0, 0x12, 0x58, 0xC4, +0x90, 0x82, 0x4A, 0xF0, 0x12, 0x7D, 0x00, 0x50, +0x05, 0x12, 0x7D, 0x0D, 0x80, 0xF6, 0x90, 0x01, +0x1F, 0xE0, 0xFE, 0x90, 0x01, 0x1E, 0x12, 0x7E, +0x83, 0x90, 0x82, 0x3F, 0xF0, 0xA3, 0x12, 0x7D, +0xC0, 0x12, 0x7D, 0x00, 0x50, 0x57, 0xB1, 0x7E, +0x90, 0x82, 0x4A, 0xE0, 0xFE, 0x24, 0xB1, 0xF5, +0x82, 0xE4, 0x34, 0x82, 0x12, 0x7E, 0x08, 0x24, +0x45, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, +0xE0, 0xFF, 0x74, 0x4C, 0x2E, 0xF5, 0x82, 0xE4, +0x34, 0x82, 0x12, 0x7E, 0x08, 0x24, 0x46, 0xF9, +0xE4, 0x34, 0xFC, 0xFA, 0x7B, 0x01, 0xEE, 0x12, +0x7D, 0x6F, 0x12, 0x46, 0xF4, 0x12, 0x7E, 0x0C, +0x24, 0x30, 0xF9, 0xE4, 0x34, 0xFC, 0xFA, 0xEE, +0x75, 0xF0, 0x03, 0xA4, 0x24, 0x93, 0xF5, 0x82, +0xE4, 0x34, 0x82, 0xF5, 0x83, 0x12, 0x46, 0xF4, +0x12, 0x7D, 0x1A, 0x80, 0xA4, 0x90, 0x02, 0x87, +0xE0, 0x70, 0x03, 0x02, 0x7C, 0xE4, 0x90, 0x80, +0xFC, 0xE0, 0x20, 0xE0, 0x03, 0x02, 0x7C, 0xE4, +0xC3, 0x13, 0x30, 0xE0, 0x0A, 0xE0, 0xC4, 0x54, +0x0F, 0x30, 0xE0, 0x03, 0x02, 0x7C, 0xE4, 0xE4, +0x90, 0x82, 0xBB, 0x12, 0x58, 0xCC, 0x90, 0x82, +0x3F, 0xE0, 0xFF, 0xA3, 0xE0, 0xA3, 0xCF, 0xF0, +0xA3, 0xEF, 0xF0, 0x90, 0x82, 0x41, 0xE0, 0xFC, +0xA3, 0xE0, 0xFD, 0xEC, 0x90, 0xFD, 0x11, 0xF0, +0x74, 0x01, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0xFB, +0xF5, 0x83, 0xE0, 0xFE, 0x74, 0x00, 0x2D, 0x12, +0x7E, 0x7A, 0x7A, 0x00, 0x24, 0x00, 0xFF, 0xEA, +0x3E, 0x54, 0x3F, 0x90, 0x82, 0x43, 0xF0, 0xA3, +0xEF, 0xF0, 0x74, 0x02, 0x2D, 0xF5, 0x82, 0xE4, +0x34, 0xFB, 0xF5, 0x83, 0xE0, 0x54, 0x0F, 0x33, +0x33, 0x33, 0x54, 0xF8, 0x90, 0x82, 0x46, 0xF0, +0xFC, 0x74, 0x07, 0x2D, 0xF5, 0x82, 0xE4, 0x34, +0xFB, 0xF5, 0x83, 0xE0, 0x54, 0xC0, 0x90, 0x82, +0x48, 0xF0, 0xEC, 0x24, 0x18, 0x90, 0x82, 0x45, +0xF0, 0xFD, 0x90, 0x82, 0x41, 0xE0, 0xFE, 0xA3, +0xE0, 0xFF, 0x12, 0x59, 0xD3, 0xEF, 0x54, 0xFC, +0x90, 0x82, 0x47, 0xF0, 0x90, 0x82, 0x46, 0xE0, +0x24, 0x18, 0xFF, 0xE4, 0x33, 0x90, 0x82, 0x43, +0x8F, 0xF0, 0x12, 0x46, 0x9F, 0x90, 0x82, 0x43, +0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x12, 0x75, 0xB4, +0x90, 0x82, 0x3F, 0xEE, 0x8F, 0xF0, 0x12, 0x46, +0x9F, 0x90, 0x80, 0xFA, 0xE0, 0xFE, 0xA3, 0xE0, +0xFF, 0x90, 0x82, 0x3F, 0xE0, 0xFC, 0xA3, 0xE0, +0xFD, 0xD3, 0x9F, 0xEC, 0x9E, 0x40, 0x11, 0x90, +0x80, 0xFB, 0xB1, 0xC8, 0xED, 0x9F, 0xFF, 0xEC, +0x9E, 0x90, 0x82, 0x3F, 0xF0, 0xA3, 0xEF, 0xF0, +0x12, 0x5F, 0x19, 0x20, 0xE0, 0x02, 0x41, 0x76, +0xE4, 0x90, 0x82, 0x4B, 0xF0, 0x90, 0x82, 0x4A, +0xF0, 0xB1, 0x00, 0x50, 0x36, 0x12, 0x75, 0x7E, +0xE4, 0x90, 0x82, 0x49, 0xF0, 0xB1, 0x26, 0x94, +0x06, 0x50, 0x15, 0x91, 0xE5, 0x24, 0x04, 0xFC, +0xED, 0x2C, 0x12, 0x5B, 0x00, 0x12, 0x76, 0x23, +0xB5, 0x07, 0x05, 0x12, 0x5A, 0xA7, 0x80, 0xE5, +0x90, 0x82, 0x49, 0xE0, 0xB4, 0x06, 0x08, 0x90, +0x82, 0x4B, 0x74, 0x01, 0xF0, 0x80, 0x04, 0xB1, +0x1A, 0x80, 0xC6, 0x90, 0x82, 0x47, 0xE0, 0x24, +0x60, 0x70, 0x02, 0x41, 0x21, 0x24, 0xFC, 0x70, +0x02, 0x41, 0x21, 0x24, 0xF4, 0x70, 0x02, 0x41, +0x16, 0x24, 0xF0, 0x70, 0x02, 0x41, 0x21, 0x24, +0x80, 0x60, 0x02, 0x41, 0x35, 0x91, 0xE5, 0x24, +0x18, 0xFD, 0x12, 0x59, 0xD3, 0xEF, 0x60, 0x02, +0x61, 0xCE, 0x91, 0xE5, 0x24, 0x19, 0xFD, 0x12, +0x59, 0xD3, 0x90, 0x82, 0x60, 0xB1, 0x5E, 0xB1, +0x21, 0x9F, 0x50, 0x0A, 0x91, 0xE5, 0x12, 0x5B, +0x08, 0x12, 0x5A, 0xA3, 0x80, 0xF1, 0x90, 0x82, +0x60, 0xE0, 0x70, 0x02, 0x21, 0x6E, 0xE4, 0x90, +0x82, 0x4A, 0xF0, 0xB1, 0x00, 0x50, 0x5F, 0x12, +0x75, 0x7E, 0xB1, 0xA0, 0x70, 0x1D, 0xB1, 0x6E, +0x12, 0x46, 0xEB, 0xC0, 0x03, 0xC0, 0x02, 0xC0, +0x01, 0xB1, 0x2D, 0xED, 0xF0, 0xD0, 0x01, 0xD0, +0x02, 0xD0, 0x03, 0x12, 0x75, 0xF0, 0xEF, 0x60, +0x02, 0x80, 0x26, 0x90, 0x82, 0x60, 0xE0, 0x64, +0x03, 0x70, 0x29, 0xB1, 0x2D, 0x12, 0x76, 0x3F, +0x70, 0x07, 0xB1, 0x2D, 0x12, 0x76, 0x4A, 0x60, +0x17, 0xB1, 0x7D, 0x60, 0x02, 0x80, 0x05, 0xB1, +0x44, 0xE0, 0x60, 0x05, 0x74, 0xBB, 0x2F, 0x80, +0x0D, 0x91, 0xF2, 0x74, 0x01, 0xF0, 0x80, 0x0A, +0xB1, 0x3D, 0x80, 0x02, 0xB1, 0x3D, 0x91, 0xF8, +0xE4, 0xF0, 0xB1, 0x1A, 0x80, 0x9D, 0x90, 0x82, +0xBB, 0xE0, 0x70, 0x50, 0xA3, 0xE0, 0x70, 0x4C, +0xA3, 0xE0, 0x70, 0x48, 0xA3, 0xE0, 0x70, 0x44, +0xA3, 0xE0, 0x70, 0x40, 0x61, 0xCE, 0xE4, 0x90, +0x82, 0x4A, 0xF0, 0xB1, 0x00, 0x50, 0x1D, 0x74, +0xA7, 0x2E, 0xB1, 0x4B, 0xE0, 0x60, 0x09, 0x74, +0xBB, 0x2E, 0x91, 0xF8, 0xE4, 0xF0, 0x80, 0x08, +0x74, 0xBB, 0x2E, 0x91, 0xF8, 0x74, 0x01, 0xF0, +0xB1, 0x1A, 0x80, 0xDF, 0x90, 0x82, 0xBB, 0xE0, +0x70, 0x12, 0xA3, 0xE0, 0x70, 0x0E, 0xA3, 0xE0, +0x70, 0x0A, 0xA3, 0xE0, 0x70, 0x06, 0xA3, 0xE0, +0x70, 0x02, 0x61, 0xCE, 0xE4, 0x90, 0x82, 0x4A, +0xF0, 0xB1, 0x00, 0x40, 0x02, 0x61, 0xCE, 0x12, +0x75, 0x7E, 0x91, 0xF2, 0xE0, 0x60, 0x53, 0x90, +0x82, 0x09, 0xE0, 0x30, 0xE0, 0x06, 0xC4, 0x54, +0x0F, 0x30, 0xE0, 0x46, 0xB1, 0x66, 0x90, 0x04, +0x1D, 0xE0, 0x60, 0x1B, 0xD3, 0x90, 0x82, 0xC1, +0xE0, 0x94, 0x28, 0x90, 0x82, 0xC0, 0xE0, 0x94, +0x00, 0x50, 0x0C, 0x7F, 0xFA, 0x7E, 0x00, 0x12, +0x32, 0xAA, 0x12, 0x5C, 0x37, 0x80, 0xDF, 0x90, +0x04, 0x1D, 0xE0, 0x70, 0x1D, 0xB1, 0x8D, 0x74, +0x0A, 0xF0, 0xE4, 0xFB, 0xB1, 0x53, 0xB1, 0x26, +0x94, 0x06, 0x50, 0x07, 0x91, 0xE5, 0x12, 0x5A, +0x89, 0x80, 0xF3, 0x12, 0x62, 0x57, 0x90, 0x06, +0x35, 0xF0, 0xB1, 0x1A, 0x80, 0x9B, 0x90, 0x82, +0x4B, 0xE0, 0xB4, 0x01, 0x02, 0x80, 0x4F, 0x81, +0xDE, 0x90, 0x82, 0x4B, 0xE0, 0xB4, 0x01, 0x0B, +0x90, 0x80, 0xFC, 0x12, 0x55, 0x3A, 0x30, 0xE0, +0x02, 0x80, 0x3B, 0x81, 0xDE, 0x90, 0x82, 0x48, +0xE0, 0x70, 0x12, 0x90, 0x82, 0x4B, 0xE0, 0xB4, +0x01, 0x0B, 0x90, 0x80, 0xFC, 0xE0, 0x13, 0x13, +0x54, 0x3F, 0x20, 0xE0, 0x02, 0x81, 0xDE, 0x91, +0xE5, 0xFD, 0x12, 0x5A, 0xB7, 0xEF, 0x60, 0x02, +0x80, 0x14, 0x91, 0xE5, 0xFD, 0x12, 0x5A, 0x5F, +0xEF, 0x60, 0x02, 0x80, 0x09, 0x91, 0xE5, 0xFD, +0x12, 0x5A, 0x03, 0xEF, 0x60, 0x06, 0x12, 0x6F, +0x12, 0x02, 0x77, 0x5D, 0x81, 0xDE, 0x90, 0x82, +0x47, 0xE0, 0x24, 0xC0, 0x60, 0x02, 0x61, 0xDA, +0x91, 0xE5, 0x24, 0x18, 0xFD, 0x12, 0x59, 0xD3, +0xEF, 0x60, 0x02, 0x61, 0xCE, 0x91, 0xE5, 0x24, +0x19, 0xFD, 0x12, 0x59, 0xD3, 0x90, 0x82, 0x60, +0xB1, 0x5E, 0xB1, 0x21, 0x9F, 0x50, 0x0A, 0x91, +0xE5, 0x12, 0x5B, 0x08, 0x12, 0x5A, 0xA3, 0x80, +0xF1, 0x90, 0x82, 0x60, 0xE0, 0x70, 0x02, 0x61, +0x31, 0xE4, 0x90, 0x82, 0x4A, 0xF0, 0xB1, 0x00, +0x50, 0x5F, 0x12, 0x75, 0x7E, 0xB1, 0xA0, 0x70, +0x1D, 0xB1, 0x6E, 0x12, 0x46, 0xEB, 0xC0, 0x03, +0xC0, 0x02, 0xC0, 0x01, 0xB1, 0x2D, 0xED, 0xF0, +0xD0, 0x01, 0xD0, 0x02, 0xD0, 0x03, 0x12, 0x75, +0xF0, 0xEF, 0x60, 0x02, 0x80, 0x26, 0x90, 0x82, +0x60, 0xE0, 0x64, 0x03, 0x70, 0x29, 0xB1, 0x2D, +0x12, 0x76, 0x3F, 0x70, 0x07, 0xB1, 0x2D, 0x12, +0x76, 0x4A, 0x60, 0x17, 0xB1, 0x7D, 0x60, 0x02, +0x80, 0x05, 0xB1, 0x44, 0xE0, 0x60, 0x05, 0x74, +0xBB, 0x2F, 0x80, 0x0D, 0x91, 0xF2, 0x74, 0x01, +0xF0, 0x80, 0x0A, 0xB1, 0x3D, 0x80, 0x02, 0xB1, +0x3D, 0x91, 0xF8, 0xE4, 0xF0, 0xB1, 0x1A, 0x80, +0x9D, 0x90, 0x82, 0xBB, 0xE0, 0x70, 0x4E, 0xA3, +0xE0, 0x70, 0x4A, 0xA3, 0xE0, 0x70, 0x46, 0xA3, +0xE0, 0x70, 0x42, 0xA3, 0xE0, 0x70, 0x3E, 0x61, +0xCE, 0xE4, 0x90, 0x82, 0x4A, 0xF0, 0xB1, 0x00, +0x50, 0x1D, 0x74, 0xA7, 0x2E, 0xB1, 0x4B, 0xE0, +0x60, 0x09, 0x74, 0xBB, 0x2E, 0x91, 0xF8, 0xE4, +0xF0, 0x80, 0x08, 0x74, 0xBB, 0x2E, 0x91, 0xF8, +0x74, 0x01, 0xF0, 0xB1, 0x1A, 0x80, 0xDF, 0x90, +0x82, 0xBB, 0xE0, 0x70, 0x10, 0xA3, 0xE0, 0x70, +0x0C, 0xA3, 0xE0, 0x70, 0x08, 0xA3, 0xE0, 0x70, +0x04, 0xA3, 0xE0, 0x60, 0x61, 0xE4, 0x90, 0x82, +0x4A, 0xF0, 0xB1, 0x00, 0x50, 0x58, 0x12, 0x75, +0x7E, 0x91, 0xF2, 0xE0, 0x60, 0x4C, 0x90, 0x82, +0x09, 0xE0, 0x30, 0xE0, 0x06, 0xC4, 0x54, 0x0F, +0x30, 0xE0, 0x3F, 0xB1, 0x66, 0x90, 0x04, 0x1D, +0xE0, 0x60, 0x14, 0xD3, 0x90, 0x82, 0xC1, 0xE0, +0x94, 0xE8, 0x90, 0x82, 0xC0, 0xE0, 0x94, 0x03, +0x50, 0x05, 0x12, 0x5C, 0x37, 0x80, 0xE6, 0x90, +0x04, 0x1D, 0xE0, 0x70, 0x1D, 0xB1, 0x8D, 0x74, +0x06, 0xF0, 0x7B, 0x08, 0xB1, 0x53, 0xB1, 0x26, +0x94, 0x06, 0x50, 0x07, 0x91, 0xE5, 0x12, 0x5A, +0x89, 0x80, 0xF3, 0x12, 0x62, 0x57, 0x90, 0x06, +0x35, 0xF0, 0xB1, 0x1A, 0x80, 0xA4, 0x12, 0x75, +0x9E, 0x90, 0x06, 0x36, 0x74, 0xDD, 0xF0, 0x02, +0x77, 0x5D, 0x90, 0x82, 0x48, 0xE0, 0x60, 0x02, +0x81, 0xDE, 0x91, 0xE5, 0x24, 0x16, 0xFD, 0x12, +0x59, 0xD3, 0x90, 0x06, 0x34, 0xEF, 0xF0, 0x91, +0xE5, 0x24, 0x17, 0xFD, 0x12, 0x59, 0xD3, 0x90, +0x06, 0x37, 0xB1, 0xC0, 0xB1, 0x00, 0x50, 0x34, +0x12, 0x75, 0x7E, 0xE4, 0x90, 0x82, 0x49, 0xF0, +0xB1, 0x26, 0x94, 0x06, 0x50, 0x22, 0x91, 0xE5, +0x24, 0x04, 0x2D, 0x12, 0x5B, 0x00, 0xFE, 0x12, +0x76, 0x23, 0x6F, 0x60, 0x0E, 0x74, 0xB6, 0x2E, +0xF5, 0x82, 0xE4, 0x34, 0x82, 0xF5, 0x83, 0xE4, +0xF0, 0x80, 0x05, 0x12, 0x5A, 0xA7, 0x80, 0xD8, +0xB1, 0x1A, 0x80, 0xC8, 0x90, 0x82, 0xB6, 0xE0, +0x64, 0x01, 0x60, 0x17, 0xA3, 0xE0, 0x64, 0x01, +0x60, 0x11, 0xA3, 0xE0, 0x64, 0x01, 0x60, 0x0B, +0xA3, 0xE0, 0x64, 0x01, 0x60, 0x05, 0xA3, 0xE0, +0xB4, 0x01, 0x06, 0x90, 0x82, 0x4B, 0x74, 0x01, +0xF0, 0x90, 0x82, 0x4B, 0xE0, 0x64, 0x01, 0x70, +0x6E, 0x12, 0x6E, 0xD6, 0x12, 0x4F, 0xD1, 0x30, +0xE0, 0x0D, 0xE0, 0xC3, 0x13, 0x30, 0xE0, 0x3F, +0x90, 0x81, 0x2B, 0xE0, 0x30, 0xE0, 0x38, 0x12, +0x6E, 0x74, 0x90, 0x81, 0x1E, 0xE0, 0x70, 0x03, +0x02, 0x77, 0x5D, 0x90, 0x01, 0x3C, 0xE0, 0x30, +0xE4, 0x03, 0x74, 0x10, 0xF0, 0x12, 0x73, 0xA1, +0x90, 0x81, 0x1F, 0xE0, 0x60, 0x07, 0xF5, 0x2D, +0xE4, 0xF5, 0x2E, 0x80, 0x25, 0x90, 0x81, 0x20, +0xE0, 0x60, 0x08, 0xFB, 0xE4, 0xF5, 0x2D, 0xF5, +0x2E, 0x80, 0x18, 0xB1, 0xB8, 0x80, 0x14, 0x90, +0x01, 0x3C, 0xE0, 0x30, 0xE4, 0x03, 0x74, 0x10, +0xF0, 0x12, 0x73, 0xA1, 0xE4, 0xF5, 0x2D, 0x75, +0x2E, 0x9C, 0xFB, 0x7D, 0x01, 0x7F, 0x60, 0x7E, +0x01, 0x12, 0x31, 0x21, 0x02, 0x77, 0x5D, 0x12, +0x58, 0xC4, 0x90, 0x82, 0x4A, 0xF0, 0xB1, 0x00, +0x50, 0x04, 0xB1, 0x0D, 0x80, 0xF8, 0x12, 0x75, +0x9E, 0x02, 0x77, 0x5D, 0x22, 0x90, 0x82, 0x41, +0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x82, 0x45, +0xE0, 0x22, 0x90, 0x82, 0x4A, 0xE0, 0x24, 0xBB, +0xF5, 0x82, 0xE4, 0x34, 0x82, 0xF5, 0x83, 0x22, +0x90, 0x81, 0x07, 0xE0, 0xFF, 0x90, 0x82, 0x4A, +0xE0, 0xFE, 0xC3, 0x9F, 0x22, 0x74, 0xB6, 0x2E, +0xF5, 0x82, 0xE4, 0x34, 0x82, 0xF5, 0x83, 0x74, +0x01, 0xF0, 0x90, 0x82, 0x4A, 0xE0, 0x04, 0xF0, +0x22, 0x90, 0x82, 0x60, 0xE0, 0xFF, 0x90, 0x82, +0x49, 0xE0, 0xFD, 0xC3, 0x22, 0x7B, 0x01, 0x7A, +0x82, 0x79, 0x61, 0x90, 0x82, 0xC5, 0x12, 0x46, +0xF4, 0x90, 0x82, 0xC8, 0x22, 0x90, 0x82, 0x4A, +0xE0, 0x24, 0xBB, 0x22, 0x90, 0x82, 0x4A, 0xE0, +0xFF, 0x24, 0xA7, 0xF5, 0x82, 0xE4, 0x34, 0x82, +0xF5, 0x83, 0x22, 0x7D, 0x01, 0x12, 0x57, 0x19, +0x90, 0x82, 0x43, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, +0xE4, 0x90, 0x82, 0x49, 0xF0, 0x22, 0xE4, 0x90, +0x82, 0xC0, 0xF0, 0xA3, 0xF0, 0x22, 0xEF, 0x75, +0xF0, 0x03, 0xA4, 0x24, 0x51, 0xF5, 0x82, 0xE4, +0x34, 0x82, 0xF5, 0x83, 0x22, 0x90, 0x82, 0x4A, +0xE0, 0xFF, 0x24, 0xAC, 0xF5, 0x82, 0xE4, 0x34, +0x82, 0xF5, 0x83, 0xE0, 0x22, 0x90, 0x82, 0x4A, +0xE0, 0x24, 0xA2, 0xF5, 0x82, 0xE4, 0x34, 0x82, +0xF5, 0x83, 0xE0, 0xFF, 0x90, 0x83, 0x1B, 0x22, +0x90, 0x82, 0x4A, 0xE0, 0xFF, 0x24, 0x4C, 0xF5, +0x82, 0xE4, 0x34, 0x82, 0xF5, 0x83, 0xE0, 0xFE, +0x90, 0x82, 0x60, 0xE0, 0xFD, 0xEE, 0x6D, 0x22, +0x75, 0x2D, 0x20, 0xE4, 0xF5, 0x2E, 0xFB, 0x22, +0xEF, 0xF0, 0xE4, 0x90, 0x82, 0x4A, 0xF0, 0x22, +0xE0, 0x24, 0x01, 0xFF, 0x90, 0x80, 0xFA, 0xE0, +0x34, 0x00, 0xFE, 0xC3, 0x22, 0xEF, 0x30, 0xE7, +0x04, 0x7E, 0x02, 0x80, 0x02, 0xE4, 0xFE, 0xED, +0x30, 0xE6, 0x12, 0xEB, 0x20, 0xE0, 0x07, 0x90, +0x81, 0x01, 0xE0, 0xFC, 0x80, 0x09, 0x90, 0x81, +0x02, 0xE0, 0xFC, 0x80, 0x02, 0xE4, 0xFC, 0xEE, +0x24, 0x18, 0x2C, 0xFF, 0x22, 0x90, 0x01, 0x57, +0xE4, 0xF0, 0x90, 0x01, 0x3C, 0x74, 0x02, 0x22, +0xF5, 0x83, 0xEF, 0xF0, 0x74, 0xB1, 0x2E, 0xF5, +0x82, 0xE4, 0x34, 0x82, 0xF5, 0x83, 0xE0, 0x22, +0x90, 0x81, 0xEF, 0xE0, 0x24, 0x01, 0xFF, 0x90, +0x81, 0xEE, 0xE0, 0x34, 0x00, 0xFE, 0x12, 0x32, +0xAA, 0x90, 0x81, 0x33, 0xE0, 0x22, 0xF0, 0x90, +0x81, 0x3C, 0xA3, 0xE0, 0x90, 0x05, 0x58, 0xF0, +0x22, 0x7D, 0x08, 0x7F, 0x02, 0x12, 0x56, 0x0B, +0x90, 0x82, 0x1B, 0xE0, 0x04, 0xF0, 0x22, 0x54, +0xFB, 0xF0, 0x90, 0x81, 0x34, 0xE0, 0x54, 0xFD, +0xF0, 0x54, 0x07, 0x22, 0xE0, 0x90, 0x01, 0xBA, +0xF0, 0x90, 0x81, 0x32, 0xE0, 0x90, 0x01, 0xBB, +0x22, 0x12, 0x1F, 0xA4, 0xFE, 0x54, 0x04, 0xFD, +0xEF, 0x54, 0xFB, 0x4D, 0xFF, 0x22, 0x74, 0x11, +0x2C, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, +0xE0, 0x22, 0xF5, 0x82, 0xE4, 0x34, 0xFB, 0xF5, +0x83, 0xE0, 0x22, 0xE0, 0x7C, 0x00, 0x24, 0x00, +0xFF, 0xEC, 0x3E, 0x22, 0x90, 0x06, 0x0A, 0xE0, +0x54, 0xF8, 0xF0, 0x22, 0x81, 0xA3 +}; + +u32 array_length_mp_8188e_s_fw_ap = 16054; + +#endif /*defined(CONFIG_AP_WOWLAN) */ + +u8 array_mp_8188e_s_fw_nic[] = { +0xE3, 0x88, 0x10, 0x00, 0x1C, 0x00, 0x00, 0x00, +0x05, 0x04, 0x22, 0x24, 0xE6, 0x4A, 0x02, 0x00, +0xA5, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x02, 0x48, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x02, 0x49, 0x78, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x02, 0x57, 0xFB, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x02, 0x48, 0xEF, 0x00, 0x00, +0x00, 0x00, 0x00, 0x02, 0x4F, 0xFD, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x05, 0x04, 0x03, 0x02, 0x00, 0x03, 0x06, 0x05, +0x04, 0x03, 0x00, 0x04, 0x06, 0x05, 0x04, 0x02, +0x00, 0x04, 0x08, 0x07, 0x06, 0x04, 0x00, 0x06, +0x0A, 0x09, 0x08, 0x06, 0x00, 0x08, 0x0A, 0x09, +0x08, 0x04, 0x00, 0x08, 0x0A, 0x09, 0x08, 0x02, +0x00, 0x08, 0x0A, 0x09, 0x08, 0x00, 0x00, 0x08, +0x12, 0x11, 0x10, 0x08, 0x00, 0x10, 0x1A, 0x19, +0x18, 0x10, 0x00, 0x18, 0x22, 0x21, 0x20, 0x18, +0x00, 0x20, 0x22, 0x21, 0x20, 0x10, 0x00, 0x20, +0x22, 0x21, 0x20, 0x08, 0x00, 0x20, 0x22, 0x21, +0x1C, 0x08, 0x00, 0x20, 0x22, 0x21, 0x14, 0x08, +0x00, 0x20, 0x22, 0x20, 0x18, 0x08, 0x00, 0x20, +0x31, 0x30, 0x20, 0x10, 0x00, 0x30, 0x31, 0x30, +0x18, 0x00, 0x00, 0x30, 0x31, 0x2F, 0x10, 0x10, +0x00, 0x30, 0x31, 0x2C, 0x10, 0x10, 0x00, 0x30, +0x31, 0x28, 0x10, 0x00, 0x00, 0x30, 0x31, 0x20, +0x10, 0x00, 0x00, 0x30, 0x31, 0x10, 0x10, 0x00, +0x00, 0x30, 0x04, 0x04, 0x04, 0x05, 0x04, 0x04, +0x05, 0x07, 0x07, 0x07, 0x08, 0x0A, 0x04, 0x04, +0x04, 0x04, 0x06, 0x0A, 0x0B, 0x0D, 0x05, 0x05, +0x07, 0x07, 0x08, 0x0B, 0x0D, 0x0F, 0x04, 0x04, +0x04, 0x05, 0x07, 0x07, 0x09, 0x09, 0x0C, 0x0E, +0x10, 0x12, 0x07, 0x07, 0x08, 0x08, 0x0B, 0x0F, +0x10, 0x12, 0x09, 0x09, 0x09, 0x09, 0x0C, 0x0E, +0x11, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x24, 0x26, 0x2A, 0x18, 0x1A, +0x1D, 0x1F, 0x21, 0x27, 0x29, 0x2A, 0x00, 0x00, +0x00, 0x1F, 0x23, 0x28, 0x2A, 0x2C, 0x00, 0x04, +0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x18, +0x00, 0x24, 0x00, 0x30, 0x00, 0x48, 0x00, 0x60, +0x00, 0x90, 0x00, 0xC0, 0x00, 0xD8, 0x00, 0x50, +0x00, 0x64, 0x00, 0xA0, 0x00, 0xDC, 0x01, 0x18, +0x01, 0x90, 0x01, 0xE0, 0x02, 0x30, 0x01, 0x2C, +0x01, 0x40, 0x01, 0xE0, 0x02, 0xD0, 0x03, 0xE8, +0x04, 0xB0, 0x06, 0x40, 0x07, 0xD0, 0x00, 0x02, +0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, +0x00, 0x12, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, +0x00, 0x48, 0x00, 0x60, 0x00, 0x6C, 0x00, 0x28, +0x00, 0x32, 0x00, 0x50, 0x00, 0x6E, 0x00, 0x8C, +0x00, 0xC8, 0x00, 0xF0, 0x01, 0x18, 0x00, 0x64, +0x00, 0xA0, 0x00, 0xF0, 0x01, 0x68, 0x01, 0xF4, +0x02, 0x58, 0x03, 0x20, 0x03, 0xE8, 0x02, 0x02, +0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, +0x05, 0x07, 0x04, 0x05, 0x08, 0x08, 0x0C, 0x0E, +0x10, 0x12, 0x05, 0x07, 0x07, 0x08, 0x0B, 0x12, +0x24, 0x3C, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, +0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, +0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x05, 0x06, +0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x20, 0x1E, +0x1C, 0x18, 0x10, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xC2, 0xAF, 0x80, 0xFE, 0x32, 0x12, 0x43, 0x04, +0x85, 0xD0, 0x0B, 0x75, 0xD0, 0x08, 0xAA, 0xE0, +0xC2, 0x8C, 0xE5, 0x8A, 0x24, 0x67, 0xF5, 0x8A, +0xE5, 0x8C, 0x34, 0x79, 0xF5, 0x8C, 0xD2, 0x8C, +0xEC, 0x24, 0x87, 0xF8, 0xE6, 0xBC, 0x02, 0x02, +0x74, 0xFF, 0xC3, 0x95, 0x81, 0xB4, 0x40, 0x00, +0x40, 0xCE, 0x79, 0x03, 0x78, 0x80, 0x16, 0xE6, +0x08, 0x70, 0x0B, 0xC2, 0xAF, 0xE6, 0x30, 0xE1, +0x03, 0x44, 0x18, 0xF6, 0xD2, 0xAF, 0x08, 0xD9, +0xED, 0xEA, 0x8B, 0xD0, 0x22, 0xE5, 0x0C, 0xFF, +0x23, 0x24, 0x81, 0xF8, 0x0F, 0x08, 0x08, 0xBF, +0x03, 0x04, 0x7F, 0x00, 0x78, 0x81, 0xE6, 0x30, +0xE4, 0xF2, 0x00, 0xE5, 0x0C, 0xC3, 0x9F, 0x50, +0x20, 0x05, 0x0C, 0x74, 0x86, 0x25, 0x0C, 0xF8, +0xE6, 0xFD, 0xA6, 0x81, 0x08, 0xE6, 0xAE, 0x0C, +0xBE, 0x02, 0x02, 0x74, 0xFF, 0xCD, 0xF8, 0xE8, +0x6D, 0x60, 0xE0, 0x08, 0xE6, 0xC0, 0xE0, 0x80, +0xF6, 0xE5, 0x0C, 0xD3, 0x9F, 0x40, 0x27, 0xE5, +0x0C, 0x24, 0x87, 0xF8, 0xE6, 0xAE, 0x0C, 0xBE, +0x02, 0x02, 0x74, 0xFF, 0xFD, 0x18, 0xE6, 0xCD, +0xF8, 0xE5, 0x81, 0x6D, 0x60, 0x06, 0xD0, 0xE0, +0xF6, 0x18, 0x80, 0xF5, 0xE5, 0x0C, 0x24, 0x86, +0xC8, 0xF6, 0x15, 0x0C, 0x80, 0xD3, 0xE5, 0x0C, +0x23, 0x24, 0x81, 0xF8, 0x7F, 0x04, 0xC2, 0xAF, +0xE6, 0x30, 0xE0, 0x03, 0x10, 0xE2, 0x0C, 0x7F, +0x00, 0x30, 0xE1, 0x07, 0x30, 0xE3, 0x04, 0x7F, +0x08, 0x54, 0xF4, 0x54, 0x7C, 0xC6, 0xD2, 0xAF, +0x54, 0x80, 0x42, 0x07, 0x22, 0x78, 0x86, 0xA6, +0x81, 0x74, 0x02, 0x60, 0x06, 0xFF, 0x08, 0x76, +0xFF, 0xDF, 0xFB, 0x7F, 0x03, 0xE4, 0x78, 0x80, +0xF6, 0x08, 0xF6, 0x08, 0xDF, 0xFA, 0x78, 0x81, +0x76, 0x30, 0x90, 0x48, 0xE9, 0x74, 0x01, 0x93, +0xC0, 0xE0, 0xE4, 0x93, 0xC0, 0xE0, 0x43, 0x89, +0x01, 0x75, 0x8A, 0x60, 0x75, 0x8C, 0x79, 0xD2, +0x8C, 0xD2, 0xAF, 0x22, 0x02, 0xEF, 0xD3, 0x94, +0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, 0x74, 0x81, +0x2F, 0x2F, 0xF8, 0xE6, 0x20, 0xE5, 0xF4, 0xC2, +0xAF, 0xE6, 0x44, 0x30, 0xF6, 0xD2, 0xAF, 0xAE, +0x0C, 0xEE, 0xC3, 0x9F, 0x50, 0x21, 0x0E, 0x74, +0x86, 0x2E, 0xF8, 0xE6, 0xF9, 0x08, 0xE6, 0x18, +0xBE, 0x02, 0x02, 0x74, 0xFF, 0xFD, 0xED, 0x69, +0x60, 0x09, 0x09, 0xE7, 0x19, 0x19, 0xF7, 0x09, +0x09, 0x80, 0xF3, 0x16, 0x16, 0x80, 0xDA, 0xEE, +0xD3, 0x9F, 0x40, 0x04, 0x05, 0x81, 0x05, 0x81, +0xEE, 0xD3, 0x9F, 0x40, 0x22, 0x74, 0x86, 0x2E, +0xF8, 0x08, 0xE6, 0xF9, 0xEE, 0xB5, 0x0C, 0x02, +0xA9, 0x81, 0x18, 0x06, 0x06, 0xE6, 0xFD, 0xED, +0x69, 0x60, 0x09, 0x19, 0x19, 0xE7, 0x09, 0x09, +0xF7, 0x19, 0x80, 0xF3, 0x1E, 0x80, 0xD9, 0xEF, +0x24, 0x86, 0xF8, 0xE6, 0x04, 0xF8, 0xEF, 0x2F, +0x04, 0x90, 0x48, 0xE9, 0x93, 0xF6, 0x08, 0xEF, +0x2F, 0x93, 0xF6, 0x7F, 0x00, 0x22, 0xEF, 0xD3, +0x94, 0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, 0xEF, +0x23, 0x24, 0x81, 0xF8, 0xE6, 0x30, 0xE5, 0xF4, +0xC2, 0xAF, 0xE6, 0x54, 0x8C, 0xF6, 0xD2, 0xAF, +0xE5, 0x0C, 0xB5, 0x07, 0x0A, 0x74, 0x86, 0x2F, +0xF8, 0xE6, 0xF5, 0x81, 0x02, 0x43, 0x4D, 0x50, +0x2E, 0x74, 0x87, 0x2F, 0xF8, 0xE6, 0xBF, 0x02, +0x02, 0x74, 0xFF, 0xFD, 0x18, 0xE6, 0xF9, 0x74, +0x86, 0x2F, 0xF8, 0xFB, 0xE6, 0xFC, 0xE9, 0x6C, +0x60, 0x08, 0xA8, 0x05, 0xE7, 0xF6, 0x1D, 0x19, +0x80, 0xF4, 0xA8, 0x03, 0xA6, 0x05, 0x1F, 0xE5, +0x0C, 0xB5, 0x07, 0xE3, 0x7F, 0x00, 0x22, 0x74, +0x87, 0x2F, 0xF8, 0xE6, 0xFD, 0x18, 0x86, 0x01, +0x0F, 0x74, 0x86, 0x2F, 0xF8, 0xA6, 0x01, 0x08, +0x86, 0x04, 0xE5, 0x0C, 0xB5, 0x07, 0x02, 0xAC, +0x81, 0xED, 0x6C, 0x60, 0x08, 0x0D, 0x09, 0xA8, +0x05, 0xE6, 0xF7, 0x80, 0xF4, 0xE5, 0x0C, 0xB5, +0x07, 0xDE, 0x89, 0x81, 0x7F, 0x00, 0x22, 0xEF, +0xD3, 0x94, 0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, +0xEF, 0x23, 0x24, 0x81, 0xF8, 0xC2, 0xAF, 0xE6, +0x30, 0xE5, 0x05, 0x30, 0xE0, 0x02, 0xD2, 0xE4, +0xD2, 0xE2, 0xC6, 0xD2, 0xAF, 0x7F, 0x00, 0x30, +0xE2, 0x01, 0x0F, 0x02, 0x43, 0x4C, 0x8F, 0xF0, +0xE4, 0xFF, 0xFE, 0xE5, 0x0C, 0x23, 0x24, 0x80, +0xF8, 0xC2, 0xA9, 0x30, 0xF7, 0x0D, 0x7F, 0x08, +0xE6, 0x60, 0x0B, 0x2D, 0xF6, 0x60, 0x30, 0x50, +0x2E, 0x80, 0x07, 0x30, 0xF1, 0x06, 0xED, 0xF6, +0x60, 0x25, 0x7E, 0x02, 0x08, 0x30, 0xF0, 0x10, +0xC2, 0xAF, 0xE6, 0x10, 0xE7, 0x23, 0x0E, 0x30, +0xE2, 0x0C, 0xD2, 0xAF, 0x7F, 0x04, 0x80, 0x12, +0xC2, 0xAF, 0xE6, 0x10, 0xE7, 0x13, 0x54, 0xEC, +0x4E, 0xF6, 0xD2, 0xAF, 0x02, 0x43, 0x4D, 0x7F, +0x08, 0x08, 0xEF, 0x44, 0x83, 0xF4, 0xC2, 0xAF, +0x56, 0xC6, 0xD2, 0xAF, 0x54, 0x80, 0x4F, 0xFF, +0x22, 0xE7, 0x09, 0xF6, 0x08, 0xDF, 0xFA, 0x80, +0x46, 0xE7, 0x09, 0xF2, 0x08, 0xDF, 0xFA, 0x80, +0x3E, 0x88, 0x82, 0x8C, 0x83, 0xE7, 0x09, 0xF0, +0xA3, 0xDF, 0xFA, 0x80, 0x32, 0xE3, 0x09, 0xF6, +0x08, 0xDF, 0xFA, 0x80, 0x78, 0xE3, 0x09, 0xF2, +0x08, 0xDF, 0xFA, 0x80, 0x70, 0x88, 0x82, 0x8C, +0x83, 0xE3, 0x09, 0xF0, 0xA3, 0xDF, 0xFA, 0x80, +0x64, 0x89, 0x82, 0x8A, 0x83, 0xE0, 0xA3, 0xF6, +0x08, 0xDF, 0xFA, 0x80, 0x58, 0x89, 0x82, 0x8A, +0x83, 0xE0, 0xA3, 0xF2, 0x08, 0xDF, 0xFA, 0x80, +0x4C, 0x80, 0xD2, 0x80, 0xFA, 0x80, 0xC6, 0x80, +0xD4, 0x80, 0x69, 0x80, 0xF2, 0x80, 0x33, 0x80, +0x10, 0x80, 0xA6, 0x80, 0xEA, 0x80, 0x9A, 0x80, +0xA8, 0x80, 0xDA, 0x80, 0xE2, 0x80, 0xCA, 0x80, +0x33, 0x89, 0x82, 0x8A, 0x83, 0xEC, 0xFA, 0xE4, +0x93, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, 0xC5, +0x83, 0xCC, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, +0xCC, 0xC5, 0x83, 0xCC, 0xDF, 0xE9, 0xDE, 0xE7, +0x80, 0x0D, 0x89, 0x82, 0x8A, 0x83, 0xE4, 0x93, +0xA3, 0xF6, 0x08, 0xDF, 0xF9, 0xEC, 0xFA, 0xA9, +0xF0, 0xED, 0xFB, 0x22, 0x89, 0x82, 0x8A, 0x83, +0xEC, 0xFA, 0xE0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, +0xCC, 0xC5, 0x83, 0xCC, 0xF0, 0xA3, 0xC8, 0xC5, +0x82, 0xC8, 0xCC, 0xC5, 0x83, 0xCC, 0xDF, 0xEA, +0xDE, 0xE8, 0x80, 0xDB, 0x89, 0x82, 0x8A, 0x83, +0xE4, 0x93, 0xA3, 0xF2, 0x08, 0xDF, 0xF9, 0x80, +0xCC, 0x88, 0xF0, 0xEF, 0x60, 0x01, 0x0E, 0x4E, +0x60, 0xC3, 0x88, 0xF0, 0xED, 0x24, 0x02, 0xB4, +0x04, 0x00, 0x50, 0xB9, 0xF5, 0x82, 0xEB, 0x24, +0x02, 0xB4, 0x04, 0x00, 0x50, 0xAF, 0x23, 0x23, +0x45, 0x82, 0x23, 0x90, 0x45, 0xF9, 0x73, 0xC5, +0xF0, 0xF8, 0xA3, 0xE0, 0x28, 0xF0, 0xC5, 0xF0, +0xF8, 0xE5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, +0x83, 0xE0, 0x38, 0xF0, 0x22, 0xBB, 0x01, 0x0A, +0x89, 0x82, 0x8A, 0x83, 0xE0, 0xF5, 0xF0, 0xA3, +0xE0, 0x22, 0x50, 0x06, 0x87, 0xF0, 0x09, 0xE7, +0x19, 0x22, 0xBB, 0xFE, 0x07, 0xE3, 0xF5, 0xF0, +0x09, 0xE3, 0x19, 0x22, 0x89, 0x82, 0x8A, 0x83, +0xE4, 0x93, 0xF5, 0xF0, 0x74, 0x01, 0x93, 0x22, +0xBB, 0x01, 0x10, 0xE5, 0x82, 0x29, 0xF5, 0x82, +0xE5, 0x83, 0x3A, 0xF5, 0x83, 0xE0, 0xF5, 0xF0, +0xA3, 0xE0, 0x22, 0x50, 0x09, 0xE9, 0x25, 0x82, +0xF8, 0x86, 0xF0, 0x08, 0xE6, 0x22, 0xBB, 0xFE, +0x0A, 0xE9, 0x25, 0x82, 0xF8, 0xE2, 0xF5, 0xF0, +0x08, 0xE2, 0x22, 0xE5, 0x83, 0x2A, 0xF5, 0x83, +0xE9, 0x93, 0xF5, 0xF0, 0xA3, 0xE9, 0x93, 0x22, +0xBB, 0x01, 0x0A, 0x89, 0x82, 0x8A, 0x83, 0xF0, +0xE5, 0xF0, 0xA3, 0xF0, 0x22, 0x50, 0x06, 0xF7, +0x09, 0xA7, 0xF0, 0x19, 0x22, 0xBB, 0xFE, 0x06, +0xF3, 0xE5, 0xF0, 0x09, 0xF3, 0x19, 0x22, 0xF8, +0xBB, 0x01, 0x11, 0xE5, 0x82, 0x29, 0xF5, 0x82, +0xE5, 0x83, 0x3A, 0xF5, 0x83, 0xE8, 0xF0, 0xE5, +0xF0, 0xA3, 0xF0, 0x22, 0x50, 0x09, 0xE9, 0x25, +0x82, 0xC8, 0xF6, 0x08, 0xA6, 0xF0, 0x22, 0xBB, +0xFE, 0x09, 0xE9, 0x25, 0x82, 0xC8, 0xF2, 0xE5, +0xF0, 0x08, 0xF2, 0x22, 0xC3, 0xEF, 0x9B, 0xFF, +0xEE, 0x9A, 0xFE, 0xED, 0x99, 0xFD, 0xEC, 0x98, +0xFC, 0x22, 0xEF, 0x5B, 0xFF, 0xEE, 0x5A, 0xFE, +0xED, 0x59, 0xFD, 0xEC, 0x58, 0xFC, 0x22, 0xEF, +0x4B, 0xFF, 0xEE, 0x4A, 0xFE, 0xED, 0x49, 0xFD, +0xEC, 0x48, 0xFC, 0x22, 0xEB, 0x9F, 0xF5, 0xF0, +0xEA, 0x9E, 0x42, 0xF0, 0xE9, 0x9D, 0x42, 0xF0, +0xE8, 0x9C, 0x45, 0xF0, 0x22, 0xE0, 0xFC, 0xA3, +0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, +0x22, 0xE2, 0xFC, 0x08, 0xE2, 0xFD, 0x08, 0xE2, +0xFE, 0x08, 0xE2, 0xFF, 0x22, 0xE0, 0xF8, 0xA3, +0xE0, 0xF9, 0xA3, 0xE0, 0xFA, 0xA3, 0xE0, 0xFB, +0x22, 0xE2, 0xFB, 0x08, 0xE2, 0xF9, 0x08, 0xE2, +0xFA, 0x08, 0xE2, 0xCB, 0xF8, 0x22, 0xEC, 0xF2, +0x08, 0xED, 0xF2, 0x08, 0xEE, 0xF2, 0x08, 0xEF, +0xF2, 0x22, 0xA4, 0x25, 0x82, 0xF5, 0x82, 0xE5, +0xF0, 0x35, 0x83, 0xF5, 0x83, 0x22, 0xE0, 0xFB, +0xA3, 0xE0, 0xFA, 0xA3, 0xE0, 0xF9, 0x22, 0xEB, +0xF0, 0xA3, 0xEA, 0xF0, 0xA3, 0xE9, 0xF0, 0x22, +0xD0, 0x83, 0xD0, 0x82, 0xF8, 0xE4, 0x93, 0x70, +0x12, 0x74, 0x01, 0x93, 0x70, 0x0D, 0xA3, 0xA3, +0x93, 0xF8, 0x74, 0x01, 0x93, 0xF5, 0x82, 0x88, +0x83, 0xE4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, +0xEF, 0xA3, 0xA3, 0xA3, 0x80, 0xDF, 0xEF, 0x4E, +0x60, 0x12, 0xEF, 0x60, 0x01, 0x0E, 0xED, 0xBB, +0x01, 0x0B, 0x89, 0x82, 0x8A, 0x83, 0xF0, 0xA3, +0xDF, 0xFC, 0xDE, 0xFA, 0x22, 0x89, 0xF0, 0x50, +0x07, 0xF7, 0x09, 0xDF, 0xFC, 0xA9, 0xF0, 0x22, +0xBB, 0xFE, 0xFC, 0xF3, 0x09, 0xDF, 0xFC, 0xA9, +0xF0, 0x22, 0x02, 0x48, 0x88, 0x02, 0x43, 0xDD, +0xE4, 0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0x40, +0x03, 0xF6, 0x80, 0x01, 0xF2, 0x08, 0xDF, 0xF4, +0x80, 0x29, 0xE4, 0x93, 0xA3, 0xF8, 0x54, 0x07, +0x24, 0x0C, 0xC8, 0xC3, 0x33, 0xC4, 0x54, 0x0F, +0x44, 0x20, 0xC8, 0x83, 0x40, 0x04, 0xF4, 0x56, +0x80, 0x01, 0x46, 0xF6, 0xDF, 0xE4, 0x80, 0x0B, +0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, +0x90, 0x48, 0xCD, 0xE4, 0x7E, 0x01, 0x93, 0x60, +0xBC, 0xA3, 0xFF, 0x54, 0x3F, 0x30, 0xE5, 0x09, +0x54, 0x1F, 0xFE, 0xE4, 0x93, 0xA3, 0x60, 0x01, +0x0E, 0xCF, 0x54, 0xC0, 0x25, 0xE0, 0x60, 0xA8, +0x40, 0xB8, 0xE4, 0x93, 0xA3, 0xFA, 0xE4, 0x93, +0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0xC8, 0xC5, 0x82, +0xC8, 0xCA, 0xC5, 0x83, 0xCA, 0xF0, 0xA3, 0xC8, +0xC5, 0x82, 0xC8, 0xCA, 0xC5, 0x83, 0xCA, 0xDF, +0xE9, 0xDE, 0xE7, 0x80, 0xBE, 0x41, 0x83, 0x68, +0x00, 0x41, 0x83, 0x69, 0x00, 0x48, 0x95, 0x43, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x41, 0x83, 0x73, 0x00, 0x41, 0x83, 0x75, 0x00, +0x00, 0x68, 0xC7, 0x6F, 0xF0, 0x77, 0xDF, 0xC0, +0xE0, 0xC0, 0xF0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, +0xD0, 0x75, 0xD0, 0x00, 0xC0, 0x00, 0xC0, 0x01, +0xC0, 0x02, 0xC0, 0x03, 0xC0, 0x04, 0xC0, 0x05, +0xC0, 0x06, 0xC0, 0x07, 0x90, 0x01, 0xC4, 0x74, +0xEF, 0xF0, 0x74, 0x48, 0xA3, 0xF0, 0x31, 0x3E, +0x74, 0xEF, 0x04, 0x90, 0x01, 0xC4, 0xF0, 0x74, +0x48, 0xA3, 0xF0, 0xD0, 0x07, 0xD0, 0x06, 0xD0, +0x05, 0xD0, 0x04, 0xD0, 0x03, 0xD0, 0x02, 0xD0, +0x01, 0xD0, 0x00, 0xD0, 0xD0, 0xD0, 0x82, 0xD0, +0x83, 0xD0, 0xF0, 0xD0, 0xE0, 0x32, 0x90, 0x00, +0x54, 0xE0, 0x55, 0x35, 0xF5, 0x39, 0xA3, 0xE0, +0x55, 0x36, 0xF5, 0x3A, 0xA3, 0xE0, 0x55, 0x37, +0xF5, 0x3B, 0xA3, 0xE0, 0x55, 0x38, 0xF5, 0x3C, +0xAD, 0x39, 0x7F, 0x54, 0x12, 0x32, 0x1E, 0xAD, +0x3A, 0x7F, 0x55, 0x12, 0x32, 0x1E, 0xAD, 0x3B, +0x7F, 0x56, 0x12, 0x32, 0x1E, 0xAD, 0x3C, 0x7F, +0x57, 0x12, 0x32, 0x1E, 0x53, 0x91, 0xEF, 0x22, +0xC0, 0xE0, 0xC0, 0xF0, 0xC0, 0x83, 0xC0, 0x82, +0xC0, 0xD0, 0x75, 0xD0, 0x00, 0xC0, 0x00, 0xC0, +0x01, 0xC0, 0x02, 0xC0, 0x03, 0xC0, 0x04, 0xC0, +0x05, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x01, 0xC4, +0x74, 0x78, 0xF0, 0x74, 0x49, 0xA3, 0xF0, 0x12, +0x84, 0x73, 0xE5, 0x41, 0x30, 0xE4, 0x03, 0x12, +0x7A, 0x25, 0xE5, 0x41, 0x30, 0xE6, 0x03, 0x12, +0x85, 0x0C, 0xE5, 0x43, 0x30, 0xE0, 0x03, 0x12, +0x7D, 0x76, 0xE5, 0x43, 0x30, 0xE1, 0x02, 0x51, +0x1F, 0xE5, 0x43, 0x30, 0xE2, 0x03, 0x12, 0x82, +0x24, 0xE5, 0x43, 0x30, 0xE3, 0x03, 0x12, 0x6A, +0xA9, 0xE5, 0x43, 0x30, 0xE4, 0x03, 0x12, 0x6A, +0xC8, 0xE5, 0x43, 0x30, 0xE5, 0x03, 0x12, 0x6F, +0x9B, 0xE5, 0x43, 0x30, 0xE6, 0x03, 0x12, 0x6C, +0x10, 0xE5, 0x44, 0x30, 0xE1, 0x03, 0x12, 0x81, +0x21, 0xE5, 0x44, 0x30, 0xE5, 0x03, 0x12, 0x7C, +0x2D, 0x74, 0x78, 0x04, 0x90, 0x01, 0xC4, 0xF0, +0x74, 0x49, 0xA3, 0xF0, 0xD0, 0x07, 0xD0, 0x06, +0xD0, 0x05, 0xD0, 0x04, 0xD0, 0x03, 0xD0, 0x02, +0xD0, 0x01, 0xD0, 0x00, 0xD0, 0xD0, 0xD0, 0x82, +0xD0, 0x83, 0xD0, 0xF0, 0xD0, 0xE0, 0x32, 0x90, +0x81, 0x83, 0xE0, 0x30, 0xE0, 0x06, 0x90, 0x81, +0x85, 0x74, 0x01, 0xF0, 0x90, 0x81, 0x8D, 0xE0, +0x70, 0x02, 0x41, 0xCB, 0x90, 0x81, 0xA4, 0xE0, +0x04, 0xF0, 0x90, 0x05, 0x61, 0x71, 0x11, 0x78, +0x08, 0x12, 0x74, 0x5C, 0x90, 0x05, 0x60, 0x71, +0x11, 0x12, 0x47, 0x7F, 0xC0, 0x04, 0xC0, 0x05, +0xC0, 0x06, 0xC0, 0x07, 0x90, 0x05, 0x62, 0x71, +0x11, 0x78, 0x10, 0x12, 0x20, 0xBB, 0xD0, 0x03, +0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, 0x47, +0x7F, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, +0x07, 0xA3, 0x71, 0x11, 0x78, 0x18, 0x12, 0x20, +0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, +0x00, 0x12, 0x47, 0x7F, 0x90, 0x82, 0x4D, 0x12, +0x20, 0xCE, 0x90, 0x81, 0x89, 0xE0, 0x54, 0x7F, +0xF0, 0xA3, 0xE0, 0x30, 0xE0, 0x0C, 0x12, 0x85, +0x63, 0x74, 0x05, 0xF0, 0x12, 0x5B, 0x02, 0x12, +0x8A, 0x9E, 0x90, 0x81, 0x89, 0x12, 0x5A, 0xE1, +0x30, 0xE0, 0x09, 0x90, 0x01, 0x3B, 0xE0, 0x30, +0xE4, 0x02, 0xB1, 0xC8, 0x90, 0x83, 0x6E, 0xE0, +0x04, 0xF0, 0xE0, 0xC3, 0x94, 0x80, 0x40, 0x0B, +0x90, 0x01, 0x98, 0xE0, 0x54, 0xFE, 0xF0, 0xE0, +0x44, 0x01, 0xF0, 0x7F, 0x01, 0x12, 0x7A, 0x29, +0x12, 0x88, 0xBD, 0x90, 0x82, 0x6E, 0xE0, 0x30, +0xE0, 0x09, 0x90, 0x01, 0x3B, 0xE0, 0x30, 0xE4, +0x02, 0xB1, 0xC8, 0x22, 0x90, 0x82, 0xA3, 0xE0, +0x24, 0xB5, 0xF5, 0x82, 0xE4, 0x34, 0x82, 0xF5, +0x83, 0xE0, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x78, +0x08, 0x12, 0x20, 0xBB, 0xA8, 0x04, 0xA9, 0x05, +0xAA, 0x06, 0xAB, 0x07, 0x90, 0x82, 0xA3, 0xE0, +0x24, 0xB4, 0xF5, 0x82, 0xE4, 0x34, 0x82, 0xF5, +0x83, 0xE0, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x22, +0xE4, 0x90, 0x82, 0xA3, 0xF0, 0x90, 0x87, 0x5F, +0xE0, 0x90, 0x82, 0xA2, 0xF0, 0xE4, 0x90, 0x82, +0xAF, 0xF0, 0x90, 0x82, 0x9F, 0xF0, 0x90, 0x82, +0x9F, 0xE0, 0xFF, 0xC3, 0x94, 0x40, 0x50, 0x11, +0x74, 0xB2, 0x2F, 0x12, 0x8A, 0xDC, 0x74, 0xFF, +0xF0, 0x90, 0x82, 0x9F, 0xE0, 0x04, 0xF0, 0x80, +0xE5, 0xE4, 0x90, 0x82, 0x9F, 0xF0, 0x90, 0x82, +0xA2, 0xE0, 0xFF, 0x90, 0x82, 0x9F, 0xE0, 0xFE, +0xC3, 0x9F, 0x40, 0x02, 0x81, 0x19, 0x74, 0xDF, +0x2E, 0xF9, 0xE4, 0x34, 0x86, 0xB1, 0xFC, 0x75, +0x16, 0x0A, 0x7B, 0x01, 0x7A, 0x82, 0x79, 0x94, +0x12, 0x2B, 0xED, 0x90, 0x82, 0x95, 0xE0, 0xFF, +0x12, 0x2F, 0x27, 0xEF, 0x04, 0x90, 0x82, 0xAF, +0xF0, 0x90, 0x82, 0x94, 0xE0, 0xFF, 0xA3, 0xE0, +0xFD, 0x12, 0x31, 0xEA, 0xEF, 0x24, 0xC8, 0x90, +0x82, 0xB1, 0xF0, 0x75, 0xF0, 0x08, 0xA4, 0xF0, +0x90, 0x82, 0x95, 0xE0, 0x54, 0x0F, 0x90, 0x82, +0xB0, 0xF0, 0xE4, 0x90, 0x82, 0x9E, 0xF0, 0x90, +0x82, 0xA0, 0xF0, 0x90, 0x82, 0xA0, 0xE0, 0xFF, +0xC3, 0x94, 0x04, 0x50, 0x57, 0x90, 0x82, 0xB0, +0xE0, 0xFE, 0xA8, 0x07, 0x08, 0x80, 0x02, 0xC3, +0x13, 0xD8, 0xFC, 0x20, 0xE0, 0x3E, 0x90, 0x82, +0xA0, 0xE0, 0x25, 0xE0, 0xFF, 0x90, 0x82, 0xB1, +0xE0, 0x2F, 0x24, 0xB2, 0xF9, 0xE4, 0x34, 0x82, +0xFA, 0x7B, 0x01, 0xC0, 0x03, 0xC0, 0x01, 0x90, +0x82, 0x9E, 0xE0, 0x75, 0xF0, 0x02, 0xA4, 0x24, +0x96, 0xF9, 0x74, 0x82, 0x35, 0xF0, 0x8B, 0x13, +0xF5, 0x14, 0x89, 0x15, 0x75, 0x16, 0x02, 0xD0, +0x01, 0xD0, 0x03, 0x12, 0x2B, 0xED, 0x90, 0x82, +0x9E, 0xE0, 0x04, 0xF0, 0x90, 0x82, 0xA0, 0xE0, +0x04, 0xF0, 0x80, 0x9F, 0x90, 0x82, 0xAF, 0xE0, +0xFF, 0x90, 0x82, 0x9F, 0xE0, 0x2F, 0xF0, 0x61, +0x4E, 0xE4, 0x90, 0x82, 0xA3, 0xF0, 0x90, 0x82, +0xA3, 0xE0, 0xC3, 0x94, 0x40, 0x40, 0x02, 0xA1, +0xC7, 0xE0, 0xFF, 0x24, 0xB2, 0x12, 0x8A, 0xDC, +0xE0, 0x90, 0x82, 0xA5, 0xF0, 0xE0, 0xFE, 0x54, +0xF0, 0xC4, 0x54, 0x0F, 0xFD, 0x90, 0x82, 0xA4, +0xF0, 0xEE, 0x54, 0x0F, 0xFE, 0xA3, 0xF0, 0x74, +0xB3, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x82, 0xF5, +0x83, 0xE0, 0x90, 0x82, 0xA6, 0xF0, 0xFC, 0xEE, +0xFE, 0xEC, 0xFB, 0xEB, 0xFF, 0x90, 0x82, 0xAB, +0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xED, 0x12, 0x47, +0xF8, 0x4C, 0x8E, 0x00, 0x4C, 0xC0, 0x01, 0x4D, +0x2E, 0x02, 0x4D, 0xB8, 0x03, 0x4D, 0x39, 0x04, +0x4D, 0x4A, 0x05, 0x4D, 0x4A, 0x06, 0x4D, 0x4A, +0x07, 0x4D, 0x4A, 0x08, 0x4D, 0x93, 0x09, 0x4D, +0xA5, 0x0A, 0x00, 0x00, 0x4D, 0xC7, 0x90, 0x82, +0xA3, 0xE0, 0xFD, 0x24, 0xB5, 0xF5, 0x82, 0xE4, +0x34, 0x82, 0xF5, 0x83, 0xE0, 0xFE, 0x74, 0xB4, +0x2D, 0xB1, 0xE9, 0xE0, 0xFD, 0xED, 0xFF, 0x90, +0x82, 0xAD, 0xEE, 0xF0, 0xFC, 0xA3, 0xEF, 0xF0, +0x90, 0x82, 0xA6, 0xE0, 0xFF, 0x12, 0x2F, 0x96, +0x90, 0x82, 0xA1, 0x74, 0x02, 0xF0, 0xA1, 0xB8, +0x51, 0xE4, 0x12, 0x47, 0x7F, 0xC0, 0x04, 0xC0, +0x05, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x82, 0xA3, +0xE0, 0x24, 0xB6, 0xF5, 0x82, 0xE4, 0x34, 0x82, +0x71, 0x0F, 0x78, 0x10, 0x12, 0x20, 0xBB, 0xD0, +0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, +0x47, 0x7F, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, +0xC0, 0x07, 0x90, 0x82, 0xA3, 0xE0, 0x24, 0xB7, +0xF5, 0x82, 0xE4, 0x34, 0x82, 0x71, 0x0F, 0x78, +0x18, 0x12, 0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, +0xD0, 0x01, 0xD0, 0x00, 0x12, 0x8A, 0x85, 0x90, +0x82, 0xA7, 0x12, 0x47, 0x9D, 0x90, 0x85, 0x96, +0x12, 0x20, 0xCE, 0x90, 0x82, 0xAB, 0xE0, 0xFE, +0xA3, 0xE0, 0xFF, 0x12, 0x2E, 0xE4, 0x90, 0x82, +0xA1, 0x74, 0x04, 0xF0, 0xA1, 0xB8, 0xB1, 0xDE, +0xE0, 0xFB, 0xE4, 0xFF, 0x12, 0x30, 0xC7, 0x80, +0x09, 0xB1, 0xDE, 0xE0, 0xFB, 0xE4, 0xFF, 0x12, +0x30, 0x6A, 0x90, 0x82, 0xA1, 0x74, 0x01, 0xF0, +0x80, 0x6E, 0x90, 0x82, 0xA1, 0x74, 0x02, 0xF0, +0x51, 0xE4, 0x12, 0x47, 0x7F, 0xC0, 0x04, 0xC0, +0x05, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x82, 0xA5, +0x71, 0x11, 0x78, 0x10, 0x12, 0x20, 0xBB, 0xD0, +0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, +0x8A, 0x85, 0x90, 0x82, 0xA4, 0xE0, 0x24, 0xFB, +0xFF, 0xC0, 0x07, 0x90, 0x82, 0xA7, 0x12, 0x47, +0x9D, 0x90, 0x83, 0x42, 0x12, 0x20, 0xCE, 0x90, +0x82, 0xA6, 0xE0, 0xFD, 0xD0, 0x07, 0x12, 0x77, +0x52, 0x80, 0x25, 0x90, 0x82, 0xA1, 0x74, 0x01, +0xB1, 0xF1, 0x75, 0x16, 0x01, 0x12, 0x89, 0x7E, +0xF0, 0x7B, 0x04, 0x80, 0x10, 0x90, 0x82, 0xA1, +0x74, 0x04, 0xB1, 0xF1, 0x75, 0x16, 0x04, 0x12, +0x89, 0x7E, 0xF0, 0x7B, 0x06, 0x12, 0x75, 0x7C, +0x90, 0x82, 0xA1, 0xE0, 0x24, 0x02, 0xFF, 0x90, +0x82, 0xA3, 0xE0, 0x2F, 0xF0, 0x81, 0x1E, 0x22, +0x7D, 0x02, 0x7F, 0x02, 0xB1, 0xD2, 0x7D, 0x01, +0x7F, 0x02, 0x74, 0x3D, 0x12, 0x8A, 0xBE, 0xFE, +0xF6, 0x74, 0x30, 0x02, 0x6E, 0x33, 0x90, 0x82, +0xA6, 0xE0, 0xFD, 0x90, 0x82, 0xA3, 0xE0, 0x24, +0xB4, 0xF5, 0x82, 0xE4, 0x34, 0x82, 0xF5, 0x83, +0x22, 0xF0, 0x90, 0x82, 0xA3, 0xE0, 0x24, 0xB4, +0xF9, 0xE4, 0x34, 0x82, 0x75, 0x13, 0x01, 0xF5, +0x14, 0x89, 0x15, 0x22, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x8B, 0x56, 0x8A, 0x57, 0x89, +0x58, 0x90, 0x05, 0x27, 0xE0, 0xF5, 0x59, 0x8B, +0x13, 0x8A, 0x14, 0x89, 0x15, 0x75, 0x16, 0x01, +0x7B, 0x01, 0x7A, 0x81, 0x79, 0x83, 0x12, 0x2B, +0xED, 0x12, 0x8A, 0x7C, 0xFF, 0xC3, 0x13, 0x20, +0xE0, 0x02, 0xC1, 0xC4, 0x90, 0x81, 0x83, 0xE0, +0x30, 0xE0, 0x77, 0x12, 0x6E, 0x3E, 0x75, 0x59, +0x21, 0x90, 0x81, 0x83, 0xE0, 0x13, 0x13, 0x54, +0x3F, 0x30, 0xE0, 0x05, 0x12, 0x89, 0xD2, 0x80, +0x0C, 0xE4, 0x90, 0x81, 0x84, 0xF0, 0xA3, 0xF0, +0x7D, 0x40, 0xFF, 0xB1, 0xD2, 0x12, 0x8A, 0xD4, +0x13, 0x54, 0x1F, 0x30, 0xE0, 0x03, 0x43, 0x59, +0x12, 0xEF, 0xC4, 0x54, 0x0F, 0x30, 0xE0, 0x03, +0x43, 0x59, 0x14, 0x90, 0x81, 0x83, 0xE0, 0xC4, +0x13, 0x54, 0x07, 0x30, 0xE0, 0x03, 0x43, 0x59, +0x80, 0x12, 0x89, 0xFE, 0x20, 0xE0, 0x03, 0x43, +0x59, 0x40, 0xF1, 0x76, 0x90, 0x81, 0x86, 0xE0, +0x70, 0x05, 0x7F, 0x01, 0x12, 0x7D, 0xC6, 0x12, +0x80, 0xE3, 0x30, 0xE0, 0x04, 0x7F, 0x04, 0x80, +0x0C, 0x12, 0x6B, 0x88, 0xEF, 0x60, 0x04, 0x7F, +0x01, 0x80, 0x02, 0x7F, 0x02, 0x12, 0x7D, 0xC6, +0xE1, 0x3D, 0xF1, 0x73, 0x90, 0x81, 0x86, 0xE0, +0x64, 0x04, 0x60, 0x02, 0xE1, 0x6E, 0xFF, 0x12, +0x7D, 0xC6, 0xE1, 0x6E, 0x90, 0x81, 0x83, 0xE0, +0x30, 0xE0, 0x7A, 0x12, 0x6E, 0x3E, 0x43, 0x59, +0x31, 0x90, 0x81, 0x83, 0xE0, 0x13, 0x13, 0x54, +0x3F, 0x30, 0xE0, 0x05, 0x12, 0x89, 0xD2, 0x80, +0x06, 0x7D, 0x40, 0xE4, 0xFF, 0xB1, 0xD2, 0x12, +0x8A, 0xD4, 0x13, 0x54, 0x1F, 0x30, 0xE0, 0x03, +0x43, 0x59, 0x02, 0xEF, 0xC4, 0x54, 0x0F, 0x30, +0xE0, 0x03, 0x43, 0x59, 0x04, 0xF1, 0x76, 0x12, +0x80, 0xE3, 0x30, 0xE0, 0x0B, 0x12, 0x81, 0x05, +0x60, 0x33, 0xE4, 0xFD, 0x7F, 0x02, 0x80, 0x20, +0x12, 0x7F, 0xC9, 0xF0, 0x90, 0x81, 0x87, 0xE0, +0xB4, 0x02, 0x1A, 0x12, 0x88, 0x3A, 0x12, 0x6B, +0x88, 0xBF, 0x01, 0x09, 0x90, 0x81, 0x8F, 0xE0, +0xFF, 0x7D, 0x01, 0x80, 0x03, 0xE4, 0xFD, 0xFF, +0x12, 0x52, 0x54, 0x80, 0x08, 0x90, 0x81, 0x90, +0xE0, 0x90, 0x81, 0x87, 0xF0, 0x90, 0x05, 0x40, +0x74, 0x22, 0xF0, 0x80, 0x29, 0xF1, 0x73, 0x90, +0x81, 0x87, 0xE0, 0xB4, 0x02, 0x06, 0x7D, 0x01, +0x7F, 0x04, 0x80, 0x0B, 0x90, 0x81, 0x87, 0xE0, +0xB4, 0x08, 0x07, 0x7D, 0x01, 0x7F, 0x0C, 0x12, +0x52, 0x54, 0x12, 0x81, 0x65, 0x90, 0x81, 0x8F, +0x12, 0x6C, 0x09, 0x12, 0x69, 0xD9, 0xD0, 0xD0, +0x92, 0xAF, 0x22, 0x75, 0x59, 0x01, 0x90, 0x05, +0x27, 0xE5, 0x59, 0xF0, 0x22, 0xEF, 0x70, 0x3F, +0x7D, 0x78, 0x7F, 0x02, 0xB1, 0xD2, 0x7D, 0x02, +0x7F, 0x03, 0xB1, 0xD2, 0x7D, 0xC8, 0x7F, 0x02, +0x12, 0x6E, 0x2A, 0x12, 0x6C, 0x63, 0xF0, 0xE4, +0xFF, 0x12, 0x69, 0xF6, 0xEF, 0x70, 0x0E, 0x12, +0x55, 0x60, 0x12, 0x55, 0x4A, 0x12, 0x8A, 0x96, +0x54, 0x7F, 0xF0, 0x80, 0x07, 0x7D, 0x01, 0x7F, +0x0C, 0x12, 0x52, 0x54, 0x12, 0x82, 0x91, 0x90, +0x06, 0x0A, 0xE0, 0x54, 0xF8, 0xF0, 0x22, 0x90, +0x01, 0x36, 0x74, 0x78, 0xF0, 0xA3, 0x74, 0x02, +0xF0, 0x7D, 0x78, 0xFF, 0x12, 0x6D, 0xAB, 0x7D, +0x02, 0x7F, 0x03, 0x12, 0x6D, 0xAB, 0x90, 0x06, +0x0A, 0xE0, 0x44, 0x07, 0x12, 0x89, 0xAC, 0xE4, +0xFF, 0x12, 0x69, 0xF6, 0xBF, 0x01, 0x11, 0x12, +0x6B, 0xF3, 0x90, 0x81, 0x90, 0xE0, 0x20, 0xE2, +0x0B, 0x7D, 0x01, 0x7F, 0x04, 0x02, 0x52, 0x54, +0x12, 0x6D, 0x71, 0xF0, 0x22, 0xC0, 0xE0, 0xC0, +0xF0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0xD0, 0x75, +0xD0, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x02, +0xC0, 0x03, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, +0xC0, 0x07, 0x90, 0x01, 0xC4, 0x74, 0xFD, 0xF0, +0x74, 0x4F, 0xA3, 0xF0, 0x12, 0x84, 0xA0, 0xE5, +0x49, 0x30, 0xE1, 0x02, 0x11, 0xA5, 0xE5, 0x49, +0x30, 0xE2, 0x03, 0x12, 0x82, 0x7C, 0xE5, 0x4A, +0x30, 0xE0, 0x03, 0x12, 0x85, 0x19, 0xE5, 0x4A, +0x30, 0xE4, 0x03, 0x12, 0x86, 0x04, 0xE5, 0x4B, +0x30, 0xE1, 0x03, 0x12, 0x86, 0x1A, 0xE5, 0x4B, +0x30, 0xE0, 0x03, 0x12, 0x82, 0x99, 0xE5, 0x4B, +0x30, 0xE4, 0x02, 0xF1, 0xF4, 0xE5, 0x4C, 0x30, +0xE1, 0x05, 0x7F, 0x04, 0x12, 0x7A, 0x29, 0xE5, +0x4C, 0x30, 0xE4, 0x03, 0x12, 0x6D, 0xB7, 0xE5, +0x4C, 0x30, 0xE5, 0x03, 0x12, 0x80, 0xBB, 0xE5, +0x4C, 0x30, 0xE6, 0x03, 0x12, 0x7D, 0x46, 0x74, +0xFD, 0x04, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x4F, +0xA3, 0xF0, 0xD0, 0x07, 0xD0, 0x06, 0xD0, 0x05, +0xD0, 0x04, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, +0xD0, 0x00, 0xD0, 0xD0, 0xD0, 0x82, 0xD0, 0x83, +0xD0, 0xF0, 0xD0, 0xE0, 0x32, 0x90, 0x81, 0x8D, +0xE0, 0x60, 0x03, 0x12, 0x6B, 0x94, 0x90, 0x82, +0x66, 0xE0, 0x30, 0xE0, 0x47, 0xC4, 0x54, 0x0F, +0x20, 0xE0, 0x15, 0xE4, 0xF5, 0x1D, 0x90, 0x82, +0x68, 0x31, 0x07, 0x91, 0x6B, 0x12, 0x8A, 0x64, +0x30, 0xE0, 0x02, 0x31, 0xC5, 0x02, 0x88, 0xE9, +0x90, 0x82, 0x66, 0xE0, 0xC4, 0x54, 0x0F, 0x30, +0xE0, 0x22, 0xE4, 0xF5, 0x1D, 0x90, 0x82, 0x69, +0x31, 0x07, 0x90, 0x82, 0x66, 0xE0, 0x54, 0xEF, +0xF0, 0xE0, 0xC3, 0x13, 0x30, 0xE0, 0x06, 0x7D, +0x04, 0x7F, 0x01, 0x21, 0xC9, 0x7B, 0x31, 0xF1, +0xF5, 0x12, 0x7E, 0xD9, 0x22, 0xE0, 0x44, 0x02, +0xF0, 0xE4, 0xF5, 0x1D, 0x90, 0x82, 0x60, 0xE0, +0xF5, 0x1E, 0xE4, 0xFB, 0xFD, 0x7F, 0x54, 0x7E, +0x01, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x8E, 0x19, 0x8F, 0x1A, 0xE5, 0x1E, 0x31, 0x66, +0x85, 0x19, 0x83, 0x85, 0x1A, 0x82, 0xF0, 0xE5, +0x1D, 0x31, 0x66, 0xFF, 0xE5, 0x1E, 0x13, 0x13, +0x13, 0x54, 0x1F, 0x4F, 0xA3, 0xF0, 0xEB, 0x31, +0x66, 0xFF, 0xE5, 0x1D, 0x13, 0x13, 0x13, 0x54, +0x1F, 0x4F, 0x31, 0x6D, 0xF0, 0xBD, 0x01, 0x0D, +0x85, 0x1A, 0x82, 0x8E, 0x83, 0xA3, 0xA3, 0xA3, +0x74, 0x03, 0xF0, 0x80, 0x06, 0x31, 0x6D, 0xA3, +0x74, 0x01, 0xF0, 0x31, 0x6D, 0xA3, 0x74, 0x05, +0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x54, 0x07, +0xC4, 0x33, 0x54, 0xE0, 0x22, 0x85, 0x1A, 0x82, +0x85, 0x19, 0x83, 0xA3, 0xA3, 0x22, 0x90, 0x81, +0x91, 0xE0, 0x44, 0x10, 0xF0, 0x90, 0x81, 0x96, +0xE0, 0x60, 0x04, 0x64, 0x01, 0x70, 0x11, 0xE4, +0xF5, 0x1D, 0x90, 0x81, 0x96, 0xE0, 0x31, 0xBA, +0x31, 0x08, 0x90, 0x81, 0x96, 0xE0, 0x80, 0x11, +0xE4, 0xF5, 0x1D, 0x31, 0xB0, 0x31, 0x08, 0x90, +0x81, 0x96, 0xE0, 0x75, 0xF0, 0x03, 0xA4, 0x24, +0xFE, 0x31, 0xBA, 0x90, 0x81, 0xA6, 0xF0, 0x22, +0x90, 0x81, 0x96, 0xE0, 0x75, 0xF0, 0x03, 0xA4, +0x24, 0xFE, 0xFF, 0x90, 0x81, 0x95, 0xE0, 0x2F, +0x22, 0xE0, 0x54, 0x7F, 0xF0, 0x7D, 0x0C, 0x7F, +0x01, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0xAC, 0x07, 0xEF, 0x14, 0x60, 0x15, 0x14, 0x60, +0x19, 0x24, 0x02, 0x70, 0x1A, 0xED, 0x54, 0x01, +0xFE, 0x90, 0x81, 0x88, 0xE0, 0x54, 0xFE, 0x4E, +0xF0, 0x80, 0x0C, 0x90, 0x81, 0x90, 0xED, 0xF0, +0x80, 0x05, 0x90, 0x81, 0x8F, 0xED, 0xF0, 0x90, +0x00, 0x8F, 0xE0, 0x30, 0xE4, 0x2E, 0xEC, 0x14, +0x60, 0x07, 0x14, 0x60, 0x1D, 0x24, 0x02, 0x70, +0x23, 0x90, 0x81, 0x88, 0xE0, 0x54, 0x01, 0xC4, +0x33, 0x33, 0x33, 0x54, 0x80, 0xFF, 0x90, 0x81, +0x90, 0xE0, 0x54, 0x7F, 0x4F, 0xFD, 0x7F, 0x88, +0x80, 0x07, 0x90, 0x81, 0x8F, 0xE0, 0xFD, 0x7F, +0x89, 0x12, 0x32, 0x1E, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x90, 0x81, 0x89, 0xE0, 0xC3, 0x13, 0x20, +0xE0, 0x04, 0x31, 0xC5, 0x80, 0x0B, 0x12, 0x8A, +0x36, 0x12, 0x88, 0x49, 0x44, 0x80, 0x12, 0x88, +0x41, 0xE4, 0xFB, 0xFD, 0x7F, 0xFF, 0x81, 0x72, +0x7D, 0x01, 0x7F, 0x04, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x90, 0x83, 0x71, 0xED, 0xF0, +0x90, 0x81, 0x88, 0xE0, 0xFE, 0xC4, 0x13, 0x13, +0x54, 0x03, 0x30, 0xE0, 0x02, 0x61, 0x9A, 0xEE, +0x12, 0x7D, 0x36, 0x30, 0xE0, 0x02, 0x61, 0x9A, +0x90, 0x81, 0x90, 0xE0, 0xFE, 0x6F, 0x70, 0x02, +0x61, 0x9A, 0xEF, 0x70, 0x02, 0x61, 0x10, 0x24, +0xFE, 0x70, 0x02, 0x61, 0x4A, 0x24, 0xFE, 0x60, +0x47, 0x24, 0xFC, 0x70, 0x02, 0x61, 0x84, 0x24, +0xFC, 0x60, 0x02, 0x61, 0x93, 0xEE, 0xB4, 0x0E, +0x02, 0x51, 0x31, 0x90, 0x81, 0x90, 0xE0, 0x70, +0x04, 0x7F, 0x01, 0x91, 0x22, 0x90, 0x81, 0x90, +0xE0, 0xB4, 0x06, 0x02, 0x71, 0xF6, 0x90, 0x81, +0x90, 0xE0, 0xB4, 0x04, 0x0D, 0x90, 0x83, 0x71, +0xE0, 0xFF, 0x60, 0x04, 0xB1, 0xEF, 0x80, 0x02, +0xB1, 0x4A, 0x90, 0x81, 0x90, 0xE0, 0x64, 0x08, +0x60, 0x02, 0x61, 0x93, 0xB1, 0x55, 0x61, 0x93, +0x90, 0x81, 0x90, 0xE0, 0x70, 0x04, 0x7F, 0x01, +0x91, 0x22, 0x90, 0x81, 0x90, 0xE0, 0xB4, 0x06, +0x02, 0x71, 0xF6, 0x90, 0x81, 0x90, 0xE0, 0xB4, +0x0E, 0x07, 0x71, 0x9F, 0xBF, 0x01, 0x02, 0x51, +0x31, 0x90, 0x81, 0x90, 0xE0, 0x64, 0x0C, 0x60, +0x02, 0x61, 0x93, 0x71, 0x9F, 0xEF, 0x64, 0x01, +0x60, 0x02, 0x61, 0x93, 0x91, 0x39, 0x61, 0x93, +0x90, 0x81, 0x90, 0xE0, 0xB4, 0x0E, 0x07, 0x71, +0x9F, 0xBF, 0x01, 0x02, 0x51, 0x31, 0x90, 0x81, +0x90, 0xE0, 0xB4, 0x06, 0x02, 0x71, 0xF6, 0x90, +0x81, 0x90, 0xE0, 0xB4, 0x0C, 0x07, 0x71, 0x9F, +0xBF, 0x01, 0x02, 0x91, 0x39, 0x90, 0x81, 0x90, +0xE0, 0x64, 0x04, 0x70, 0x56, 0x12, 0x81, 0x86, +0xEF, 0x64, 0x01, 0x70, 0x4E, 0x12, 0x88, 0x16, +0x80, 0x49, 0x90, 0x81, 0x90, 0xE0, 0xB4, 0x0E, +0x07, 0x71, 0x9F, 0xBF, 0x01, 0x02, 0x51, 0x31, +0x90, 0x81, 0x90, 0xE0, 0xB4, 0x06, 0x02, 0x71, +0xF6, 0x90, 0x81, 0x90, 0xE0, 0xB4, 0x0C, 0x07, +0x71, 0x9F, 0xBF, 0x01, 0x02, 0x91, 0x39, 0x90, +0x81, 0x90, 0xE0, 0x70, 0x04, 0x7F, 0x01, 0x91, +0x22, 0x90, 0x81, 0x90, 0xE0, 0xB4, 0x04, 0x13, +0xB1, 0xBE, 0x80, 0x0F, 0x90, 0x81, 0x90, 0xE0, +0xB4, 0x0C, 0x08, 0x12, 0x6D, 0x80, 0x30, 0xE0, +0x02, 0xD1, 0x30, 0x90, 0x81, 0x90, 0x12, 0x81, +0xF9, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x81, +0x6D, 0xEF, 0x64, 0x01, 0x60, 0x05, 0x75, 0x1F, +0x01, 0x80, 0x30, 0x12, 0x5A, 0xDE, 0x30, 0xE0, +0x05, 0x75, 0x1F, 0x02, 0x80, 0x25, 0x90, 0x81, +0x8F, 0xE0, 0xD3, 0x94, 0x04, 0x40, 0x05, 0x75, +0x1F, 0x08, 0x80, 0x17, 0x90, 0x82, 0x66, 0xE0, +0x30, 0xE0, 0x0B, 0xC4, 0x54, 0x0F, 0x30, 0xE0, +0x05, 0x75, 0x1F, 0x11, 0x80, 0x05, 0x12, 0x77, +0x83, 0x80, 0x0E, 0x90, 0x01, 0xB9, 0x74, 0x02, +0xF0, 0x90, 0x01, 0xB8, 0xE5, 0x1F, 0xF0, 0x7F, +0x00, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x81, +0x89, 0xE0, 0x90, 0x06, 0x04, 0x20, 0xE0, 0x0C, +0xE0, 0x44, 0x40, 0xF0, 0x7D, 0x04, 0x7F, 0x01, +0x31, 0xC9, 0x80, 0x0F, 0x31, 0xC1, 0x90, 0x05, +0x27, 0xE0, 0x54, 0x7F, 0xF0, 0x90, 0x81, 0x87, +0x74, 0x0C, 0xF0, 0xE4, 0xFB, 0xFD, 0x7F, 0xFF, +0x80, 0x50, 0x90, 0x83, 0x70, 0xEF, 0xF0, 0xB1, +0x60, 0x90, 0x83, 0x70, 0xE0, 0x60, 0x02, 0x91, +0x6D, 0x7D, 0x04, 0xD1, 0x28, 0x74, 0x04, 0xF0, +0x22, 0x12, 0x6A, 0xC0, 0x70, 0x2C, 0x90, 0x81, +0x89, 0xE0, 0x54, 0xFD, 0xF0, 0x7B, 0x2C, 0x7D, +0x6F, 0x7F, 0xFF, 0x91, 0x72, 0x7D, 0x08, 0x7F, +0x01, 0xD1, 0x43, 0xBF, 0x01, 0x0F, 0x90, 0x81, +0x88, 0xE0, 0x44, 0x80, 0xF0, 0x7D, 0x0E, 0xD1, +0x28, 0x74, 0x0E, 0xF0, 0x22, 0x12, 0x80, 0xB1, +0x04, 0xF0, 0x22, 0xB1, 0x60, 0xE4, 0xFB, 0xFD, +0x7F, 0xFF, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x90, 0x05, 0x22, 0xED, 0xF0, 0x90, 0x80, +0x40, 0xEB, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x7E, 0x00, 0x7F, 0xD7, 0x7D, 0x00, 0x7B, 0x01, +0x7A, 0x81, 0x79, 0x88, 0x12, 0x48, 0x1E, 0x12, +0x8A, 0x08, 0x12, 0x48, 0x1E, 0x90, 0x81, 0x8C, +0x74, 0x02, 0xF0, 0x90, 0x81, 0x93, 0x14, 0xF0, +0xA3, 0xF0, 0xA3, 0x74, 0x10, 0xF0, 0x90, 0x81, +0x99, 0xE4, 0xF0, 0xA3, 0x74, 0x02, 0x12, 0x89, +0xB7, 0x12, 0x88, 0x55, 0xE4, 0xFD, 0xFF, 0x31, +0xC9, 0x7D, 0x0C, 0x7F, 0x02, 0x31, 0xC9, 0x31, +0xC5, 0x90, 0x80, 0x42, 0xE0, 0xFF, 0xB4, 0x01, +0x08, 0x90, 0x81, 0x98, 0x74, 0x99, 0xF0, 0x80, +0x29, 0xEF, 0xB4, 0x03, 0x08, 0x90, 0x81, 0x98, +0x74, 0x90, 0xF0, 0x80, 0x1D, 0x90, 0x81, 0x98, +0x74, 0x40, 0xF0, 0x90, 0x00, 0x2C, 0xE0, 0x54, +0x0F, 0xFF, 0xBF, 0x05, 0x08, 0x90, 0x81, 0xAA, +0x74, 0x02, 0xF0, 0x80, 0x05, 0xE4, 0x90, 0x81, +0xAA, 0xF0, 0x90, 0x82, 0x5F, 0x74, 0x02, 0xF0, +0xA3, 0x74, 0x0F, 0xF0, 0xA3, 0xE0, 0x54, 0x01, +0x44, 0x28, 0xF0, 0xA3, 0x74, 0x07, 0x12, 0x89, +0xB7, 0x7F, 0x01, 0x12, 0x88, 0x6F, 0x90, 0x05, +0x58, 0x74, 0x02, 0xF0, 0x7E, 0x00, 0xFF, 0x7D, +0x00, 0x7B, 0x01, 0x7A, 0x82, 0x79, 0x63, 0x12, +0x48, 0x1E, 0x12, 0x8A, 0x8E, 0x90, 0x06, 0x0A, +0xE0, 0x54, 0xF8, 0xF0, 0x7B, 0x56, 0xE4, 0xFD, +0x7F, 0xFF, 0x91, 0x72, 0xE4, 0x90, 0x82, 0x65, +0xF0, 0x22, 0x12, 0x8A, 0x8E, 0x91, 0x6D, 0x7D, +0x0C, 0x7F, 0x01, 0x21, 0xC9, 0x91, 0x6B, 0x31, +0xC5, 0x90, 0x81, 0x87, 0x74, 0x0C, 0xF0, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, +0x01, 0x01, 0xE0, 0x44, 0x02, 0xF0, 0x90, 0x01, +0x00, 0x74, 0xFF, 0xF0, 0x90, 0x06, 0xB7, 0x74, +0x09, 0xF0, 0x90, 0x06, 0xB4, 0x74, 0x86, 0xF0, +0x12, 0x8A, 0xCD, 0xEC, 0x54, 0x7F, 0xFC, 0x90, +0x83, 0x59, 0x12, 0x20, 0xCE, 0x90, 0x83, 0x59, +0x12, 0x75, 0x61, 0x7F, 0x7C, 0x12, 0x89, 0xC9, +0x12, 0x20, 0xDA, 0xCC, 0xC0, 0x00, 0xC0, 0x12, +0x89, 0xC7, 0x12, 0x20, 0xDA, 0x00, 0xC0, 0x00, +0x14, 0x12, 0x8A, 0x59, 0x12, 0x20, 0xDA, 0x00, +0x03, 0x3E, 0x60, 0xE4, 0xFD, 0xFF, 0x12, 0x77, +0x52, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x7B, 0x2E, +0x7D, 0x6F, 0x7F, 0xFF, 0x91, 0x72, 0x7D, 0x02, +0x12, 0x88, 0x4B, 0x54, 0xBF, 0xF0, 0x90, 0x81, +0x87, 0x74, 0x02, 0xF0, 0x22, 0x90, 0x82, 0x66, +0xE0, 0x30, 0xE0, 0x12, 0x90, 0x01, 0x57, 0xE4, +0xF0, 0x91, 0x6B, 0x12, 0x8A, 0x64, 0x30, 0xE0, +0x02, 0x31, 0xC5, 0x12, 0x88, 0xE9, 0x22, 0xEF, +0x60, 0x35, 0x12, 0x6A, 0xC0, 0x70, 0x30, 0x90, +0x81, 0x89, 0xE0, 0x54, 0xFE, 0xF0, 0x7B, 0x2B, +0x7D, 0x0F, 0x7F, 0xFF, 0x91, 0x72, 0x90, 0x06, +0x04, 0xE0, 0x54, 0xBF, 0xF0, 0xD1, 0x3F, 0xBF, +0x01, 0x0F, 0x90, 0x81, 0x88, 0xE0, 0x44, 0x40, +0xF0, 0x7D, 0x06, 0xD1, 0x28, 0x74, 0x06, 0xF0, +0x22, 0x12, 0x80, 0xB1, 0x74, 0x08, 0xF0, 0x22, +0x7F, 0x01, 0x31, 0xC9, 0x90, 0x81, 0x87, 0x22, +0x7B, 0x2F, 0xF1, 0xF5, 0x12, 0x7E, 0xD9, 0x7D, +0x08, 0xD1, 0x28, 0x74, 0x08, 0xF0, 0x22, 0x7D, +0x08, 0xE4, 0xFF, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x83, 0x4C, 0xEF, 0xF0, 0xA3, +0xED, 0xF0, 0x90, 0x80, 0x3E, 0xE0, 0x04, 0xF0, +0x90, 0x04, 0x1D, 0xE0, 0x60, 0x2A, 0x90, 0x05, +0x22, 0xE0, 0x90, 0x83, 0x50, 0xF0, 0x7B, 0x26, +0xF1, 0xEE, 0xF1, 0x8C, 0xEF, 0x64, 0x01, 0x70, +0x03, 0x12, 0x87, 0x07, 0x90, 0x83, 0x50, 0xE0, +0xFD, 0x7B, 0x27, 0xE4, 0xFF, 0x91, 0x72, 0x90, +0x83, 0x4C, 0xE0, 0xFF, 0xD1, 0x9C, 0x80, 0x0A, +0x90, 0x83, 0x4C, 0xE0, 0xFF, 0xD1, 0x9C, 0x12, +0x87, 0x07, 0x12, 0x8A, 0x6B, 0x7F, 0x01, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x90, 0x83, 0x74, 0xEF, 0xF0, +0xC3, 0x94, 0x02, 0x50, 0x44, 0x90, 0x80, 0x88, +0xE0, 0xFF, 0x90, 0x04, 0x1C, 0xE0, 0x6F, 0x70, +0x38, 0x90, 0x81, 0x90, 0xE0, 0x64, 0x0E, 0x70, +0x14, 0x90, 0x83, 0x74, 0xE0, 0x70, 0x2A, 0x90, +0x81, 0x88, 0xE0, 0x54, 0x7F, 0xF0, 0x90, 0x06, +0x04, 0x31, 0xC1, 0x80, 0x1A, 0x90, 0x81, 0x90, +0xE0, 0x64, 0x06, 0x70, 0x14, 0x90, 0x83, 0x74, +0xE0, 0x60, 0x0E, 0x12, 0x8A, 0x96, 0x12, 0x8A, +0x36, 0x90, 0x81, 0x90, 0x74, 0x04, 0xF0, 0x91, +0x6D, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x80, +0x89, 0xE0, 0xFF, 0x90, 0x83, 0x58, 0x74, 0x0B, +0xF0, 0x7B, 0x08, 0x7D, 0x01, 0x12, 0x86, 0x63, +0x90, 0x83, 0x62, 0xEE, 0xF0, 0xFC, 0xA3, 0xEF, +0xF0, 0xFD, 0x90, 0x83, 0x61, 0xE0, 0xFF, 0xF1, +0x44, 0x54, 0x3F, 0xF0, 0xBF, 0x01, 0x02, 0x80, +0x17, 0xEF, 0x70, 0x02, 0x80, 0x07, 0x90, 0x81, +0x90, 0xE0, 0x30, 0xE3, 0x0B, 0x12, 0x87, 0xAC, +0x54, 0xEF, 0xF1, 0x43, 0x44, 0x40, 0xF0, 0x22, +0x12, 0x87, 0xAC, 0x44, 0x10, 0xF1, 0x43, 0x44, +0x80, 0xF0, 0x22, 0xF0, 0x74, 0x1F, 0x2D, 0xF5, +0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, +0x83, 0x61, 0xEF, 0xF0, 0x90, 0x04, 0x1D, 0xE0, +0x60, 0x20, 0x90, 0x05, 0x22, 0xE0, 0x90, 0x83, +0x64, 0xF0, 0x7B, 0x29, 0xF1, 0xEE, 0xF1, 0x8C, +0xBF, 0x01, 0x02, 0xD1, 0xF6, 0x90, 0x83, 0x64, +0xE0, 0xFD, 0x7B, 0x2A, 0xE4, 0xFF, 0x91, 0x72, +0x80, 0x02, 0xD1, 0xF6, 0x12, 0x8A, 0x6B, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0xE4, 0x90, 0x83, 0x65, +0xF0, 0xA3, 0xF0, 0x90, 0x05, 0x22, 0xE0, 0x90, +0x83, 0x67, 0xF0, 0x7B, 0x47, 0xF1, 0xEE, 0x90, +0x05, 0xF8, 0xE0, 0x70, 0x1A, 0xA3, 0xE0, 0x70, +0x16, 0xA3, 0xE0, 0x70, 0x12, 0xA3, 0xE0, 0x70, +0x0E, 0x90, 0x83, 0x67, 0xE0, 0xFD, 0x7B, 0x48, +0xE4, 0xFF, 0x91, 0x72, 0x7F, 0x01, 0x22, 0xD3, +0x90, 0x83, 0x66, 0xE0, 0x94, 0xE8, 0x90, 0x83, +0x65, 0xE0, 0x94, 0x03, 0x40, 0x15, 0x90, 0x01, +0xC0, 0xE0, 0x44, 0x20, 0xF0, 0x90, 0x83, 0x67, +0xE0, 0xFD, 0x7B, 0x5B, 0xE4, 0xFF, 0x91, 0x72, +0x7F, 0x00, 0x22, 0x12, 0x8A, 0xC6, 0x90, 0x83, +0x65, 0x12, 0x77, 0x75, 0x80, 0xB1, 0x7D, 0xFF, +0xE4, 0xFF, 0x81, 0x72, 0x22, 0x7D, 0xFF, 0x7F, +0xFF, 0x81, 0x72, 0xC0, 0xE0, 0xC0, 0x83, 0xC0, +0x82, 0xC0, 0xD0, 0x75, 0xD0, 0x00, 0xC0, 0x05, +0xC0, 0x07, 0x7D, 0xFB, 0x90, 0x01, 0xC4, 0xED, +0xF0, 0x74, 0x57, 0xFF, 0xA3, 0xF0, 0xED, 0x04, +0x90, 0x01, 0xC4, 0xF0, 0xA3, 0xEF, 0xF0, 0xD0, +0x07, 0xD0, 0x05, 0xD0, 0xD0, 0xD0, 0x82, 0xD0, +0x83, 0xD0, 0xE0, 0x32, 0x90, 0x01, 0xC8, 0xE4, +0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0x7B, 0x01, 0x7A, +0x82, 0x79, 0x88, 0x7F, 0xFF, 0xFE, 0x12, 0x2B, +0x27, 0xBF, 0x01, 0x09, 0x90, 0x82, 0x88, 0xE0, +0x64, 0x03, 0x60, 0x03, 0x22, 0x01, 0xEA, 0xE4, +0x90, 0x82, 0x8D, 0xF0, 0x90, 0x82, 0x8D, 0xE0, +0xFF, 0xC3, 0x94, 0x02, 0x40, 0x02, 0x21, 0x25, +0xC3, 0x74, 0xFE, 0x31, 0x2E, 0x7B, 0x01, 0x7A, +0x82, 0x79, 0x89, 0x12, 0x2B, 0x27, 0xEF, 0x64, +0x01, 0x70, 0x77, 0x90, 0x82, 0x89, 0xE0, 0xFF, +0x54, 0xC0, 0xFE, 0x60, 0x05, 0xEF, 0x54, 0x0C, +0x70, 0x16, 0x90, 0x82, 0x89, 0xE0, 0xFF, 0x54, +0x30, 0x60, 0x67, 0xEF, 0x54, 0x03, 0x60, 0x62, +0x90, 0x82, 0x8A, 0x74, 0x01, 0xF0, 0x80, 0x05, +0xE4, 0x90, 0x82, 0x8A, 0xF0, 0x90, 0x82, 0x8A, +0xE0, 0x90, 0x82, 0x89, 0x70, 0x16, 0xE0, 0xFF, +0xEE, 0x13, 0x13, 0x54, 0x3F, 0x90, 0x82, 0x8B, +0xF0, 0xEF, 0x54, 0x0C, 0x13, 0x13, 0x54, 0x3F, +0xA3, 0xF0, 0x80, 0x0D, 0xE0, 0xFE, 0x54, 0x30, +0x90, 0x82, 0x8B, 0xF0, 0xEE, 0x54, 0x03, 0xA3, +0xF0, 0x90, 0x82, 0x8B, 0xE0, 0x64, 0x30, 0x70, +0x54, 0xA3, 0xE0, 0x64, 0x02, 0x70, 0x4E, 0x90, +0x00, 0xF5, 0xE0, 0x54, 0x40, 0x90, 0x82, 0x8E, +0xF0, 0xE0, 0x70, 0x41, 0xA3, 0x74, 0x02, 0xF0, +0x80, 0x10, 0x90, 0x82, 0x8F, 0x74, 0x01, 0xF0, +0x80, 0x08, 0x90, 0x82, 0x8D, 0xE0, 0x04, 0xF0, +0x01, 0x54, 0x90, 0x01, 0xC4, 0x74, 0x2C, 0xF0, +0x74, 0x58, 0xA3, 0xF0, 0x90, 0x82, 0x8F, 0xE0, +0x90, 0x01, 0xC8, 0xF0, 0x90, 0x82, 0x89, 0xE0, +0x90, 0x01, 0xC9, 0xF0, 0x90, 0x82, 0x8A, 0xE0, +0x90, 0x01, 0xCA, 0xF0, 0xE4, 0xFD, 0x7F, 0x1F, +0x12, 0x32, 0x1E, 0x80, 0xD5, 0x22, 0x90, 0x81, +0xA5, 0xE0, 0xFF, 0xC3, 0x74, 0x0A, 0x9F, 0xFF, +0xE4, 0x94, 0x00, 0xFE, 0x22, 0x90, 0x82, 0x55, +0x12, 0x47, 0x9D, 0x90, 0x82, 0x51, 0x12, 0x47, +0xB5, 0xC3, 0x12, 0x47, 0x8C, 0x50, 0x02, 0x21, +0xED, 0x90, 0x82, 0x55, 0x12, 0x47, 0xB5, 0x90, +0x82, 0x51, 0x12, 0x47, 0x9D, 0x12, 0x47, 0x64, +0x78, 0x07, 0x12, 0x20, 0xA8, 0xC0, 0x07, 0x90, +0x82, 0x59, 0xE0, 0xFB, 0xE4, 0xFA, 0xF9, 0xF8, +0xD0, 0x07, 0x12, 0x47, 0x64, 0xEE, 0x54, 0x07, +0xFE, 0xAD, 0x07, 0xAC, 0x06, 0x90, 0x81, 0x88, +0xE0, 0x30, 0xE0, 0x31, 0x31, 0x26, 0xEF, 0x78, +0x03, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, +0x2D, 0xFD, 0xEE, 0x3C, 0xFC, 0x90, 0x81, 0xAA, +0xE0, 0x24, 0x05, 0xFF, 0xE4, 0x33, 0xFE, 0xEF, +0x78, 0x03, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, +0xF9, 0x2D, 0xFF, 0xEC, 0x3E, 0xCF, 0x24, 0xFA, +0xCF, 0x34, 0xFF, 0x80, 0x16, 0x31, 0x26, 0xEF, +0x78, 0x03, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, +0xF9, 0x2D, 0xFF, 0xEE, 0x3C, 0xCF, 0x24, 0x10, +0xCF, 0x34, 0x00, 0x90, 0x82, 0x76, 0xF0, 0xA3, +0xEF, 0xF0, 0x90, 0x82, 0x76, 0xE0, 0xFE, 0xA3, +0xE0, 0xFF, 0xC3, 0x94, 0xA0, 0xEE, 0x94, 0x00, +0x50, 0x13, 0x74, 0xAB, 0x2F, 0xF5, 0x82, 0xE4, +0x34, 0x81, 0xF5, 0x83, 0xE0, 0x04, 0xF0, 0x90, +0x81, 0xA3, 0xE0, 0x04, 0xF0, 0x90, 0x81, 0xA3, +0xE0, 0xFF, 0xD3, 0x90, 0x82, 0x5C, 0xE0, 0x9F, +0x90, 0x82, 0x5B, 0xE0, 0x94, 0x00, 0x40, 0x02, +0x41, 0xDD, 0xE4, 0xFF, 0xFE, 0x51, 0xEF, 0xEF, +0xD3, 0x9D, 0x40, 0x07, 0x90, 0x82, 0x78, 0xEE, +0xF0, 0x80, 0x05, 0x0E, 0xEE, 0xB4, 0xA0, 0xED, +0xE4, 0xFF, 0xFE, 0x51, 0xEF, 0xC3, 0x90, 0x82, +0x5C, 0xE0, 0x9D, 0xFD, 0x90, 0x82, 0x5B, 0xE0, +0x94, 0x00, 0xFC, 0xEF, 0xD3, 0x9D, 0xE4, 0x9C, +0x40, 0x07, 0x90, 0x82, 0x79, 0xEE, 0xF0, 0x80, +0x05, 0x0E, 0xEE, 0xB4, 0xA0, 0xDD, 0x90, 0x82, +0x78, 0xE0, 0x90, 0x81, 0xA8, 0xF0, 0x90, 0x82, +0x79, 0xE0, 0x90, 0x81, 0xA9, 0x51, 0xE8, 0xC3, +0x94, 0x50, 0x40, 0x20, 0xEF, 0x24, 0xB0, 0x90, +0x81, 0xA0, 0xF0, 0xE4, 0x90, 0x81, 0x9F, 0xF0, +0xA3, 0xE0, 0x54, 0x07, 0x75, 0xF0, 0x80, 0xA4, +0xFF, 0x90, 0x82, 0x4B, 0xE5, 0xF0, 0xF0, 0xA3, +0xEF, 0xF0, 0x80, 0x11, 0xE4, 0x90, 0x81, 0xA0, +0x51, 0xE8, 0xC3, 0x74, 0x50, 0x9F, 0x90, 0x81, +0x9F, 0x12, 0x85, 0xA2, 0xF0, 0x90, 0x81, 0xA8, +0x51, 0xE1, 0xF0, 0xA3, 0x51, 0xE1, 0xF0, 0x90, +0x81, 0xA0, 0x51, 0xE1, 0xF0, 0x90, 0x81, 0x9F, +0x51, 0xE1, 0x51, 0xE8, 0xA3, 0xE0, 0xC3, 0x9F, +0x90, 0x81, 0xA6, 0xF0, 0x90, 0x81, 0x88, 0xE0, +0x30, 0xE0, 0x07, 0x90, 0x82, 0x59, 0x51, 0xE1, +0x80, 0x04, 0x90, 0x82, 0x5A, 0xE0, 0x04, 0xFF, +0x90, 0x81, 0xA6, 0xE0, 0x2F, 0xF0, 0x90, 0x81, +0xA6, 0xE0, 0xC3, 0x94, 0x10, 0x50, 0x03, 0x74, +0x10, 0xF0, 0x90, 0x81, 0xA6, 0xE0, 0x24, 0x02, +0x12, 0x85, 0x62, 0x74, 0x03, 0xF0, 0x71, 0x02, +0xE4, 0xFF, 0x12, 0x88, 0x6F, 0x22, 0x90, 0x81, +0x88, 0xE0, 0x13, 0x13, 0x13, 0x54, 0x1F, 0x22, +0xF0, 0x90, 0x81, 0xA8, 0xE0, 0xFF, 0x22, 0x74, +0xAB, 0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, +0x83, 0xE0, 0x2F, 0xFF, 0x90, 0x82, 0x5D, 0xE0, +0xFD, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0xAC, 0x07, 0x90, 0x81, 0x89, 0x12, 0x7D, +0x35, 0x30, 0xE0, 0x02, 0x61, 0xBA, 0x90, 0x81, +0x88, 0xE0, 0x30, 0xE0, 0x16, 0x90, 0x81, 0xAA, +0xE0, 0x24, 0x05, 0x90, 0x81, 0xA2, 0xF0, 0x90, +0x81, 0xAA, 0xE0, 0x24, 0x03, 0x90, 0x81, 0xA1, +0xF0, 0x80, 0x0D, 0x90, 0x81, 0xA2, 0x74, 0x02, +0xF0, 0x90, 0x81, 0xA1, 0x14, 0xF0, 0x0B, 0x0B, +0x90, 0x81, 0xA1, 0xE0, 0xFA, 0x90, 0x81, 0xA0, +0xE0, 0xD3, 0x9A, 0x50, 0x12, 0x90, 0x81, 0x95, +0xEB, 0xF0, 0x90, 0x81, 0xA2, 0xE0, 0xC3, 0x9D, +0x2C, 0x90, 0x81, 0xA5, 0xF0, 0x80, 0x18, 0xC3, +0xED, 0x9A, 0x2B, 0x90, 0x81, 0x95, 0xF0, 0x90, +0x81, 0xA1, 0xE0, 0xFF, 0xA3, 0xE0, 0xC3, 0x9F, +0x90, 0x81, 0xA5, 0x12, 0x85, 0xA2, 0xF0, 0x90, +0x81, 0xA2, 0x71, 0xC6, 0xFC, 0x90, 0x81, 0xA5, +0x71, 0xCE, 0x40, 0x04, 0xEF, 0x24, 0x0A, 0xF0, +0x90, 0x81, 0xA5, 0x71, 0xC6, 0xFC, 0x90, 0x81, +0x95, 0x71, 0xCE, 0x40, 0x04, 0xEF, 0x24, 0x0A, +0xF0, 0x90, 0x81, 0xA5, 0xE0, 0xFF, 0x7E, 0x00, +0x90, 0x81, 0x99, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, +0x90, 0x05, 0x58, 0xE0, 0x6F, 0x70, 0x01, 0xE4, +0x60, 0x03, 0x12, 0x89, 0xAD, 0x12, 0x8A, 0x9E, +0x80, 0x07, 0x90, 0x81, 0x8A, 0xE0, 0x44, 0x01, +0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xE0, 0xFF, +0x24, 0x0A, 0xFD, 0xE4, 0x33, 0x22, 0xE0, 0xD3, +0x9D, 0xEC, 0x64, 0x80, 0xF8, 0x74, 0x80, 0x98, +0x22, 0x12, 0x81, 0xEE, 0x54, 0x01, 0xFE, 0x90, +0x82, 0x66, 0x12, 0x89, 0xF0, 0x4F, 0xFF, 0xF0, +0x12, 0x1F, 0xA4, 0xFE, 0x54, 0x04, 0xFD, 0xEF, +0x54, 0xFB, 0x4D, 0xFF, 0x90, 0x82, 0x66, 0xF0, +0xEE, 0x54, 0x08, 0xFE, 0xEF, 0x54, 0xF7, 0x4E, +0xFF, 0xF0, 0x12, 0x1F, 0xA4, 0x54, 0x10, 0x25, +0xE0, 0x25, 0xE0, 0xFE, 0xEF, 0x54, 0xBF, 0x4E, +0x90, 0x82, 0x66, 0xF0, 0x90, 0x05, 0x52, 0xE0, +0x54, 0x07, 0xFF, 0x90, 0x82, 0xFB, 0x60, 0x12, +0xB1, 0x30, 0xFD, 0x90, 0x05, 0x56, 0xE0, 0xC3, +0x9D, 0x90, 0x82, 0x68, 0xF0, 0xA3, 0xED, 0xF0, +0x80, 0x1E, 0xB1, 0x30, 0xFB, 0xFF, 0x90, 0x05, +0x54, 0xE0, 0xC3, 0x31, 0x2E, 0x7C, 0x00, 0x7D, +0x05, 0x12, 0x20, 0x30, 0x90, 0x82, 0x68, 0xEF, +0xF0, 0xEB, 0x75, 0xF0, 0x05, 0x84, 0xA3, 0xF0, +0x90, 0x82, 0xFB, 0x12, 0x67, 0x59, 0x20, 0xE0, +0x0A, 0x12, 0x54, 0x6B, 0x90, 0x01, 0x57, 0xE4, +0xF0, 0x80, 0x06, 0x12, 0x51, 0xC5, 0x12, 0x88, +0xE9, 0x12, 0x88, 0xF1, 0x13, 0x54, 0x1F, 0x20, +0xE0, 0x04, 0xEF, 0x44, 0x20, 0xF0, 0x12, 0x8A, +0x64, 0x30, 0xE0, 0x16, 0x90, 0x81, 0x8D, 0x74, +0x01, 0xF0, 0xE4, 0x90, 0x81, 0x8F, 0xF0, 0x12, +0x6D, 0x71, 0x12, 0x85, 0x62, 0x74, 0x06, 0xF0, +0x61, 0x02, 0xE4, 0x90, 0x81, 0x8D, 0xF0, 0x90, +0x81, 0x8F, 0x74, 0x0C, 0xF0, 0x90, 0x81, 0x88, +0xE0, 0x54, 0xFE, 0xF0, 0xA3, 0xE0, 0x54, 0xFB, +0xF0, 0x22, 0x90, 0x82, 0xF8, 0x12, 0x47, 0xEF, +0x90, 0x82, 0xF7, 0xEF, 0xF0, 0x12, 0x47, 0xF8, +0x5C, 0xE0, 0x00, 0x5C, 0xE5, 0x01, 0x5C, 0xEA, +0x12, 0x5C, 0xEF, 0x14, 0x5C, 0xF4, 0x20, 0x5C, +0xF9, 0x24, 0x5C, 0xFE, 0x25, 0x5D, 0x03, 0x26, +0x5D, 0x07, 0x27, 0x5D, 0x0C, 0x40, 0x5D, 0x10, +0x42, 0x5D, 0x15, 0xC0, 0x00, 0x00, 0x5D, 0x1A, +0xB1, 0x2A, 0x02, 0x7F, 0xD0, 0xB1, 0x2A, 0x02, +0x6A, 0x18, 0xB1, 0x2A, 0x02, 0x80, 0x1B, 0xB1, +0x2A, 0x02, 0x80, 0x2F, 0xB1, 0x2A, 0x02, 0x80, +0x3E, 0xB1, 0x2A, 0x02, 0x4E, 0x04, 0xB1, 0x2A, +0x02, 0x82, 0xE0, 0xB1, 0x2A, 0x61, 0xD9, 0xB1, +0x2A, 0x02, 0x6E, 0x6E, 0xB1, 0x2A, 0xE1, 0x97, +0xB1, 0x2A, 0x02, 0x6A, 0x7D, 0xB1, 0x2A, 0x02, +0x82, 0xE8, 0x90, 0x01, 0xC0, 0xE0, 0x44, 0x01, +0xF0, 0x90, 0x82, 0xF7, 0xE0, 0x90, 0x01, 0xC2, +0xF0, 0x22, 0x90, 0x82, 0xF8, 0x02, 0x47, 0xE6, +0x12, 0x47, 0xE6, 0x90, 0x00, 0x01, 0x02, 0x1F, +0xBD, 0xE4, 0x90, 0x82, 0xF7, 0xF0, 0x90, 0x81, +0x82, 0xE0, 0xFE, 0x90, 0x82, 0xF7, 0xE0, 0xFF, +0xC3, 0x9E, 0x40, 0x02, 0xE1, 0x60, 0x12, 0x69, +0xF6, 0xEF, 0x70, 0x02, 0xE1, 0x58, 0x90, 0x82, +0xF7, 0x12, 0x8A, 0x42, 0x12, 0x7D, 0x35, 0x30, +0xE0, 0x02, 0xE1, 0x58, 0x12, 0x7C, 0x20, 0xE0, +0xFE, 0xA3, 0xE0, 0xD3, 0x94, 0x00, 0xEE, 0x94, +0x00, 0x50, 0x02, 0xE1, 0x58, 0x90, 0x82, 0xF7, +0xE0, 0x75, 0xF0, 0x0A, 0xA4, 0x24, 0x00, 0xF9, +0x74, 0x8D, 0x35, 0xF0, 0xFA, 0x7B, 0x01, 0x90, +0x82, 0xFC, 0x12, 0x47, 0xEF, 0x90, 0x82, 0xF7, +0xE0, 0xFF, 0x12, 0x7C, 0x21, 0xE0, 0xFD, 0xA3, +0xE0, 0x90, 0x83, 0x01, 0xCD, 0xF0, 0xA3, 0xED, +0xF0, 0xEF, 0x12, 0x8A, 0x2A, 0xE0, 0xFF, 0xA3, +0xE0, 0x90, 0x83, 0x03, 0xCF, 0xF0, 0xA3, 0xEF, +0xF0, 0x90, 0x82, 0xF7, 0xE0, 0xFD, 0x24, 0xB0, +0x12, 0x65, 0x99, 0xE0, 0x54, 0x3F, 0x90, 0x82, +0xF8, 0xF0, 0xE0, 0xFF, 0x54, 0x1F, 0xFE, 0x75, +0xF0, 0x08, 0xED, 0x12, 0x66, 0x1D, 0xE0, 0xFD, +0x90, 0x82, 0xF7, 0xE0, 0xF9, 0x24, 0x8C, 0x12, +0x8A, 0xB6, 0xE0, 0xC3, 0x94, 0x05, 0x40, 0x02, +0xC1, 0xF5, 0xEE, 0x9D, 0x40, 0x0B, 0xAE, 0x05, +0xEF, 0x54, 0x40, 0x90, 0x82, 0xF8, 0xF0, 0x4D, +0xF0, 0xEE, 0x90, 0x41, 0x82, 0x93, 0xFF, 0x74, +0xCB, 0x29, 0x12, 0x8A, 0xAE, 0xE0, 0xC3, 0x9F, +0xEE, 0x40, 0x05, 0x90, 0x41, 0x4A, 0x80, 0x03, +0x90, 0x41, 0x66, 0x93, 0x90, 0x83, 0x05, 0xF0, +0x90, 0x83, 0x05, 0xE0, 0x75, 0xF0, 0x06, 0xA4, +0x24, 0xC0, 0xF9, 0x74, 0x40, 0x35, 0xF0, 0xFA, +0x7B, 0xFF, 0x90, 0x82, 0xF9, 0x12, 0x47, 0xEF, +0x90, 0x82, 0xF8, 0xE0, 0x90, 0x42, 0x2A, 0x93, +0xFF, 0xD3, 0x90, 0x83, 0x04, 0xE0, 0x9F, 0x90, +0x83, 0x03, 0xE0, 0x94, 0x00, 0x40, 0x02, 0xC1, +0xEB, 0x90, 0x82, 0xF7, 0xE0, 0x12, 0x65, 0xCE, +0xE0, 0xFF, 0xA3, 0xE0, 0x90, 0x82, 0xFF, 0xCF, +0xF0, 0xA3, 0xEF, 0xF0, 0xF1, 0x7F, 0x12, 0x1F, +0xA4, 0xF1, 0x64, 0x12, 0x46, 0xB5, 0xF1, 0x70, +0xB1, 0x33, 0xF1, 0x64, 0x90, 0x00, 0x02, 0xF1, +0x6D, 0x90, 0x00, 0x02, 0xF1, 0x61, 0x90, 0x00, +0x04, 0xF1, 0x6D, 0x90, 0x00, 0x03, 0xF1, 0x61, +0x90, 0x00, 0x06, 0xF1, 0x6D, 0x90, 0x00, 0x04, +0xF1, 0x61, 0x90, 0x00, 0x08, 0xF1, 0x6D, 0x12, +0x80, 0x15, 0xFF, 0x7E, 0x00, 0x90, 0x83, 0x01, +0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0x12, 0x20, 0x1E, +0xF1, 0x8B, 0x40, 0x0C, 0xA3, 0xE0, 0x9F, 0xF0, +0x90, 0x82, 0xFF, 0xE0, 0x9E, 0xF0, 0x80, 0x07, +0xE4, 0x90, 0x82, 0xFF, 0xF0, 0xA3, 0xF0, 0x90, +0x82, 0xFF, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0x90, +0x82, 0xF7, 0xE0, 0xFF, 0x12, 0x65, 0xCE, 0xEC, +0xF0, 0xA3, 0xED, 0xF0, 0x12, 0x7A, 0xC8, 0x90, +0x82, 0xF8, 0xE0, 0x12, 0x67, 0x6F, 0x12, 0x67, +0x4F, 0xF1, 0x8B, 0x40, 0x0A, 0x90, 0x82, 0xF7, +0xE0, 0xFF, 0x12, 0x63, 0x73, 0x80, 0x16, 0x90, +0x82, 0xF8, 0xE0, 0x12, 0x67, 0x46, 0xC3, 0xF1, +0x8C, 0x50, 0x0A, 0x90, 0x82, 0xF7, 0xE0, 0xFF, +0x7D, 0x01, 0x12, 0x64, 0xAE, 0xF1, 0x67, 0xE4, +0xF5, 0xF0, 0x12, 0x47, 0x18, 0xF1, 0x67, 0x90, +0x00, 0x02, 0xF1, 0x85, 0x90, 0x00, 0x04, 0xF1, +0x85, 0x90, 0x00, 0x06, 0xF1, 0x85, 0x90, 0x00, +0x08, 0xF1, 0x85, 0x90, 0x82, 0xF7, 0xE0, 0xFF, +0x12, 0x67, 0x0C, 0x12, 0x8A, 0x22, 0xF5, 0x83, +0xE4, 0xF0, 0xA3, 0xF0, 0x90, 0x82, 0xF8, 0xE0, +0xFF, 0x25, 0xE0, 0x24, 0xD6, 0xF5, 0x82, 0xE4, +0x34, 0x41, 0xF5, 0x83, 0xE4, 0x93, 0xFC, 0x74, +0x01, 0x93, 0xFD, 0xEF, 0x12, 0x67, 0x6F, 0xF5, +0x83, 0x74, 0x01, 0x93, 0x2D, 0xFF, 0xE4, 0x93, +0x3C, 0x12, 0x67, 0xDC, 0x90, 0x82, 0xF7, 0xE0, +0x12, 0x65, 0xCE, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, +0x90, 0x82, 0xF7, 0xE0, 0x04, 0xF0, 0xA1, 0x3E, +0x22, 0x12, 0x1F, 0xBD, 0xFF, 0x7E, 0x00, 0x90, +0x82, 0xFC, 0x02, 0x47, 0xE6, 0x12, 0x46, 0xE0, +0xFD, 0xAC, 0xF0, 0x12, 0x20, 0x1E, 0x90, 0x82, +0xFF, 0xEE, 0x8F, 0xF0, 0x12, 0x46, 0x9F, 0x90, +0x82, 0xF9, 0x02, 0x47, 0xE6, 0xE4, 0xF5, 0xF0, +0x02, 0x47, 0x37, 0xD3, 0x90, 0x83, 0x00, 0xE0, +0x9F, 0x90, 0x82, 0xFF, 0xE0, 0x9E, 0x22, 0x12, +0x1F, 0xA4, 0x54, 0x3F, 0xFF, 0xB1, 0x33, 0x54, +0x80, 0x12, 0x7D, 0x36, 0xFE, 0xFD, 0x90, 0x82, +0xFB, 0x12, 0x77, 0x7C, 0x12, 0x47, 0xEF, 0xB1, +0x33, 0x54, 0x0F, 0x90, 0x83, 0x00, 0x12, 0x6A, +0x76, 0x54, 0x40, 0xC4, 0x13, 0x13, 0x54, 0x03, +0x90, 0x83, 0x01, 0xF0, 0x90, 0x82, 0xFB, 0xE0, +0x12, 0x89, 0xE2, 0xFA, 0x7B, 0x01, 0x90, 0x83, +0x02, 0x12, 0x8A, 0x4D, 0x90, 0x83, 0x05, 0x12, +0x47, 0xEF, 0x12, 0x65, 0xDA, 0x90, 0x00, 0x06, +0x12, 0x1F, 0xBD, 0xFF, 0x90, 0x83, 0x05, 0x12, +0x63, 0x3F, 0x12, 0x65, 0xDA, 0x12, 0x80, 0x15, +0xFF, 0x90, 0x83, 0x05, 0x12, 0x63, 0x5A, 0x12, +0x65, 0xDA, 0x12, 0x67, 0xEB, 0xFF, 0x90, 0x83, +0x02, 0x71, 0x3F, 0xB1, 0xDA, 0xF1, 0xE4, 0xFF, +0x90, 0x83, 0x02, 0x71, 0x5A, 0x90, 0x83, 0x00, +0xE0, 0xFF, 0x90, 0x82, 0xFB, 0xE0, 0xFE, 0x24, +0x81, 0xF1, 0x3D, 0xEF, 0xF0, 0x90, 0x82, 0xFC, +0xE0, 0x54, 0x01, 0xC4, 0x33, 0x54, 0xE0, 0xFF, +0x75, 0xF0, 0x08, 0xEE, 0xF1, 0x35, 0x54, 0xDF, +0x4F, 0xF0, 0x90, 0x83, 0x01, 0xE0, 0x54, 0x01, +0xC4, 0x33, 0x33, 0x54, 0xC0, 0xFE, 0x90, 0x82, +0xFB, 0x12, 0x8A, 0x42, 0xE0, 0x54, 0xBF, 0x4E, +0xF0, 0x8F, 0x56, 0xEF, 0x75, 0xF0, 0x02, 0xA4, +0xFF, 0xAE, 0xF0, 0x24, 0x0C, 0xF9, 0x74, 0x98, +0x3E, 0xFA, 0x7B, 0x01, 0x90, 0x83, 0x09, 0x12, +0x47, 0xEF, 0x74, 0x01, 0x2F, 0xF9, 0x74, 0x92, +0x3E, 0xFA, 0x90, 0x83, 0x0C, 0x12, 0x47, 0xEF, +0xE5, 0x56, 0x12, 0x89, 0xE2, 0xFA, 0x90, 0x83, +0x0F, 0x12, 0x8A, 0x4D, 0x90, 0x83, 0x12, 0x12, +0x47, 0xEF, 0x74, 0x81, 0x25, 0x56, 0xF1, 0x3D, +0xE0, 0x12, 0x47, 0xF8, 0x60, 0xB1, 0x00, 0x60, +0xBB, 0x01, 0x60, 0xC5, 0x02, 0x60, 0xCF, 0x03, +0x60, 0xE2, 0x04, 0x60, 0xEC, 0x05, 0x60, 0xF6, +0x06, 0x61, 0x06, 0x0C, 0x61, 0x24, 0x0D, 0x61, +0x42, 0x0E, 0x61, 0x60, 0x0F, 0x00, 0x00, 0x61, +0x83, 0x71, 0x31, 0x74, 0xF0, 0xF0, 0xA3, 0x74, +0x15, 0x80, 0x1B, 0x71, 0x31, 0x74, 0xF0, 0xF0, +0xA3, 0x74, 0x10, 0x80, 0x11, 0x71, 0x31, 0x74, +0xF0, 0xF0, 0xA3, 0x74, 0x05, 0x80, 0x07, 0x71, +0x31, 0x74, 0xF0, 0xF0, 0xA3, 0xE4, 0xF0, 0x71, +0x47, 0x74, 0x0F, 0xF0, 0xA3, 0x74, 0x8F, 0xF0, +0x21, 0x83, 0x71, 0x31, 0x74, 0x0F, 0xF0, 0xA3, +0x74, 0xF5, 0x80, 0x11, 0x71, 0x31, 0x74, 0x0F, +0xF0, 0xA3, 0x74, 0xF0, 0x80, 0x07, 0x71, 0x31, +0xE4, 0xF0, 0xA3, 0x74, 0x0D, 0xF0, 0x71, 0x47, +0xE4, 0xF0, 0xA3, 0xF0, 0x80, 0x7D, 0x90, 0x04, +0x47, 0xE0, 0xFF, 0x90, 0x83, 0x0C, 0x71, 0x3F, +0x90, 0x04, 0x46, 0x71, 0x55, 0x90, 0x04, 0x45, +0xE0, 0xFF, 0x90, 0x83, 0x09, 0x71, 0x3F, 0x90, +0x04, 0x44, 0x80, 0x58, 0x90, 0x04, 0x4B, 0xE0, +0xFF, 0x90, 0x83, 0x0C, 0x71, 0x3F, 0x90, 0x04, +0x4A, 0x71, 0x55, 0x90, 0x04, 0x49, 0xE0, 0xFF, +0x90, 0x83, 0x09, 0x71, 0x3F, 0x90, 0x04, 0x48, +0x80, 0x3A, 0x90, 0x04, 0x4F, 0xE0, 0xFF, 0x90, +0x83, 0x0C, 0x71, 0x3F, 0x90, 0x04, 0x4E, 0x71, +0x55, 0x90, 0x04, 0x4D, 0xE0, 0xFF, 0x90, 0x83, +0x09, 0x71, 0x3F, 0x90, 0x04, 0x4C, 0x80, 0x1C, +0x90, 0x04, 0x53, 0xE0, 0xFF, 0x90, 0x83, 0x0C, +0x71, 0x3F, 0x90, 0x04, 0x52, 0x71, 0x55, 0x90, +0x04, 0x51, 0xE0, 0xFF, 0x90, 0x83, 0x09, 0x71, +0x3F, 0x90, 0x04, 0x50, 0xE0, 0xFF, 0x90, 0x83, +0x09, 0x71, 0x5A, 0x90, 0x83, 0x0C, 0x12, 0x47, +0xE6, 0xC0, 0x03, 0xC0, 0x02, 0xC0, 0x01, 0xF1, +0x67, 0xF1, 0x59, 0x5F, 0xD0, 0x01, 0xD0, 0x02, +0xD0, 0x03, 0x12, 0x1F, 0xEA, 0x90, 0x83, 0x0C, +0xF1, 0xC9, 0xC0, 0x03, 0xC0, 0x02, 0xC0, 0x01, +0xF1, 0x67, 0x12, 0x5D, 0x30, 0x5F, 0xD0, 0x01, +0xD0, 0x02, 0xD0, 0x03, 0x12, 0x1F, 0xEA, 0x90, +0x83, 0x09, 0x12, 0x47, 0xE6, 0xC0, 0x03, 0xC0, +0x02, 0xC0, 0x01, 0xF1, 0x5F, 0xF1, 0x59, 0x5F, +0xD0, 0x01, 0xD0, 0x02, 0xD0, 0x03, 0x12, 0x1F, +0xEA, 0x90, 0x83, 0x09, 0xF1, 0xC9, 0xC0, 0x03, +0xC0, 0x02, 0xC0, 0x01, 0xF1, 0x5F, 0x12, 0x5D, +0x30, 0x5F, 0xD0, 0x01, 0xD0, 0x02, 0xD0, 0x03, +0x12, 0x1F, 0xEA, 0x71, 0x47, 0xE0, 0xFE, 0xA3, +0xE0, 0x4E, 0x60, 0x2D, 0x90, 0x83, 0x08, 0x74, +0x0B, 0xF0, 0x71, 0x64, 0x94, 0x00, 0x40, 0x5A, +0x91, 0xA6, 0x80, 0x05, 0xC3, 0x33, 0xCE, 0x33, +0xCE, 0xD8, 0xF9, 0x71, 0x46, 0x71, 0x6B, 0x60, +0x08, 0x90, 0x83, 0x08, 0xE0, 0x24, 0x10, 0x80, +0x3D, 0x90, 0x83, 0x08, 0xE0, 0x14, 0xF0, 0x80, +0xD9, 0x71, 0x31, 0xE0, 0xFE, 0xA3, 0xE0, 0x4E, +0x60, 0x2B, 0x90, 0x83, 0x08, 0x74, 0x0F, 0xF0, +0x71, 0x64, 0x94, 0x00, 0x40, 0x24, 0x91, 0xA6, +0x80, 0x05, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, +0xF9, 0x71, 0x30, 0x71, 0x6B, 0x60, 0x06, 0x90, +0x83, 0x08, 0xE0, 0x80, 0x09, 0x90, 0x83, 0x08, +0xE0, 0x14, 0xF0, 0x80, 0xDB, 0xE4, 0x90, 0x83, +0x15, 0xF0, 0x71, 0x31, 0xE0, 0xFE, 0xA3, 0xE0, +0x4E, 0x60, 0x2A, 0xE4, 0x90, 0x83, 0x08, 0xF0, +0x71, 0x64, 0x94, 0x10, 0x50, 0x59, 0x91, 0xA6, +0x80, 0x05, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, +0xF9, 0x71, 0x30, 0x71, 0x6B, 0x60, 0x06, 0x90, +0x83, 0x08, 0xE0, 0x80, 0x3E, 0x90, 0x83, 0x08, +0xE0, 0x04, 0xF0, 0x80, 0xDB, 0x71, 0x47, 0xE0, +0xFE, 0xA3, 0xE0, 0x4E, 0x60, 0x2C, 0xE4, 0x90, +0x83, 0x08, 0xF0, 0x71, 0x64, 0x94, 0x0C, 0x50, +0x26, 0x91, 0xA6, 0x80, 0x05, 0xC3, 0x33, 0xCE, +0x33, 0xCE, 0xD8, 0xF9, 0x71, 0x46, 0x71, 0x6B, +0x60, 0x08, 0x90, 0x83, 0x08, 0xE0, 0x24, 0x10, +0x80, 0x09, 0x90, 0x83, 0x08, 0xE0, 0x04, 0xF0, +0x80, 0xD9, 0xE4, 0x90, 0x83, 0x16, 0xF0, 0x90, +0x83, 0x15, 0xE0, 0xFF, 0x75, 0xF0, 0x08, 0xE5, +0x56, 0xD1, 0x1D, 0xEF, 0xF0, 0x90, 0x83, 0x16, +0xE0, 0xFE, 0x75, 0xF0, 0x08, 0xE5, 0x56, 0xF1, +0x2F, 0xEE, 0xF0, 0x90, 0x81, 0x82, 0xE0, 0xFD, +0xE5, 0x56, 0xC3, 0x9D, 0x50, 0x28, 0x74, 0xB0, +0x25, 0x56, 0xB1, 0x99, 0xE0, 0xD3, 0x9F, 0x40, +0x02, 0x80, 0x13, 0x74, 0xB0, 0x25, 0x56, 0xB1, +0x99, 0xE0, 0xC3, 0x9E, 0x50, 0x08, 0x90, 0x83, +0x16, 0xE0, 0xA3, 0xF0, 0x80, 0x08, 0x90, 0x83, +0x15, 0xE0, 0x90, 0x83, 0x17, 0xF0, 0x90, 0x83, +0x17, 0xE0, 0xFD, 0xAF, 0x56, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x74, 0xB0, 0x2F, 0xB1, +0x99, 0xED, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0xFF, 0xE5, 0x56, 0x25, 0xE0, 0x24, 0x0C, 0xF5, +0x82, 0xE4, 0x34, 0x98, 0xF5, 0x83, 0x22, 0x12, +0x47, 0xE6, 0xEF, 0x02, 0x1F, 0xEA, 0xFF, 0xE5, +0x56, 0x25, 0xE0, 0x24, 0x01, 0xF5, 0x82, 0xE4, +0x34, 0x92, 0xF5, 0x83, 0x22, 0xE0, 0xFF, 0x90, +0x83, 0x0C, 0x12, 0x47, 0xE6, 0x90, 0x00, 0x01, +0xEF, 0x02, 0x1F, 0xFC, 0x90, 0x83, 0x08, 0xE0, +0xFF, 0xC3, 0x22, 0xE0, 0x5E, 0xFE, 0xA3, 0xE0, +0x5F, 0x4E, 0x22, 0xB1, 0x94, 0xE0, 0x54, 0x7F, +0x90, 0x83, 0x06, 0xF0, 0xE0, 0x54, 0x1F, 0xFD, +0xD1, 0x19, 0xE0, 0xFF, 0x90, 0x83, 0x07, 0xF0, +0xE9, 0x71, 0x49, 0xE0, 0xFB, 0xA3, 0xE0, 0x90, +0x83, 0x08, 0xCB, 0xF0, 0xA3, 0xEB, 0xF0, 0xE9, +0x71, 0x33, 0xE0, 0xFB, 0xA3, 0xE0, 0x90, 0x83, +0x0A, 0xCB, 0xF0, 0xA3, 0xEB, 0xF0, 0xED, 0xF1, +0x6F, 0xF5, 0x83, 0xE4, 0x93, 0xFA, 0x74, 0x01, +0x93, 0xFB, 0xB1, 0xCD, 0xEA, 0xF0, 0xA3, 0xEB, +0xF0, 0xED, 0xC3, 0x9F, 0x50, 0x75, 0xB1, 0xE0, +0xED, 0xF0, 0x04, 0xFC, 0x90, 0x83, 0x07, 0xE0, +0xFF, 0xEC, 0xD3, 0x9F, 0x40, 0x02, 0x81, 0x5F, +0xEC, 0xC3, 0x94, 0x10, 0x40, 0x14, 0xEC, 0x91, +0xA3, 0x80, 0x05, 0xC3, 0x33, 0xCE, 0x33, 0xCE, +0xD8, 0xF9, 0xFF, 0x90, 0x83, 0x08, 0x71, 0x6B, +0x70, 0x1E, 0xEC, 0xC3, 0x94, 0x10, 0x50, 0x40, +0x74, 0x01, 0x7E, 0x00, 0xA8, 0x04, 0x08, 0x80, +0x05, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, +0xFF, 0x90, 0x83, 0x0A, 0x71, 0x6B, 0x60, 0x28, +0xEC, 0xB4, 0x11, 0x09, 0x90, 0x83, 0x09, 0xE0, +0x30, 0xE7, 0x02, 0x7C, 0x17, 0xEC, 0x64, 0x13, +0x60, 0x04, 0xEC, 0xB4, 0x12, 0x09, 0x90, 0x83, +0x08, 0xE0, 0x30, 0xE0, 0x02, 0x7C, 0x18, 0xAD, +0x04, 0x90, 0x83, 0x06, 0xED, 0xF0, 0x80, 0x2F, +0x0C, 0x80, 0x91, 0x90, 0x83, 0x07, 0xE0, 0xFC, +0x6D, 0x70, 0x2E, 0xB1, 0xE0, 0xED, 0xF0, 0x75, +0xF0, 0x08, 0xE9, 0xF1, 0x35, 0xC4, 0x13, 0x54, +0x07, 0x30, 0xE0, 0x0D, 0x90, 0x83, 0x06, 0xE0, +0x20, 0xE6, 0x06, 0xED, 0x44, 0x40, 0xF0, 0x80, +0x06, 0x90, 0x83, 0x06, 0xE0, 0xFF, 0x22, 0xED, +0xB1, 0xA1, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x80, +0x20, 0xED, 0xD3, 0x9C, 0x40, 0x1B, 0x90, 0x83, +0x07, 0xE0, 0xFF, 0xB1, 0xE0, 0xEF, 0xF0, 0xAD, +0x07, 0x90, 0x83, 0x06, 0xEF, 0xF0, 0xFC, 0xB1, +0xA1, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xAF, 0x04, +0x22, 0x74, 0x01, 0x29, 0xF1, 0x7C, 0xE4, 0xF0, +0xAF, 0x01, 0x90, 0x83, 0x06, 0xE0, 0x44, 0x80, +0xFD, 0x71, 0x1D, 0x90, 0x83, 0x06, 0xE0, 0x44, +0x80, 0xFF, 0x22, 0x24, 0xF0, 0xFF, 0x74, 0x01, +0x7E, 0x00, 0xA8, 0x07, 0x08, 0x22, 0xB1, 0x94, +0xE0, 0x54, 0x7F, 0xFC, 0x54, 0x1F, 0xFF, 0x75, +0xF0, 0x08, 0xE9, 0xF1, 0x2F, 0xE0, 0x90, 0x83, +0x08, 0xF0, 0xD1, 0x19, 0xE0, 0xFE, 0xE9, 0x71, +0x33, 0xE0, 0xFB, 0xA3, 0xE0, 0x90, 0x83, 0x09, +0xCB, 0xF0, 0xA3, 0xEB, 0xF0, 0xE9, 0x71, 0x49, +0xE0, 0xFB, 0xA3, 0xE0, 0x90, 0x83, 0x0B, 0xCB, +0xF0, 0xA3, 0xEB, 0xF0, 0xEF, 0xD3, 0x9E, 0x40, +0x04, 0xAF, 0x06, 0xAC, 0x06, 0xED, 0x70, 0x02, +0xA1, 0x81, 0x90, 0x83, 0x07, 0xED, 0xF0, 0xEC, +0x30, 0xE6, 0x05, 0xAC, 0x07, 0xE0, 0x14, 0xF0, +0x90, 0x83, 0x07, 0xE0, 0x60, 0x7B, 0xEF, 0xD3, +0x94, 0x00, 0x40, 0x75, 0xE4, 0x90, 0x83, 0x06, +0xF0, 0xEF, 0x14, 0xFD, 0x90, 0x83, 0x08, 0xE0, +0xFF, 0xED, 0xD3, 0x9F, 0x40, 0x4C, 0xED, 0x94, +0x10, 0x40, 0x14, 0xED, 0x91, 0xA3, 0x80, 0x05, +0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, +0x90, 0x83, 0x0B, 0x71, 0x6B, 0x70, 0x1E, 0xED, +0xC3, 0x94, 0x10, 0x50, 0x2A, 0x74, 0x01, 0x7E, +0x00, 0xA8, 0x05, 0x08, 0x80, 0x05, 0xC3, 0x33, +0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, 0x90, 0x83, +0x09, 0x71, 0x6B, 0x60, 0x12, 0xAC, 0x05, 0x90, +0x83, 0x06, 0xE0, 0x04, 0xF0, 0xA3, 0xE0, 0xFF, +0x90, 0x83, 0x06, 0xE0, 0x6F, 0x60, 0x03, 0x1D, +0x80, 0xAA, 0x90, 0x83, 0x07, 0xE0, 0xFF, 0x90, +0x83, 0x06, 0xE0, 0xC3, 0x9F, 0x50, 0x0A, 0x90, +0x83, 0x08, 0xE0, 0xFF, 0xB5, 0x05, 0x02, 0xAC, +0x07, 0xF1, 0x45, 0xEC, 0xB1, 0xB4, 0xEE, 0xF0, +0xA3, 0xEF, 0xF0, 0xAF, 0x01, 0xAD, 0x04, 0x71, +0x1D, 0xAF, 0x04, 0x22, 0xA9, 0x07, 0x74, 0xB0, +0x29, 0xF5, 0x82, 0xE4, 0x34, 0x02, 0xF5, 0x83, +0x22, 0x25, 0xE0, 0x24, 0xD6, 0xF5, 0x82, 0xE4, +0x34, 0x41, 0xF5, 0x83, 0xE4, 0x93, 0xFE, 0x74, +0x01, 0x93, 0xFF, 0xED, 0x25, 0xE0, 0x24, 0x9E, +0xF5, 0x82, 0xE4, 0x34, 0x41, 0xF5, 0x83, 0x74, +0x01, 0x93, 0x2F, 0xFF, 0xE4, 0x93, 0x3E, 0xC3, +0x13, 0xFE, 0xEF, 0x13, 0xFF, 0xE9, 0x25, 0xE0, +0x24, 0xC1, 0xF5, 0x82, 0xE4, 0x34, 0x92, 0xF5, +0x83, 0x22, 0x90, 0x82, 0xFD, 0x02, 0x47, 0xE6, +0x74, 0xCD, 0x29, 0xF5, 0x82, 0xE4, 0x34, 0x98, +0xF5, 0x83, 0x22, 0xAD, 0x07, 0x75, 0xF0, 0x08, +0xED, 0xD1, 0x1D, 0xE0, 0xFF, 0x74, 0xCD, 0x2D, +0xB1, 0xE3, 0xE0, 0x54, 0x1F, 0xFC, 0xD3, 0x9F, +0x40, 0x02, 0xAC, 0x07, 0xF1, 0x45, 0xEC, 0xF1, +0x6F, 0xF5, 0x83, 0xF1, 0xD4, 0xED, 0xB1, 0xCE, +0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xAF, 0x05, 0xA1, +0x8D, 0x75, 0xF0, 0x08, 0xE9, 0x90, 0x93, 0x43, +0x02, 0x47, 0xDA, 0x90, 0x04, 0x44, 0x74, 0x11, +0xF0, 0xA3, 0x74, 0xF0, 0xF0, 0xA3, 0x74, 0x0F, +0xF0, 0xA3, 0xE4, 0xF0, 0x90, 0x82, 0x88, 0xF0, +0x90, 0x81, 0x82, 0xE0, 0xFF, 0x90, 0x82, 0x88, +0xE0, 0xC3, 0x9F, 0x40, 0x02, 0xC1, 0xFF, 0xE0, +0xFF, 0x75, 0xF0, 0x0A, 0x90, 0x8D, 0x00, 0xF1, +0x00, 0x90, 0x8D, 0x02, 0xF1, 0x00, 0x90, 0x8D, +0x04, 0xF1, 0x00, 0x90, 0x8D, 0x06, 0xF1, 0x00, +0x90, 0x8D, 0x08, 0x12, 0x47, 0xDA, 0xE4, 0xF0, +0xA3, 0xF0, 0xEF, 0xF1, 0x0C, 0x24, 0x4B, 0xF5, +0x82, 0xE4, 0x34, 0x96, 0xF1, 0x25, 0x12, 0x8A, +0x22, 0xF1, 0x25, 0x24, 0x0C, 0xF5, 0x82, 0xE4, +0x34, 0x97, 0xF1, 0x25, 0x24, 0x8C, 0xF5, 0x82, +0xE4, 0x34, 0x97, 0xF5, 0x83, 0xE4, 0xF0, 0xA3, +0xF0, 0x74, 0x8C, 0x2F, 0x12, 0x8A, 0xB6, 0xE4, +0xF0, 0x90, 0x41, 0xFC, 0xF1, 0x52, 0x90, 0x41, +0xC4, 0xF1, 0xD4, 0x90, 0x82, 0x88, 0xE0, 0xFD, +0xB1, 0xCE, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x75, +0xF0, 0x08, 0xED, 0xF1, 0x35, 0x44, 0x20, 0xF0, +0x74, 0x81, 0x2D, 0xF1, 0x3D, 0x74, 0x0C, 0xF0, +0x75, 0xF0, 0x08, 0xED, 0x90, 0x93, 0x49, 0x12, +0x47, 0xDA, 0x74, 0xFF, 0xF0, 0xA3, 0xF0, 0x75, +0xF0, 0x08, 0xED, 0x90, 0x93, 0x47, 0x12, 0x47, +0xDA, 0xE4, 0xF0, 0xA3, 0x74, 0x0F, 0xF0, 0x75, +0xF0, 0x08, 0xED, 0xD1, 0x1D, 0x74, 0x13, 0xF0, +0x75, 0xF0, 0x08, 0xED, 0xF1, 0x2F, 0xE4, 0xF0, +0x74, 0xB0, 0x2D, 0xB1, 0x99, 0xE4, 0xF0, 0x90, +0x82, 0x88, 0xE0, 0x04, 0xF0, 0xC1, 0x38, 0x22, +0x12, 0x47, 0xDA, 0xE4, 0xF0, 0xA3, 0xF0, 0x75, +0xF0, 0x0A, 0xEF, 0x22, 0x25, 0xE0, 0x24, 0x80, +0xF5, 0x82, 0xE4, 0x34, 0x90, 0xF5, 0x83, 0xE4, +0xF0, 0xA3, 0xF0, 0xEF, 0x25, 0xE0, 0x24, 0x4B, +0xF5, 0x82, 0xE4, 0x34, 0x95, 0xF5, 0x83, 0xE4, +0xF0, 0xA3, 0xF0, 0xEF, 0x25, 0xE0, 0x22, 0x90, +0x93, 0x44, 0x02, 0x47, 0xDA, 0x90, 0x93, 0x45, +0x12, 0x47, 0xDA, 0xE0, 0x22, 0xF5, 0x82, 0xE4, +0x34, 0x92, 0xF5, 0x83, 0x22, 0xEC, 0x25, 0xE0, +0x24, 0xD6, 0xF5, 0x82, 0xE4, 0x34, 0x41, 0xF5, +0x83, 0xE4, 0x93, 0xFE, 0x74, 0x01, 0x93, 0xFF, +0x22, 0x12, 0x47, 0xE6, 0x02, 0x1F, 0xA4, 0x12, +0x1F, 0xA4, 0xFF, 0x90, 0x83, 0x0F, 0x22, 0x12, +0x1F, 0xA4, 0xFF, 0x90, 0x83, 0x12, 0x22, 0x25, +0xE0, 0x24, 0x9E, 0xF5, 0x82, 0xE4, 0x34, 0x41, +0x22, 0x74, 0x01, 0x2A, 0xF5, 0x82, 0xE4, 0x34, +0x91, 0xF5, 0x83, 0x22, 0xAA, 0x07, 0xED, 0x54, +0x1F, 0x90, 0x82, 0x82, 0xF0, 0xF1, 0x79, 0xE0, +0x90, 0x82, 0x80, 0xF0, 0x90, 0x82, 0x83, 0x74, +0x01, 0xF0, 0xEB, 0xC3, 0x94, 0x01, 0x40, 0x02, +0xA1, 0xEB, 0x90, 0x82, 0x80, 0xE0, 0x25, 0x51, +0xFF, 0xA3, 0xF0, 0xA3, 0xE0, 0x90, 0x42, 0x0E, +0x93, 0xFE, 0xEF, 0xD3, 0x9E, 0x40, 0x08, 0xF1, +0x79, 0xE4, 0xF0, 0xAF, 0x02, 0x61, 0x1D, 0x90, +0x82, 0x81, 0xE0, 0xFF, 0xF1, 0x79, 0xEF, 0xF0, +0x22, 0x12, 0x47, 0xE6, 0xE9, 0x24, 0x01, 0xF9, +0xE4, 0x3A, 0xFA, 0x22, 0x74, 0x01, 0x93, 0x2F, +0xFF, 0xE4, 0x93, 0x3E, 0xC3, 0x13, 0xFE, 0xEF, +0x13, 0xFF, 0x22, 0xF0, 0x90, 0x00, 0x03, 0x02, +0x1F, 0xBD, 0xF0, 0x90, 0x00, 0x04, 0x02, 0x1F, +0xBD, 0x90, 0x00, 0xF7, 0xE0, 0x20, 0xE7, 0x09, +0xE0, 0x7F, 0x01, 0x20, 0xE6, 0x0C, 0x7F, 0x02, +0x22, 0x90, 0x00, 0xF7, 0xE0, 0x30, 0xE6, 0x02, +0x7F, 0x03, 0x22, 0x12, 0x67, 0xF1, 0x90, 0x80, +0x42, 0xEF, 0xF0, 0x11, 0x2C, 0x90, 0x01, 0x64, +0x74, 0x01, 0xF0, 0x90, 0x00, 0x12, 0xE0, 0x54, +0xC7, 0x44, 0x20, 0xFD, 0x7F, 0x12, 0x12, 0x32, +0x1E, 0x02, 0x2D, 0xA7, 0x90, 0x00, 0x08, 0xE0, +0x54, 0xEF, 0xF0, 0x11, 0x65, 0x11, 0x95, 0x12, +0x83, 0x65, 0x12, 0x83, 0x84, 0xE4, 0xF5, 0x35, +0xF5, 0x37, 0xF5, 0x36, 0xF5, 0x37, 0x75, 0x38, +0x80, 0xAD, 0x35, 0x7F, 0x50, 0x12, 0x32, 0x1E, +0xAD, 0x36, 0x7F, 0x51, 0x12, 0x32, 0x1E, 0xAD, +0x37, 0x7F, 0x52, 0x12, 0x32, 0x1E, 0xAD, 0x38, +0x7F, 0x53, 0x02, 0x32, 0x1E, 0x90, 0x01, 0x30, +0xE4, 0x11, 0x8E, 0xF0, 0x90, 0x01, 0x38, 0x11, +0x8E, 0xF0, 0xFD, 0x7F, 0x50, 0x12, 0x32, 0x1E, +0xE4, 0xFD, 0x7F, 0x51, 0x12, 0x32, 0x1E, 0xE4, +0xFD, 0x7F, 0x52, 0x12, 0x32, 0x1E, 0xE4, 0xFD, +0x7F, 0x53, 0x02, 0x32, 0x1E, 0xA3, 0xF0, 0xA3, +0xF0, 0xA3, 0xF0, 0xA3, 0x22, 0x90, 0x01, 0x34, +0x74, 0xFF, 0x11, 0x8E, 0xF0, 0x90, 0x01, 0x3C, +0x11, 0x8E, 0xF0, 0xFD, 0x7F, 0x54, 0x12, 0x32, +0x1E, 0x7D, 0xFF, 0x7F, 0x55, 0x12, 0x32, 0x1E, +0x7D, 0xFF, 0x7F, 0x56, 0x12, 0x32, 0x1E, 0x7D, +0xFF, 0x7F, 0x57, 0x02, 0x32, 0x1E, 0xE4, 0x90, +0x80, 0x3C, 0xF0, 0x11, 0x8D, 0xF0, 0x22, 0x90, +0x00, 0x80, 0xE0, 0x44, 0x80, 0xFD, 0x7F, 0x80, +0x12, 0x32, 0x1E, 0x90, 0xFD, 0x00, 0xE0, 0x54, +0xBF, 0xF0, 0x12, 0x58, 0x2C, 0x12, 0x83, 0xA6, +0x12, 0x32, 0x77, 0x12, 0x83, 0xB3, 0x11, 0xBE, +0x7F, 0x01, 0x12, 0x44, 0x15, 0x90, 0x82, 0x72, +0x74, 0x02, 0xF0, 0xFF, 0x12, 0x44, 0x15, 0x90, +0x82, 0x72, 0xE0, 0x04, 0xF0, 0x11, 0x0B, 0x31, +0x23, 0x90, 0x01, 0xCC, 0x74, 0x0F, 0xF0, 0x90, +0x00, 0x80, 0xE0, 0x44, 0x40, 0xFD, 0x7F, 0x80, +0x12, 0x32, 0x1E, 0x75, 0x20, 0xFF, 0xF1, 0xE9, +0x12, 0x83, 0xE3, 0x12, 0x84, 0x69, 0xE4, 0xFF, +0x02, 0x44, 0x9E, 0x31, 0x39, 0x12, 0x82, 0xF7, +0x12, 0x66, 0x23, 0x31, 0xD9, 0x12, 0x54, 0x88, +0x12, 0x88, 0xAC, 0x12, 0x8A, 0x08, 0x02, 0x48, +0x1E, 0xE4, 0xFD, 0xFF, 0x51, 0x9D, 0xED, 0x70, +0x12, 0x31, 0x77, 0xC0, 0x83, 0xC0, 0x82, 0x31, +0x6F, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xF4, +0x5E, 0x80, 0x0F, 0x31, 0x77, 0xC0, 0x83, 0xC0, +0x82, 0x31, 0x6F, 0x80, 0x02, 0xC3, 0x33, 0xD8, +0xFC, 0x4E, 0xD0, 0x82, 0xD0, 0x83, 0xF0, 0x31, +0x82, 0x90, 0x81, 0x82, 0xEF, 0xF0, 0x22, 0xE0, +0xFE, 0x74, 0x01, 0xA8, 0x07, 0x08, 0x22, 0x74, +0x7A, 0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, +0x83, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x7D, 0x08, 0xED, 0x14, 0xF9, 0x24, 0x7A, +0x31, 0x7A, 0xE0, 0x60, 0x3B, 0x7C, 0x08, 0xEC, +0x14, 0x90, 0x83, 0x6D, 0xF0, 0x74, 0x7A, 0x29, +0x31, 0x7A, 0xE0, 0xFB, 0x7A, 0x00, 0x90, 0x83, +0x6D, 0xE0, 0x12, 0x64, 0xA5, 0x80, 0x05, 0xC3, +0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, 0xEE, +0x5A, 0xFE, 0xEF, 0x5B, 0x4E, 0x60, 0x0F, 0xE9, +0x75, 0xF0, 0x08, 0xA4, 0xFF, 0x90, 0x83, 0x6D, +0xE0, 0x2F, 0x04, 0xFF, 0x80, 0x06, 0xDC, 0xC7, +0xDD, 0xB9, 0x7F, 0x00, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x7E, 0x00, 0x7F, 0x01, 0x7D, 0x00, 0x7B, +0x01, 0x7A, 0x81, 0x79, 0x83, 0x12, 0x48, 0x1E, +0x90, 0x81, 0x83, 0xE0, 0x54, 0xFD, 0xF0, 0xE4, +0x11, 0x8D, 0x74, 0x0C, 0xF0, 0x22, 0x51, 0x9D, +0x31, 0x77, 0xE0, 0xFD, 0x7C, 0x00, 0x12, 0x64, +0xA6, 0x80, 0x05, 0xC3, 0x33, 0xCE, 0x33, 0xCE, +0xD8, 0xF9, 0xFF, 0xEE, 0x5C, 0xFE, 0xEF, 0x5D, +0x4E, 0x7F, 0x00, 0x60, 0x02, 0x7F, 0x01, 0x22, +0x8B, 0x56, 0x8A, 0x57, 0x89, 0x58, 0x12, 0x5D, +0x33, 0xFF, 0xF5, 0x5A, 0x12, 0x1F, 0xA4, 0xFE, +0xC3, 0x13, 0x30, 0xE0, 0x06, 0x51, 0x77, 0xF5, +0x5B, 0x80, 0x02, 0x8F, 0x5B, 0x85, 0x5A, 0x59, +0xE5, 0x59, 0xD3, 0x95, 0x5B, 0x50, 0x1D, 0x12, +0x8A, 0x7C, 0x54, 0x01, 0xFD, 0xAF, 0x59, 0x31, +0x3C, 0xAF, 0x59, 0x31, 0xF6, 0xEF, 0xAF, 0x59, +0x70, 0x04, 0xF1, 0xE0, 0x80, 0x02, 0xF1, 0xDF, +0x05, 0x59, 0x80, 0xDC, 0xE5, 0x5A, 0x70, 0x15, +0xFF, 0x31, 0xF6, 0xEF, 0x70, 0x0F, 0x12, 0x55, +0x60, 0x12, 0x55, 0x4A, 0x12, 0x82, 0x91, 0x54, +0xBF, 0xF0, 0x54, 0x7F, 0xF0, 0x22, 0xF0, 0x90, +0x00, 0x02, 0x02, 0x1F, 0xBD, 0x12, 0x1F, 0xA4, +0xFF, 0xC3, 0x94, 0x40, 0x50, 0x0C, 0x51, 0x77, +0xFE, 0x74, 0xCB, 0x2F, 0x12, 0x8A, 0xAE, 0xEE, +0xF0, 0x22, 0xEF, 0xB4, 0x40, 0x06, 0x51, 0x77, +0x90, 0x93, 0x41, 0xF0, 0x22, 0xEF, 0x13, 0x13, +0x13, 0x54, 0x1F, 0xFE, 0xEF, 0x54, 0x07, 0xFF, +0x22, 0x51, 0xC0, 0x70, 0x12, 0x90, 0x81, 0x8D, +0xE0, 0x60, 0x0C, 0x90, 0x81, 0x91, 0xE0, 0x20, +0xE4, 0x05, 0x91, 0x63, 0x12, 0x51, 0x00, 0x22, +0xE4, 0xFF, 0x31, 0xF6, 0xEF, 0x64, 0x01, 0x22, +0x51, 0xC0, 0x70, 0x1C, 0x90, 0x81, 0x8D, 0xE0, +0x60, 0x16, 0x90, 0x81, 0x91, 0xE0, 0x20, 0xE4, +0x0F, 0x91, 0x63, 0xF0, 0x90, 0x81, 0x88, 0xE0, +0xB1, 0x96, 0x54, 0x07, 0x70, 0x02, 0x71, 0xFB, +0x22, 0xE4, 0xF5, 0x4E, 0x90, 0x81, 0x8D, 0xE0, +0x60, 0x45, 0x51, 0xC0, 0x70, 0x41, 0x12, 0x89, +0x56, 0x90, 0x81, 0x8B, 0xE0, 0xFF, 0xC4, 0x54, +0x0F, 0x60, 0x09, 0x90, 0x81, 0x89, 0x12, 0x80, +0xE6, 0x20, 0xE0, 0x03, 0x75, 0x4E, 0x01, 0x90, +0x81, 0x83, 0xE0, 0x30, 0xE0, 0x11, 0x90, 0x81, +0x87, 0xE0, 0xB4, 0x02, 0x03, 0xE4, 0xF5, 0x4E, +0x71, 0x88, 0xEF, 0x70, 0x02, 0xF5, 0x4E, 0xE5, +0x4E, 0x60, 0x0C, 0x12, 0x89, 0x96, 0x20, 0xE2, +0x03, 0x12, 0x52, 0x50, 0x12, 0x51, 0x76, 0x22, +0xE4, 0x90, 0x82, 0x84, 0xF0, 0x90, 0x81, 0x8D, +0xE0, 0x60, 0x44, 0x51, 0xC0, 0x70, 0x40, 0x12, +0x8A, 0xA6, 0xF0, 0x12, 0x89, 0x56, 0x90, 0x82, +0x84, 0x74, 0x01, 0xF0, 0xE4, 0x90, 0x81, 0x94, +0xF0, 0x90, 0x81, 0x83, 0xE0, 0x30, 0xE0, 0x15, +0x90, 0x81, 0x87, 0xE0, 0xB4, 0x02, 0x05, 0xE4, +0x90, 0x82, 0x84, 0xF0, 0x71, 0x88, 0xEF, 0x70, +0x04, 0x90, 0x82, 0x84, 0xF0, 0x90, 0x82, 0x84, +0xE0, 0x60, 0x0C, 0x12, 0x89, 0x96, 0x20, 0xE2, +0x03, 0x12, 0x52, 0x50, 0x12, 0x51, 0x76, 0x22, +0x90, 0x05, 0x43, 0xE0, 0x7F, 0x00, 0x30, 0xE7, +0x02, 0x7F, 0x01, 0x22, 0x90, 0x81, 0x89, 0xE0, +0xFF, 0x13, 0x13, 0x13, 0x54, 0x1F, 0x30, 0xE0, +0x10, 0xEF, 0xC4, 0x13, 0x13, 0x54, 0x03, 0x30, +0xE0, 0x07, 0x7D, 0x02, 0x7F, 0x02, 0x12, 0x4D, +0xD2, 0x90, 0x81, 0x88, 0xB1, 0x83, 0x30, 0xE0, +0x08, 0xB1, 0x95, 0x54, 0x07, 0x70, 0x33, 0x80, +0x2F, 0x12, 0x85, 0xAA, 0x40, 0x2A, 0x51, 0xC0, +0x70, 0x28, 0x12, 0x85, 0x74, 0xF1, 0x14, 0x70, +0x02, 0x80, 0x20, 0x90, 0x81, 0x97, 0xE0, 0x04, +0xF0, 0xE0, 0xD3, 0x94, 0x02, 0x40, 0x09, 0x71, +0xF3, 0xE4, 0x90, 0x81, 0x97, 0xF0, 0x80, 0x02, +0xF1, 0x86, 0xE4, 0x90, 0x81, 0x96, 0xF0, 0x22, +0x71, 0xFB, 0x22, 0x90, 0x81, 0x89, 0xE0, 0x54, +0xFB, 0xF0, 0x22, 0x90, 0x81, 0x83, 0xE0, 0x90, +0x81, 0x8F, 0x30, 0xE0, 0x04, 0xE0, 0xFF, 0x80, +0x1E, 0xE0, 0xFF, 0x7D, 0x01, 0x02, 0x52, 0x54, +0xE4, 0xFF, 0x31, 0xF6, 0xBF, 0x01, 0x0F, 0x90, +0x81, 0x8D, 0xE0, 0x60, 0x09, 0xF1, 0x06, 0xF0, +0x54, 0x07, 0x70, 0x02, 0x71, 0xFB, 0x22, 0xAE, +0x07, 0x71, 0x88, 0xBF, 0x01, 0x10, 0x12, 0x89, +0xFE, 0x20, 0xE0, 0x0A, 0xAF, 0x06, 0x7D, 0x01, +0x12, 0x52, 0x54, 0x7F, 0x01, 0x22, 0x7F, 0x00, +0x22, 0x90, 0x01, 0x57, 0xE0, 0x60, 0x1B, 0x91, +0x66, 0xF0, 0x90, 0x81, 0x88, 0xB1, 0x83, 0x30, +0xE0, 0x02, 0xA1, 0x95, 0x12, 0x85, 0xAA, 0x40, +0x09, 0xE4, 0xFF, 0x31, 0xF6, 0xBF, 0x01, 0x02, +0x71, 0xF3, 0x22, 0x90, 0x01, 0x57, 0xE4, 0xF0, +0x90, 0x01, 0x3C, 0x74, 0x02, 0x22, 0x51, 0xC0, +0x60, 0x02, 0xA1, 0x64, 0x90, 0x81, 0x8D, 0xE0, +0x70, 0x02, 0xA1, 0x64, 0x90, 0x81, 0x83, 0xE0, +0x20, 0xE0, 0x05, 0x90, 0x06, 0xA9, 0xE0, 0xFF, +0x90, 0x05, 0x63, 0xE0, 0x90, 0x82, 0x51, 0xF0, +0x90, 0x05, 0x62, 0xE0, 0x90, 0x82, 0x52, 0xF0, +0x90, 0x05, 0x61, 0xE0, 0x90, 0x82, 0x53, 0xF0, +0x90, 0x05, 0x60, 0xE0, 0x90, 0x82, 0x54, 0xF0, +0x91, 0x63, 0xF0, 0x90, 0x81, 0x91, 0xE0, 0x54, +0xED, 0xF0, 0x90, 0x81, 0x83, 0xE0, 0x30, 0xE0, +0x04, 0xF1, 0x1B, 0x80, 0x02, 0xD1, 0xC4, 0x90, +0x81, 0x8B, 0xE0, 0xFF, 0xC4, 0x54, 0x0F, 0x64, +0x01, 0x70, 0x27, 0x90, 0x06, 0xAB, 0xE0, 0x90, +0x81, 0x94, 0xF0, 0x90, 0x06, 0xAA, 0xE0, 0x60, +0x05, 0xE0, 0x90, 0x81, 0x93, 0xF0, 0x90, 0x81, +0x94, 0xE0, 0xFF, 0x70, 0x08, 0x90, 0x81, 0x93, +0xE0, 0xFE, 0xFF, 0x80, 0x00, 0x90, 0x81, 0x94, +0xEF, 0xF0, 0x12, 0x59, 0x35, 0xE4, 0x90, 0x81, +0x96, 0xF0, 0xA3, 0x12, 0x89, 0xAC, 0x90, 0x81, +0x89, 0xE0, 0xFF, 0x13, 0x13, 0x13, 0x54, 0x1F, +0x30, 0xE0, 0x56, 0xEF, 0xC4, 0x13, 0x13, 0x54, +0x03, 0x20, 0xE0, 0x25, 0xB1, 0x78, 0x6F, 0x70, +0x48, 0x90, 0x81, 0x89, 0xE0, 0x44, 0x40, 0xF0, +0x12, 0x8A, 0xA6, 0xB1, 0x8A, 0xD1, 0x42, 0x12, +0x4D, 0xCE, 0x7D, 0x02, 0x7F, 0x02, 0x12, 0x4D, +0xD2, 0x90, 0x81, 0x94, 0xE0, 0x14, 0xF0, 0x80, +0x28, 0x90, 0x81, 0x8B, 0xE0, 0xC4, 0x54, 0x0F, +0x64, 0x01, 0x70, 0x1D, 0xB1, 0x78, 0xFE, 0x6F, +0x60, 0x17, 0x90, 0x05, 0x73, 0xE0, 0xFF, 0xEE, +0x6F, 0x60, 0x0E, 0xB1, 0x80, 0x30, 0xE0, 0x09, +0xEF, 0x54, 0xBF, 0xB1, 0x8A, 0xD1, 0x2A, 0xB1, +0xA1, 0xB1, 0x71, 0xF0, 0x90, 0x81, 0x83, 0xE0, +0xC3, 0x13, 0x20, 0xE0, 0x03, 0xB1, 0x71, 0xF0, +0x22, 0x90, 0x81, 0x89, 0xE0, 0x44, 0x04, 0x22, +0x90, 0x81, 0x93, 0xE0, 0xFF, 0xA3, 0xE0, 0x22, +0x90, 0x81, 0x89, 0xE0, 0xFF, 0x13, 0x13, 0x54, +0x3F, 0x22, 0xF0, 0x90, 0x01, 0x3F, 0x74, 0x10, +0xF0, 0xFD, 0x7F, 0x03, 0x22, 0xEF, 0x54, 0xFB, +0xF0, 0x90, 0x81, 0x91, 0xE0, 0x54, 0xFD, 0xF0, +0x22, 0x7D, 0x01, 0x7F, 0x02, 0xB1, 0xAB, 0x7D, +0x02, 0x7F, 0x02, 0x74, 0x3D, 0x2F, 0xF8, 0xE6, +0x4D, 0xFE, 0xF6, 0x74, 0x30, 0x80, 0x7C, 0x71, +0x38, 0xB1, 0xA7, 0x7F, 0x01, 0x12, 0x7A, 0x38, +0x90, 0x82, 0x6E, 0xE0, 0x30, 0xE0, 0x15, 0xF1, +0xE1, 0xF0, 0x90, 0x82, 0x71, 0xE0, 0x60, 0x05, +0x14, 0xF0, 0x02, 0x56, 0x30, 0x12, 0x8A, 0x72, +0xE4, 0xFF, 0xB1, 0xDD, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x01, 0x3F, 0x74, +0x10, 0xF0, 0xEF, 0x64, 0x01, 0x70, 0x1B, 0x90, +0x82, 0x70, 0xE0, 0x7D, 0x10, 0x7F, 0x03, 0x60, +0x07, 0xD1, 0x42, 0xF1, 0xE1, 0xF0, 0x80, 0x05, +0xD1, 0x2A, 0x12, 0x4D, 0xC8, 0x12, 0x56, 0x30, +0x80, 0x1B, 0x90, 0x82, 0x70, 0xE0, 0x7D, 0x10, +0x7F, 0x03, 0x60, 0x04, 0xD1, 0x42, 0x80, 0x02, +0xD1, 0x2A, 0xB1, 0xA7, 0x7D, 0x01, 0x7F, 0x02, +0xB1, 0xAB, 0x12, 0x55, 0x55, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0x74, 0x45, 0x12, 0x8A, 0xBE, 0xFE, +0xF6, 0x74, 0x38, 0x2F, 0xF5, 0x82, 0xE4, 0x34, +0x01, 0xF5, 0x83, 0xEE, 0xF0, 0x22, 0x7D, 0x03, +0x7F, 0x02, 0x74, 0x45, 0x2F, 0xF8, 0xE6, 0x4D, +0x80, 0xE5, 0x90, 0x81, 0x88, 0xE0, 0x54, 0xFB, +0xF0, 0xE4, 0x90, 0x81, 0x96, 0xF0, 0xA3, 0xF0, +0x90, 0x81, 0x91, 0xF0, 0x90, 0x81, 0x89, 0xE0, +0x54, 0xF7, 0xF0, 0x54, 0xBF, 0xF0, 0xB1, 0xA1, +0x7D, 0x10, 0x7F, 0x03, 0x80, 0xBC, 0x12, 0x1F, +0xA4, 0xFF, 0x54, 0x01, 0xFE, 0x90, 0x82, 0x6E, +0x12, 0x89, 0xF0, 0x4F, 0xF0, 0x12, 0x5D, 0x33, +0x90, 0x82, 0x6F, 0x51, 0x76, 0x90, 0x82, 0x70, +0xF0, 0x12, 0x8A, 0x72, 0x90, 0x82, 0x6E, 0xE0, +0x54, 0x01, 0xFF, 0xA1, 0xDD, 0x90, 0x82, 0xFE, +0x12, 0x47, 0xEF, 0xD1, 0x4A, 0x90, 0x81, 0x8D, +0xE0, 0xFF, 0x12, 0x4F, 0x7D, 0x90, 0x81, 0x8D, +0xE0, 0x60, 0x18, 0x90, 0x82, 0xFE, 0x12, 0x5D, +0x30, 0x54, 0x0F, 0xFF, 0x51, 0x77, 0xFD, 0x12, +0x87, 0xE9, 0x12, 0x85, 0x63, 0x74, 0x01, 0xF0, +0x12, 0x5B, 0x02, 0x22, 0x90, 0x06, 0xA9, 0xE0, +0xF5, 0x4E, 0x54, 0xC0, 0x70, 0x08, 0xF1, 0x06, +0xF0, 0x54, 0xFD, 0xF0, 0x61, 0xFB, 0xE5, 0x4E, +0x30, 0xE6, 0x16, 0x90, 0x81, 0x8D, 0xE0, 0x64, +0x01, 0x70, 0x11, 0xF1, 0x0D, 0x64, 0x02, 0x60, +0x04, 0xF1, 0xB3, 0x80, 0x07, 0xF1, 0x86, 0x80, +0x03, 0xF1, 0x06, 0xF0, 0xE5, 0x4E, 0x90, 0x81, +0x91, 0x30, 0xE7, 0x05, 0x12, 0x50, 0xFD, 0xE1, +0xD7, 0xE0, 0x54, 0xFD, 0xF0, 0x22, 0x90, 0x81, +0x91, 0xE0, 0x54, 0xFE, 0x22, 0x90, 0x81, 0x91, +0xE0, 0x44, 0x01, 0xF0, 0x90, 0x81, 0x8B, 0xE0, +0x54, 0x0F, 0x22, 0x90, 0x06, 0xA9, 0xE0, 0x90, +0x82, 0x76, 0xF0, 0xE0, 0xFD, 0x54, 0xC0, 0x70, +0x05, 0xF1, 0x06, 0xF0, 0x80, 0x54, 0xED, 0x30, +0xE6, 0x3D, 0x90, 0x81, 0x8D, 0xE0, 0x64, 0x02, +0x70, 0x27, 0x90, 0x81, 0x88, 0xE0, 0xFF, 0xC3, +0x13, 0x20, 0xE0, 0x09, 0x90, 0x81, 0x91, 0xE0, +0x44, 0x01, 0xF0, 0x80, 0x1A, 0xF1, 0x14, 0x64, +0x01, 0x70, 0x1F, 0x90, 0x81, 0x91, 0xE0, 0x44, +0x04, 0xF0, 0x7F, 0x01, 0x12, 0x57, 0x50, 0x80, +0x11, 0xF1, 0x0D, 0x64, 0x02, 0x60, 0x04, 0xF1, +0xB3, 0x80, 0x07, 0xF1, 0x86, 0x80, 0x03, 0xF1, +0x06, 0xF0, 0x90, 0x82, 0x76, 0xE0, 0x90, 0x81, +0x91, 0x30, 0xE7, 0x05, 0x12, 0x50, 0xFD, 0x80, +0x56, 0xE0, 0x54, 0xFD, 0xF0, 0x22, 0x12, 0x82, +0x46, 0x90, 0x81, 0x90, 0xE0, 0x64, 0x0C, 0x60, +0x09, 0x12, 0x81, 0x5E, 0x12, 0x54, 0x6D, 0x12, +0x56, 0x3F, 0x22, 0xE4, 0xFF, 0x31, 0xF6, 0xBF, +0x01, 0x10, 0x90, 0x81, 0x8D, 0xE0, 0x60, 0x0A, +0xF1, 0x14, 0x64, 0x02, 0x60, 0x02, 0x80, 0x03, +0xF1, 0x86, 0x22, 0x90, 0x04, 0x1D, 0xE0, 0x70, +0x1D, 0x90, 0x80, 0x87, 0xE0, 0xFF, 0x90, 0x83, +0x58, 0x74, 0x09, 0xF0, 0x7B, 0x18, 0xE4, 0xFD, +0x12, 0x86, 0x63, 0x90, 0x82, 0x77, 0xEE, 0xF0, +0xA3, 0xEF, 0xF0, 0x12, 0x8A, 0x6B, 0x22, 0x90, +0x81, 0x88, 0xE0, 0x44, 0x04, 0xF0, 0x22, 0x22, +0x22, 0x90, 0x82, 0x70, 0xE0, 0x90, 0x05, 0x73, +0x22, 0x75, 0xE8, 0x03, 0x75, 0xA8, 0x84, 0x22, +0xE4, 0x90, 0x82, 0x90, 0xF0, 0xA3, 0xF0, 0xA3, +0xF0, 0x90, 0x82, 0x90, 0xE0, 0x64, 0x01, 0xF0, +0x24, 0xF0, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x6F, +0xA3, 0xF0, 0x90, 0x81, 0x8D, 0xE0, 0x60, 0x0F, +0x90, 0x81, 0x90, 0xE0, 0xFF, 0x90, 0x81, 0x8F, +0xE0, 0x6F, 0x60, 0x03, 0x12, 0x6B, 0xFB, 0xC2, +0xAF, 0x12, 0x84, 0x42, 0xBF, 0x01, 0x02, 0x11, +0x3A, 0xD2, 0xAF, 0xF1, 0x74, 0x12, 0x32, 0x9E, +0xBF, 0x01, 0x02, 0x31, 0x9F, 0x12, 0x43, 0x4D, +0x80, 0xBF, 0x90, 0x81, 0x88, 0xE0, 0x30, 0xE0, +0x19, 0x90, 0x81, 0x83, 0xE0, 0xFF, 0x30, 0xE0, +0x0F, 0xC3, 0x13, 0x30, 0xE0, 0x08, 0x12, 0x89, +0x49, 0xBF, 0x01, 0x06, 0x80, 0x02, 0x80, 0x00, +0x11, 0x5B, 0x22, 0x90, 0x81, 0x90, 0xE0, 0xFF, +0x60, 0x03, 0xB4, 0x08, 0x0D, 0x11, 0xF8, 0xBF, +0x01, 0x08, 0x11, 0x73, 0x90, 0x01, 0xE5, 0xE0, +0x04, 0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x31, 0x47, 0x11, 0x83, 0xD0, 0xD0, +0x92, 0xAF, 0x22, 0x12, 0x87, 0xCC, 0x90, 0x81, +0x98, 0xE0, 0x20, 0xE0, 0x0C, 0x90, 0x00, 0x26, +0xE0, 0x54, 0x7F, 0xFD, 0x7F, 0x26, 0x12, 0x32, +0x1E, 0x90, 0x00, 0x08, 0xE0, 0x54, 0xEF, 0xFD, +0x7F, 0x08, 0x12, 0x32, 0x1E, 0xE4, 0xFF, 0x90, +0x82, 0x93, 0xF1, 0x8B, 0x90, 0x01, 0x09, 0xE0, +0x7F, 0x00, 0x30, 0xE7, 0x02, 0x7F, 0x01, 0x90, +0x82, 0x93, 0xE0, 0x6F, 0x60, 0x39, 0xC3, 0x90, +0x82, 0x95, 0xE0, 0x94, 0x88, 0x90, 0x82, 0x94, +0xE0, 0x94, 0x13, 0x40, 0x08, 0x90, 0x01, 0xC0, +0xE0, 0x44, 0x10, 0xF0, 0x22, 0x90, 0x82, 0x94, +0xF1, 0x75, 0x7F, 0x14, 0x7E, 0x00, 0x12, 0x32, +0xAA, 0xD3, 0x90, 0x82, 0x95, 0xE0, 0x94, 0x32, +0x90, 0x82, 0x94, 0xE0, 0x94, 0x00, 0x40, 0xBC, +0x90, 0x01, 0xC6, 0xE0, 0x30, 0xE0, 0xB5, 0x22, +0x90, 0x82, 0x6E, 0xE0, 0xC3, 0x13, 0x20, 0xE0, +0x35, 0x90, 0x02, 0x87, 0xE0, 0x60, 0x02, 0x80, +0x08, 0x90, 0x01, 0x00, 0xE0, 0x64, 0x3F, 0x60, +0x05, 0x75, 0x53, 0x01, 0x80, 0x22, 0x90, 0x02, +0x96, 0xE0, 0x60, 0x05, 0x75, 0x53, 0x10, 0x80, +0x17, 0x90, 0x02, 0x86, 0xE0, 0x20, 0xE1, 0x02, +0x80, 0x07, 0x90, 0x02, 0x86, 0xE0, 0x30, 0xE3, +0x05, 0x75, 0x53, 0x04, 0x80, 0x02, 0xE1, 0x83, +0x90, 0x01, 0xB9, 0x74, 0x08, 0xF0, 0x90, 0x01, +0xB8, 0xE5, 0x53, 0xF0, 0x7F, 0x00, 0x22, 0x90, +0x81, 0x98, 0xE0, 0xFD, 0x7F, 0x93, 0x12, 0x32, +0x1E, 0x90, 0x81, 0x8E, 0xE0, 0x60, 0x12, 0x90, +0x01, 0x2F, 0xE0, 0x30, 0xE7, 0x05, 0x74, 0x10, +0xF0, 0x80, 0x06, 0x90, 0x01, 0x2F, 0x74, 0x90, +0xF0, 0x90, 0x00, 0x08, 0xE0, 0x44, 0x10, 0xFD, +0x7F, 0x08, 0x12, 0x32, 0x1E, 0x7F, 0x01, 0x11, +0xA7, 0x90, 0x81, 0x98, 0xE0, 0x20, 0xE0, 0x0C, +0x90, 0x00, 0x26, 0xE0, 0x44, 0x80, 0xFD, 0x7F, +0x26, 0x12, 0x32, 0x1E, 0x90, 0x00, 0x90, 0xE0, +0x44, 0x01, 0xFD, 0x7F, 0x90, 0x12, 0x32, 0x1E, +0x7F, 0x14, 0x7E, 0x00, 0x02, 0x32, 0xAA, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x2D, +0xA7, 0xE4, 0xF5, 0x55, 0x12, 0x32, 0x9E, 0xEF, +0x60, 0x72, 0x63, 0x55, 0x01, 0xE5, 0x55, 0x24, +0x9F, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x71, 0xA3, +0xF0, 0x90, 0x00, 0x88, 0xE0, 0xF5, 0x53, 0xF5, +0x54, 0x54, 0x0F, 0x60, 0xDF, 0xE5, 0x53, 0x30, +0xE0, 0x0B, 0x20, 0xE4, 0x03, 0x12, 0x29, 0xC5, +0x53, 0x54, 0xEE, 0x80, 0x3E, 0xE5, 0x53, 0x30, +0xE1, 0x16, 0x20, 0xE5, 0x0E, 0x12, 0x11, 0xBD, +0xEF, 0x70, 0x03, 0x43, 0x54, 0x20, 0x90, 0x01, +0x06, 0xE4, 0xF0, 0x53, 0x54, 0xFD, 0x80, 0x23, +0xE5, 0x53, 0x30, 0xE2, 0x0B, 0x20, 0xE6, 0x03, +0x12, 0x4B, 0x18, 0x53, 0x54, 0xFB, 0x80, 0x13, +0xE5, 0x53, 0x30, 0xE3, 0x0E, 0x20, 0xE7, 0x08, +0x51, 0x29, 0xEF, 0x70, 0x03, 0x43, 0x54, 0x80, +0x53, 0x54, 0xF7, 0xAD, 0x54, 0x7F, 0x88, 0x12, +0x32, 0x1E, 0x80, 0x88, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x78, 0x10, 0x74, 0x01, 0xF2, 0x90, 0x02, +0x09, 0xE0, 0x78, 0x00, 0xF2, 0x08, 0x74, 0x20, +0xF2, 0x18, 0xE2, 0xFF, 0x30, 0xE0, 0x05, 0x08, +0xE2, 0x24, 0x80, 0xF2, 0xEF, 0xC3, 0x13, 0x90, +0xFD, 0x10, 0xF0, 0x78, 0x01, 0xE2, 0x91, 0x51, +0x78, 0x03, 0xF2, 0x64, 0x04, 0x60, 0x0D, 0xE2, +0xFF, 0x64, 0x08, 0x60, 0x07, 0xEF, 0x64, 0x0C, +0x60, 0x02, 0x81, 0x47, 0xE4, 0x78, 0x02, 0xF2, +0x78, 0x03, 0xE2, 0xFF, 0x18, 0xE2, 0xC3, 0x9F, +0x50, 0x25, 0xE2, 0xFD, 0x18, 0xE2, 0x2D, 0x90, +0x82, 0x93, 0xF0, 0xE0, 0xFF, 0x91, 0x51, 0xFE, +0x74, 0x04, 0x2D, 0xF8, 0xEE, 0xF2, 0xEF, 0xB4, +0xFF, 0x06, 0x90, 0xFD, 0x10, 0xE0, 0x04, 0xF0, +0x78, 0x02, 0xE2, 0x04, 0xF2, 0x80, 0xD1, 0x78, +0x04, 0xE2, 0x78, 0x12, 0xF2, 0xFF, 0x78, 0x05, +0xE2, 0x78, 0x11, 0xF2, 0x78, 0x06, 0xE2, 0x78, +0x13, 0xF2, 0x78, 0x07, 0xE2, 0x78, 0x14, 0xF2, +0x78, 0x08, 0xE2, 0x78, 0x33, 0xF2, 0x78, 0x09, +0xE2, 0x78, 0x34, 0xF2, 0x78, 0x0A, 0xE2, 0x78, +0x35, 0xF2, 0x78, 0x0B, 0xE2, 0x78, 0x36, 0xF2, +0x78, 0x0C, 0xE2, 0x78, 0x37, 0xF2, 0x78, 0x0D, +0xE2, 0x78, 0x38, 0xF2, 0x78, 0x0E, 0xE2, 0x78, +0x39, 0xF2, 0x78, 0x0F, 0xE2, 0x78, 0x3A, 0xF2, +0xE4, 0x78, 0x15, 0xF2, 0xEF, 0x24, 0xF8, 0x60, +0x56, 0x24, 0xFC, 0x60, 0x4D, 0x24, 0x08, 0x60, +0x02, 0x81, 0x29, 0x78, 0x11, 0xE2, 0xB4, 0x01, +0x05, 0x12, 0x29, 0xC5, 0x81, 0x2E, 0x78, 0x11, +0xE2, 0xB4, 0x02, 0x05, 0x12, 0x11, 0xBD, 0x81, +0x2E, 0x78, 0x11, 0xE2, 0xB4, 0x03, 0x05, 0x12, +0x4B, 0x18, 0x81, 0x2E, 0x78, 0x11, 0xE2, 0xB4, +0x10, 0x07, 0x91, 0x68, 0x12, 0x32, 0xAA, 0x81, +0x2E, 0x78, 0x11, 0xE2, 0xB4, 0x11, 0x07, 0x91, +0x68, 0x12, 0x32, 0x06, 0x81, 0x2E, 0x78, 0x11, +0xE2, 0xF4, 0x60, 0x02, 0x81, 0x2E, 0x18, 0xF2, +0x81, 0x2E, 0x78, 0x15, 0x74, 0x01, 0xF2, 0x78, +0x11, 0xE2, 0x64, 0x07, 0x60, 0x02, 0x81, 0x13, +0x78, 0x34, 0x91, 0x4A, 0x78, 0x08, 0x12, 0x20, +0xBB, 0xC0, 0x04, 0x91, 0x61, 0x78, 0x33, 0x91, +0x4A, 0xD0, 0x00, 0x12, 0x47, 0x7F, 0xC0, 0x04, +0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0x78, 0x35, +0x91, 0x4A, 0x78, 0x10, 0x12, 0x20, 0xBB, 0xD0, +0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, +0x47, 0x7F, 0x78, 0x18, 0x12, 0x47, 0xCE, 0x78, +0x15, 0xE2, 0x60, 0x79, 0x18, 0xE2, 0xFF, 0x18, +0xE2, 0xFD, 0xF1, 0x44, 0x78, 0x1C, 0x12, 0x47, +0xCE, 0x78, 0x38, 0x91, 0x4A, 0x78, 0x08, 0x12, +0x20, 0xBB, 0xC0, 0x04, 0x91, 0x61, 0x78, 0x37, +0x91, 0x4A, 0xD0, 0x00, 0x12, 0x47, 0x7F, 0xC0, +0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0x78, +0x39, 0x91, 0x4A, 0x78, 0x10, 0x12, 0x20, 0xBB, +0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, +0x12, 0x47, 0x7F, 0x78, 0x20, 0x12, 0x47, 0xCE, +0x78, 0x20, 0x12, 0x47, 0xA9, 0x12, 0x20, 0x9B, +0x78, 0x1C, 0x12, 0x47, 0xC1, 0x12, 0x47, 0x72, +0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, +0x78, 0x18, 0x12, 0x47, 0xA9, 0x78, 0x20, 0x12, +0x47, 0xC1, 0x12, 0x47, 0x72, 0xD0, 0x03, 0xD0, +0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, 0x47, 0x7F, +0x78, 0x18, 0x12, 0x47, 0xCE, 0x78, 0x18, 0x12, +0x47, 0xA9, 0x90, 0x83, 0x42, 0x12, 0x20, 0xCE, +0x78, 0x13, 0xE2, 0xFD, 0x08, 0xE2, 0xFF, 0xF1, +0x52, 0x80, 0x1B, 0x78, 0x13, 0xE2, 0xFF, 0x08, +0xE2, 0xFD, 0x78, 0x11, 0xE2, 0xFB, 0x78, 0x15, +0xE2, 0x90, 0x82, 0xF5, 0xF0, 0xB1, 0x7C, 0x80, +0x05, 0x78, 0x10, 0x74, 0x02, 0xF2, 0x78, 0x10, +0xE2, 0xFF, 0xC3, 0x94, 0x02, 0x50, 0x10, 0xEF, +0x60, 0x0A, 0x78, 0x02, 0xE2, 0xFF, 0x18, 0xE2, +0x2F, 0xF2, 0x41, 0x4B, 0x7F, 0x01, 0x22, 0x7F, +0x00, 0x22, 0xE2, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, +0x22, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0xFC, +0xF5, 0x83, 0xE0, 0x22, 0x12, 0x20, 0xBB, 0xA8, +0x04, 0xA9, 0x05, 0xAA, 0x06, 0xAB, 0x07, 0x22, +0x78, 0x14, 0xE2, 0xFE, 0x18, 0xE2, 0xFD, 0xED, +0xFF, 0x78, 0x16, 0xEE, 0xF2, 0xFE, 0x08, 0xEF, +0xF2, 0xFF, 0x22, 0x90, 0x83, 0x18, 0xF1, 0x7C, +0x12, 0x20, 0xDA, 0x00, 0x00, 0x00, 0x00, 0xE4, +0x90, 0x83, 0x26, 0xF0, 0x7F, 0x24, 0x7E, 0x08, +0x12, 0x2D, 0x5C, 0x90, 0x83, 0x1E, 0x12, 0x20, +0xCE, 0x90, 0x83, 0x18, 0xE0, 0xFB, 0x70, 0x04, +0xB1, 0x5B, 0x80, 0x07, 0xEB, 0xB1, 0x6A, 0xFF, +0x12, 0x2D, 0x5C, 0x90, 0x83, 0x22, 0x12, 0x20, +0xCE, 0x90, 0x83, 0x19, 0x12, 0x4B, 0x11, 0x78, +0x17, 0x91, 0x5C, 0x90, 0x83, 0x22, 0x12, 0x47, +0x9D, 0xED, 0x54, 0x7F, 0xFD, 0xEC, 0x54, 0x80, +0xFC, 0x12, 0x47, 0x7F, 0xEC, 0x44, 0x80, 0xFC, +0x90, 0x83, 0x22, 0x12, 0x20, 0xCE, 0xB1, 0x5B, +0xEC, 0x54, 0x7F, 0xFC, 0xB1, 0x64, 0xD1, 0xC3, +0xB1, 0x6A, 0xFF, 0xC0, 0x06, 0xC0, 0x07, 0x90, +0x83, 0x22, 0xB1, 0x61, 0xD0, 0x07, 0xD0, 0x06, +0x12, 0x2E, 0xA2, 0xB1, 0x5B, 0xEC, 0x44, 0x80, +0xFC, 0xB1, 0x64, 0xD1, 0xC3, 0x70, 0x04, 0x7F, +0x20, 0x80, 0x09, 0x90, 0x83, 0x18, 0xE0, 0xB4, +0x01, 0x16, 0x7F, 0x28, 0x7E, 0x08, 0x12, 0x2D, +0x5C, 0x78, 0x08, 0x12, 0x20, 0xA8, 0xEF, 0x54, +0x01, 0xFF, 0xE4, 0x90, 0x83, 0x26, 0xEF, 0xF0, +0x90, 0x83, 0x26, 0xE0, 0x90, 0x83, 0x18, 0x60, +0x0E, 0xE0, 0x75, 0xF0, 0x08, 0xA4, 0x24, 0x66, +0xF5, 0x82, 0xE4, 0x34, 0x87, 0x80, 0x0C, 0xE0, +0x75, 0xF0, 0x08, 0xA4, 0x24, 0x64, 0xF5, 0x82, +0xE4, 0x34, 0x87, 0xB1, 0x75, 0xFF, 0x12, 0x2D, +0x5C, 0xED, 0x54, 0x0F, 0xFD, 0xE4, 0xFC, 0x90, +0x83, 0x1A, 0x12, 0x20, 0xCE, 0x90, 0x83, 0x1A, +0x02, 0x47, 0x9D, 0x90, 0x83, 0x1E, 0x02, 0x47, +0x9D, 0x12, 0x47, 0x9D, 0x90, 0x85, 0xBB, 0x02, +0x20, 0xCE, 0x75, 0xF0, 0x08, 0xA4, 0x24, 0x62, +0xF5, 0x82, 0xE4, 0x34, 0x87, 0xF5, 0x83, 0xE0, +0xFE, 0xA3, 0xE0, 0x22, 0xAC, 0x07, 0xED, 0xAD, +0x04, 0x78, 0x24, 0xF2, 0xED, 0x08, 0xF2, 0xEB, +0xB4, 0x04, 0x07, 0x78, 0x27, 0x74, 0x01, 0xF2, +0x80, 0x0E, 0xEB, 0x78, 0x27, 0xB4, 0x05, 0x05, +0x74, 0x02, 0xF2, 0x80, 0x03, 0x74, 0x04, 0xF2, +0xD1, 0xBB, 0xE2, 0x94, 0x00, 0x50, 0x44, 0xE4, +0x78, 0x26, 0xF2, 0xD1, 0x94, 0x40, 0x02, 0xC1, +0x93, 0xD1, 0x9E, 0x60, 0x1F, 0x74, 0x37, 0x2E, +0xF8, 0xE2, 0x78, 0x32, 0xF2, 0xEE, 0xFF, 0x78, +0x25, 0xE2, 0x2F, 0xFF, 0x18, 0xE2, 0x34, 0x00, +0x8F, 0x82, 0xF5, 0x83, 0xE0, 0x78, 0x29, 0xF2, +0x78, 0x32, 0xD1, 0xDD, 0x78, 0x24, 0x08, 0xE2, +0xFF, 0x08, 0xE2, 0x2F, 0xFF, 0x78, 0x28, 0xE2, +0xFD, 0x12, 0x32, 0x1E, 0x78, 0x26, 0xE2, 0x04, +0xF2, 0x80, 0xC0, 0xD1, 0xBB, 0xE2, 0x94, 0x07, +0x50, 0x2F, 0xE4, 0x78, 0x26, 0xF2, 0xD1, 0x94, +0x40, 0x02, 0xC1, 0x93, 0xD1, 0x9E, 0x60, 0x14, +0x78, 0x26, 0xE2, 0xFF, 0xD1, 0xCF, 0xE0, 0x78, +0x29, 0xF2, 0x74, 0x37, 0x2F, 0xF8, 0xE2, 0x78, +0x32, 0xF2, 0xD1, 0xDD, 0xD1, 0xB3, 0xD1, 0xCF, +0xEF, 0xF0, 0x78, 0x26, 0xE2, 0x04, 0xF2, 0x80, +0xD5, 0x90, 0x82, 0xF5, 0xE0, 0x60, 0x0A, 0xD1, +0xAB, 0x12, 0x2D, 0x5C, 0x78, 0x2E, 0x12, 0x47, +0xCE, 0xE4, 0x78, 0x26, 0xF2, 0xD1, 0x94, 0x50, +0x4E, 0xD1, 0x9E, 0x60, 0x2B, 0x78, 0x2E, 0x12, +0x47, 0xA9, 0x78, 0x26, 0xE2, 0xFB, 0x75, 0xF0, +0x08, 0xA4, 0xF9, 0xF8, 0x12, 0x20, 0xA8, 0x78, +0x29, 0xEF, 0xF2, 0x74, 0x37, 0x2B, 0xF8, 0xE2, +0x78, 0x32, 0xF2, 0xE2, 0xFE, 0xF4, 0x5F, 0xFF, +0x78, 0x28, 0xE2, 0xFD, 0xEE, 0x5D, 0x4F, 0xF2, +0xD1, 0xB3, 0xFD, 0xC3, 0x74, 0x03, 0x9D, 0xFD, +0xE4, 0x94, 0x00, 0xFC, 0x7B, 0xFE, 0x74, 0x2A, +0x2D, 0xF9, 0x74, 0x80, 0x3C, 0xFA, 0xEF, 0x12, +0x1F, 0xEA, 0xE2, 0x04, 0xF2, 0x80, 0xAE, 0x78, +0x2A, 0x12, 0x47, 0xA9, 0xB1, 0x64, 0xD1, 0xAB, +0x12, 0x2E, 0xA2, 0x22, 0x78, 0x27, 0xE2, 0xFF, +0x18, 0xE2, 0xFE, 0xC3, 0x9F, 0x22, 0x74, 0x33, +0x2E, 0xF8, 0xE2, 0x78, 0x28, 0xF2, 0x90, 0x82, +0xF5, 0xE0, 0x22, 0x78, 0x24, 0xE2, 0xFE, 0x08, +0xE2, 0xFF, 0x22, 0x78, 0x28, 0xE2, 0xFF, 0x78, +0x26, 0xE2, 0x22, 0xD3, 0x78, 0x25, 0xE2, 0x94, +0xFF, 0x18, 0x22, 0x7F, 0x24, 0x7E, 0x08, 0x12, +0x2E, 0xA2, 0x90, 0x83, 0x18, 0xE0, 0x22, 0xFD, +0x18, 0xE2, 0x2D, 0xFD, 0x18, 0xE2, 0x34, 0x00, +0x8D, 0x82, 0xF5, 0x83, 0x22, 0xE2, 0xFF, 0xF4, +0xFE, 0x78, 0x29, 0xE2, 0x5E, 0xFE, 0x18, 0xE2, +0xFD, 0xEF, 0x5D, 0x4E, 0xF2, 0x22, 0x90, 0x83, +0x36, 0xEF, 0xF0, 0xAB, 0x05, 0x90, 0x83, 0x3C, +0x12, 0x20, 0xDA, 0x00, 0x00, 0x00, 0x00, 0xAF, +0x03, 0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x14, 0x91, +0x5C, 0x90, 0x83, 0x38, 0x12, 0x47, 0x9D, 0xED, +0x54, 0x0F, 0xFD, 0xE4, 0xFC, 0x12, 0x47, 0x7F, +0xEC, 0x54, 0x0F, 0xFC, 0x90, 0x83, 0x3C, 0x12, +0x20, 0xCE, 0x90, 0x83, 0x36, 0xE0, 0x75, 0xF0, +0x08, 0xA4, 0x24, 0x60, 0xF5, 0x82, 0xE4, 0x34, +0x87, 0xB1, 0x75, 0xFF, 0xC0, 0x06, 0xC0, 0x07, +0x90, 0x83, 0x3C, 0xB1, 0x61, 0xD0, 0x07, 0xD0, +0x06, 0x02, 0x2E, 0xA2, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x91, 0x7B, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0xC0, 0x07, 0xC0, 0x05, 0x90, 0x83, 0x42, +0x12, 0x47, 0x9D, 0x90, 0x83, 0x38, 0x12, 0x20, +0xCE, 0xD0, 0x05, 0xD0, 0x07, 0xD1, 0xEE, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x22, 0xE4, 0x75, 0xF0, +0x01, 0x02, 0x46, 0x9F, 0xEF, 0xF0, 0xA3, 0xED, +0xF0, 0xA3, 0x22, 0x90, 0x01, 0xB8, 0xE4, 0xF0, +0x7F, 0x01, 0x22, 0xEF, 0xF0, 0xE4, 0xA3, 0xF0, +0xA3, 0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x83, 0x51, 0xEE, 0xF0, 0xA3, +0xF1, 0x8B, 0x90, 0x83, 0x51, 0xE0, 0xFE, 0xA3, +0xE0, 0xF5, 0x82, 0x8E, 0x83, 0xE0, 0x60, 0x28, +0xC3, 0x90, 0x83, 0x54, 0xE0, 0x94, 0xE8, 0x90, +0x83, 0x53, 0xE0, 0x94, 0x03, 0x40, 0x0B, 0x90, +0x01, 0xC0, 0xE0, 0x44, 0x80, 0xF0, 0x7F, 0x00, +0x80, 0x10, 0x90, 0x83, 0x53, 0xF1, 0x75, 0x7F, +0x0A, 0x7E, 0x00, 0x12, 0x32, 0xAA, 0x80, 0xCA, +0x7F, 0x01, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xE4, +0xFB, 0xFA, 0xFD, 0x7F, 0x01, 0x12, 0x45, 0x4E, +0x90, 0x82, 0xF6, 0xEF, 0xF0, 0x60, 0xF0, 0x90, +0x80, 0x3C, 0xE0, 0xFF, 0x70, 0x04, 0xA3, 0xE0, +0x60, 0xE5, 0xC2, 0xAF, 0xEF, 0x30, 0xE0, 0x0A, +0x90, 0x80, 0x3C, 0xE0, 0x54, 0xFE, 0xF0, 0x12, +0x5D, 0x39, 0x11, 0x22, 0x30, 0xE1, 0x05, 0x54, +0xFD, 0xF0, 0x11, 0x2C, 0x11, 0x22, 0x30, 0xE2, +0x05, 0x54, 0xFB, 0xF0, 0x31, 0xBD, 0xD2, 0xAF, +0x80, 0xCD, 0xD2, 0xAF, 0xC2, 0xAF, 0x90, 0x80, +0x3C, 0xE0, 0xFF, 0x22, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x90, 0x80, 0xDE, 0xE0, 0xFF, +0x90, 0x80, 0xDD, 0xE0, 0xB5, 0x07, 0x04, 0x7F, +0x01, 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x70, 0x3F, +0x90, 0x80, 0xDD, 0xE0, 0xFE, 0x75, 0xF0, 0x08, +0x90, 0x80, 0x8D, 0x12, 0x47, 0xDA, 0xE0, 0xFD, +0xEE, 0x75, 0xF0, 0x08, 0xA4, 0x24, 0x8E, 0xF9, +0x74, 0x80, 0x35, 0xF0, 0xFA, 0x7B, 0x01, 0xAF, +0x05, 0x12, 0x5C, 0xAA, 0x90, 0x80, 0xDD, 0x31, +0xB6, 0xB4, 0x0A, 0x02, 0x7F, 0x01, 0xEF, 0x60, +0x05, 0xE4, 0x90, 0x80, 0xDD, 0xF0, 0x11, 0x8C, +0x90, 0x80, 0x3C, 0xE0, 0x44, 0x02, 0xF0, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x90, 0x01, 0xCC, 0xE0, +0x54, 0x0F, 0x90, 0x83, 0x6A, 0xF0, 0x90, 0x83, +0x6A, 0xE0, 0xFD, 0x70, 0x02, 0x21, 0x8B, 0x90, +0x80, 0xDD, 0xE0, 0xFF, 0x70, 0x06, 0xA3, 0xE0, +0x64, 0x09, 0x60, 0x0A, 0xEF, 0x14, 0xFF, 0x90, +0x80, 0xDE, 0xE0, 0xB5, 0x07, 0x04, 0x7F, 0x01, +0x80, 0x02, 0x7F, 0x00, 0xEF, 0x60, 0x08, 0x90, +0x01, 0xC1, 0xE0, 0x44, 0x01, 0xF0, 0x22, 0x90, +0x83, 0x68, 0xE0, 0x12, 0x64, 0xA5, 0x80, 0x05, +0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, +0xEF, 0x5D, 0x70, 0x02, 0x21, 0x6D, 0xE4, 0x90, +0x83, 0x6B, 0xF0, 0x90, 0x83, 0x6B, 0xE0, 0xF9, +0xC3, 0x94, 0x04, 0x50, 0x31, 0x31, 0x8C, 0xA4, +0xFF, 0xE9, 0xFD, 0x7C, 0x00, 0x2F, 0xFF, 0xEC, +0x35, 0xF0, 0xFE, 0x74, 0xD0, 0x31, 0xA4, 0x90, +0x80, 0x8D, 0x31, 0x94, 0x31, 0x8C, 0xA4, 0x2D, +0xFF, 0xEC, 0x35, 0xF0, 0xFE, 0x74, 0xF0, 0x31, +0xA4, 0x90, 0x80, 0x91, 0x31, 0x94, 0x90, 0x83, +0x6B, 0xE0, 0x04, 0xF0, 0x80, 0xC5, 0x90, 0x83, +0x6A, 0xE0, 0xFF, 0x90, 0x83, 0x68, 0xE0, 0xFE, +0x74, 0x01, 0xA8, 0x06, 0x08, 0x80, 0x02, 0xC3, +0x33, 0xD8, 0xFC, 0xF4, 0x5F, 0x90, 0x83, 0x6A, +0xF0, 0x90, 0x83, 0x68, 0xE0, 0xFF, 0x74, 0x01, +0xA8, 0x07, 0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8, +0xFC, 0x90, 0x01, 0xCC, 0xF0, 0x90, 0x83, 0x68, +0xE0, 0x04, 0xF0, 0xE0, 0x54, 0x03, 0xF0, 0x90, +0x80, 0xDE, 0x31, 0xB6, 0xB4, 0x0A, 0x02, 0x7F, +0x01, 0xEF, 0x70, 0x02, 0x01, 0x96, 0xE4, 0x90, +0x80, 0xDE, 0xF0, 0x01, 0x96, 0x90, 0x01, 0xC0, +0xE0, 0x44, 0x02, 0xF0, 0x90, 0x83, 0x68, 0xE0, +0x44, 0x80, 0x90, 0x00, 0x8A, 0xF0, 0x31, 0x8C, +0x90, 0x01, 0xD0, 0x12, 0x47, 0xDA, 0xE0, 0x90, +0x01, 0xC3, 0xF0, 0x22, 0x90, 0x83, 0x68, 0xE0, +0x75, 0xF0, 0x04, 0x22, 0x12, 0x47, 0xDA, 0xE5, +0x82, 0x29, 0xF5, 0x82, 0xE4, 0x35, 0x83, 0xF5, +0x83, 0xEF, 0xF0, 0x22, 0x2F, 0xF5, 0x82, 0x74, +0x01, 0x3E, 0xF5, 0x83, 0xE0, 0xFF, 0x90, 0x80, +0xDE, 0xE0, 0x75, 0xF0, 0x08, 0x22, 0xE0, 0x04, +0xF0, 0xE0, 0x7F, 0x00, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0xE4, 0xFF, 0x90, 0x81, +0x76, 0xE0, 0xFE, 0x90, 0x81, 0x75, 0xE0, 0xFD, +0xB5, 0x06, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, +0x00, 0xEE, 0x64, 0x01, 0x60, 0x42, 0x90, 0x01, +0xAF, 0xE0, 0x70, 0x0B, 0xED, 0x91, 0x14, 0xFA, +0x7B, 0x01, 0x12, 0x83, 0x05, 0x7F, 0x01, 0xEF, +0x60, 0x2E, 0x90, 0x81, 0x75, 0x31, 0xB6, 0xB4, +0x0A, 0x02, 0x7F, 0x01, 0xEF, 0x60, 0x05, 0xE4, +0x90, 0x81, 0x75, 0xF0, 0x90, 0x81, 0x76, 0xE0, +0xFF, 0x90, 0x81, 0x75, 0xE0, 0xB5, 0x07, 0x04, +0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x70, +0x07, 0x90, 0x80, 0x3C, 0xE0, 0x44, 0x04, 0xF0, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x11, 0x8C, 0x7F, +0x02, 0x8F, 0x0F, 0x7F, 0x02, 0x12, 0x45, 0x27, +0x90, 0x80, 0x3C, 0xE0, 0x45, 0x0F, 0xF0, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, +0x81, 0x8A, 0xE0, 0xFE, 0xC3, 0x13, 0x30, 0xE0, +0x1D, 0x90, 0x83, 0x27, 0x74, 0x1E, 0xF0, 0x90, +0x83, 0x35, 0x74, 0x01, 0xF0, 0x90, 0x83, 0x29, +0xEF, 0xF0, 0x7B, 0x01, 0x7A, 0x83, 0x79, 0x27, +0x51, 0x6B, 0x7F, 0x04, 0x51, 0x29, 0xD0, 0xD0, +0x92, 0xAF, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x81, 0x75, 0xE0, 0xFF, 0x70, +0x06, 0xA3, 0xE0, 0x64, 0x09, 0x60, 0x0A, 0xEF, +0x14, 0xFF, 0x90, 0x81, 0x76, 0xE0, 0xB5, 0x07, +0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xEF, +0x60, 0x09, 0x90, 0x01, 0xC1, 0xE0, 0x44, 0x02, +0xF0, 0x80, 0x28, 0xC0, 0x01, 0x90, 0x81, 0x76, +0xE0, 0x91, 0x14, 0xA8, 0x01, 0xFC, 0x7D, 0x01, +0xD0, 0x01, 0x7E, 0x00, 0x7F, 0x0F, 0x12, 0x46, +0x79, 0x90, 0x81, 0x76, 0x31, 0xB6, 0xB4, 0x0A, +0x02, 0x7F, 0x01, 0xEF, 0x60, 0x05, 0xE4, 0x90, +0x81, 0x76, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0xAD, 0x07, 0x90, 0x83, 0x06, 0x74, 0x13, 0xF0, +0x90, 0x83, 0x14, 0x74, 0x0C, 0xF0, 0x90, 0x83, +0x08, 0xED, 0xF0, 0x12, 0x65, 0xCE, 0x71, 0x4D, +0x90, 0x83, 0x09, 0xF0, 0xA3, 0xEB, 0xF0, 0xED, +0x91, 0x21, 0x71, 0x4D, 0x90, 0x83, 0x0B, 0x71, +0x54, 0x90, 0x8D, 0x00, 0x71, 0x4A, 0x90, 0x83, +0x0D, 0x71, 0x54, 0x90, 0x8D, 0x02, 0x71, 0x4A, +0x90, 0x83, 0x0F, 0x71, 0x54, 0x90, 0x8D, 0x04, +0x12, 0x47, 0xDA, 0xE0, 0x90, 0x83, 0x11, 0xF0, +0x75, 0xF0, 0x0A, 0xED, 0x90, 0x8D, 0x06, 0x12, +0x47, 0xDA, 0xE0, 0x90, 0x83, 0x12, 0xF0, 0x75, +0xF0, 0x0A, 0xEF, 0x90, 0x8D, 0x08, 0x12, 0x47, +0xDA, 0xE0, 0x90, 0x83, 0x13, 0x91, 0x08, 0x90, +0x83, 0x6C, 0xEF, 0xF0, 0x7F, 0x02, 0x12, 0x45, +0x27, 0x90, 0x80, 0x3C, 0xE0, 0xFF, 0x90, 0x83, +0x6C, 0xE0, 0xFE, 0xEF, 0x4E, 0x90, 0x80, 0x3C, +0xF0, 0x22, 0x12, 0x47, 0xDA, 0xE0, 0xFA, 0xA3, +0xE0, 0xFB, 0xEA, 0x22, 0xF0, 0xA3, 0xEB, 0xF0, +0x75, 0xF0, 0x0A, 0xED, 0x22, 0x90, 0x83, 0x06, +0x74, 0x12, 0xF0, 0x90, 0x83, 0x14, 0x74, 0x05, +0xF0, 0x90, 0x83, 0x08, 0x12, 0x77, 0x7C, 0xEB, +0xF0, 0x90, 0x83, 0x04, 0xE0, 0x90, 0x83, 0x0B, +0xF0, 0x90, 0x83, 0x05, 0xE0, 0x90, 0x83, 0x0C, +0x91, 0x08, 0x80, 0xAB, 0x91, 0x01, 0x7F, 0xF5, +0x7E, 0x00, 0x12, 0x2B, 0x27, 0xBF, 0x01, 0x06, +0x90, 0x82, 0xFB, 0xE0, 0xA3, 0xF0, 0x91, 0x01, +0x7F, 0xF6, 0x7E, 0x00, 0x12, 0x2B, 0x27, 0xBF, +0x01, 0x08, 0x90, 0x82, 0xFB, 0xE0, 0x90, 0x82, +0xFD, 0xF0, 0x91, 0x01, 0x7F, 0xF4, 0x7E, 0x00, +0x12, 0x2B, 0x27, 0xBF, 0x01, 0x08, 0x90, 0x82, +0xFB, 0xE0, 0x90, 0x82, 0xFE, 0xF0, 0x91, 0x01, +0x7F, 0xF3, 0x7E, 0x00, 0x12, 0x2B, 0x27, 0xBF, +0x01, 0x08, 0x90, 0x82, 0xFB, 0xE0, 0x90, 0x82, +0xFF, 0xF0, 0x91, 0x01, 0x7F, 0xF2, 0x7E, 0x00, +0x12, 0x2B, 0x27, 0xBF, 0x01, 0x08, 0x90, 0x82, +0xFB, 0xE0, 0x90, 0x83, 0x00, 0xF0, 0x90, 0x82, +0xFC, 0xE0, 0xFF, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, +0xFB, 0xA3, 0xE0, 0x90, 0x83, 0x04, 0xF0, 0x90, +0x83, 0x00, 0xE0, 0x90, 0x83, 0x05, 0xF0, 0x61, +0x5D, 0x7B, 0x01, 0x7A, 0x82, 0x79, 0xFB, 0x22, +0xF0, 0x7B, 0x01, 0x7A, 0x83, 0x79, 0x06, 0x51, +0x6B, 0x7F, 0x04, 0x22, 0x75, 0xF0, 0x0F, 0xA4, +0x24, 0xDF, 0xF9, 0x74, 0x80, 0x35, 0xF0, 0x22, +0xEF, 0x25, 0xE0, 0x24, 0x80, 0xF5, 0x82, 0xE4, +0x34, 0x90, 0xF5, 0x83, 0x22, 0x90, 0x82, 0x76, +0xE5, 0xD1, 0xF0, 0xA3, 0xE5, 0xD2, 0xF0, 0xA3, +0xE5, 0xD3, 0xF0, 0xA3, 0xE5, 0xD4, 0xF0, 0xA3, +0xE5, 0xD5, 0xF0, 0xA3, 0xE5, 0xD6, 0xF0, 0xA3, +0xE5, 0xD7, 0xF0, 0xA3, 0xE5, 0xD9, 0xF0, 0x75, +0x13, 0x01, 0x75, 0x14, 0x82, 0x75, 0x15, 0x76, +0x75, 0x16, 0x08, 0x7B, 0x01, 0x7A, 0x95, 0x79, +0x43, 0x12, 0x2B, 0xED, 0x90, 0x95, 0x44, 0xE0, +0xFF, 0xB1, 0x36, 0x30, 0xE0, 0x02, 0xA1, 0x2C, +0xEF, 0x54, 0x3F, 0xFF, 0x90, 0x82, 0x7E, 0xF0, +0x90, 0x95, 0x45, 0xE0, 0x54, 0x3F, 0xFE, 0x90, +0x82, 0x7F, 0xB1, 0x2D, 0xFD, 0x91, 0x20, 0xE4, +0x8D, 0xF0, 0x12, 0x46, 0x9F, 0xEE, 0xD3, 0x94, +0x04, 0x40, 0x06, 0x90, 0x82, 0x7F, 0x74, 0x04, +0xF0, 0x90, 0x95, 0x44, 0x12, 0x8A, 0x01, 0x30, +0xE0, 0x6C, 0x90, 0x82, 0x7E, 0xE0, 0xB1, 0x3D, +0xC0, 0x83, 0xC0, 0x82, 0x90, 0x82, 0x7F, 0xE0, +0xD0, 0x82, 0xD0, 0x83, 0x75, 0xF0, 0x02, 0x12, +0x47, 0xDA, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xB1, +0x2E, 0x2F, 0xFF, 0xE4, 0x3E, 0xFE, 0x90, 0x82, +0x7E, 0xE0, 0xFC, 0xB1, 0x3D, 0xC0, 0x83, 0xC0, +0x82, 0x90, 0x82, 0x7F, 0xE0, 0xFB, 0xD0, 0x82, +0xD0, 0x83, 0x75, 0xF0, 0x02, 0x12, 0x47, 0xDA, +0xEE, 0xF0, 0xA3, 0xEF, 0xB1, 0x2D, 0xFA, 0xFF, +0xEC, 0x25, 0xE0, 0x12, 0x8A, 0x22, 0xF5, 0x83, +0xE4, 0x8F, 0xF0, 0x12, 0x46, 0x9F, 0x90, 0x95, +0x46, 0xE0, 0xFD, 0xB1, 0x36, 0x30, 0xE0, 0x2C, +0x90, 0x82, 0x7E, 0xE0, 0xFF, 0xED, 0x54, 0x7F, +0xFD, 0x8A, 0x51, 0x02, 0x67, 0x84, 0xB1, 0x2E, +0xFD, 0x90, 0x82, 0x7E, 0xE0, 0xFE, 0x12, 0x8A, +0x2A, 0xE4, 0x8D, 0xF0, 0x12, 0x46, 0x9F, 0x90, +0x95, 0x46, 0xB1, 0x35, 0x30, 0xE0, 0x05, 0xAF, +0x06, 0x12, 0x65, 0xEB, 0x22, 0xF0, 0x90, 0x95, +0x47, 0xE0, 0x54, 0x1F, 0x22, 0xE0, 0xC4, 0x13, +0x13, 0x13, 0x54, 0x01, 0x22, 0x75, 0xF0, 0x0A, +0x90, 0x8D, 0x00, 0x02, 0x47, 0xDA, 0x90, 0x81, +0x88, 0xE0, 0xFF, 0xB1, 0x36, 0x30, 0xE0, 0x25, +0xEF, 0x54, 0x7F, 0xF0, 0x90, 0x04, 0xE0, 0xE0, +0x90, 0x81, 0x89, 0x30, 0xE1, 0x06, 0xE0, 0x44, +0x02, 0xF0, 0x80, 0x08, 0xE0, 0x54, 0xFD, 0x12, +0x80, 0xB0, 0x04, 0xF0, 0x90, 0x81, 0x8D, 0xE0, +0x60, 0x03, 0x12, 0x6B, 0xFB, 0x22, 0x90, 0x82, +0x74, 0xE0, 0x60, 0x0F, 0xE4, 0xF0, 0x90, 0x05, +0x53, 0xE0, 0x44, 0x02, 0xF0, 0x90, 0x05, 0xFC, +0xE0, 0x04, 0xF0, 0x90, 0x81, 0x83, 0xE0, 0x30, +0xE0, 0x10, 0xA3, 0x74, 0x01, 0xF0, 0x90, 0x81, +0x83, 0xE0, 0xFF, 0xC3, 0x13, 0x30, 0xE0, 0x02, +0xB1, 0xAC, 0x12, 0x6A, 0xE9, 0xE4, 0xFF, 0x51, +0x38, 0x02, 0x55, 0xD5, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x12, 0x6B, 0x88, 0xBF, 0x01, +0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x02, 0xB1, +0xC6, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x81, 0x86, +0xE0, 0xF5, 0x5C, 0xE5, 0x5C, 0x6F, 0x70, 0x02, +0xC1, 0xA2, 0xEF, 0x14, 0x60, 0x38, 0x14, 0x60, +0x58, 0x14, 0x60, 0x78, 0x14, 0x70, 0x02, 0xC1, +0x80, 0x24, 0x04, 0x60, 0x02, 0xC1, 0xA2, 0xE5, +0x5C, 0xB4, 0x04, 0x04, 0xF1, 0xA3, 0xC1, 0xA2, +0xE5, 0x5C, 0xB4, 0x02, 0x04, 0xF1, 0xB7, 0xC1, +0xA2, 0xE5, 0x5C, 0xB4, 0x03, 0x04, 0xF1, 0xC5, +0xC1, 0xA2, 0xE5, 0x5C, 0x64, 0x01, 0x60, 0x02, +0xC1, 0xA2, 0xF1, 0xA5, 0xC1, 0xA2, 0xE5, 0x5C, +0xB4, 0x04, 0x04, 0xF1, 0x7F, 0xC1, 0xA2, 0xE5, +0x5C, 0xB4, 0x02, 0x04, 0xF1, 0xB2, 0x80, 0x7A, +0xE5, 0x5C, 0xB4, 0x03, 0x04, 0xF1, 0xC0, 0x80, +0x71, 0xE5, 0x5C, 0x70, 0x6D, 0xD1, 0xA7, 0x80, +0x69, 0xE5, 0x5C, 0xB4, 0x04, 0x04, 0xF1, 0x87, +0x80, 0x60, 0xE5, 0x5C, 0xB4, 0x01, 0x04, 0xD1, +0xC9, 0x80, 0x57, 0xE5, 0x5C, 0xB4, 0x03, 0x04, +0xD1, 0xD7, 0x80, 0x4E, 0xE5, 0x5C, 0x70, 0x4A, +0xD1, 0xC7, 0x80, 0x46, 0xE5, 0x5C, 0xB4, 0x04, +0x05, 0x12, 0x89, 0x35, 0x80, 0x3C, 0xE5, 0x5C, +0xB4, 0x01, 0x04, 0xF1, 0x97, 0x80, 0x33, 0xE5, +0x5C, 0xB4, 0x02, 0x04, 0xF1, 0xBB, 0x80, 0x2A, +0xE5, 0x5C, 0x70, 0x26, 0xF1, 0x95, 0x80, 0x22, +0xE5, 0x5C, 0xB4, 0x03, 0x04, 0xF1, 0x91, 0x80, +0x19, 0xE5, 0x5C, 0xB4, 0x01, 0x04, 0xD1, 0xB0, +0x80, 0x10, 0xE5, 0x5C, 0xB4, 0x02, 0x05, 0x12, +0x89, 0x41, 0x80, 0x06, 0xE5, 0x5C, 0x70, 0x02, +0xD1, 0xAE, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, +0x81, 0x86, 0x74, 0x01, 0xF0, 0x22, 0xD1, 0xA7, +0x7B, 0x1F, 0x7D, 0x6F, 0x7F, 0xFF, 0x12, 0x54, +0x72, 0x90, 0x05, 0x27, 0xE0, 0x54, 0xBF, 0xF0, +0x90, 0x81, 0x86, 0x74, 0x04, 0xF0, 0x22, 0xD1, +0xA7, 0x7B, 0x20, 0x12, 0x57, 0xF5, 0xD1, 0xD9, +0x90, 0x81, 0x86, 0x74, 0x02, 0xF0, 0x22, 0x80, +0xF5, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0xE4, 0x90, 0x83, 0x46, 0xF0, 0xA3, 0xF0, 0x12, +0x57, 0x8C, 0x90, 0x85, 0xBB, 0x12, 0x20, 0xDA, +0xCC, 0xF0, 0x00, 0xC0, 0x12, 0x89, 0xC7, 0x12, +0x20, 0xDA, 0x00, 0x00, 0x00, 0x14, 0x12, 0x8A, +0x59, 0x12, 0x20, 0xDA, 0x00, 0x00, 0x00, 0x00, +0xE4, 0xFD, 0xFF, 0x12, 0x77, 0x52, 0x7F, 0xE8, +0x7E, 0x08, 0x12, 0x2D, 0x5C, 0xEF, 0x54, 0x0E, +0xFF, 0xE4, 0xFE, 0xED, 0x54, 0xF4, 0xFD, 0xEC, +0x54, 0x03, 0xFC, 0xE4, 0xFB, 0xFA, 0xF9, 0xF8, +0xC3, 0x12, 0x47, 0x8C, 0x60, 0x1A, 0xD3, 0x12, +0x8A, 0x15, 0x40, 0x09, 0x90, 0x01, 0xC3, 0xE0, +0x44, 0x02, 0xF0, 0x80, 0x0B, 0x12, 0x8A, 0xC6, +0x90, 0x83, 0x46, 0x12, 0x77, 0x75, 0x80, 0xC6, +0xC3, 0x12, 0x8A, 0x15, 0x50, 0x1A, 0x12, 0x8A, +0xCD, 0xEC, 0x44, 0x80, 0xFC, 0x90, 0x83, 0x48, +0x12, 0x20, 0xCE, 0x90, 0x83, 0x48, 0x12, 0x75, +0x61, 0x7F, 0x7C, 0x7E, 0x08, 0x12, 0x2E, 0xA2, +0x90, 0x01, 0x00, 0x74, 0x3F, 0xF0, 0xA3, 0xE0, +0x54, 0xFD, 0xF0, 0x90, 0x05, 0x53, 0xE0, 0x44, +0x20, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x12, +0x54, 0x6D, 0xF1, 0xC9, 0xF0, 0xC1, 0xA7, 0xF1, +0xC9, 0xF0, 0x7B, 0x23, 0x12, 0x57, 0xF5, 0xC1, +0xCE, 0x7B, 0x25, 0xC1, 0xB2, 0xD1, 0xA7, 0x7B, +0x21, 0x12, 0x57, 0xF5, 0x90, 0x81, 0x86, 0x74, +0x03, 0xF0, 0x22, 0xF1, 0x7F, 0x90, 0x05, 0x27, +0xE0, 0x54, 0xBF, 0xF0, 0xE4, 0x90, 0x81, 0x86, +0xF0, 0x22, 0x12, 0x54, 0x6B, 0xC1, 0xA7, 0xF1, +0xB2, 0x80, 0xEA, 0x12, 0x55, 0x60, 0x80, 0xDC, +0x12, 0x54, 0x6D, 0xC1, 0xA7, 0xF1, 0xC0, 0x80, +0xDC, 0x90, 0x05, 0x27, 0xE0, 0x44, 0x40, 0x22, +0x90, 0x02, 0x09, 0xE0, 0xF5, 0x56, 0x12, 0x1F, +0xA4, 0x25, 0x56, 0x90, 0x80, 0x86, 0xF0, 0x12, +0x5D, 0x33, 0x25, 0x56, 0x90, 0x80, 0x87, 0x12, +0x6A, 0x76, 0x25, 0x56, 0x90, 0x80, 0x88, 0x12, +0x67, 0xE3, 0x25, 0x56, 0x90, 0x80, 0x89, 0x12, +0x67, 0xEA, 0x25, 0x56, 0x90, 0x80, 0x8A, 0xF0, +0x11, 0x15, 0x25, 0x56, 0x90, 0x80, 0x8B, 0xF0, +0x90, 0x00, 0x06, 0x12, 0x1F, 0xBD, 0x25, 0x56, +0x90, 0x80, 0x8C, 0xF0, 0x22, 0x90, 0x00, 0x05, +0x02, 0x1F, 0xBD, 0x12, 0x1F, 0xA4, 0xFF, 0x90, +0x81, 0x79, 0xF0, 0xBF, 0x01, 0x08, 0x12, 0x7B, +0x84, 0xE4, 0x90, 0x81, 0x79, 0xF0, 0x22, 0x12, +0x1F, 0xA4, 0x54, 0x01, 0xFF, 0x90, 0x82, 0x75, +0xE0, 0x54, 0xFE, 0x4F, 0xF0, 0x22, 0x31, 0xEE, +0x54, 0x7F, 0x90, 0x81, 0x8D, 0xF0, 0xEF, 0x12, +0x7D, 0x36, 0xA3, 0xF0, 0x12, 0x5D, 0x33, 0xFD, +0x54, 0xF0, 0xC4, 0x54, 0x0F, 0xFF, 0x90, 0x81, +0x8B, 0xE0, 0x54, 0xF0, 0x4F, 0x12, 0x67, 0xE3, +0xFC, 0x54, 0x01, 0x25, 0xE0, 0xFF, 0x90, 0x81, +0x88, 0xE0, 0x54, 0xFD, 0x4F, 0xF0, 0xEC, 0x54, +0x04, 0xC3, 0x13, 0xFF, 0x90, 0x81, 0x8A, 0xE0, +0x54, 0xFD, 0x4F, 0xF0, 0xED, 0x54, 0x0F, 0xC4, +0x54, 0xF0, 0xFF, 0xA3, 0xE0, 0x54, 0x0F, 0x4F, +0x12, 0x6A, 0x76, 0x90, 0x81, 0x8C, 0x12, 0x67, +0xEA, 0xFD, 0x7F, 0x02, 0x12, 0x51, 0xC9, 0x90, +0x82, 0xFB, 0x12, 0x47, 0xE6, 0x12, 0x6E, 0x95, +0x11, 0xB1, 0xF0, 0x90, 0x81, 0x8D, 0x31, 0xF9, +0x12, 0x6F, 0x13, 0x90, 0x01, 0xBE, 0xF0, 0x22, +0xF0, 0x90, 0x01, 0xB9, 0x74, 0x01, 0xF0, 0x90, +0x01, 0xB8, 0x22, 0x90, 0x81, 0x88, 0x11, 0xE6, +0x30, 0xE0, 0x1F, 0xEF, 0x54, 0xBF, 0xF0, 0x90, +0x04, 0xE0, 0xE0, 0x90, 0x81, 0x89, 0x30, 0xE0, +0x06, 0xE0, 0x44, 0x01, 0xF0, 0x80, 0x08, 0xE0, +0x54, 0xFE, 0x11, 0xB0, 0x74, 0x04, 0xF0, 0x12, +0x6B, 0xFB, 0x22, 0x90, 0x81, 0x83, 0xE0, 0xFF, +0xC4, 0x13, 0x13, 0x54, 0x03, 0x22, 0x11, 0xE3, +0x30, 0xE0, 0x0B, 0x31, 0x05, 0x60, 0x07, 0x7D, +0x01, 0x7F, 0x02, 0x12, 0x52, 0x54, 0x31, 0x05, +0x60, 0x02, 0x31, 0x0C, 0x22, 0x90, 0x81, 0x87, +0xE0, 0x64, 0x02, 0x22, 0x90, 0x81, 0x8D, 0xE0, +0x64, 0x02, 0x60, 0x0C, 0x12, 0x6F, 0x14, 0x60, +0x07, 0x31, 0x6D, 0xEF, 0x70, 0x02, 0x31, 0x5F, +0x22, 0x90, 0x81, 0x8D, 0xE0, 0x70, 0x07, 0x90, +0x81, 0x83, 0xE0, 0x30, 0xE0, 0x11, 0x90, 0x81, +0x83, 0xE0, 0x30, 0xE0, 0x08, 0x12, 0x6B, 0x88, +0xBF, 0x01, 0x04, 0x80, 0xCF, 0x31, 0x40, 0x22, +0x90, 0x81, 0x8D, 0xE0, 0x64, 0x01, 0x70, 0x15, +0x12, 0x6F, 0x14, 0x60, 0x07, 0x31, 0x5E, 0x12, +0x54, 0x6D, 0x41, 0x46, 0x90, 0x81, 0x90, 0xE0, +0x70, 0x03, 0x12, 0x52, 0x50, 0x22, 0xE4, 0xFD, +0x7F, 0x0C, 0x02, 0x52, 0x54, 0x31, 0x6D, 0xEF, +0x70, 0x02, 0x31, 0x40, 0x22, 0x90, 0x04, 0x1A, +0xE0, 0xF4, 0x60, 0x03, 0x7F, 0x00, 0x22, 0x90, +0x04, 0x1B, 0xE0, 0x54, 0x07, 0x64, 0x07, 0x7F, +0x01, 0x60, 0x02, 0x7F, 0x00, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x31, 0x6D, 0xEF, +0x64, 0x01, 0x60, 0x05, 0x75, 0x0D, 0x01, 0x80, +0x42, 0x90, 0x81, 0x91, 0xE0, 0xFF, 0x54, 0x03, +0x60, 0x05, 0x75, 0x0D, 0x02, 0x80, 0x34, 0xEF, +0x30, 0xE2, 0x05, 0x75, 0x0D, 0x08, 0x80, 0x2B, +0x90, 0x81, 0x91, 0xE0, 0x30, 0xE4, 0x05, 0x75, +0x0D, 0x10, 0x80, 0x1F, 0x12, 0x6D, 0x80, 0x20, +0xE0, 0x05, 0x75, 0x0D, 0x20, 0x80, 0x14, 0x51, +0x06, 0x8F, 0x0E, 0xE5, 0x0E, 0x64, 0x01, 0x60, +0x05, 0x85, 0x0E, 0x0D, 0x80, 0x05, 0x12, 0x77, +0x83, 0x80, 0x0E, 0x90, 0x01, 0xB9, 0x74, 0x04, +0xF0, 0x90, 0x01, 0xB8, 0xE5, 0x0D, 0xF0, 0x7F, +0x00, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x82, +0xFB, 0x12, 0x47, 0xEF, 0x12, 0x1F, 0xA4, 0xFF, +0x22, 0xE0, 0x90, 0x01, 0xBA, 0xF0, 0x90, 0x81, +0x8F, 0xE0, 0x90, 0x01, 0xBB, 0x22, 0x90, 0x81, +0x8F, 0xE0, 0xD3, 0x94, 0x00, 0x40, 0x06, 0x75, +0x5A, 0x04, 0x7F, 0xFF, 0x22, 0x90, 0x82, 0x65, +0xE0, 0x60, 0x06, 0x75, 0x5A, 0x80, 0x7F, 0xFF, +0x22, 0x7F, 0x01, 0x22, 0x90, 0x81, 0x83, 0xE0, +0xFF, 0x30, 0xE0, 0x04, 0x31, 0x05, 0x60, 0x15, +0x90, 0x81, 0x8D, 0xE0, 0x70, 0x04, 0xEF, 0x30, +0xE0, 0x0B, 0x90, 0x81, 0x90, 0xE0, 0x64, 0x02, +0x60, 0x03, 0x12, 0x6C, 0x6E, 0x22, 0x12, 0x5A, +0xDE, 0x30, 0xE0, 0x05, 0x90, 0x01, 0x5B, 0xE4, +0xF0, 0x90, 0x06, 0x92, 0x74, 0x02, 0xF0, 0x90, +0x01, 0x3C, 0x74, 0x04, 0xF0, 0xE4, 0xF5, 0x1D, +0x90, 0x82, 0x61, 0xE0, 0xC3, 0x13, 0x54, 0x7F, +0xF5, 0x1E, 0xE4, 0xFB, 0xFD, 0x7F, 0x58, 0x7E, +0x01, 0x12, 0x51, 0x11, 0x90, 0x81, 0x88, 0xE0, +0x44, 0x08, 0xF0, 0x22, 0x90, 0x81, 0x8D, 0xE0, +0x60, 0x0E, 0x90, 0x06, 0x92, 0xE0, 0x30, 0xE1, +0x02, 0x80, 0xBB, 0x51, 0x91, 0x12, 0x6B, 0xFB, +0x22, 0x90, 0x81, 0x88, 0xE0, 0x54, 0xF7, 0xF0, +0x22, 0x90, 0x81, 0x83, 0xE0, 0xFF, 0x30, 0xE0, +0x3E, 0x90, 0x81, 0x87, 0xE0, 0x7E, 0x00, 0xB4, +0x02, 0x02, 0x7E, 0x01, 0x90, 0x81, 0x86, 0xE0, +0x7D, 0x00, 0xB4, 0x04, 0x02, 0x7D, 0x01, 0xED, +0x4E, 0x70, 0x24, 0xEF, 0xC3, 0x13, 0x30, 0xE0, +0x03, 0x02, 0x7D, 0xAC, 0x11, 0xEE, 0x90, 0x81, +0x87, 0xE0, 0xB4, 0x08, 0x06, 0xE4, 0xFD, 0x7F, +0x0C, 0x80, 0x09, 0x90, 0x81, 0x87, 0xE0, 0x70, +0x06, 0xFD, 0x7F, 0x04, 0x12, 0x52, 0x54, 0x22, +0x12, 0x1F, 0xA4, 0x90, 0x82, 0x65, 0xF0, 0x22, +0x12, 0x1F, 0xA4, 0x90, 0x82, 0x73, 0xF0, 0x12, +0x5D, 0x33, 0x90, 0x82, 0x74, 0xF0, 0x22, 0xE4, +0x90, 0x81, 0x75, 0xF0, 0xA3, 0xF0, 0x90, 0x80, +0xDD, 0xF0, 0xA3, 0xF0, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x82, 0xF7, 0x12, +0x47, 0xEF, 0x90, 0x83, 0x69, 0xE0, 0xFF, 0x04, +0xF0, 0x12, 0x63, 0x5D, 0x7F, 0xAF, 0x7E, 0x01, +0x12, 0x77, 0x93, 0xEF, 0x60, 0x3A, 0x90, 0x82, +0xF7, 0x12, 0x47, 0xE6, 0x8B, 0x13, 0x8A, 0x14, +0x89, 0x15, 0x90, 0x00, 0x0E, 0x12, 0x1F, 0xBD, +0x24, 0x02, 0xF5, 0x16, 0x7B, 0x01, 0x7A, 0x01, +0x79, 0xA0, 0x12, 0x2B, 0xED, 0x90, 0x82, 0xF7, +0x12, 0x47, 0xE6, 0x90, 0x00, 0x0E, 0x12, 0x1F, +0xBD, 0x90, 0x01, 0xAE, 0xF0, 0xA3, 0x74, 0xFF, +0xF0, 0x90, 0x01, 0xCB, 0xE0, 0x64, 0x80, 0xF0, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x75, 0x3D, 0x10, +0xE4, 0xF5, 0x3E, 0x75, 0x3F, 0x07, 0x75, 0x40, +0x22, 0x90, 0x01, 0x30, 0xE5, 0x3D, 0xF0, 0xA3, +0xE5, 0x3E, 0xF0, 0xA3, 0xE5, 0x3F, 0xF0, 0xA3, +0xE5, 0x40, 0xF0, 0x22, 0x75, 0x45, 0x07, 0x75, +0x46, 0x01, 0x43, 0x46, 0x10, 0x75, 0x47, 0x03, +0x75, 0x48, 0x62, 0x90, 0x01, 0x38, 0xE5, 0x45, +0xF0, 0xA3, 0xE5, 0x46, 0xF0, 0xA3, 0xE5, 0x47, +0xF0, 0xA3, 0xE5, 0x48, 0xF0, 0x22, 0x90, 0x01, +0x94, 0xE0, 0x44, 0x01, 0xF0, 0x90, 0x01, 0xC7, +0xE4, 0xF0, 0x22, 0x90, 0x01, 0x01, 0xE0, 0x44, +0x04, 0xF0, 0x90, 0x01, 0x9C, 0x74, 0x7E, 0xF0, +0xA3, 0x74, 0x92, 0xF0, 0xA3, 0x74, 0xA0, 0xF0, +0xA3, 0x74, 0x24, 0xF0, 0x90, 0x01, 0x9B, 0x74, +0x49, 0xF0, 0x90, 0x01, 0x9A, 0x74, 0xE0, 0xF0, +0x90, 0x01, 0x99, 0xE4, 0xF0, 0x90, 0x01, 0x98, +0x04, 0xF0, 0x22, 0xE4, 0x90, 0x82, 0x88, 0xF0, +0xA3, 0xF0, 0x90, 0x01, 0x98, 0xE0, 0x7F, 0x00, +0x30, 0xE4, 0x02, 0x7F, 0x01, 0xEF, 0x64, 0x01, +0x60, 0x41, 0xC3, 0x90, 0x82, 0x89, 0xE0, 0x94, +0x88, 0x90, 0x82, 0x88, 0xE0, 0x94, 0x13, 0x40, +0x0F, 0x90, 0x01, 0xC1, 0xE0, 0x44, 0x10, 0xF0, +0x90, 0x01, 0xC7, 0x74, 0xFD, 0xF0, 0x80, 0x23, +0x90, 0x82, 0x88, 0x12, 0x77, 0x75, 0x7F, 0x14, +0x7E, 0x00, 0x12, 0x32, 0xAA, 0xD3, 0x90, 0x82, +0x89, 0xE0, 0x94, 0x32, 0x90, 0x82, 0x88, 0xE0, +0x94, 0x00, 0x40, 0xB6, 0x90, 0x01, 0xC6, 0xE0, +0x30, 0xE3, 0xAF, 0x90, 0x01, 0xC7, 0x74, 0xFE, +0xF0, 0x22, 0x7F, 0x02, 0x90, 0x82, 0x72, 0xE0, +0xFE, 0xEF, 0xC3, 0x9E, 0x50, 0x18, 0xEF, 0x25, +0xE0, 0x24, 0x81, 0xF8, 0xE6, 0x30, 0xE4, 0x0B, +0x90, 0x01, 0xB8, 0x74, 0x08, 0xF0, 0xA3, 0xF0, +0x7F, 0x00, 0x22, 0x0F, 0x80, 0xDE, 0x7F, 0x01, +0x22, 0x90, 0x01, 0xE4, 0x74, 0x1C, 0xF0, 0xA3, +0xE4, 0xF0, 0x22, 0x90, 0x01, 0x34, 0xE0, 0x55, +0x3D, 0xF5, 0x41, 0xA3, 0xE0, 0x55, 0x3E, 0xF5, +0x42, 0xA3, 0xE0, 0x55, 0x3F, 0xF5, 0x43, 0xA3, +0xE0, 0x55, 0x40, 0xF5, 0x44, 0x90, 0x01, 0x34, +0xE5, 0x41, 0xF0, 0xA3, 0xE5, 0x42, 0xF0, 0xA3, +0xE5, 0x43, 0xF0, 0xA3, 0xE5, 0x44, 0xF0, 0x22, +0x90, 0x01, 0x3C, 0xE0, 0x55, 0x45, 0xF5, 0x49, +0xA3, 0xE0, 0x55, 0x46, 0xF5, 0x4A, 0xA3, 0xE0, +0x55, 0x47, 0xF5, 0x4B, 0xA3, 0xE0, 0x55, 0x48, +0xF5, 0x4C, 0x90, 0x01, 0x3C, 0xE5, 0x49, 0xF0, +0xA3, 0xE5, 0x4A, 0xF0, 0xA3, 0xE5, 0x4B, 0xF0, +0xA3, 0xE5, 0x4C, 0xF0, 0x53, 0x91, 0xDF, 0x22, +0x90, 0x01, 0xCF, 0xE0, 0x90, 0x83, 0x6F, 0xF0, +0xE0, 0xFF, 0x30, 0xE0, 0x07, 0x90, 0x01, 0xCF, +0xE0, 0x54, 0xFE, 0xF0, 0xEF, 0x30, 0xE5, 0x23, +0x90, 0x01, 0xCF, 0xE0, 0x54, 0xDF, 0xF0, 0x90, +0x01, 0x34, 0x74, 0x20, 0xF0, 0xE4, 0xF5, 0xA8, +0xF5, 0xE8, 0x12, 0x68, 0x65, 0x90, 0x00, 0x03, +0xE0, 0x54, 0xFB, 0xFD, 0x7F, 0x03, 0x12, 0x32, +0x1E, 0x80, 0xFE, 0x22, 0x90, 0x81, 0x83, 0xE0, +0x30, 0xE0, 0x05, 0xE4, 0xA3, 0xF0, 0xA3, 0xF0, +0x22, 0xB1, 0xC3, 0x90, 0x82, 0x84, 0xEF, 0xF0, +0x30, 0xE0, 0x05, 0x7D, 0x01, 0xE4, 0x80, 0x02, +0xE4, 0xFD, 0xFF, 0x12, 0x51, 0xC9, 0x90, 0x82, +0x84, 0xE0, 0x30, 0xE6, 0x11, 0x90, 0x01, 0x2F, +0xE0, 0x30, 0xE7, 0x04, 0xE4, 0xF0, 0x80, 0x06, +0x90, 0x01, 0x2F, 0x74, 0x80, 0xF0, 0x90, 0x81, +0x88, 0xE0, 0x90, 0x04, 0xEC, 0x30, 0xE0, 0x06, +0xE0, 0x54, 0xDD, 0xF0, 0x80, 0x04, 0xE0, 0x44, +0x22, 0xF0, 0xB1, 0x63, 0x74, 0x02, 0xF0, 0x02, +0x5B, 0x02, 0xF0, 0x90, 0x81, 0x9F, 0xE0, 0xFF, +0xA3, 0xE0, 0xFD, 0x90, 0x81, 0xA6, 0xE0, 0xFB, +0x90, 0x83, 0x60, 0x22, 0xB1, 0xB7, 0x40, 0x29, +0x90, 0x81, 0xA7, 0xE0, 0x04, 0xF0, 0x90, 0x82, +0x5E, 0xE0, 0xFF, 0x90, 0x81, 0xA7, 0xE0, 0xD3, +0x9F, 0x50, 0x16, 0x90, 0x81, 0x9F, 0xE0, 0x04, +0xF0, 0x12, 0x51, 0xB0, 0x90, 0x81, 0xA6, 0xB1, +0xA2, 0xB1, 0x62, 0x74, 0x04, 0xF0, 0x12, 0x5B, +0x02, 0x22, 0xF0, 0xE4, 0x90, 0x82, 0x4B, 0xF0, +0xA3, 0x22, 0x90, 0x81, 0x96, 0xE0, 0x04, 0xF0, +0x90, 0x81, 0x91, 0xE0, 0x54, 0xEF, 0xF0, 0x90, +0x82, 0x5F, 0xE0, 0xFF, 0x90, 0x81, 0x96, 0xE0, +0xD3, 0x9F, 0x22, 0xE4, 0x90, 0x82, 0x86, 0xF0, +0xA3, 0xF0, 0x90, 0x00, 0x83, 0xE0, 0x90, 0x82, +0x85, 0xF0, 0x90, 0x00, 0x83, 0xE0, 0xFE, 0x90, +0x82, 0x85, 0xE0, 0xFF, 0xB5, 0x06, 0x01, 0x22, +0xC3, 0x90, 0x82, 0x87, 0xE0, 0x94, 0x64, 0x90, +0x82, 0x86, 0xE0, 0x94, 0x00, 0x40, 0x0D, 0x90, +0x01, 0xC0, 0xE0, 0x44, 0x40, 0xF0, 0x90, 0x82, +0x85, 0xE0, 0xFF, 0x22, 0x90, 0x82, 0x86, 0x12, +0x77, 0x75, 0x80, 0xC6, 0x90, 0x82, 0x73, 0xE0, +0x60, 0x0F, 0xE4, 0xF0, 0x90, 0x05, 0x53, 0xE0, +0x44, 0x01, 0xF0, 0x90, 0x05, 0xFD, 0xE0, 0x04, +0xF0, 0x22, 0x90, 0x81, 0x83, 0xE0, 0xFF, 0x30, +0xE0, 0x40, 0x90, 0x81, 0x87, 0xE0, 0x7E, 0x00, +0xB4, 0x02, 0x02, 0x7E, 0x01, 0x90, 0x81, 0x86, +0xE0, 0x7D, 0x00, 0xB4, 0x04, 0x02, 0x7D, 0x01, +0xED, 0x4E, 0x70, 0x26, 0xEF, 0xC3, 0x13, 0x30, +0xE0, 0x03, 0x02, 0x7D, 0xAC, 0x12, 0x6C, 0x41, +0x90, 0x81, 0x87, 0xE0, 0xB4, 0x0C, 0x06, 0xE4, +0xFD, 0x7F, 0x08, 0x80, 0x0A, 0x90, 0x81, 0x87, +0xE0, 0xB4, 0x04, 0x06, 0xE4, 0xFD, 0xFF, 0x12, +0x52, 0x54, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x83, 0x56, 0xED, 0xF0, 0xA3, +0xEB, 0xF0, 0x90, 0x83, 0x55, 0xEF, 0xF0, 0xE4, +0xFD, 0xFC, 0xF1, 0xB8, 0x7C, 0x00, 0xAD, 0x07, +0x90, 0x83, 0x55, 0xE0, 0x90, 0x04, 0x25, 0xF0, +0x90, 0x83, 0x56, 0xE0, 0x60, 0x0E, 0x74, 0x0F, +0x2F, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, +0xE0, 0x44, 0x80, 0xF0, 0xAF, 0x05, 0x74, 0x08, +0x2F, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, +0xE4, 0xF0, 0x74, 0x09, 0x2F, 0xF5, 0x82, 0xE4, +0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x54, 0xF0, 0xF0, +0xAF, 0x05, 0x74, 0x16, 0x2F, 0xD1, 0xFF, 0xE0, +0x20, 0xE1, 0x18, 0x54, 0x01, 0xFE, 0x90, 0x83, +0x57, 0xE0, 0x25, 0xE0, 0x25, 0xE0, 0xFB, 0xEE, +0x44, 0x02, 0x4B, 0xFE, 0x74, 0x16, 0x2F, 0xD1, +0xFF, 0xEE, 0xF0, 0x90, 0x83, 0x58, 0xE0, 0xFF, +0xAE, 0x05, 0x74, 0x1E, 0x2E, 0xF5, 0x82, 0xE4, +0x34, 0xFC, 0xF5, 0x83, 0xEF, 0xF0, 0x74, 0x21, +0x2E, 0xF1, 0xAF, 0x54, 0xF7, 0xF0, 0xAE, 0x04, +0xAF, 0x05, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xF5, +0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0x22, 0x90, +0x80, 0x88, 0xE0, 0xFF, 0x90, 0x83, 0x4D, 0xE0, +0xFB, 0x90, 0x83, 0x58, 0x74, 0x0A, 0xF0, 0x7D, +0x01, 0xD1, 0x63, 0x90, 0x83, 0x4E, 0xEE, 0xF0, +0xFC, 0xA3, 0xEF, 0xF0, 0xFD, 0x90, 0x83, 0x4C, +0xE0, 0xFF, 0x12, 0x57, 0x17, 0x90, 0x83, 0x4E, +0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x04, 0x80, +0xE0, 0x54, 0x0F, 0xFD, 0xAC, 0x07, 0xF1, 0xA0, +0x44, 0x01, 0xF0, 0xF1, 0xA0, 0x54, 0xFB, 0xF0, +0xAC, 0x07, 0x74, 0x16, 0x2C, 0xD1, 0xFF, 0xE0, +0x44, 0xFA, 0xF0, 0x74, 0x15, 0x2C, 0xF5, 0x82, +0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x1F, +0xF0, 0xAC, 0x07, 0x74, 0x06, 0x2C, 0xF5, 0x82, +0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x0F, +0xF0, 0x90, 0x04, 0x53, 0xE4, 0xF0, 0x90, 0x04, +0x52, 0xF0, 0x90, 0x04, 0x51, 0x74, 0xFF, 0xF0, +0x90, 0x04, 0x50, 0x74, 0xFD, 0xF0, 0x74, 0x14, +0x2C, 0xF1, 0x98, 0xE0, 0x54, 0xC0, 0x4D, 0xFD, +0x74, 0x14, 0x2F, 0xF1, 0x98, 0xED, 0xF0, 0x22, +0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0x22, +0x74, 0x11, 0x2C, 0xF5, 0x82, 0xE4, 0x34, 0xFC, +0xF5, 0x83, 0xE0, 0x22, 0x74, 0x21, 0x2D, 0xF5, +0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x22, +0xE4, 0xFE, 0xEF, 0xC3, 0x13, 0xFD, 0xEF, 0x30, +0xE0, 0x02, 0x7E, 0x80, 0x90, 0xFD, 0x10, 0xED, +0xF0, 0xAF, 0x06, 0x22, 0x90, 0x01, 0xC4, 0x74, +0xCC, 0xF0, 0x74, 0x87, 0xA3, 0xF0, 0x90, 0x00, +0x90, 0xE0, 0x20, 0xE0, 0xF9, 0x74, 0xCC, 0x04, +0x90, 0x01, 0xC4, 0xF0, 0x74, 0x87, 0xA3, 0xF0, +0x22, 0xEF, 0x24, 0xFE, 0x60, 0x0B, 0x04, 0x70, +0x24, 0x90, 0x81, 0x93, 0x74, 0x02, 0xF0, 0x80, +0x13, 0xED, 0x70, 0x06, 0x90, 0x82, 0x62, 0xE0, +0x80, 0x02, 0xED, 0x14, 0x90, 0x81, 0x93, 0xF0, +0x90, 0x81, 0x93, 0xE0, 0xA3, 0xF0, 0x90, 0x81, +0x89, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x7B, 0x2D, +0x12, 0x57, 0xF5, 0x12, 0x57, 0x8C, 0x90, 0x01, +0x37, 0x74, 0x02, 0xF0, 0xFD, 0x7F, 0x03, 0x12, +0x6D, 0xAB, 0x12, 0x7E, 0xD9, 0xE4, 0xFD, 0x7F, +0x01, 0x12, 0x51, 0xC9, 0xE4, 0x90, 0x81, 0x87, +0xF0, 0x22, 0x12, 0x54, 0x6D, 0x11, 0x49, 0x44, +0x40, 0xF0, 0x90, 0x81, 0x87, 0x74, 0x04, 0xF0, +0x22, 0x7D, 0x04, 0x7F, 0x01, 0x12, 0x51, 0xC9, +0x90, 0x05, 0x27, 0xE0, 0x22, 0x90, 0x82, 0x59, +0x74, 0x18, 0xF0, 0xA3, 0x74, 0x03, 0xF0, 0xA3, +0xE4, 0xF0, 0xA3, 0x74, 0x64, 0xF0, 0xA3, 0x74, +0x01, 0xF0, 0xA3, 0x74, 0x05, 0xF0, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x83, +0x72, 0xEF, 0xF0, 0x7E, 0x00, 0x7F, 0xA0, 0x7D, +0x00, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0xAB, 0x12, +0x48, 0x1E, 0xE4, 0x90, 0x81, 0xA4, 0xF0, 0x90, +0x81, 0xA3, 0xF0, 0x90, 0x81, 0xA7, 0xF0, 0x90, +0x83, 0x72, 0xE0, 0xB4, 0x01, 0x09, 0x90, 0x81, +0xA8, 0x74, 0x14, 0xF0, 0xE4, 0xA3, 0xF0, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x90, 0x82, 0x66, 0xE0, +0x54, 0xFE, 0xF0, 0x54, 0xFD, 0xF0, 0x54, 0xEF, +0xF0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x82, 0x66, +0xE0, 0x30, 0xE0, 0x0B, 0xE4, 0xF5, 0x1D, 0x90, +0x82, 0x68, 0x12, 0x51, 0x07, 0x11, 0xE9, 0x90, +0x80, 0x42, 0xE0, 0xB4, 0x01, 0x12, 0x11, 0xF1, +0x13, 0x54, 0x1F, 0x20, 0xE0, 0x0A, 0xEF, 0xC4, +0x13, 0x54, 0x07, 0x30, 0xE0, 0x02, 0x11, 0xF9, +0x22, 0x90, 0x82, 0x66, 0xE0, 0x44, 0x10, 0xF0, +0x22, 0x90, 0x82, 0x66, 0xE0, 0xFF, 0x13, 0x13, +0x22, 0x90, 0x82, 0x66, 0xE0, 0x30, 0xE0, 0x34, +0xC4, 0x13, 0x54, 0x07, 0x30, 0xE0, 0x2D, 0x90, +0x83, 0x73, 0xE0, 0x04, 0xF0, 0xE0, 0xD3, 0x94, +0xC8, 0x40, 0x21, 0x90, 0x82, 0x66, 0xE0, 0x54, +0xDF, 0xF0, 0xE4, 0x90, 0x83, 0x73, 0xF0, 0x90, +0x82, 0x66, 0xE0, 0x13, 0x30, 0xE0, 0x0D, 0x90, +0x81, 0x88, 0xE0, 0x44, 0x01, 0xF0, 0x90, 0x81, +0x98, 0x74, 0xD0, 0xF0, 0x22, 0x7B, 0x22, 0x12, +0x57, 0xF5, 0x12, 0x7F, 0xC9, 0xF0, 0x02, 0x7F, +0x9C, 0x12, 0x55, 0x60, 0x7B, 0x24, 0x02, 0x7E, +0xB2, 0x90, 0x81, 0x86, 0xE0, 0x64, 0x02, 0x7F, +0x01, 0x60, 0x02, 0x7F, 0x00, 0x22, 0x90, 0x05, +0x63, 0xE0, 0x90, 0x82, 0x55, 0xF0, 0x90, 0x05, +0x62, 0xE0, 0x90, 0x82, 0x56, 0xF0, 0x90, 0x05, +0x61, 0xE0, 0x90, 0x82, 0x57, 0xF0, 0x90, 0x05, +0x60, 0xE0, 0x90, 0x82, 0x58, 0xF0, 0x90, 0x81, +0x89, 0xE0, 0x44, 0x80, 0xF0, 0x22, 0x7B, 0xFE, +0x7A, 0x80, 0x79, 0x33, 0x12, 0x2B, 0xED, 0x90, +0x82, 0xA6, 0xE0, 0xFF, 0x90, 0x82, 0xA5, 0xE0, +0xFD, 0xE4, 0x90, 0x82, 0xF5, 0x22, 0x90, 0x82, +0x4C, 0xE0, 0x24, 0x01, 0xFF, 0x90, 0x82, 0x4B, +0xE0, 0x34, 0x00, 0xFE, 0x12, 0x32, 0xAA, 0x90, +0x81, 0x90, 0xE0, 0x22, 0xF0, 0x90, 0x81, 0x99, +0xA3, 0xE0, 0x90, 0x05, 0x58, 0xF0, 0x22, 0xF0, +0x90, 0x81, 0xAA, 0xE0, 0x24, 0x05, 0x90, 0x81, +0xA5, 0xF0, 0xA3, 0x74, 0x10, 0xF0, 0x22, 0x7F, +0x8C, 0x7E, 0x08, 0x12, 0x2E, 0xA2, 0x90, 0x85, +0xBB, 0x22, 0x90, 0x01, 0x34, 0x74, 0x40, 0xF0, +0xFD, 0xE4, 0xFF, 0x12, 0x6D, 0xAB, 0x43, 0x59, +0x08, 0x22, 0x75, 0xF0, 0x08, 0xA4, 0xFF, 0xAE, +0xF0, 0x24, 0x49, 0xF9, 0x74, 0x93, 0x3E, 0x22, +0xE0, 0x54, 0xFE, 0x4E, 0xFE, 0xF0, 0xEF, 0x54, +0x02, 0xFF, 0xEE, 0x54, 0xFD, 0x22, 0x90, 0x81, +0x83, 0xE0, 0xC4, 0x13, 0x13, 0x54, 0x03, 0x22, +0x7E, 0x00, 0x7F, 0x04, 0x7D, 0x00, 0x7B, 0x01, +0x7A, 0x82, 0x79, 0x6E, 0x22, 0x90, 0x83, 0x47, +0xE0, 0x94, 0xE8, 0x90, 0x83, 0x46, 0xE0, 0x94, +0x03, 0x22, 0x24, 0xCB, 0xF5, 0x82, 0xE4, 0x34, +0x95, 0x22, 0x25, 0xE0, 0x24, 0x4B, 0xF5, 0x82, +0xE4, 0x34, 0x95, 0xF5, 0x83, 0x22, 0x90, 0x06, +0x04, 0xE0, 0x44, 0x40, 0xF0, 0xE0, 0x44, 0x80, +0xF0, 0x22, 0xE0, 0xFF, 0x75, 0xF0, 0x08, 0x90, +0x93, 0x46, 0x02, 0x47, 0xDA, 0x12, 0x47, 0xEF, +0x74, 0x47, 0x2F, 0xF9, 0x74, 0x93, 0x3E, 0xFA, +0x22, 0x7F, 0x70, 0x7E, 0x0E, 0x12, 0x2E, 0xA2, +0x90, 0x83, 0x42, 0x22, 0x90, 0x82, 0x66, 0xE0, +0xC3, 0x13, 0x22, 0x90, 0x04, 0x1F, 0x74, 0x20, +0xF0, 0x22, 0x90, 0x82, 0x6F, 0xE0, 0x14, 0x90, +0x82, 0x71, 0xF0, 0x22, 0xAB, 0x56, 0xAA, 0x57, +0xA9, 0x58, 0x02, 0x1F, 0xA4, 0x12, 0x47, 0x7F, +0x90, 0x82, 0xA7, 0x02, 0x20, 0xCE, 0x90, 0x06, +0x04, 0xE0, 0x54, 0x7F, 0xF0, 0x22, 0x90, 0x81, +0x88, 0xE0, 0x54, 0xBF, 0xF0, 0x22, 0x90, 0x81, +0x8A, 0xE0, 0x54, 0xFE, 0xF0, 0x22, 0x90, 0x81, +0x93, 0xE0, 0x90, 0x05, 0x73, 0x22, 0xF5, 0x82, +0xE4, 0x34, 0x96, 0xF5, 0x83, 0x22, 0xF5, 0x82, +0xE4, 0x34, 0x98, 0xF5, 0x83, 0x22, 0x2F, 0xF8, +0xE6, 0xFE, 0xED, 0xF4, 0x5E, 0x22, 0x7F, 0x32, +0x7E, 0x00, 0x02, 0x32, 0xAA, 0x7F, 0x7C, 0x7E, +0x08, 0x02, 0x2D, 0x5C, 0x90, 0x81, 0x83, 0xE0, +0xFF, 0x13, 0x13, 0x22, 0xF5, 0x82, 0xE4, 0x34, +0x82, 0xF5, 0x83, 0x22, 0x66, 0x1A +}; + +u32 array_length_mp_8188e_s_fw_nic = 19206; + +#ifdef CONFIG_WOWLAN + +u8 array_mp_8188e_s_fw_wowlan[] = { +0xE3, 0x88, 0x30, 0x00, 0x1C, 0x00, 0x00, 0x00, +0x05, 0x04, 0x22, 0x24, 0x96, 0x58, 0x02, 0x00, +0xA5, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x02, 0x49, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x02, 0x4A, 0x43, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x02, 0x57, 0xF7, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x02, 0x49, 0xBA, 0x00, 0x00, +0x00, 0x00, 0x00, 0x02, 0x4F, 0xFA, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xE7, 0x09, 0xF6, 0x08, 0xDF, 0xFA, 0x80, 0x46, +0xE7, 0x09, 0xF2, 0x08, 0xDF, 0xFA, 0x80, 0x3E, +0x88, 0x82, 0x8C, 0x83, 0xE7, 0x09, 0xF0, 0xA3, +0xDF, 0xFA, 0x80, 0x32, 0xE3, 0x09, 0xF6, 0x08, +0xDF, 0xFA, 0x80, 0x78, 0xE3, 0x09, 0xF2, 0x08, +0xDF, 0xFA, 0x80, 0x70, 0x88, 0x82, 0x8C, 0x83, +0xE3, 0x09, 0xF0, 0xA3, 0xDF, 0xFA, 0x80, 0x64, +0x89, 0x82, 0x8A, 0x83, 0xE0, 0xA3, 0xF6, 0x08, +0xDF, 0xFA, 0x80, 0x58, 0x89, 0x82, 0x8A, 0x83, +0xE0, 0xA3, 0xF2, 0x08, 0xDF, 0xFA, 0x80, 0x4C, +0x80, 0xD2, 0x80, 0xFA, 0x80, 0xC6, 0x80, 0xD4, +0x80, 0x69, 0x80, 0xF2, 0x80, 0x33, 0x80, 0x10, +0x80, 0xA6, 0x80, 0xEA, 0x80, 0x9A, 0x80, 0xA8, +0x80, 0xDA, 0x80, 0xE2, 0x80, 0xCA, 0x80, 0x33, +0x89, 0x82, 0x8A, 0x83, 0xEC, 0xFA, 0xE4, 0x93, +0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, 0xC5, 0x83, +0xCC, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, +0xC5, 0x83, 0xCC, 0xDF, 0xE9, 0xDE, 0xE7, 0x80, +0x0D, 0x89, 0x82, 0x8A, 0x83, 0xE4, 0x93, 0xA3, +0xF6, 0x08, 0xDF, 0xF9, 0xEC, 0xFA, 0xA9, 0xF0, +0xED, 0xFB, 0x22, 0x89, 0x82, 0x8A, 0x83, 0xEC, +0xFA, 0xE0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, +0xC5, 0x83, 0xCC, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, +0xC8, 0xCC, 0xC5, 0x83, 0xCC, 0xDF, 0xEA, 0xDE, +0xE8, 0x80, 0xDB, 0x89, 0x82, 0x8A, 0x83, 0xE4, +0x93, 0xA3, 0xF2, 0x08, 0xDF, 0xF9, 0x80, 0xCC, +0x88, 0xF0, 0xEF, 0x60, 0x01, 0x0E, 0x4E, 0x60, +0xC3, 0x88, 0xF0, 0xED, 0x24, 0x02, 0xB4, 0x04, +0x00, 0x50, 0xB9, 0xF5, 0x82, 0xEB, 0x24, 0x02, +0xB4, 0x04, 0x00, 0x50, 0xAF, 0x23, 0x23, 0x45, +0x82, 0x23, 0x90, 0x43, 0x50, 0x73, 0xC5, 0xF0, +0xF8, 0xA3, 0xE0, 0x28, 0xF0, 0xC5, 0xF0, 0xF8, +0xE5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83, +0xE0, 0x38, 0xF0, 0x22, 0xEF, 0x2B, 0xFF, 0xEE, +0x3A, 0xFE, 0xED, 0x39, 0xFD, 0xEC, 0x38, 0xFC, +0x22, 0xC3, 0xEF, 0x9B, 0xFF, 0xEE, 0x9A, 0xFE, +0xED, 0x99, 0xFD, 0xEC, 0x98, 0xFC, 0x22, 0xEF, +0x4B, 0xFF, 0xEE, 0x4A, 0xFE, 0xED, 0x49, 0xFD, +0xEC, 0x48, 0xFC, 0x22, 0xEB, 0x9F, 0xF5, 0xF0, +0xEA, 0x9E, 0x42, 0xF0, 0xE9, 0x9D, 0x42, 0xF0, +0xE8, 0x9C, 0x45, 0xF0, 0x22, 0xE0, 0xFC, 0xA3, +0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, +0x22, 0xE0, 0xF8, 0xA3, 0xE0, 0xF9, 0xA3, 0xE0, +0xFA, 0xA3, 0xE0, 0xFB, 0x22, 0xA4, 0x25, 0x82, +0xF5, 0x82, 0xE5, 0xF0, 0x35, 0x83, 0xF5, 0x83, +0x22, 0xE0, 0xFB, 0xA3, 0xE0, 0xFA, 0xA3, 0xE0, +0xF9, 0x22, 0xEB, 0xF0, 0xA3, 0xEA, 0xF0, 0xA3, +0xE9, 0xF0, 0x22, 0xD0, 0x83, 0xD0, 0x82, 0xF8, +0xE4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, +0x0D, 0xA3, 0xA3, 0x93, 0xF8, 0x74, 0x01, 0x93, +0xF5, 0x82, 0x88, 0x83, 0xE4, 0x73, 0x74, 0x02, +0x93, 0x68, 0x60, 0xEF, 0xA3, 0xA3, 0xA3, 0x80, +0xDF, 0xE3, 0xF5, 0xF0, 0x09, 0xE2, 0x08, 0xB5, +0xF0, 0x6B, 0xDF, 0xF5, 0x80, 0x67, 0xE3, 0xF5, +0xF0, 0x09, 0xE6, 0x08, 0xB5, 0xF0, 0x5E, 0xDF, +0xF5, 0x80, 0x5A, 0x87, 0xF0, 0x09, 0xE6, 0x08, +0xB5, 0xF0, 0x52, 0xDF, 0xF6, 0x80, 0x4E, 0x87, +0xF0, 0x09, 0xE2, 0x08, 0xB5, 0xF0, 0x46, 0xDF, +0xF6, 0x80, 0x42, 0x88, 0x82, 0x8C, 0x83, 0x87, +0xF0, 0x09, 0xE0, 0xA3, 0xB5, 0xF0, 0x36, 0xDF, +0xF6, 0x80, 0x32, 0x88, 0x82, 0x8C, 0x83, 0x87, +0xF0, 0x09, 0xE4, 0x93, 0xA3, 0xB5, 0xF0, 0x25, +0xDF, 0xF5, 0x80, 0x21, 0x88, 0x82, 0x8C, 0x83, +0xE3, 0xF5, 0xF0, 0x09, 0xE0, 0xA3, 0xB5, 0xF0, +0x14, 0xDF, 0xF5, 0x80, 0x10, 0x88, 0x82, 0x8C, +0x83, 0xE3, 0xF5, 0xF0, 0x09, 0xE4, 0x93, 0xA3, +0xB5, 0xF0, 0x02, 0xDF, 0xF4, 0x02, 0x45, 0xD0, +0x80, 0x87, 0x80, 0xE9, 0x80, 0x90, 0x80, 0xD4, +0x80, 0x3E, 0x80, 0x15, 0x80, 0x6E, 0x80, 0x7E, +0x80, 0x9D, 0x80, 0xB7, 0x80, 0x8D, 0x80, 0xA3, +0x80, 0x51, 0x80, 0x74, 0x80, 0x3C, 0x02, 0x45, +0xDC, 0x89, 0x82, 0x8A, 0x83, 0xEC, 0xFA, 0xE4, +0x93, 0xF5, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, +0xCC, 0xC5, 0x83, 0xCC, 0xE4, 0x93, 0xA3, 0xC8, +0xC5, 0x82, 0xC8, 0xCC, 0xC5, 0x83, 0xCC, 0xB5, +0xF0, 0x76, 0xDF, 0xE3, 0xDE, 0xE1, 0x80, 0x70, +0x89, 0x82, 0x8A, 0x83, 0xE4, 0x93, 0xF5, 0xF0, +0xA3, 0xE2, 0x08, 0xB5, 0xF0, 0x62, 0xDF, 0xF4, +0x80, 0x5E, 0x89, 0x82, 0x8A, 0x83, 0xE0, 0xF5, +0xF0, 0xA3, 0xE6, 0x08, 0xB5, 0xF0, 0x51, 0xDF, +0xF5, 0x80, 0x4D, 0x89, 0x82, 0x8A, 0x83, 0xE0, +0xF5, 0xF0, 0xA3, 0xE2, 0x08, 0xB5, 0xF0, 0x40, +0xDF, 0xF5, 0x80, 0x3C, 0x89, 0x82, 0x8A, 0x83, +0xE4, 0x93, 0xF5, 0xF0, 0xA3, 0xE6, 0x08, 0xB5, +0xF0, 0x2E, 0xDF, 0xF4, 0x80, 0x2A, 0x80, 0x02, +0x80, 0x57, 0x89, 0x82, 0x8A, 0x83, 0xEC, 0xFA, +0xE4, 0x93, 0xF5, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, +0xC8, 0xCC, 0xC5, 0x83, 0xCC, 0xE0, 0xA3, 0xC8, +0xC5, 0x82, 0xC8, 0xCC, 0xC5, 0x83, 0xCC, 0xB5, +0xF0, 0x06, 0xDF, 0xE4, 0xDE, 0xE2, 0x80, 0x00, +0x7F, 0xFF, 0xB5, 0xF0, 0x02, 0x0F, 0x22, 0x40, +0x02, 0x7F, 0x01, 0x22, 0x89, 0x82, 0x8A, 0x83, +0xEC, 0xFA, 0xE0, 0xF5, 0xF0, 0xA3, 0xC8, 0xC5, +0x82, 0xC8, 0xCC, 0xC5, 0x83, 0xCC, 0xE0, 0xA3, +0xC8, 0xC5, 0x82, 0xC8, 0xCC, 0xC5, 0x83, 0xCC, +0xB5, 0xF0, 0xD5, 0xDF, 0xE5, 0xDE, 0xE3, 0x80, +0xCF, 0x89, 0x82, 0x8A, 0x83, 0xEC, 0xFA, 0xE0, +0xF5, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, +0xC5, 0x83, 0xCC, 0xE4, 0x93, 0xA3, 0xC8, 0xC5, +0x82, 0xC8, 0xCC, 0xC5, 0x83, 0xCC, 0xB5, 0xF0, +0xAF, 0xDF, 0xE4, 0xDE, 0xE2, 0x80, 0xA9, 0x88, +0xF0, 0xEF, 0x60, 0x01, 0x0E, 0x4E, 0x60, 0xAB, +0xED, 0x24, 0x02, 0xB4, 0x04, 0x00, 0x50, 0x98, +0xF5, 0x82, 0xEB, 0x24, 0x02, 0xB4, 0x04, 0x00, +0x50, 0x8E, 0x23, 0x23, 0x45, 0x82, 0x23, 0x90, +0x45, 0x18, 0x73, 0xEF, 0x4E, 0x60, 0x12, 0xEF, +0x60, 0x01, 0x0E, 0xED, 0xBB, 0x01, 0x0B, 0x89, +0x82, 0x8A, 0x83, 0xF0, 0xA3, 0xDF, 0xFC, 0xDE, +0xFA, 0x22, 0x89, 0xF0, 0x50, 0x07, 0xF7, 0x09, +0xDF, 0xFC, 0xA9, 0xF0, 0x22, 0xBB, 0xFE, 0xFC, +0xF3, 0x09, 0xDF, 0xFC, 0xA9, 0xF0, 0x22, 0xC2, +0xAF, 0x80, 0xFE, 0x32, 0x12, 0x46, 0x7B, 0x85, +0xD0, 0x0B, 0x75, 0xD0, 0x08, 0xAA, 0xE0, 0xC2, +0x8C, 0xE5, 0x8A, 0x24, 0x67, 0xF5, 0x8A, 0xE5, +0x8C, 0x34, 0x79, 0xF5, 0x8C, 0xD2, 0x8C, 0xEC, +0x24, 0x87, 0xF8, 0xE6, 0xBC, 0x02, 0x02, 0x74, +0xFF, 0xC3, 0x95, 0x81, 0xB4, 0x40, 0x00, 0x40, +0xCE, 0x79, 0x03, 0x78, 0x80, 0x16, 0xE6, 0x08, +0x70, 0x0B, 0xC2, 0xAF, 0xE6, 0x30, 0xE1, 0x03, +0x44, 0x18, 0xF6, 0xD2, 0xAF, 0x08, 0xD9, 0xED, +0xEA, 0x8B, 0xD0, 0x22, 0xE5, 0x0C, 0xFF, 0x23, +0x24, 0x81, 0xF8, 0x0F, 0x08, 0x08, 0xBF, 0x03, +0x04, 0x7F, 0x00, 0x78, 0x81, 0xE6, 0x30, 0xE4, +0xF2, 0x00, 0xE5, 0x0C, 0xC3, 0x9F, 0x50, 0x20, +0x05, 0x0C, 0x74, 0x86, 0x25, 0x0C, 0xF8, 0xE6, +0xFD, 0xA6, 0x81, 0x08, 0xE6, 0xAE, 0x0C, 0xBE, +0x02, 0x02, 0x74, 0xFF, 0xCD, 0xF8, 0xE8, 0x6D, +0x60, 0xE0, 0x08, 0xE6, 0xC0, 0xE0, 0x80, 0xF6, +0xE5, 0x0C, 0xD3, 0x9F, 0x40, 0x27, 0xE5, 0x0C, +0x24, 0x87, 0xF8, 0xE6, 0xAE, 0x0C, 0xBE, 0x02, +0x02, 0x74, 0xFF, 0xFD, 0x18, 0xE6, 0xCD, 0xF8, +0xE5, 0x81, 0x6D, 0x60, 0x06, 0xD0, 0xE0, 0xF6, +0x18, 0x80, 0xF5, 0xE5, 0x0C, 0x24, 0x86, 0xC8, +0xF6, 0x15, 0x0C, 0x80, 0xD3, 0xE5, 0x0C, 0x23, +0x24, 0x81, 0xF8, 0x7F, 0x04, 0xC2, 0xAF, 0xE6, +0x30, 0xE0, 0x03, 0x10, 0xE2, 0x0C, 0x7F, 0x00, +0x30, 0xE1, 0x07, 0x30, 0xE3, 0x04, 0x7F, 0x08, +0x54, 0xF4, 0x54, 0x7C, 0xC6, 0xD2, 0xAF, 0x54, +0x80, 0x42, 0x07, 0x22, 0x78, 0x86, 0xA6, 0x81, +0x74, 0x02, 0x60, 0x06, 0xFF, 0x08, 0x76, 0xFF, +0xDF, 0xFB, 0x7F, 0x03, 0xE4, 0x78, 0x80, 0xF6, +0x08, 0xF6, 0x08, 0xDF, 0xFA, 0x78, 0x81, 0x76, +0x30, 0x90, 0x49, 0xB4, 0x74, 0x01, 0x93, 0xC0, +0xE0, 0xE4, 0x93, 0xC0, 0xE0, 0x43, 0x89, 0x01, +0x75, 0x8A, 0x60, 0x75, 0x8C, 0x79, 0xD2, 0x8C, +0xD2, 0xAF, 0x22, 0x02, 0xEF, 0xD3, 0x94, 0x02, +0x40, 0x03, 0x7F, 0xFF, 0x22, 0x74, 0x81, 0x2F, +0x2F, 0xF8, 0xE6, 0x20, 0xE5, 0xF4, 0xC2, 0xAF, +0xE6, 0x44, 0x30, 0xF6, 0xD2, 0xAF, 0xAE, 0x0C, +0xEE, 0xC3, 0x9F, 0x50, 0x21, 0x0E, 0x74, 0x86, +0x2E, 0xF8, 0xE6, 0xF9, 0x08, 0xE6, 0x18, 0xBE, +0x02, 0x02, 0x74, 0xFF, 0xFD, 0xED, 0x69, 0x60, +0x09, 0x09, 0xE7, 0x19, 0x19, 0xF7, 0x09, 0x09, +0x80, 0xF3, 0x16, 0x16, 0x80, 0xDA, 0xEE, 0xD3, +0x9F, 0x40, 0x04, 0x05, 0x81, 0x05, 0x81, 0xEE, +0xD3, 0x9F, 0x40, 0x22, 0x74, 0x86, 0x2E, 0xF8, +0x08, 0xE6, 0xF9, 0xEE, 0xB5, 0x0C, 0x02, 0xA9, +0x81, 0x18, 0x06, 0x06, 0xE6, 0xFD, 0xED, 0x69, +0x60, 0x09, 0x19, 0x19, 0xE7, 0x09, 0x09, 0xF7, +0x19, 0x80, 0xF3, 0x1E, 0x80, 0xD9, 0xEF, 0x24, +0x86, 0xF8, 0xE6, 0x04, 0xF8, 0xEF, 0x2F, 0x04, +0x90, 0x49, 0xB4, 0x93, 0xF6, 0x08, 0xEF, 0x2F, +0x93, 0xF6, 0x7F, 0x00, 0x22, 0xEF, 0xD3, 0x94, +0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, 0xEF, 0x23, +0x24, 0x81, 0xF8, 0xE6, 0x30, 0xE5, 0xF4, 0xC2, +0xAF, 0xE6, 0x54, 0x8C, 0xF6, 0xD2, 0xAF, 0xE5, +0x0C, 0xB5, 0x07, 0x0A, 0x74, 0x86, 0x2F, 0xF8, +0xE6, 0xF5, 0x81, 0x02, 0x46, 0xC4, 0x50, 0x2E, +0x74, 0x87, 0x2F, 0xF8, 0xE6, 0xBF, 0x02, 0x02, +0x74, 0xFF, 0xFD, 0x18, 0xE6, 0xF9, 0x74, 0x86, +0x2F, 0xF8, 0xFB, 0xE6, 0xFC, 0xE9, 0x6C, 0x60, +0x08, 0xA8, 0x05, 0xE7, 0xF6, 0x1D, 0x19, 0x80, +0xF4, 0xA8, 0x03, 0xA6, 0x05, 0x1F, 0xE5, 0x0C, +0xB5, 0x07, 0xE3, 0x7F, 0x00, 0x22, 0x74, 0x87, +0x2F, 0xF8, 0xE6, 0xFD, 0x18, 0x86, 0x01, 0x0F, +0x74, 0x86, 0x2F, 0xF8, 0xA6, 0x01, 0x08, 0x86, +0x04, 0xE5, 0x0C, 0xB5, 0x07, 0x02, 0xAC, 0x81, +0xED, 0x6C, 0x60, 0x08, 0x0D, 0x09, 0xA8, 0x05, +0xE6, 0xF7, 0x80, 0xF4, 0xE5, 0x0C, 0xB5, 0x07, +0xDE, 0x89, 0x81, 0x7F, 0x00, 0x22, 0xEF, 0xD3, +0x94, 0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, 0xEF, +0x23, 0x24, 0x81, 0xF8, 0xC2, 0xAF, 0xE6, 0x30, +0xE5, 0x05, 0x30, 0xE0, 0x02, 0xD2, 0xE4, 0xD2, +0xE2, 0xC6, 0xD2, 0xAF, 0x7F, 0x00, 0x30, 0xE2, +0x01, 0x0F, 0x02, 0x46, 0xC3, 0x8F, 0xF0, 0xE4, +0xFF, 0xFE, 0xE5, 0x0C, 0x23, 0x24, 0x80, 0xF8, +0xC2, 0xA9, 0x30, 0xF7, 0x0D, 0x7F, 0x08, 0xE6, +0x60, 0x0B, 0x2D, 0xF6, 0x60, 0x30, 0x50, 0x2E, +0x80, 0x07, 0x30, 0xF1, 0x06, 0xED, 0xF6, 0x60, +0x25, 0x7E, 0x02, 0x08, 0x30, 0xF0, 0x10, 0xC2, +0xAF, 0xE6, 0x10, 0xE7, 0x23, 0x0E, 0x30, 0xE2, +0x0C, 0xD2, 0xAF, 0x7F, 0x04, 0x80, 0x12, 0xC2, +0xAF, 0xE6, 0x10, 0xE7, 0x13, 0x54, 0xEC, 0x4E, +0xF6, 0xD2, 0xAF, 0x02, 0x46, 0xC4, 0x7F, 0x08, +0x08, 0xEF, 0x44, 0x83, 0xF4, 0xC2, 0xAF, 0x56, +0xC6, 0xD2, 0xAF, 0x54, 0x80, 0x4F, 0xFF, 0x22, +0x02, 0x49, 0x5E, 0x02, 0x47, 0x54, 0xE4, 0x93, +0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0x40, 0x03, 0xF6, +0x80, 0x01, 0xF2, 0x08, 0xDF, 0xF4, 0x80, 0x29, +0xE4, 0x93, 0xA3, 0xF8, 0x54, 0x07, 0x24, 0x0C, +0xC8, 0xC3, 0x33, 0xC4, 0x54, 0x0F, 0x44, 0x20, +0xC8, 0x83, 0x40, 0x04, 0xF4, 0x56, 0x80, 0x01, +0x46, 0xF6, 0xDF, 0xE4, 0x80, 0x0B, 0x01, 0x02, +0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x49, +0xA3, 0xE4, 0x7E, 0x01, 0x93, 0x60, 0xBC, 0xA3, +0xFF, 0x54, 0x3F, 0x30, 0xE5, 0x09, 0x54, 0x1F, +0xFE, 0xE4, 0x93, 0xA3, 0x60, 0x01, 0x0E, 0xCF, +0x54, 0xC0, 0x25, 0xE0, 0x60, 0xA8, 0x40, 0xB8, +0xE4, 0x93, 0xA3, 0xFA, 0xE4, 0x93, 0xA3, 0xF8, +0xE4, 0x93, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCA, +0xC5, 0x83, 0xCA, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, +0xC8, 0xCA, 0xC5, 0x83, 0xCA, 0xDF, 0xE9, 0xDE, +0xE7, 0x80, 0xBE, 0x41, 0x8A, 0x56, 0x00, 0x41, +0x8A, 0x57, 0x00, 0x41, 0x8A, 0x67, 0x00, 0x41, +0x8A, 0x68, 0x00, 0x00, 0x68, 0x00, 0x77, 0xF0, +0x7E, 0xCE, 0xC0, 0xE0, 0xC0, 0xF0, 0xC0, 0x83, +0xC0, 0x82, 0xC0, 0xD0, 0x75, 0xD0, 0x00, 0xC0, +0x00, 0xC0, 0x01, 0xC0, 0x02, 0xC0, 0x03, 0xC0, +0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0x90, +0x01, 0xC4, 0x74, 0xBA, 0xF0, 0x74, 0x49, 0xA3, +0xF0, 0x51, 0x09, 0x74, 0xBA, 0x04, 0x90, 0x01, +0xC4, 0xF0, 0x74, 0x49, 0xA3, 0xF0, 0xD0, 0x07, +0xD0, 0x06, 0xD0, 0x05, 0xD0, 0x04, 0xD0, 0x03, +0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0xD0, 0xD0, +0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0, 0xE0, +0x32, 0x90, 0x00, 0x54, 0xE0, 0x55, 0x35, 0xF5, +0x39, 0xA3, 0xE0, 0x55, 0x36, 0xF5, 0x3A, 0xA3, +0xE0, 0x55, 0x37, 0xF5, 0x3B, 0xA3, 0xE0, 0x55, +0x38, 0xF5, 0x3C, 0xAD, 0x39, 0x7F, 0x54, 0x12, +0x32, 0x1E, 0xAD, 0x3A, 0x7F, 0x55, 0x12, 0x32, +0x1E, 0xAD, 0x3B, 0x7F, 0x56, 0x12, 0x32, 0x1E, +0xAD, 0x3C, 0x7F, 0x57, 0x12, 0x32, 0x1E, 0x53, +0x91, 0xEF, 0x22, 0xC0, 0xE0, 0xC0, 0xF0, 0xC0, +0x83, 0xC0, 0x82, 0xC0, 0xD0, 0x75, 0xD0, 0x00, +0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x02, 0xC0, 0x03, +0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, +0x90, 0x01, 0xC4, 0x74, 0x43, 0xF0, 0x74, 0x4A, +0xA3, 0xF0, 0x12, 0x8D, 0x69, 0xE5, 0x41, 0x30, +0xE3, 0x03, 0x12, 0x8D, 0xC6, 0xE5, 0x41, 0x30, +0xE4, 0x03, 0x12, 0x50, 0xDD, 0xE5, 0x43, 0x30, +0xE0, 0x03, 0x12, 0x50, 0xC7, 0xE5, 0x43, 0x30, +0xE1, 0x02, 0x51, 0xE2, 0xE5, 0x43, 0x30, 0xE2, +0x03, 0x12, 0x8E, 0x0F, 0xE5, 0x43, 0x30, 0xE3, +0x03, 0x12, 0x6B, 0x5C, 0xE5, 0x43, 0x30, 0xE4, +0x03, 0x12, 0x6B, 0x72, 0xE5, 0x43, 0x30, 0xE5, +0x03, 0x12, 0x6F, 0x87, 0xE5, 0x43, 0x30, 0xE6, +0x03, 0x12, 0x6F, 0x69, 0xE5, 0x44, 0x30, 0xE1, +0x03, 0x12, 0x8E, 0x21, 0x74, 0x43, 0x04, 0x90, +0x01, 0xC4, 0xF0, 0x74, 0x4A, 0xA3, 0xF0, 0xD0, +0x07, 0xD0, 0x06, 0xD0, 0x05, 0xD0, 0x04, 0xD0, +0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0xD0, +0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0, +0xE0, 0x32, 0x90, 0x81, 0x0A, 0xE0, 0x70, 0x02, +0x61, 0x87, 0x90, 0x81, 0x21, 0xE0, 0x04, 0xF0, +0x90, 0x05, 0x61, 0x71, 0xEB, 0x78, 0x08, 0xB1, +0x59, 0xAB, 0x07, 0x90, 0x05, 0x60, 0x71, 0xEB, +0x12, 0x44, 0x27, 0xC0, 0x04, 0xC0, 0x05, 0xC0, +0x06, 0xC0, 0x07, 0x90, 0x05, 0x62, 0x71, 0xEB, +0x78, 0x10, 0x12, 0x20, 0xBB, 0xD0, 0x03, 0xD0, +0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, 0x44, 0x27, +0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, +0xA3, 0x71, 0xEB, 0x78, 0x18, 0x12, 0x20, 0xBB, +0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, +0x12, 0x44, 0x27, 0x90, 0x81, 0xCA, 0x12, 0x20, +0xCE, 0x90, 0x81, 0x06, 0xE0, 0x54, 0x7F, 0xF0, +0xA3, 0xE0, 0x30, 0xE0, 0x0F, 0x12, 0x7F, 0x84, +0x90, 0x8A, 0x52, 0x74, 0x05, 0xF0, 0x12, 0x88, +0xF3, 0x12, 0x8A, 0x14, 0x90, 0x81, 0x06, 0x12, +0x6E, 0x71, 0x30, 0xE0, 0x0B, 0x90, 0x01, 0x3B, +0xE0, 0x30, 0xE4, 0x04, 0xB1, 0x69, 0xB1, 0x63, +0x90, 0x8A, 0x60, 0xE0, 0x04, 0xF0, 0xE0, 0xC3, +0x94, 0x80, 0x40, 0x0B, 0x90, 0x01, 0x98, 0xE0, +0x54, 0xFE, 0xF0, 0xE0, 0x44, 0x01, 0xF0, 0x12, +0x70, 0x14, 0x12, 0x6C, 0xB6, 0xE4, 0x90, 0x84, +0x92, 0xF0, 0x12, 0x5F, 0xDF, 0x30, 0xE0, 0x52, +0x90, 0x84, 0x26, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, +0x7C, 0x00, 0x7D, 0x64, 0x12, 0x20, 0x30, 0x90, +0x84, 0x7A, 0xE0, 0x6E, 0x70, 0x03, 0xA3, 0xE0, +0x6F, 0x60, 0x0A, 0x90, 0x84, 0x7A, 0xE4, 0x75, +0xF0, 0x01, 0x02, 0x43, 0xF6, 0x90, 0x84, 0x2A, +0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x84, 0x38, +0xE0, 0xB5, 0x06, 0x14, 0xA3, 0xE0, 0xB5, 0x07, +0x0F, 0xEF, 0x4E, 0x60, 0x0B, 0x90, 0x01, 0xC7, +0x74, 0x31, 0xF0, 0x7F, 0x01, 0x02, 0x70, 0x9D, +0x12, 0x86, 0x8F, 0xE4, 0x90, 0x84, 0x7A, 0xF0, +0xA3, 0xF0, 0x22, 0xE0, 0xFF, 0xE4, 0xFC, 0xFD, +0xFE, 0x22, 0x90, 0x84, 0xB3, 0xEF, 0xF0, 0xA3, +0xED, 0xF0, 0xA3, 0x12, 0x20, 0xDA, 0x00, 0x00, +0x00, 0x00, 0xE4, 0x90, 0x84, 0xC1, 0xF0, 0x7F, +0x24, 0x7E, 0x08, 0x12, 0x2D, 0x5C, 0x90, 0x84, +0xB9, 0x12, 0x20, 0xCE, 0x90, 0x84, 0xB3, 0xE0, +0xFB, 0x70, 0x04, 0x91, 0xD4, 0x80, 0x06, 0xEB, +0x91, 0xE3, 0x12, 0x2D, 0x5C, 0x90, 0x84, 0xBD, +0x12, 0x20, 0xCE, 0x90, 0x84, 0xB4, 0x71, 0xEB, +0x78, 0x17, 0xB1, 0x59, 0xAB, 0x07, 0x90, 0x84, +0xBD, 0x12, 0x44, 0x45, 0xED, 0x54, 0x7F, 0xFD, +0xEC, 0x54, 0x80, 0xFC, 0x12, 0x44, 0x27, 0xEC, +0x44, 0x80, 0xFC, 0x90, 0x84, 0xBD, 0x12, 0x20, +0xCE, 0x91, 0xD4, 0xEC, 0x54, 0x7F, 0xFC, 0x91, +0xDD, 0x91, 0xF6, 0x91, 0xE3, 0xC0, 0x06, 0xC0, +0x07, 0x90, 0x84, 0xBD, 0x91, 0xDA, 0xD0, 0x07, +0xD0, 0x06, 0x12, 0x2E, 0xA2, 0x91, 0xD4, 0xEC, +0x44, 0x80, 0xFC, 0x91, 0xDD, 0x91, 0xF6, 0x70, +0x04, 0x7F, 0x20, 0x80, 0x09, 0x90, 0x84, 0xB3, +0xE0, 0xB4, 0x01, 0x16, 0x7F, 0x28, 0x7E, 0x08, +0x12, 0x2D, 0x5C, 0x78, 0x08, 0x12, 0x20, 0xA8, +0xEF, 0x54, 0x01, 0xFF, 0xE4, 0x90, 0x84, 0xC1, +0xEF, 0xF0, 0x90, 0x84, 0xC1, 0xE0, 0x90, 0x84, +0xB3, 0x60, 0x0E, 0xE0, 0x75, 0xF0, 0x08, 0xA4, +0x24, 0x66, 0xF5, 0x82, 0xE4, 0x34, 0x87, 0x80, +0x0C, 0xE0, 0x75, 0xF0, 0x08, 0xA4, 0x24, 0x64, +0xF5, 0x82, 0xE4, 0x34, 0x87, 0x91, 0xEE, 0x12, +0x2D, 0x5C, 0xED, 0x54, 0x0F, 0xFD, 0xE4, 0xFC, +0x90, 0x84, 0xB5, 0x12, 0x20, 0xCE, 0x90, 0x84, +0xB5, 0x02, 0x44, 0x45, 0x90, 0x84, 0xB9, 0x02, +0x44, 0x45, 0x12, 0x44, 0x45, 0x90, 0x85, 0xBB, +0x02, 0x20, 0xCE, 0x75, 0xF0, 0x08, 0xA4, 0x24, +0x62, 0xF5, 0x82, 0xE4, 0x34, 0x87, 0xF5, 0x83, +0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x22, 0x7F, 0x24, +0x7E, 0x08, 0x12, 0x2E, 0xA2, 0x90, 0x84, 0xB3, +0xE0, 0x22, 0x90, 0x84, 0xEB, 0xEF, 0xF0, 0xAB, +0x05, 0x90, 0x84, 0xF1, 0x12, 0x20, 0xDA, 0x00, +0x00, 0x00, 0x00, 0xAF, 0x03, 0xE4, 0xFC, 0xFD, +0xFE, 0x78, 0x14, 0xB1, 0x59, 0xAB, 0x07, 0x90, +0x84, 0xED, 0x12, 0x44, 0x45, 0xED, 0x54, 0x0F, +0xFD, 0xE4, 0xFC, 0x12, 0x44, 0x27, 0xEC, 0x54, +0x0F, 0xFC, 0x90, 0x84, 0xF1, 0x12, 0x20, 0xCE, +0x90, 0x84, 0xEB, 0xE0, 0x75, 0xF0, 0x08, 0xA4, +0x24, 0x60, 0xF5, 0x82, 0xE4, 0x34, 0x87, 0x91, +0xEE, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x84, 0xF1, +0x91, 0xDA, 0xD0, 0x07, 0xD0, 0x06, 0x02, 0x2E, +0xA2, 0x12, 0x20, 0xBB, 0xA8, 0x04, 0xA9, 0x05, +0xAA, 0x06, 0x22, 0x7D, 0x01, 0x7F, 0x02, 0x80, +0x04, 0x7D, 0x02, 0x7F, 0x02, 0x74, 0x3D, 0x12, +0x98, 0x8C, 0xFE, 0xF6, 0x74, 0x30, 0x02, 0x6E, +0xEC, 0xEF, 0x70, 0x3E, 0x7D, 0x78, 0x7F, 0x02, +0xB1, 0x6D, 0x7D, 0x02, 0x7F, 0x03, 0xB1, 0x6D, +0x7D, 0xC8, 0x7F, 0x02, 0x12, 0x6E, 0xE3, 0x12, +0x6E, 0x79, 0xF0, 0xE4, 0xFF, 0x12, 0x6A, 0x8A, +0xEF, 0x70, 0x0E, 0x12, 0x80, 0x18, 0x12, 0x6B, +0x11, 0x12, 0x91, 0xCB, 0x54, 0x7F, 0xF0, 0x80, +0x06, 0x7D, 0x01, 0x7F, 0x0C, 0xB1, 0xFA, 0x12, +0x8E, 0x94, 0x90, 0x06, 0x0A, 0xE0, 0x54, 0xF8, +0xF0, 0x22, 0x90, 0x01, 0x36, 0x74, 0x78, 0xF0, +0xA3, 0x74, 0x02, 0xF0, 0x7D, 0x78, 0xFF, 0x12, +0x6E, 0x99, 0x7D, 0x02, 0x7F, 0x03, 0x12, 0x6E, +0x99, 0x90, 0x06, 0x0A, 0xE0, 0x44, 0x07, 0x12, +0x8A, 0x3A, 0xE4, 0xFF, 0x12, 0x6A, 0x8A, 0xBF, +0x01, 0x10, 0x12, 0x6D, 0x55, 0x90, 0x81, 0x0D, +0xE0, 0x20, 0xE2, 0x09, 0x7D, 0x01, 0x7F, 0x04, +0x80, 0x08, 0x12, 0x98, 0x84, 0x22, 0x7D, 0x01, +0x7F, 0x04, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x90, 0x8A, 0x63, 0xED, 0xF0, 0x90, 0x81, +0x05, 0xE0, 0xFE, 0xC4, 0x13, 0x13, 0x54, 0x03, +0x30, 0xE0, 0x02, 0xE1, 0x4B, 0xEE, 0x12, 0x5F, +0xD8, 0x30, 0xE0, 0x02, 0xE1, 0x4B, 0x90, 0x81, +0x0D, 0xE0, 0xFE, 0x6F, 0x70, 0x02, 0xE1, 0x4B, +0xEF, 0x70, 0x02, 0xC1, 0xBA, 0x24, 0xFE, 0x70, +0x02, 0xC1, 0xF5, 0x24, 0xFE, 0x60, 0x4A, 0x24, +0xFC, 0x70, 0x02, 0xE1, 0x31, 0x24, 0xFC, 0x60, +0x02, 0xE1, 0x41, 0xEE, 0xB4, 0x0E, 0x02, 0xF1, +0x97, 0x90, 0x81, 0x0D, 0xE0, 0x70, 0x04, 0x7F, +0x01, 0xF1, 0xDB, 0x90, 0x81, 0x0D, 0xE0, 0xB4, +0x06, 0x02, 0xF1, 0xB6, 0x90, 0x81, 0x0D, 0xE0, +0xB4, 0x04, 0x0F, 0x90, 0x8A, 0x63, 0xE0, 0xFF, +0x60, 0x05, 0x12, 0x6B, 0x1C, 0x80, 0x03, 0x12, +0x6B, 0x11, 0x90, 0x81, 0x0D, 0xE0, 0x64, 0x08, +0x60, 0x02, 0xE1, 0x41, 0x12, 0x91, 0x64, 0xE1, +0x41, 0x90, 0x81, 0x0D, 0xE0, 0x70, 0x04, 0x7F, +0x01, 0xF1, 0xDB, 0x90, 0x81, 0x0D, 0xE0, 0xB4, +0x06, 0x02, 0xF1, 0xB6, 0x90, 0x81, 0x0D, 0xE0, +0xB4, 0x0E, 0x07, 0xF1, 0x50, 0xBF, 0x01, 0x02, +0xF1, 0x97, 0x90, 0x81, 0x0D, 0xE0, 0x64, 0x0C, +0x60, 0x02, 0xE1, 0x41, 0xF1, 0x50, 0xEF, 0x64, +0x01, 0x60, 0x02, 0xE1, 0x41, 0x12, 0x69, 0xBD, +0xE1, 0x41, 0x90, 0x81, 0x0D, 0xE0, 0xB4, 0x0E, +0x07, 0xF1, 0x50, 0xBF, 0x01, 0x02, 0xF1, 0x97, +0x90, 0x81, 0x0D, 0xE0, 0xB4, 0x06, 0x02, 0xF1, +0xB6, 0x90, 0x81, 0x0D, 0xE0, 0xB4, 0x0C, 0x08, +0xF1, 0x50, 0xBF, 0x01, 0x03, 0x12, 0x69, 0xBD, +0x90, 0x81, 0x0D, 0xE0, 0x64, 0x04, 0x70, 0x59, +0x12, 0x90, 0x0B, 0xEF, 0x64, 0x01, 0x70, 0x51, +0x12, 0x6E, 0xA5, 0x80, 0x4C, 0x90, 0x81, 0x0D, +0xE0, 0xB4, 0x0E, 0x07, 0xF1, 0x50, 0xBF, 0x01, +0x02, 0xF1, 0x97, 0x90, 0x81, 0x0D, 0xE0, 0xB4, +0x06, 0x02, 0xF1, 0xB6, 0x90, 0x81, 0x0D, 0xE0, +0xB4, 0x0C, 0x08, 0xF1, 0x50, 0xBF, 0x01, 0x03, +0x12, 0x69, 0xBD, 0x90, 0x81, 0x0D, 0xE0, 0x70, +0x04, 0x7F, 0x01, 0xF1, 0xDB, 0x90, 0x81, 0x0D, +0xE0, 0xB4, 0x04, 0x15, 0x12, 0x90, 0xFD, 0x80, +0x10, 0x90, 0x81, 0x0D, 0xE0, 0xB4, 0x0C, 0x09, +0x12, 0x6F, 0xEC, 0x30, 0xE0, 0x03, 0x12, 0x81, +0xCC, 0x90, 0x81, 0x0D, 0x12, 0x8A, 0x25, 0x90, +0x01, 0xBB, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, +0x8F, 0xF2, 0xEF, 0x64, 0x01, 0x60, 0x05, 0x75, +0x1F, 0x01, 0x80, 0x20, 0x90, 0x81, 0x05, 0xF1, +0xF3, 0x30, 0xE0, 0x05, 0x75, 0x1F, 0x02, 0x80, +0x13, 0x90, 0x81, 0x0C, 0xE0, 0xD3, 0x94, 0x04, +0x40, 0x05, 0x75, 0x1F, 0x08, 0x80, 0x05, 0x12, +0x90, 0x73, 0x80, 0x0E, 0x90, 0x01, 0xB9, 0x74, +0x02, 0xF0, 0x90, 0x01, 0xB8, 0xE5, 0x1F, 0xF0, +0x7F, 0x00, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, +0x81, 0x06, 0xE0, 0xC3, 0x13, 0x20, 0xE0, 0x04, +0x7D, 0x0C, 0x80, 0x05, 0x12, 0x91, 0xD3, 0x7D, +0x04, 0x7F, 0x01, 0x12, 0x69, 0x45, 0xE4, 0xFB, +0xFD, 0x7F, 0xFF, 0x02, 0x66, 0x73, 0x90, 0x81, +0x06, 0xE0, 0x90, 0x06, 0x04, 0x20, 0xE0, 0x08, +0xE0, 0x44, 0x40, 0xF0, 0x7D, 0x04, 0x80, 0x06, +0xE0, 0x54, 0x7F, 0xF0, 0x7D, 0x0C, 0x7F, 0x01, +0x12, 0x69, 0x45, 0xE4, 0xFB, 0xFD, 0x7F, 0xFF, +0x02, 0x66, 0x73, 0x90, 0x8A, 0x62, 0xEF, 0xF0, +0x12, 0x80, 0x18, 0x90, 0x8A, 0x62, 0xE0, 0x60, +0x03, 0x12, 0x66, 0x6E, 0x7D, 0x04, 0x7F, 0x01, +0x02, 0x69, 0x45, 0xE0, 0x13, 0x13, 0x13, 0x54, +0x1F, 0x22, 0xC0, 0xE0, 0xC0, 0xF0, 0xC0, 0x83, +0xC0, 0x82, 0xC0, 0xD0, 0x75, 0xD0, 0x00, 0xC0, +0x00, 0xC0, 0x01, 0xC0, 0x02, 0xC0, 0x03, 0xC0, +0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0x90, +0x01, 0xC4, 0x74, 0xFA, 0xF0, 0x74, 0x4F, 0xA3, +0xF0, 0x12, 0x8D, 0x96, 0xE5, 0x49, 0x30, 0xE1, +0x02, 0x11, 0x81, 0xE5, 0x49, 0x30, 0xE2, 0x03, +0x12, 0x8E, 0x7F, 0xE5, 0x4A, 0x30, 0xE0, 0x03, +0x12, 0x89, 0xC8, 0xE5, 0x4C, 0x30, 0xE1, 0x04, +0x7F, 0x04, 0x11, 0xCE, 0xE5, 0x4C, 0x30, 0xE4, +0x02, 0x11, 0x8B, 0xE5, 0x4C, 0x30, 0xE5, 0x03, +0x12, 0x8A, 0x72, 0xE5, 0x4C, 0x30, 0xE6, 0x03, +0x12, 0x8A, 0x9F, 0x74, 0xFA, 0x04, 0x90, 0x01, +0xC4, 0xF0, 0x74, 0x4F, 0xA3, 0xF0, 0xD0, 0x07, +0xD0, 0x06, 0xD0, 0x05, 0xD0, 0x04, 0xD0, 0x03, +0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0xD0, 0xD0, +0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0, 0xE0, +0x32, 0x90, 0x81, 0x0A, 0xE0, 0x60, 0x03, 0x12, +0x6C, 0xF1, 0x22, 0x12, 0x6B, 0x94, 0x12, 0x6E, +0x95, 0x7F, 0x01, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x81, 0x07, 0xE0, 0xFE, 0xC3, +0x13, 0x30, 0xE0, 0x1E, 0x90, 0x84, 0xC2, 0x74, +0x1E, 0xF0, 0x90, 0x84, 0xD0, 0x74, 0x01, 0xF0, +0x90, 0x84, 0xC4, 0xEF, 0xF0, 0x7B, 0x01, 0x7A, +0x84, 0x79, 0xC2, 0x12, 0x8C, 0x5C, 0x7F, 0x04, +0x11, 0xCE, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x12, +0x6B, 0xC4, 0xE4, 0xFF, 0x80, 0xC5, 0x8F, 0x0F, +0x7F, 0x02, 0x12, 0x48, 0x9E, 0x90, 0x80, 0x01, +0xE0, 0x45, 0x0F, 0xF0, 0x22, 0x11, 0xE3, 0x7F, +0x02, 0x80, 0xEB, 0x90, 0x01, 0xCC, 0xE0, 0x54, +0x0F, 0x90, 0x8A, 0x58, 0xF0, 0x90, 0x8A, 0x58, +0xE0, 0xFD, 0x70, 0x02, 0x21, 0xE4, 0x90, 0x80, +0x60, 0xE0, 0xFF, 0x70, 0x06, 0xA3, 0xE0, 0x64, +0x09, 0x60, 0x0A, 0xEF, 0x14, 0xFF, 0x90, 0x80, +0x61, 0xE0, 0xB5, 0x07, 0x04, 0x7F, 0x01, 0x80, +0x02, 0x7F, 0x00, 0xEF, 0x60, 0x08, 0x90, 0x01, +0xC1, 0xE0, 0x44, 0x01, 0xF0, 0x22, 0x90, 0x8A, +0x56, 0x12, 0x97, 0x99, 0x80, 0x05, 0xC3, 0x33, +0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, 0xEF, 0x5D, +0x70, 0x02, 0x21, 0xC6, 0xE4, 0x90, 0x8A, 0x59, +0xF0, 0x90, 0x8A, 0x59, 0xE0, 0xF9, 0xC3, 0x94, +0x04, 0x50, 0x35, 0xF1, 0x2A, 0xA4, 0xFF, 0xE9, +0xFD, 0x7C, 0x00, 0x2F, 0xFF, 0xEC, 0x35, 0xF0, +0xFE, 0x74, 0xD0, 0x12, 0x97, 0xA3, 0x90, 0x80, +0x10, 0x12, 0x97, 0xD0, 0xF1, 0x2A, 0xA4, 0x2D, +0xFF, 0xEC, 0x35, 0xF0, 0xFE, 0x74, 0xF0, 0x12, +0x97, 0xA3, 0x90, 0x80, 0x14, 0x12, 0x97, 0xD0, +0x90, 0x8A, 0x59, 0xE0, 0x04, 0xF0, 0x80, 0xC1, +0x90, 0x8A, 0x58, 0xE0, 0xFF, 0x90, 0x8A, 0x56, +0xE0, 0xFE, 0x74, 0x01, 0xA8, 0x06, 0x08, 0x80, +0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xF4, 0x5F, 0x90, +0x8A, 0x58, 0xF0, 0x90, 0x8A, 0x56, 0x31, 0xEB, +0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0x90, 0x01, +0xCC, 0xF0, 0x90, 0x8A, 0x56, 0xE0, 0x04, 0xF0, +0xE0, 0x54, 0x03, 0xF0, 0x90, 0x80, 0x61, 0xE0, +0x04, 0xF0, 0xE0, 0x7F, 0x00, 0xB4, 0x0A, 0x02, +0x7F, 0x01, 0xEF, 0x70, 0x02, 0x01, 0xED, 0xE4, +0x90, 0x80, 0x61, 0xF0, 0x01, 0xED, 0x90, 0x01, +0xC0, 0xE0, 0x44, 0x02, 0xF0, 0x90, 0x8A, 0x56, +0xE0, 0x44, 0x80, 0x90, 0x00, 0x8A, 0xF0, 0xF1, +0x2A, 0x90, 0x01, 0xD0, 0x12, 0x44, 0x5D, 0xE0, +0x90, 0x01, 0xC3, 0xF0, 0x22, 0x12, 0x32, 0x1E, +0x90, 0x8A, 0x5A, 0xE0, 0xFF, 0x74, 0x01, 0xA8, +0x07, 0x08, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x8A, 0x5B, 0xED, 0xF0, 0x90, +0x8A, 0x5A, 0xEF, 0xF0, 0xD3, 0x94, 0x07, 0x50, +0x4B, 0x31, 0xEB, 0x80, 0x02, 0xC3, 0x33, 0xD8, +0xFC, 0xF4, 0xFF, 0x90, 0x00, 0x47, 0xE0, 0x5F, +0xFD, 0x7F, 0x47, 0x31, 0xE5, 0x80, 0x02, 0xC3, +0x33, 0xD8, 0xFC, 0xFF, 0x90, 0x00, 0x46, 0xE0, +0x4F, 0xFD, 0x7F, 0x46, 0xF1, 0xE7, 0x60, 0x10, +0x31, 0xE8, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, +0xFF, 0x90, 0x00, 0x45, 0xE0, 0x4F, 0x80, 0x0F, +0x31, 0xE8, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, +0xF4, 0xFF, 0x90, 0x00, 0x45, 0xE0, 0x5F, 0xFD, +0x7F, 0x45, 0x80, 0x62, 0x90, 0x8A, 0x5A, 0xE0, +0x24, 0xF8, 0xF0, 0xE0, 0x24, 0x04, 0x31, 0xEC, +0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xF4, 0xFF, +0x90, 0x00, 0x43, 0xE0, 0x5F, 0xFD, 0x7F, 0x43, +0x31, 0xE5, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, +0xFF, 0x90, 0x00, 0x43, 0xE0, 0x4F, 0xFD, 0x7F, +0x43, 0xF1, 0xE7, 0x60, 0x19, 0x90, 0x8A, 0x5A, +0xE0, 0x24, 0x04, 0x31, 0xEC, 0x80, 0x02, 0xC3, +0x33, 0xD8, 0xFC, 0xFF, 0x90, 0x00, 0x42, 0xE0, +0x4F, 0xFD, 0x7F, 0x42, 0x80, 0x18, 0x90, 0x8A, +0x5A, 0xE0, 0x24, 0x04, 0x31, 0xEC, 0x80, 0x02, +0xC3, 0x33, 0xD8, 0xFC, 0xF4, 0xFF, 0x90, 0x00, +0x42, 0xE0, 0x5F, 0xFD, 0x7F, 0x42, 0x12, 0x32, +0x1E, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x89, +0x34, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x89, +0x37, 0xEB, 0xF0, 0x90, 0x89, 0x36, 0xED, 0xF0, +0x60, 0x15, 0x90, 0x89, 0x34, 0x12, 0x5F, 0x76, +0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xF0, +0xEE, 0x90, 0x89, 0x34, 0xF0, 0x80, 0x19, 0xF1, +0xD7, 0x78, 0x06, 0xC3, 0x33, 0xCE, 0x33, 0xCE, +0xD8, 0xF9, 0xF0, 0xEE, 0x90, 0x89, 0x34, 0xF0, +0x74, 0xFF, 0x75, 0xF0, 0xD0, 0x12, 0x43, 0xF6, +0x71, 0x9F, 0x54, 0x07, 0x7D, 0x00, 0x20, 0xE0, +0x02, 0x7D, 0x01, 0x31, 0xF3, 0x71, 0x9F, 0x54, +0x01, 0xFD, 0x31, 0xF3, 0x90, 0x89, 0x38, 0xE0, +0x60, 0x57, 0x71, 0x92, 0x54, 0x07, 0x7D, 0x00, +0x20, 0xE0, 0x02, 0x7D, 0x01, 0x31, 0xF3, 0x90, +0x89, 0x39, 0xE0, 0x60, 0x1D, 0x90, 0x81, 0xE6, +0xE0, 0x30, 0xE0, 0x3D, 0x90, 0x01, 0xC6, 0xE0, +0x20, 0xE4, 0x36, 0x71, 0x72, 0x54, 0x07, 0x7D, +0x00, 0x20, 0xE0, 0x02, 0x7D, 0x01, 0x31, 0xF3, +0x80, 0xE3, 0xE4, 0x90, 0x89, 0x3A, 0xF0, 0x90, +0x89, 0x37, 0xE0, 0xFF, 0x90, 0x89, 0x3A, 0xE0, +0xC3, 0x9F, 0x50, 0x15, 0x71, 0x72, 0x54, 0x07, +0x7D, 0x00, 0x20, 0xE0, 0x02, 0x7D, 0x01, 0x31, +0xF3, 0x90, 0x89, 0x3A, 0xE0, 0x04, 0xF0, 0x80, +0xDE, 0x22, 0x90, 0x89, 0x34, 0xE0, 0xFE, 0xA3, +0xE0, 0xFF, 0xA3, 0xE0, 0xFD, 0x71, 0xAE, 0x90, +0x81, 0xE7, 0xE0, 0x54, 0x7F, 0xFF, 0x90, 0x81, +0xE6, 0xE0, 0xFE, 0xC4, 0x13, 0x54, 0x01, 0xFD, +0x31, 0xF3, 0x90, 0x89, 0x34, 0xE0, 0xFE, 0xA3, +0xE0, 0xFF, 0xA3, 0xE0, 0xFD, 0x71, 0xAE, 0x90, +0x81, 0xE7, 0xE0, 0x54, 0x7F, 0xFF, 0x90, 0x81, +0xE6, 0xE0, 0xFE, 0xC4, 0x13, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x8E, 0x0D, 0x8F, +0x0E, 0xBD, 0x01, 0x05, 0x12, 0x32, 0x06, 0x80, +0x07, 0xAF, 0x0E, 0xAE, 0x0D, 0x12, 0x32, 0xAA, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x8A, 0x1C, 0x20, +0xE0, 0x1E, 0x54, 0x01, 0xFF, 0x90, 0x81, 0xE6, +0xE0, 0x54, 0xFE, 0x4F, 0xF0, 0xA3, 0x71, 0xA2, +0x54, 0x07, 0x7D, 0x00, 0x20, 0xE0, 0x02, 0x7D, +0x01, 0x31, 0xF3, 0x12, 0x86, 0x0A, 0xA1, 0x09, +0x12, 0x92, 0x04, 0xFE, 0x90, 0x81, 0xE6, 0xF1, +0xBB, 0x12, 0x87, 0x88, 0xFF, 0x90, 0x81, 0xE6, +0x12, 0x87, 0xBA, 0xF1, 0xC9, 0x12, 0x87, 0x78, +0xFF, 0x90, 0x81, 0xE6, 0x12, 0x85, 0x50, 0xF1, +0xC9, 0x12, 0x87, 0x80, 0xFF, 0x90, 0x81, 0xE6, +0x12, 0x87, 0xB0, 0xD1, 0x94, 0x54, 0x80, 0xFF, +0x90, 0x81, 0xE7, 0xE0, 0x54, 0x7F, 0x4F, 0xB1, +0x9B, 0xFF, 0x54, 0x02, 0xFE, 0x90, 0x81, 0xEA, +0xE0, 0x54, 0xFD, 0x4E, 0xFE, 0xF0, 0xEF, 0x54, +0x08, 0xFF, 0xEE, 0x54, 0xF7, 0x4F, 0xF0, 0x90, +0x00, 0x05, 0x12, 0x1F, 0xBD, 0x90, 0x81, 0xEB, +0xB1, 0x9B, 0x54, 0x10, 0xFF, 0x90, 0x81, 0xEA, +0xE0, 0x54, 0xEF, 0x4F, 0xF0, 0x12, 0x1F, 0xA4, +0xFF, 0x13, 0x13, 0x54, 0x3F, 0x30, 0xE0, 0x07, +0x90, 0x06, 0x90, 0xE0, 0x44, 0x04, 0xF0, 0xEF, +0x13, 0x13, 0x13, 0x54, 0x1F, 0x30, 0xE0, 0x07, +0x90, 0x06, 0x90, 0xE0, 0x44, 0x08, 0xF0, 0x90, +0x80, 0x07, 0xE0, 0xB4, 0x02, 0x09, 0x90, 0x81, +0xE7, 0x12, 0x5F, 0xD7, 0x20, 0xE0, 0x57, 0x90, +0x89, 0x19, 0x12, 0x44, 0x69, 0xD1, 0x95, 0x54, +0x7F, 0xFF, 0x90, 0x81, 0xE7, 0xE0, 0x54, 0x80, +0x4F, 0xF1, 0x74, 0xFF, 0x54, 0x7F, 0xFE, 0x90, +0x81, 0xE8, 0xE0, 0x54, 0x80, 0xF1, 0xB3, 0xFE, +0x54, 0x01, 0xFD, 0x90, 0x81, 0xE9, 0x12, 0x87, +0xA8, 0x54, 0xFE, 0xFE, 0xED, 0x54, 0x01, 0x4E, +0xB1, 0x9B, 0x54, 0x04, 0xFE, 0x90, 0x81, 0xEA, +0xE0, 0x54, 0xFB, 0x4E, 0xF0, 0xEF, 0x54, 0x80, +0xFF, 0x90, 0x81, 0xE8, 0xE0, 0x54, 0x7F, 0x4F, +0xF0, 0x71, 0x9F, 0x54, 0x07, 0x7D, 0x00, 0x20, +0xE0, 0x02, 0x7D, 0x01, 0x31, 0xF3, 0x90, 0x80, +0x07, 0xE0, 0xB4, 0x01, 0x07, 0x90, 0xFE, 0x10, +0xE0, 0x44, 0x04, 0xF0, 0x90, 0x84, 0x22, 0x74, +0x05, 0xF0, 0x7E, 0x00, 0x7F, 0x08, 0x7D, 0x00, +0x7B, 0x01, 0x7A, 0x83, 0x79, 0x01, 0x12, 0x46, +0x4B, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x89, +0x16, 0x12, 0x44, 0x72, 0x90, 0x89, 0x15, 0xEF, +0xF0, 0x12, 0x44, 0x7B, 0x55, 0x47, 0x00, 0x55, +0x4C, 0x01, 0x55, 0x51, 0x03, 0x55, 0x56, 0x04, +0x55, 0x5B, 0x14, 0x55, 0x60, 0x20, 0x55, 0x65, +0x25, 0x55, 0x6E, 0x80, 0x55, 0x69, 0x81, 0x55, +0x72, 0x82, 0x55, 0x77, 0x83, 0x55, 0x7B, 0x84, +0x55, 0x80, 0x88, 0x00, 0x00, 0x55, 0x85, 0xB1, +0x95, 0x02, 0x87, 0xF7, 0xB1, 0x95, 0x02, 0x6A, +0xAD, 0xB1, 0x95, 0x02, 0x91, 0xDF, 0xB1, 0x95, +0x02, 0x92, 0x11, 0xB1, 0x95, 0x02, 0x88, 0x3B, +0xB1, 0x95, 0x02, 0x88, 0x4A, 0xB1, 0x95, 0xE1, +0xEF, 0xB1, 0x95, 0x02, 0x84, 0x53, 0xB1, 0x95, +0x61, 0xCD, 0xB1, 0x95, 0x02, 0x95, 0x13, 0xB1, +0x95, 0xE1, 0x7B, 0xB1, 0x95, 0x02, 0x95, 0x21, +0xB1, 0x95, 0x02, 0x95, 0x75, 0x90, 0x01, 0xC0, +0xE0, 0x44, 0x01, 0xF0, 0x90, 0x89, 0x15, 0xE0, +0x90, 0x01, 0xC2, 0xF0, 0x22, 0x90, 0x89, 0x16, +0x02, 0x44, 0x69, 0xF0, 0x90, 0x00, 0x04, 0x02, +0x1F, 0xBD, 0x90, 0x84, 0xDE, 0x12, 0x44, 0x72, +0x90, 0x84, 0xE2, 0xE0, 0xFE, 0x64, 0x04, 0x70, +0x0C, 0xD1, 0x8D, 0x12, 0x1F, 0xA4, 0x90, 0x84, +0xE3, 0xD1, 0x94, 0x80, 0x10, 0xEE, 0x64, 0x02, +0x70, 0x2F, 0xD1, 0x8D, 0xF1, 0x75, 0x90, 0x84, +0xE3, 0xF0, 0x12, 0x1F, 0xA4, 0x90, 0x84, 0xE4, +0xB1, 0x9B, 0x90, 0x84, 0xE5, 0xF0, 0x90, 0x00, +0x05, 0x12, 0x1F, 0xBD, 0x90, 0x84, 0xE6, 0xF1, +0xD0, 0x90, 0x84, 0xE7, 0xF0, 0x90, 0x00, 0x07, +0x12, 0x1F, 0xBD, 0x90, 0x84, 0xE8, 0xF1, 0xB4, +0xFF, 0xED, 0x70, 0x19, 0xFE, 0xF1, 0x32, 0xE0, +0xB4, 0xFF, 0x06, 0xF1, 0x32, 0xE4, 0xF0, 0x80, +0x07, 0xF1, 0x32, 0xE0, 0x04, 0xF0, 0x80, 0x05, +0x0E, 0xEE, 0xB4, 0x06, 0xE8, 0x90, 0x84, 0xE2, +0xE0, 0xFE, 0xB4, 0x04, 0x18, 0xA3, 0xE0, 0xFD, +0xD1, 0x8D, 0xED, 0xF1, 0xDF, 0xFD, 0xD1, 0x8D, +0x90, 0x00, 0x01, 0xED, 0x12, 0x1F, 0xFC, 0x90, +0x00, 0x02, 0xE4, 0x80, 0x20, 0xEE, 0xB4, 0x02, +0x1F, 0x90, 0x84, 0xE4, 0xD1, 0x8B, 0xEE, 0xF1, +0xDF, 0x44, 0x20, 0x54, 0x7F, 0xD1, 0x8C, 0x90, +0x00, 0x01, 0xEE, 0x12, 0x1F, 0xFC, 0x90, 0x84, +0xE3, 0xE0, 0x90, 0x00, 0x02, 0x12, 0x1F, 0xFC, +0xD1, 0x8D, 0xE9, 0x24, 0x03, 0xF9, 0xE4, 0x3A, +0xFA, 0x12, 0x1F, 0xA4, 0x44, 0x20, 0x12, 0x1F, +0xEA, 0x90, 0x84, 0xE5, 0xD1, 0x8B, 0x90, 0x00, +0x04, 0xEE, 0x12, 0x1F, 0xFC, 0x90, 0x84, 0xE6, +0xE0, 0x90, 0x00, 0x05, 0x12, 0x1F, 0xFC, 0x90, +0x84, 0xE7, 0xE0, 0x90, 0x00, 0x06, 0x12, 0x1F, +0xFC, 0x90, 0x84, 0xE8, 0xE0, 0x90, 0x00, 0x07, +0x02, 0x1F, 0xFC, 0xE0, 0xFE, 0x90, 0x84, 0xDE, +0x02, 0x44, 0x69, 0xFE, 0xF0, 0x90, 0x00, 0x01, +0x02, 0x1F, 0xBD, 0x90, 0x8A, 0x3B, 0xED, 0xF0, +0x90, 0x8A, 0x38, 0x12, 0x44, 0x72, 0xE4, 0x90, +0x8A, 0x3C, 0xF0, 0xA3, 0xF0, 0x12, 0x1F, 0xA4, +0xFF, 0xD1, 0x95, 0xFD, 0xB1, 0x9C, 0xFB, 0x12, +0x86, 0x6E, 0x90, 0x8A, 0x3C, 0xEF, 0xF0, 0x90, +0x8A, 0x38, 0x12, 0x44, 0x69, 0xB1, 0x9C, 0xFF, +0x12, 0x93, 0xED, 0x90, 0x8A, 0x3D, 0xEF, 0xF0, +0x90, 0x84, 0x23, 0xE0, 0x24, 0xFE, 0x60, 0x16, +0x24, 0xFE, 0x60, 0x12, 0x14, 0x60, 0x07, 0x14, +0x60, 0x04, 0x24, 0x05, 0x70, 0x43, 0x12, 0x97, +0xF3, 0x12, 0x96, 0x74, 0x80, 0x0D, 0x12, 0x97, +0xF3, 0x90, 0x84, 0x23, 0xE0, 0x90, 0x84, 0xE2, +0xF0, 0xB1, 0xA2, 0x90, 0x8A, 0x3D, 0xE0, 0xFF, +0x90, 0x8A, 0x38, 0x12, 0x44, 0x69, 0x90, 0x8A, +0x3C, 0xE0, 0x7C, 0x00, 0x29, 0xF9, 0xEC, 0x3A, +0xFA, 0xC3, 0xE9, 0x9F, 0xF9, 0xEA, 0x94, 0x00, +0xFA, 0x75, 0x13, 0x01, 0x75, 0x14, 0x83, 0x75, +0x15, 0xF2, 0xA3, 0xE0, 0xF5, 0x16, 0x12, 0x2B, +0xED, 0x22, 0x90, 0x8A, 0x56, 0xE0, 0x75, 0xF0, +0x04, 0x22, 0x74, 0xE3, 0x2E, 0xF5, 0x82, 0xE4, +0x34, 0x84, 0xF5, 0x83, 0x22, 0xFF, 0x90, 0x89, +0xA9, 0xF0, 0x7B, 0x01, 0x7A, 0x89, 0x79, 0xAA, +0x12, 0x1F, 0xA4, 0x90, 0x06, 0x74, 0xD1, 0x94, +0x90, 0x06, 0x75, 0xF1, 0x74, 0x90, 0x06, 0x76, +0xF1, 0xB4, 0x90, 0x06, 0x77, 0xF0, 0x90, 0x06, +0x70, 0xEF, 0xF0, 0xA3, 0xE4, 0xF0, 0xA3, 0x04, +0xF0, 0xA3, 0x74, 0x80, 0xF0, 0x7F, 0x01, 0x7E, +0x00, 0x02, 0x32, 0xAA, 0xF0, 0x90, 0x00, 0x02, +0x02, 0x1F, 0xBD, 0x12, 0x95, 0x67, 0x90, 0x84, +0x7E, 0xD1, 0x94, 0xFF, 0xED, 0x2F, 0x90, 0x84, +0x7F, 0xF1, 0x74, 0xFF, 0xED, 0x2F, 0x90, 0x84, +0x80, 0xF1, 0xB4, 0xFF, 0xED, 0x2F, 0x90, 0x84, +0x81, 0xB1, 0x9B, 0xFF, 0xED, 0x2F, 0x90, 0x84, +0x82, 0x12, 0x95, 0x5C, 0x90, 0x84, 0x83, 0xF1, +0xD0, 0xFF, 0xAE, 0x05, 0xED, 0x2F, 0x90, 0x84, +0x84, 0xF0, 0x22, 0x4E, 0xF0, 0x90, 0x00, 0x03, +0x02, 0x1F, 0xBD, 0xE0, 0x54, 0xFE, 0x4E, 0xFE, +0xF0, 0xEF, 0x54, 0x02, 0xFF, 0xEE, 0x54, 0xFD, +0x4F, 0xFF, 0xF0, 0x12, 0x1F, 0xA4, 0xFE, 0x22, +0xF0, 0x90, 0x00, 0x06, 0x02, 0x1F, 0xBD, 0x90, +0x89, 0x34, 0xE0, 0xFE, 0xA3, 0xE0, 0x22, 0x12, +0x1F, 0xEA, 0x90, 0x84, 0xE4, 0xE0, 0x22, 0x12, +0x32, 0x1E, 0x90, 0x8A, 0x5B, 0xE0, 0x22, 0x12, +0x1F, 0xA4, 0x90, 0x81, 0xE2, 0xF0, 0x22, 0xC0, +0xE0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0xD0, 0x75, +0xD0, 0x00, 0xC0, 0x05, 0xC0, 0x07, 0x7D, 0xF7, +0x90, 0x01, 0xC4, 0xED, 0xF0, 0x74, 0x57, 0xFF, +0xA3, 0xF0, 0xED, 0x04, 0x90, 0x01, 0xC4, 0xF0, +0xA3, 0xEF, 0xF0, 0xD0, 0x07, 0xD0, 0x05, 0xD0, +0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xE0, 0x32, +0x90, 0x00, 0xF7, 0xE0, 0x20, 0xE7, 0x09, 0xE0, +0x7F, 0x01, 0x20, 0xE6, 0x0C, 0x7F, 0x02, 0x22, +0x90, 0x00, 0xF7, 0xE0, 0x30, 0xE6, 0x02, 0x7F, +0x03, 0x22, 0x11, 0x28, 0x90, 0x80, 0x07, 0xEF, +0xF0, 0x11, 0x62, 0x90, 0x01, 0x64, 0x74, 0x01, +0xF0, 0x90, 0x00, 0x12, 0xE0, 0x54, 0xC7, 0x44, +0x20, 0xFD, 0x7F, 0x12, 0x12, 0x32, 0x1E, 0x02, +0x2D, 0xA7, 0x90, 0x00, 0x08, 0xE0, 0x54, 0xEF, +0xF0, 0x11, 0x9C, 0x12, 0x8C, 0xBD, 0x12, 0x8C, +0xE6, 0x12, 0x8D, 0x05, 0xE4, 0xF5, 0x35, 0xF5, +0x37, 0xF5, 0x36, 0xF5, 0x37, 0x75, 0x38, 0x80, +0xAD, 0x35, 0x7F, 0x50, 0x12, 0x32, 0x1E, 0xAD, +0x36, 0x7F, 0x51, 0x12, 0x32, 0x1E, 0xAD, 0x37, +0x7F, 0x52, 0x12, 0x32, 0x1E, 0xAD, 0x38, 0x7F, +0x53, 0x02, 0x32, 0x1E, 0x90, 0x01, 0x30, 0xE4, +0x11, 0xC4, 0x90, 0x01, 0x38, 0x11, 0xC4, 0xFD, +0x7F, 0x50, 0x12, 0x32, 0x1E, 0xE4, 0xFD, 0x7F, +0x51, 0x12, 0x32, 0x1E, 0xE4, 0xFD, 0x7F, 0x52, +0x12, 0x32, 0x1E, 0xE4, 0xFD, 0x7F, 0x53, 0x02, +0x32, 0x1E, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3, +0xF0, 0xA3, 0xF0, 0x22, 0x12, 0x70, 0xEB, 0xE4, +0x90, 0x84, 0x88, 0x11, 0xC4, 0x90, 0x84, 0x26, +0x11, 0xC2, 0xA3, 0x11, 0xC2, 0x90, 0x84, 0x38, +0xF0, 0xA3, 0xF0, 0x90, 0x84, 0x7A, 0xF0, 0xA3, +0xF0, 0x22, 0x90, 0x89, 0xA4, 0xEF, 0xF0, 0xA3, +0xED, 0xF0, 0xA3, 0x12, 0x44, 0x72, 0x90, 0x89, +0xA6, 0x12, 0x66, 0x5D, 0x31, 0x6F, 0x24, 0x02, +0x12, 0x57, 0x3D, 0x31, 0x84, 0x24, 0x04, 0x31, +0x66, 0x24, 0x03, 0x12, 0x57, 0x3D, 0x31, 0x84, +0x24, 0x08, 0x31, 0x66, 0x24, 0x04, 0x12, 0x57, +0x3D, 0x31, 0x84, 0x24, 0x0C, 0x31, 0x66, 0x24, +0x05, 0x12, 0x57, 0x3D, 0x90, 0x89, 0xA5, 0xE0, +0xFD, 0xB4, 0x02, 0x08, 0x90, 0x89, 0xA4, 0xE0, +0x44, 0x48, 0x80, 0x0A, 0xED, 0xB4, 0x04, 0x0A, +0x90, 0x89, 0xA4, 0xE0, 0x44, 0x50, 0x90, 0x89, +0xAA, 0xF0, 0x90, 0x89, 0xAB, 0x74, 0x80, 0xF0, +0xA3, 0x74, 0xFF, 0xF0, 0xA3, 0xF0, 0x31, 0x7B, +0x12, 0x57, 0x3D, 0x90, 0x89, 0xAA, 0x74, 0xFF, +0x11, 0xC4, 0x31, 0x7B, 0x04, 0x12, 0x57, 0x3D, +0x90, 0x06, 0x72, 0xE4, 0xF0, 0x22, 0xF9, 0xE4, +0x3A, 0x8B, 0x13, 0xF5, 0x14, 0x89, 0x15, 0x75, +0x16, 0x04, 0x7B, 0x01, 0x7A, 0x89, 0x79, 0xAA, +0x12, 0x2B, 0xED, 0x90, 0x89, 0xA4, 0xE0, 0x75, +0xF0, 0x08, 0xA4, 0x22, 0x90, 0x89, 0xA6, 0x12, +0x44, 0x69, 0xE9, 0x22, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x90, 0x89, 0x1F, 0x74, 0x08, +0xF0, 0xE4, 0x11, 0xC3, 0x90, 0x89, 0x26, 0xF0, +0xA3, 0xF0, 0xA3, 0xF0, 0x90, 0x01, 0x1F, 0xE0, +0xFE, 0x90, 0x01, 0x1E, 0x12, 0x81, 0xF8, 0x90, +0x89, 0x15, 0x12, 0x93, 0x77, 0xE0, 0x90, 0x89, +0x1E, 0xF0, 0x90, 0x81, 0xE3, 0xE0, 0x20, 0xE0, +0x02, 0x81, 0xE0, 0xE4, 0x90, 0x89, 0x1D, 0xF0, +0x90, 0x89, 0x1E, 0xE0, 0xFF, 0x90, 0x89, 0x1D, +0xE0, 0xC3, 0x9F, 0x40, 0x02, 0x81, 0xE0, 0xF1, +0x6B, 0xFD, 0xEC, 0xFF, 0x90, 0xFD, 0x11, 0xF0, +0xAE, 0x05, 0xAA, 0x06, 0x90, 0x89, 0x21, 0xEF, +0xF0, 0x74, 0x02, 0x2A, 0x12, 0x93, 0x9E, 0xFF, +0x74, 0x03, 0x2A, 0x12, 0x93, 0x87, 0xFE, 0xEF, +0x24, 0x18, 0x2E, 0x90, 0x89, 0x26, 0xF0, 0xE0, +0xFF, 0x2A, 0x90, 0x89, 0x19, 0xF0, 0x7E, 0x00, +0xF1, 0x6B, 0x2F, 0xFF, 0xEE, 0x3C, 0x90, 0x89, +0x1A, 0x12, 0x93, 0x6F, 0xE0, 0xFD, 0x24, 0x00, +0xF1, 0xA2, 0xFE, 0x54, 0xFC, 0x90, 0x89, 0x1C, +0xF0, 0xAF, 0x06, 0x12, 0x93, 0x30, 0xFD, 0x90, +0x89, 0x19, 0xE0, 0x12, 0x98, 0x65, 0x12, 0x86, +0x6A, 0x90, 0x89, 0x20, 0xEF, 0xF0, 0x74, 0x01, +0x2A, 0x12, 0x93, 0x33, 0xFE, 0x74, 0x00, 0x2A, +0xF5, 0x82, 0xE4, 0x34, 0xFB, 0xF5, 0x83, 0x12, +0x81, 0xF8, 0x54, 0x3F, 0xFE, 0x90, 0x89, 0x22, +0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x89, 0x26, 0xE0, +0x2F, 0xFF, 0xEC, 0x3E, 0xFE, 0x12, 0x93, 0x3C, +0x90, 0x89, 0x17, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, +0x90, 0x89, 0x1C, 0xE0, 0x64, 0x80, 0x70, 0x5F, +0x74, 0x0C, 0x2A, 0xF5, 0x82, 0xE4, 0x34, 0xFB, +0xF5, 0x83, 0xE0, 0x54, 0x1F, 0x14, 0x60, 0x08, +0x24, 0xFD, 0x60, 0x18, 0x24, 0x04, 0x70, 0x31, +0xF1, 0x73, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, +0xF9, 0xF1, 0x86, 0xCE, 0xC3, 0x13, 0xCE, 0x13, +0xD8, 0xF9, 0x80, 0x2F, 0xF1, 0x73, 0xC3, 0x33, +0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, 0x7C, 0x00, +0x7D, 0x06, 0x12, 0x20, 0x30, 0xEF, 0xF1, 0x86, +0xCE, 0xC3, 0x13, 0xCE, 0x13, 0xD8, 0xF9, 0x80, +0x12, 0xF1, 0x73, 0xC3, 0x33, 0xCE, 0x33, 0xCE, +0xD8, 0xF9, 0xF1, 0x86, 0xCE, 0xC3, 0x13, 0xCE, +0x13, 0xD8, 0xF9, 0x90, 0x81, 0xD6, 0xF0, 0x74, +0x0F, 0x2A, 0xF5, 0x82, 0xE4, 0x34, 0xFB, 0xF5, +0x83, 0xE0, 0xFF, 0x90, 0x89, 0x17, 0xE0, 0xFC, +0xA3, 0xE0, 0xFD, 0x90, 0x89, 0x15, 0xEC, 0x8D, +0xF0, 0x12, 0x93, 0x67, 0xFC, 0xA3, 0xE0, 0xFD, +0x90, 0x89, 0x15, 0xE0, 0xFA, 0xA3, 0xE0, 0xD3, +0x9D, 0xEA, 0x9C, 0x40, 0x1D, 0xF1, 0x6B, 0xFD, +0x90, 0x80, 0xFA, 0xE0, 0xFA, 0xA3, 0xE0, 0x24, +0x01, 0xFB, 0xE4, 0x3A, 0xFA, 0xC3, 0xED, 0x9B, +0xFD, 0xEC, 0x9A, 0x90, 0x89, 0x15, 0xF0, 0xA3, +0xED, 0xF0, 0xEF, 0x30, 0xE7, 0x08, 0x91, 0xE6, +0x90, 0x01, 0xC7, 0x74, 0x21, 0xF0, 0xEF, 0x30, +0xE6, 0x08, 0x91, 0xE6, 0x90, 0x01, 0xC7, 0x74, +0x22, 0xF0, 0xEF, 0x30, 0xE5, 0x08, 0x91, 0xE6, +0x90, 0x01, 0xC7, 0x74, 0x23, 0xF0, 0x90, 0x89, +0x1C, 0xE0, 0x24, 0xF8, 0x60, 0x2A, 0x24, 0x80, +0x60, 0x26, 0x24, 0xC8, 0x60, 0x06, 0x24, 0x20, +0x60, 0x02, 0x81, 0x75, 0x90, 0x81, 0xE6, 0xE0, +0xFF, 0xF1, 0xD8, 0x20, 0xE0, 0x02, 0x81, 0x75, +0xF1, 0xE9, 0x70, 0x02, 0x81, 0x75, 0x90, 0x89, +0x1C, 0xE0, 0xFF, 0x12, 0x93, 0xDB, 0x81, 0x75, +0xF1, 0xDF, 0x30, 0xE0, 0x5B, 0x90, 0x89, 0x20, +0xE0, 0xFF, 0x90, 0x89, 0x19, 0xE0, 0x2F, 0xFF, +0xE4, 0x33, 0xCF, 0x24, 0x08, 0xCF, 0x34, 0x00, +0x90, 0x89, 0x24, 0xF0, 0xA3, 0xEF, 0xF0, 0x24, +0x00, 0xF1, 0xA2, 0x64, 0x45, 0x70, 0x39, 0x91, +0xFC, 0x12, 0x96, 0xD8, 0xEF, 0x64, 0x01, 0x70, +0x2F, 0x91, 0xFC, 0x12, 0x96, 0xFC, 0xEF, 0x64, +0x01, 0x70, 0x25, 0x90, 0x89, 0x28, 0x04, 0xF0, +0x91, 0xFC, 0x90, 0x89, 0x21, 0xE0, 0xFD, 0x12, +0x8F, 0x5C, 0x90, 0x89, 0x21, 0xE0, 0xFD, 0x90, +0xFD, 0x11, 0xF0, 0x91, 0xFC, 0x12, 0x8F, 0x10, +0x90, 0x89, 0x21, 0xE0, 0x90, 0xFD, 0x11, 0xF0, +0xF1, 0xE9, 0x60, 0x37, 0x91, 0xEE, 0x90, 0x89, +0x1F, 0xE0, 0xFB, 0x90, 0x89, 0x21, 0xE0, 0x90, +0x89, 0x2D, 0xF0, 0xD1, 0x53, 0xEF, 0x60, 0x06, +0x90, 0x89, 0x28, 0x74, 0x01, 0xF0, 0x90, 0x81, +0xE4, 0xE0, 0xC4, 0x13, 0x54, 0x07, 0x30, 0xE0, +0x12, 0x91, 0xEE, 0x90, 0x89, 0x1F, 0xE0, 0xFB, +0xB1, 0x05, 0xEF, 0x60, 0x06, 0x90, 0x89, 0x28, +0x74, 0x01, 0xF0, 0x90, 0x81, 0xE3, 0xE0, 0xC3, +0x13, 0x30, 0xE0, 0x0E, 0x91, 0xEE, 0x12, 0x60, +0x2B, 0xEF, 0x60, 0x06, 0x90, 0x89, 0x28, 0x74, +0x01, 0xF0, 0x90, 0x81, 0xE3, 0xE0, 0x13, 0x13, +0x54, 0x3F, 0x30, 0xE0, 0x18, 0x90, 0x89, 0x19, +0xE0, 0xFF, 0x7E, 0x00, 0x90, 0x89, 0x20, 0xE0, +0xFD, 0x12, 0x61, 0xAE, 0xEF, 0x60, 0x06, 0x90, +0x89, 0x28, 0x74, 0x01, 0xF0, 0x90, 0x81, 0xE3, +0xF1, 0xD7, 0x30, 0xE0, 0x15, 0x90, 0x89, 0x28, +0xE0, 0x70, 0x0F, 0x91, 0xEE, 0xF1, 0xBC, 0xEF, +0x60, 0x08, 0x91, 0xE6, 0x90, 0x01, 0xC7, 0x74, +0x22, 0xF0, 0x91, 0xEE, 0xB1, 0xA3, 0xEF, 0x60, +0x0C, 0x90, 0x81, 0xEE, 0xE0, 0x54, 0xFE, 0xF0, +0x90, 0x01, 0xC7, 0xE4, 0xF0, 0x90, 0x81, 0xEE, +0xE0, 0x30, 0xE0, 0x1A, 0x90, 0x80, 0x07, 0xE0, +0xB4, 0x01, 0x0E, 0x90, 0xFD, 0x01, 0xE0, 0x20, +0xE6, 0x07, 0x90, 0xFD, 0x00, 0xE0, 0x44, 0x10, +0xF0, 0x7F, 0x01, 0x12, 0x70, 0x9D, 0x12, 0x93, +0xC4, 0xEF, 0x64, 0x01, 0x70, 0x42, 0x12, 0x93, +0xAE, 0x90, 0x89, 0x27, 0xEF, 0xF0, 0x64, 0x01, +0x60, 0x23, 0x91, 0xE6, 0x90, 0x89, 0x27, 0xE0, +0xFF, 0xB4, 0x02, 0x08, 0x90, 0x01, 0xC7, 0x74, +0x42, 0xF0, 0x80, 0x0A, 0xEF, 0xB4, 0x04, 0x06, +0x90, 0x01, 0xC7, 0x74, 0x43, 0xF0, 0x7F, 0x01, +0x12, 0x70, 0x9D, 0x80, 0x13, 0x90, 0x89, 0x15, +0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x12, 0x92, 0x6F, +0x90, 0x89, 0x1D, 0xE0, 0x04, 0xF0, 0x21, 0xC8, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xF0, 0x90, 0x81, +0xEE, 0xE0, 0x44, 0x01, 0xF0, 0x22, 0x90, 0x89, +0x1A, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x89, +0x20, 0xE0, 0xFD, 0x22, 0x90, 0x89, 0x24, 0xE0, +0xFE, 0xA3, 0xE0, 0xFF, 0x22, 0xF1, 0xAB, 0xE4, +0x90, 0x89, 0x2D, 0xF0, 0xA3, 0xF1, 0x91, 0x70, +0x41, 0xD1, 0x4A, 0xA3, 0xE0, 0xD1, 0xCF, 0x64, +0x88, 0x70, 0x37, 0xD1, 0x4A, 0xF1, 0x7D, 0x64, +0x8E, 0x70, 0x2F, 0x90, 0x89, 0x2D, 0xD1, 0x48, +0xD1, 0xC4, 0x04, 0xFD, 0xB1, 0x7A, 0xEF, 0x70, +0x21, 0xD1, 0x4A, 0xD1, 0xC4, 0x24, 0x04, 0xFD, +0xB1, 0x7A, 0xEF, 0x64, 0x01, 0x70, 0x13, 0xD1, +0x4A, 0xD1, 0xC4, 0x24, 0x08, 0xFD, 0xB1, 0x7A, +0xBF, 0x01, 0x07, 0x90, 0x01, 0xC7, 0x74, 0x0B, +0x91, 0xE5, 0x90, 0x89, 0x2D, 0xE0, 0xFF, 0x22, +0x90, 0x89, 0x2B, 0xE0, 0xFD, 0x90, 0x89, 0x2A, +0xE0, 0x2D, 0xFD, 0x90, 0x89, 0x29, 0xE0, 0x34, +0x00, 0xCD, 0x24, 0x10, 0xCD, 0x34, 0x00, 0xFC, +0x7E, 0x00, 0xED, 0x2F, 0xFF, 0xEE, 0x3C, 0xFE, +0xE4, 0xFD, 0xAB, 0x07, 0xAA, 0x06, 0xED, 0x2B, +0xFB, 0xE4, 0x3A, 0xFA, 0xC3, 0x90, 0x80, 0xFB, +0xE0, 0x9B, 0x90, 0x80, 0xFA, 0xE0, 0x9A, 0x50, +0x0B, 0xA3, 0x12, 0x93, 0x92, 0xC3, 0xEB, 0x9F, +0xFB, 0xEA, 0x9E, 0xFA, 0x12, 0x93, 0x7F, 0xF1, +0x9F, 0xFF, 0x22, 0x90, 0x89, 0x2B, 0xED, 0xF1, +0xB2, 0xF1, 0xF2, 0xEF, 0x70, 0x02, 0xC1, 0x45, +0xD1, 0x4A, 0xF1, 0xD0, 0x70, 0x02, 0xC1, 0x45, +0x12, 0x61, 0x9C, 0xCF, 0x24, 0x08, 0xCF, 0x34, +0x00, 0x90, 0x89, 0x2E, 0xF0, 0xA3, 0xEF, 0xF0, +0x90, 0x81, 0xE4, 0xE0, 0xC4, 0x54, 0x0F, 0x30, +0xE0, 0x2F, 0xD1, 0xBB, 0x7D, 0x09, 0xB1, 0x7A, +0xEF, 0x64, 0x06, 0x70, 0x24, 0xD1, 0xBB, 0x7D, +0x14, 0xB1, 0x7A, 0xEF, 0x70, 0x1B, 0xD1, 0xBB, +0x7D, 0x15, 0xB1, 0x7A, 0xEF, 0x64, 0x50, 0x70, +0x10, 0xD1, 0xBB, 0x7D, 0x21, 0xB1, 0x7A, 0xEF, +0x20, 0xE0, 0x03, 0x30, 0xE2, 0x03, 0x7F, 0x01, +0x22, 0x90, 0x81, 0xE4, 0xE0, 0x13, 0x13, 0x54, +0x3F, 0x30, 0xE0, 0x39, 0xD1, 0xBB, 0x7D, 0x09, +0xB1, 0x7A, 0xEF, 0x64, 0x11, 0x70, 0x2E, 0x90, +0x89, 0x2F, 0xE0, 0x24, 0x14, 0xFF, 0x90, 0x89, +0x2E, 0xE0, 0x34, 0x00, 0xFE, 0x90, 0x89, 0x2C, +0xF0, 0xA3, 0xEF, 0xF0, 0x7D, 0x02, 0xB1, 0x7A, +0xEF, 0x70, 0x12, 0x90, 0x89, 0x2C, 0xE0, 0xFE, +0xA3, 0xE0, 0xFF, 0x7D, 0x03, 0xB1, 0x7A, 0xBF, +0x89, 0x03, 0x7F, 0x01, 0x22, 0x7F, 0x00, 0x22, +0x04, 0xF0, 0x90, 0x89, 0x29, 0xE0, 0xFE, 0xA3, +0xE0, 0xFF, 0x22, 0xF1, 0xAB, 0xE4, 0x90, 0x89, +0x2E, 0xF0, 0x90, 0x89, 0x2D, 0xF1, 0x91, 0x70, +0x54, 0xD1, 0x4A, 0xA3, 0xE0, 0xD1, 0xCF, 0x64, +0x88, 0x70, 0x4A, 0xD1, 0x4A, 0xF1, 0x7D, 0x64, +0x8E, 0x70, 0x42, 0x90, 0x89, 0x2E, 0xD1, 0x48, +0xD1, 0xC4, 0x04, 0xFD, 0xB1, 0x7A, 0xEF, 0x64, +0x03, 0x70, 0x32, 0xD1, 0x4A, 0xD1, 0xC4, 0xD1, +0xCF, 0x30, 0xE3, 0x07, 0x90, 0x01, 0xC7, 0x74, +0x01, 0x80, 0x20, 0x90, 0x81, 0xE3, 0x12, 0x4F, +0xF3, 0x30, 0xE0, 0x0A, 0xD1, 0x4A, 0xA3, 0xE0, +0xFD, 0x12, 0x70, 0xF3, 0x80, 0x0F, 0x90, 0x81, +0xE6, 0xF1, 0xE2, 0x30, 0xE0, 0x07, 0x90, 0x01, +0xC7, 0x74, 0x02, 0x91, 0xE5, 0x90, 0x89, 0x2E, +0xE0, 0xFF, 0x22, 0x90, 0x89, 0x2E, 0xE0, 0xFE, +0xA3, 0xE0, 0xFF, 0x22, 0x90, 0x89, 0x2C, 0xE0, +0xFD, 0x90, 0x89, 0x2B, 0xE0, 0x2D, 0x22, 0x24, +0x06, 0xFD, 0xB1, 0x7A, 0xEF, 0x22, 0xFF, 0x90, +0x89, 0x32, 0xE0, 0x34, 0x00, 0xFE, 0xE4, 0xFD, +0xA1, 0x7A, 0x90, 0x89, 0x30, 0x12, 0x94, 0xCB, +0x78, 0x34, 0x7C, 0x89, 0x7D, 0x01, 0x7B, 0xFF, +0x7A, 0x40, 0x79, 0xFA, 0x12, 0x97, 0xE0, 0x90, +0x89, 0x32, 0xE0, 0xFF, 0x90, 0x89, 0x31, 0xE0, +0x2F, 0xFF, 0x90, 0x89, 0x30, 0xE0, 0x34, 0x00, +0xFE, 0x90, 0x89, 0x38, 0xF0, 0xA3, 0xEF, 0xF0, +0x24, 0x06, 0xFF, 0xE4, 0x3E, 0xD1, 0xDD, 0xEF, +0x64, 0x08, 0x70, 0x4E, 0x90, 0x89, 0x39, 0xE0, +0x24, 0x07, 0xFF, 0x90, 0x89, 0x38, 0xD1, 0xDA, +0xEF, 0x70, 0x3F, 0x90, 0x89, 0x33, 0xF0, 0x90, +0x89, 0x33, 0xE0, 0xFF, 0xC3, 0x94, 0x04, 0x50, +0x21, 0x90, 0x89, 0x39, 0xE0, 0x24, 0x18, 0xFD, +0x90, 0x89, 0x38, 0xE0, 0xB1, 0x6D, 0x90, 0x89, +0x33, 0xE0, 0x24, 0x34, 0xF5, 0x82, 0xE4, 0x34, +0x89, 0xF5, 0x83, 0x12, 0x72, 0x59, 0x04, 0xF0, +0x80, 0xD5, 0x78, 0x34, 0x7C, 0x89, 0x12, 0x67, +0xF0, 0x12, 0x96, 0xF3, 0x7F, 0x00, 0x70, 0x02, +0x7F, 0x01, 0x22, 0x90, 0x89, 0x15, 0xE0, 0xFC, +0xA3, 0xE0, 0x22, 0x90, 0x89, 0x22, 0xE0, 0xFE, +0xA3, 0xE0, 0x78, 0x03, 0x22, 0xA3, 0xE0, 0x24, +0x07, 0xFD, 0xB1, 0x7A, 0xEF, 0x22, 0x24, 0x63, +0xFF, 0xEE, 0x34, 0x01, 0xFE, 0xEF, 0x78, 0x07, +0x22, 0xF0, 0xFD, 0xB1, 0x7A, 0xEF, 0x54, 0x0C, +0x64, 0x08, 0x22, 0xF5, 0x83, 0xE0, 0xFE, 0x74, +0x00, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0xFB, 0xF5, +0x83, 0xE0, 0x22, 0x90, 0x89, 0x2B, 0xED, 0xF0, +0xA3, 0xEB, 0xF0, 0x90, 0x89, 0x29, 0xEE, 0xF0, +0xA3, 0xEF, 0xF0, 0x22, 0x90, 0x89, 0x2B, 0xED, +0xF1, 0xB2, 0xF1, 0xF2, 0xEF, 0x60, 0x08, 0xD1, +0x4A, 0xF1, 0xD0, 0x60, 0x02, 0x7F, 0x01, 0x22, +0xA3, 0xE0, 0xFD, 0xD1, 0xE2, 0xEF, 0x22, 0xE0, +0xC4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x22, 0x90, +0x81, 0xE3, 0xE0, 0xC4, 0x13, 0x13, 0x54, 0x03, +0x22, 0x90, 0x89, 0x19, 0xE0, 0xFF, 0xF1, 0xF2, +0xEF, 0x22, 0xE4, 0xFE, 0xEF, 0x2E, 0x12, 0x98, +0x65, 0xF5, 0x83, 0xE0, 0xFD, 0x74, 0x30, 0x2E, +0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xED, +0xF0, 0x0E, 0xEE, 0xB4, 0x06, 0xE6, 0x78, 0xEF, +0x7C, 0x81, 0x7D, 0x01, 0x7B, 0x01, 0x7A, 0x89, +0x79, 0x30, 0x11, 0x24, 0xEF, 0x7F, 0x00, 0x70, +0x02, 0x7F, 0x01, 0x22, 0x7E, 0x00, 0x7F, 0x06, +0x02, 0x46, 0x27, 0x12, 0x5F, 0xB3, 0xA3, 0xED, +0xF0, 0x78, 0x32, 0x7C, 0x89, 0x7D, 0x01, 0x7B, +0xFF, 0x7A, 0x40, 0x79, 0xC0, 0xF1, 0xDB, 0x78, +0x38, 0x7C, 0x89, 0x7D, 0x01, 0x7B, 0xFF, 0x7A, +0x40, 0x79, 0xC6, 0x12, 0x97, 0xE0, 0x78, 0x3C, +0x7C, 0x89, 0x7D, 0x01, 0x7B, 0xFF, 0x7A, 0x40, +0x79, 0xCA, 0x12, 0x97, 0xE0, 0xE4, 0x90, 0x89, +0x41, 0xF0, 0x31, 0x9C, 0xCF, 0x24, 0x06, 0xCF, +0x12, 0x5E, 0xDB, 0xEF, 0x64, 0x08, 0x60, 0x02, +0x21, 0x8B, 0x31, 0x9C, 0xCF, 0x24, 0x07, 0xCF, +0x12, 0x5E, 0xDB, 0xEF, 0x64, 0x06, 0x60, 0x02, +0x21, 0x8B, 0x90, 0x89, 0x41, 0x04, 0xF0, 0xE4, +0x90, 0x89, 0x40, 0xF0, 0x90, 0x89, 0x40, 0xE0, +0xFF, 0xC3, 0x94, 0x06, 0x50, 0x1D, 0x90, 0x89, +0x2A, 0xE0, 0x24, 0x0A, 0xFD, 0x90, 0x89, 0x29, +0xE0, 0x12, 0x5D, 0x6D, 0x90, 0x89, 0x40, 0xE0, +0x24, 0x2C, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0x31, +0x91, 0x80, 0xD9, 0x78, 0x2C, 0x7C, 0x89, 0x7D, +0x01, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0xF5, 0x11, +0x24, 0xEF, 0x60, 0x02, 0x21, 0x8B, 0x90, 0x89, +0x40, 0xF0, 0x90, 0x89, 0x40, 0xE0, 0xFF, 0xC3, +0x94, 0x04, 0x50, 0x19, 0x71, 0x94, 0x31, 0xA7, +0xCD, 0x24, 0x20, 0x12, 0x5D, 0x6C, 0x90, 0x89, +0x40, 0xE0, 0x24, 0x3C, 0xF5, 0x82, 0xE4, 0x34, +0x89, 0x31, 0x91, 0x80, 0xDD, 0x78, 0x3C, 0x7C, +0x89, 0xF1, 0xF0, 0x12, 0x96, 0xF3, 0x60, 0x02, +0x21, 0x82, 0x90, 0x06, 0x30, 0xE0, 0x44, 0x01, +0x54, 0xDF, 0xF0, 0x90, 0x81, 0xE5, 0xE0, 0x30, +0xE0, 0x02, 0x80, 0x10, 0x90, 0x84, 0x7C, 0xE0, +0xB4, 0x02, 0x13, 0x90, 0x81, 0xE4, 0x12, 0x4F, +0xF3, 0x20, 0xE0, 0x0A, 0x90, 0x01, 0xC7, 0x74, +0x09, 0x12, 0x5C, 0xE5, 0x80, 0x65, 0xE4, 0x90, +0x89, 0x40, 0xF0, 0x90, 0x89, 0x40, 0xE0, 0xFF, +0xC3, 0x94, 0x06, 0x50, 0x12, 0x12, 0x5D, 0x58, +0x90, 0x89, 0x40, 0xE0, 0x24, 0x32, 0xF5, 0x82, +0xE4, 0x34, 0x89, 0x31, 0x91, 0x80, 0xE4, 0xE4, +0x90, 0x89, 0x40, 0xF0, 0x90, 0x89, 0x40, 0xE0, +0xFF, 0xC3, 0x94, 0x04, 0x50, 0x19, 0x71, 0x94, +0x31, 0xA7, 0xCD, 0x24, 0x16, 0x12, 0x5D, 0x6C, +0x90, 0x89, 0x40, 0xE0, 0x24, 0x38, 0xF5, 0x82, +0xE4, 0x34, 0x89, 0x31, 0x91, 0x80, 0xDD, 0x7B, +0x01, 0x7A, 0x89, 0x79, 0x32, 0x12, 0x97, 0xE7, +0xA3, 0xF0, 0x7A, 0x89, 0x79, 0x38, 0xB1, 0x30, +0x80, 0x09, 0x90, 0x06, 0x30, 0xE0, 0x44, 0x21, +0x54, 0xEF, 0xF0, 0x90, 0x89, 0x41, 0xE0, 0xFF, +0x22, 0xF5, 0x83, 0xEF, 0xF0, 0x90, 0x89, 0x40, +0xE0, 0x04, 0xF0, 0x22, 0x90, 0x89, 0x2B, 0xE0, +0xFF, 0x90, 0x89, 0x2A, 0xE0, 0x2F, 0xFF, 0x90, +0x89, 0x29, 0xE0, 0x34, 0x00, 0x22, 0x12, 0x5F, +0xB3, 0xA3, 0xED, 0xF0, 0x78, 0x2C, 0x7C, 0x89, +0x7D, 0x01, 0x7B, 0xFF, 0x7A, 0x40, 0x79, 0xD4, +0xF1, 0xDB, 0x78, 0x32, 0x7C, 0x89, 0x7D, 0x01, +0x7B, 0xFF, 0x7A, 0x40, 0x79, 0xDA, 0x12, 0x98, +0x7D, 0x78, 0x42, 0x7C, 0x89, 0x7D, 0x01, 0x7B, +0xFF, 0x7A, 0x40, 0x79, 0xEA, 0x12, 0x98, 0x7D, +0xE4, 0x90, 0x89, 0x55, 0x12, 0x5E, 0x49, 0xA3, +0xE0, 0xFD, 0x12, 0x94, 0x97, 0xEF, 0x64, 0x01, +0x60, 0x02, 0x61, 0x8E, 0x31, 0x9C, 0xCF, 0x24, +0x0E, 0xCF, 0x12, 0x5E, 0xDB, 0xEF, 0x64, 0x3A, +0x60, 0x02, 0x61, 0x8E, 0x31, 0x9C, 0xCF, 0x24, +0x30, 0xCF, 0x12, 0x5E, 0xDB, 0xEF, 0x64, 0x87, +0x60, 0x02, 0x61, 0x8E, 0x90, 0x89, 0x55, 0x04, +0xF0, 0xE4, 0x90, 0x89, 0x52, 0xF0, 0xF1, 0xE9, +0x94, 0x10, 0x50, 0x1A, 0x71, 0x94, 0x31, 0xA7, +0xCD, 0x24, 0x38, 0x12, 0x5D, 0x6C, 0x90, 0x89, +0x52, 0xE0, 0x24, 0x42, 0xF5, 0x82, 0xE4, 0x34, +0x89, 0x12, 0x97, 0x8E, 0x80, 0xE0, 0xE4, 0x90, +0x89, 0x53, 0xF0, 0x90, 0x89, 0x53, 0xE0, 0xFF, +0xC3, 0x94, 0x02, 0x40, 0x02, 0x61, 0x8E, 0x75, +0xF0, 0x38, 0xEF, 0x12, 0x98, 0x75, 0x20, 0xE0, +0x02, 0x61, 0x8E, 0xE4, 0x90, 0x89, 0x54, 0xF0, +0x90, 0x89, 0x53, 0xE0, 0xFF, 0x75, 0xF0, 0x38, +0x90, 0x82, 0x1F, 0x12, 0x44, 0x5D, 0xE0, 0xFE, +0x90, 0x89, 0x54, 0xE0, 0xC3, 0x9E, 0x40, 0x02, +0x61, 0x86, 0xEF, 0x75, 0xF0, 0x38, 0xA4, 0x24, +0x36, 0xF9, 0x74, 0x82, 0x35, 0xF0, 0xFA, 0x7B, +0x01, 0xE0, 0x75, 0xF0, 0x10, 0xA4, 0x29, 0xF9, +0xEA, 0x35, 0xF0, 0xFA, 0x78, 0x42, 0x7C, 0x89, +0x12, 0x98, 0x2C, 0x60, 0x02, 0x61, 0x77, 0x90, +0x06, 0x33, 0xE0, 0x44, 0x01, 0x54, 0xFB, 0xF0, +0xE4, 0x90, 0x89, 0x52, 0xF0, 0xF1, 0xE9, 0x94, +0x06, 0x50, 0x1A, 0x71, 0x94, 0x31, 0xA7, 0xCD, +0x24, 0x4A, 0x12, 0x5D, 0x6C, 0x90, 0x89, 0x52, +0xE0, 0x24, 0x2C, 0xF5, 0x82, 0xE4, 0x34, 0x89, +0x12, 0x97, 0x8E, 0x80, 0xE0, 0xE4, 0x90, 0x89, +0x52, 0xF0, 0xF1, 0xE9, 0x94, 0x10, 0x50, 0x13, +0x12, 0x5D, 0x58, 0x90, 0x89, 0x52, 0xE0, 0x24, +0x32, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0x12, 0x97, +0x8E, 0x80, 0xE7, 0x90, 0x89, 0x53, 0xE0, 0xFF, +0x75, 0xF0, 0x38, 0x12, 0x98, 0x75, 0xFE, 0xC3, +0x13, 0x30, 0xE0, 0x29, 0xEF, 0x75, 0xF0, 0x38, +0xA4, 0x24, 0x26, 0xF9, 0x74, 0x82, 0x35, 0xF0, +0xFA, 0x7B, 0x01, 0x78, 0x32, 0x7C, 0x89, 0x12, +0x98, 0x2C, 0x70, 0x6A, 0x90, 0x84, 0x7C, 0xE0, +0xB4, 0x02, 0x08, 0x12, 0x6E, 0x6E, 0x20, 0xE0, +0x1B, 0x80, 0x0F, 0x80, 0x17, 0x90, 0x84, 0x7C, +0xE0, 0xB4, 0x02, 0x10, 0x12, 0x6E, 0x6E, 0x20, +0xE0, 0x0A, 0x90, 0x01, 0xC7, 0x74, 0x0A, 0x12, +0x5C, 0xE5, 0x80, 0x52, 0x7B, 0x01, 0x7A, 0x89, +0x79, 0x2C, 0x90, 0x89, 0x59, 0x12, 0x44, 0x72, +0x7A, 0x89, 0x79, 0x42, 0x90, 0x89, 0x5C, 0x12, +0x44, 0x72, 0x90, 0x89, 0x53, 0xE0, 0x75, 0xF0, +0x38, 0xA4, 0x24, 0x20, 0xF9, 0x74, 0x82, 0x35, +0xF0, 0xFA, 0x90, 0x89, 0x5F, 0x12, 0x44, 0x72, +0xE4, 0x90, 0x89, 0x62, 0xF0, 0xA3, 0xF0, 0x7A, +0x89, 0x79, 0x32, 0x71, 0xA0, 0x80, 0x07, 0x90, +0x06, 0x33, 0xE0, 0x44, 0x05, 0xF0, 0x90, 0x89, +0x54, 0xE0, 0x04, 0xF0, 0x41, 0x60, 0x90, 0x89, +0x53, 0xE0, 0x04, 0xF0, 0x41, 0x43, 0x90, 0x89, +0x55, 0xE0, 0xFF, 0x22, 0x90, 0x89, 0x2B, 0xE0, +0xFD, 0x90, 0x89, 0x2A, 0xE0, 0x2D, 0xFD, 0x22, +0x90, 0x89, 0x56, 0x12, 0x44, 0x72, 0x90, 0x05, +0x22, 0xE0, 0x90, 0x89, 0x67, 0xF0, 0x90, 0x04, +0x1D, 0xE0, 0x60, 0x0B, 0x7B, 0x39, 0xD1, 0x89, +0xEF, 0x64, 0x01, 0x70, 0x1C, 0x80, 0x00, 0x90, +0x84, 0x80, 0xE0, 0xFF, 0x90, 0x8A, 0x4A, 0x74, +0x11, 0xF0, 0x7B, 0x18, 0x7D, 0x01, 0x12, 0x82, +0xD7, 0x90, 0x89, 0x64, 0xEE, 0xF0, 0xA3, 0xEF, +0xF0, 0x90, 0x89, 0x64, 0x12, 0x86, 0x48, 0x90, +0x89, 0x66, 0xEF, 0xF0, 0x90, 0x89, 0x64, 0x12, +0x87, 0xD0, 0x90, 0x89, 0x62, 0xE0, 0xFD, 0x12, +0x56, 0x9B, 0x90, 0x89, 0x63, 0xE0, 0x60, 0x02, +0x81, 0x82, 0xD1, 0xF5, 0xC0, 0x03, 0xC0, 0x02, +0xC0, 0x01, 0x90, 0x89, 0x59, 0xD1, 0x5D, 0x75, +0x16, 0x06, 0xD0, 0x01, 0xD0, 0x02, 0xD0, 0x03, +0xB1, 0x23, 0x12, 0x97, 0xC6, 0xC0, 0x03, 0xC0, +0x02, 0xC0, 0x01, 0x90, 0x89, 0x56, 0xD1, 0x5D, +0x75, 0x16, 0x10, 0xD0, 0x01, 0xD0, 0x02, 0xD0, +0x03, 0xB1, 0x23, 0xD1, 0xF8, 0xC0, 0x03, 0xC0, +0x02, 0xC0, 0x01, 0x90, 0x89, 0x5C, 0xD1, 0x5D, +0x75, 0x16, 0x10, 0xD0, 0x01, 0xD0, 0x02, 0xD0, +0x03, 0xB1, 0x23, 0x24, 0x58, 0xF9, 0xE4, 0x34, +0xFC, 0xFA, 0x7B, 0x01, 0xC0, 0x03, 0xC0, 0x02, +0xC0, 0x01, 0x90, 0x89, 0x5C, 0xD1, 0x5D, 0x75, +0x16, 0x10, 0xD0, 0x01, 0xD0, 0x02, 0xD0, 0x03, +0xB1, 0x23, 0x24, 0x6A, 0xF9, 0xE4, 0x34, 0xFC, +0xFA, 0x7B, 0x01, 0xC0, 0x03, 0xC0, 0x02, 0xC0, +0x01, 0x90, 0x89, 0x5F, 0xD1, 0x5D, 0x75, 0x16, +0x06, 0xD0, 0x01, 0xD0, 0x02, 0xD0, 0x03, 0x12, +0x2B, 0xED, 0x90, 0x89, 0x5C, 0x12, 0x44, 0x69, +0x90, 0x89, 0x93, 0x12, 0x44, 0x72, 0x90, 0x89, +0x96, 0x12, 0x20, 0xDA, 0x00, 0x00, 0x00, 0x20, +0x90, 0x89, 0x9A, 0x74, 0x3A, 0xF0, 0x90, 0x89, +0x56, 0x12, 0x44, 0x69, 0x12, 0x94, 0xD4, 0xB1, +0x26, 0x24, 0x28, 0xF9, 0xE4, 0x34, 0xFC, 0xF1, +0xD3, 0x75, 0x16, 0x28, 0x7B, 0x01, 0x7A, 0x89, +0x79, 0x68, 0xB1, 0x23, 0x12, 0x98, 0x42, 0xC0, +0x03, 0x8B, 0x13, 0x75, 0x14, 0x82, 0x75, 0x15, +0x8E, 0x75, 0x16, 0x28, 0xD0, 0x03, 0x12, 0x2B, +0xED, 0x90, 0x89, 0x66, 0xE0, 0xFF, 0x90, 0x89, +0x65, 0xE0, 0x2F, 0xFF, 0x90, 0x89, 0x64, 0xE0, +0x34, 0x00, 0xCF, 0x24, 0x28, 0xFD, 0xE4, 0x3F, +0xFC, 0x90, 0x84, 0x80, 0xE0, 0xFB, 0x7F, 0x3A, +0x12, 0x75, 0x52, 0xB1, 0x26, 0x12, 0x98, 0x42, +0xC0, 0x03, 0x8B, 0x13, 0x75, 0x14, 0x89, 0x75, +0x15, 0x68, 0x75, 0x16, 0x28, 0xD0, 0x03, 0x12, +0x2B, 0xED, 0x90, 0x06, 0x33, 0xE0, 0x44, 0x02, +0xF0, 0x90, 0x89, 0x67, 0xE0, 0xFD, 0x7B, 0x3A, +0xE4, 0xFF, 0xD1, 0x73, 0x90, 0x04, 0x1F, 0x74, +0x20, 0xF0, 0x22, 0x12, 0x2B, 0xED, 0x90, 0x89, +0x64, 0xA3, 0xE0, 0xFF, 0xA3, 0xE0, 0x2F, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, +0x84, 0xA1, 0x12, 0x44, 0x72, 0x78, 0xAD, 0x7C, +0x84, 0x7D, 0x01, 0x7B, 0xFF, 0x7A, 0x40, 0x79, +0xCE, 0xF1, 0xDB, 0x90, 0x05, 0x22, 0xE0, 0x90, +0x84, 0xAC, 0xF0, 0x90, 0x04, 0x1D, 0xE0, 0x60, +0x0B, 0x7B, 0x33, 0xD1, 0x89, 0xEF, 0x64, 0x01, +0x70, 0x1C, 0x80, 0x00, 0x90, 0x84, 0x7F, 0xE0, +0xFF, 0x90, 0x8A, 0x4A, 0x74, 0x10, 0xF0, 0x7B, +0x18, 0x7D, 0x01, 0x12, 0x82, 0xD7, 0x90, 0x84, +0xA9, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x84, +0xA9, 0x12, 0x86, 0x48, 0x90, 0x84, 0xAB, 0xEF, +0xF0, 0x90, 0x84, 0xA9, 0x12, 0x87, 0xD0, 0x90, +0x84, 0xA7, 0xE0, 0xFD, 0x12, 0x56, 0x9B, 0x90, +0x84, 0xA8, 0xE0, 0x70, 0x56, 0xD1, 0xF5, 0xC0, +0x03, 0xC0, 0x02, 0xC0, 0x01, 0x90, 0x84, 0xA4, +0xD1, 0x5D, 0x75, 0x16, 0x06, 0xD0, 0x01, 0xD0, +0x02, 0xD0, 0x03, 0x12, 0x2B, 0xED, 0x90, 0x84, +0xA9, 0xB1, 0x29, 0xF1, 0xE2, 0xFA, 0x7B, 0x01, +0xC0, 0x03, 0xC0, 0x02, 0xC0, 0x01, 0x90, 0x84, +0xA4, 0xD1, 0x5D, 0x75, 0x16, 0x06, 0xD0, 0x01, +0xD0, 0x02, 0xD0, 0x03, 0x12, 0x2B, 0xED, 0x90, +0x84, 0xA9, 0xB1, 0x29, 0x12, 0x97, 0xC6, 0xC0, +0x03, 0xC0, 0x02, 0xC0, 0x01, 0x90, 0x84, 0xA1, +0xD1, 0x5D, 0x75, 0x16, 0x04, 0xD0, 0x01, 0xD0, +0x02, 0x80, 0x4D, 0x90, 0x84, 0xA8, 0xE0, 0x64, +0x01, 0x70, 0x4A, 0xD1, 0xF5, 0xC0, 0x03, 0x8B, +0x13, 0x75, 0x14, 0x82, 0x75, 0x15, 0x0A, 0x75, +0x16, 0x06, 0xD0, 0x03, 0x12, 0x2B, 0xED, 0x90, +0x84, 0xA9, 0xB1, 0x29, 0xF1, 0xE2, 0xFA, 0x7B, +0x01, 0xC0, 0x03, 0x8B, 0x13, 0x75, 0x14, 0x82, +0x75, 0x15, 0x14, 0x75, 0x16, 0x06, 0xD0, 0x03, +0x12, 0x2B, 0xED, 0x90, 0x84, 0xA9, 0xB1, 0x29, +0x12, 0x97, 0xC6, 0xC0, 0x03, 0x8B, 0x13, 0x75, +0x14, 0x82, 0x75, 0x15, 0x1A, 0x75, 0x16, 0x04, +0xD0, 0x03, 0x12, 0x2B, 0xED, 0x90, 0x06, 0x30, +0xE0, 0x44, 0x10, 0xF0, 0x90, 0x84, 0xAC, 0xE0, +0xFD, 0x7B, 0x34, 0xB1, 0x18, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0x90, 0x89, 0xDA, 0x12, 0x44, 0x69, +0x8B, 0x13, 0x8A, 0x14, 0x89, 0x15, 0x22, 0xE4, +0xFD, 0x7F, 0x0C, 0x12, 0x4D, 0xFA, 0xE4, 0xFB, +0xFD, 0x7F, 0xFF, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x05, 0x22, 0xED, 0xF0, 0x90, +0x80, 0x05, 0xEB, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x7D, 0xFF, 0xE4, 0xFF, 0xD1, 0x73, 0xE4, +0x90, 0x84, 0xFD, 0xF0, 0xA3, 0xF0, 0x90, 0x05, +0x22, 0xE0, 0x90, 0x84, 0xFF, 0xF0, 0x7B, 0x47, +0x7D, 0xFF, 0xE4, 0xFF, 0xD1, 0x73, 0x90, 0x05, +0xF8, 0xE0, 0x70, 0x1A, 0xA3, 0xE0, 0x70, 0x16, +0xA3, 0xE0, 0x70, 0x12, 0xA3, 0xE0, 0x70, 0x0E, +0x90, 0x84, 0xFF, 0xE0, 0xFD, 0x7B, 0x48, 0xE4, +0xFF, 0xD1, 0x73, 0x7F, 0x01, 0x22, 0xD3, 0x90, +0x84, 0xFE, 0xE0, 0x94, 0xE8, 0x90, 0x84, 0xFD, +0xE0, 0x94, 0x03, 0x40, 0x15, 0x90, 0x01, 0xC0, +0xE0, 0x44, 0x20, 0xF0, 0x90, 0x84, 0xFF, 0xE0, +0xFD, 0x7B, 0x5B, 0xE4, 0xFF, 0xD1, 0x73, 0x7F, +0x00, 0x22, 0x12, 0x87, 0x71, 0x90, 0x84, 0xFD, +0x12, 0x78, 0xE3, 0x80, 0xB1, 0xA3, 0xA3, 0xE0, +0x24, 0x30, 0xF9, 0xE4, 0x34, 0xFC, 0xFA, 0x7B, +0x01, 0x22, 0x7D, 0x08, 0xE4, 0xFF, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x8A, 0x3E, +0xEF, 0xF0, 0xA3, 0xED, 0xF0, 0x90, 0x80, 0x03, +0xE0, 0x04, 0xF0, 0x90, 0x04, 0x1D, 0xE0, 0x60, +0x29, 0x90, 0x05, 0x22, 0xE0, 0x90, 0x8A, 0x42, +0xF0, 0x7B, 0x26, 0xD1, 0x89, 0xEF, 0x64, 0x01, +0x70, 0x03, 0x12, 0x83, 0xA4, 0x90, 0x8A, 0x42, +0xE0, 0xFD, 0x7B, 0x27, 0xE4, 0xFF, 0xD1, 0x73, +0x90, 0x8A, 0x3E, 0xE0, 0xFF, 0x12, 0x91, 0x71, +0x80, 0x0B, 0x90, 0x8A, 0x3E, 0xE0, 0xFF, 0x12, +0x91, 0x71, 0x12, 0x83, 0xA4, 0xB1, 0x1C, 0x7F, +0x01, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x12, 0x82, +0xC3, 0x90, 0x8A, 0x53, 0xE4, 0xF0, 0xA3, 0xEF, +0xF0, 0x90, 0x8A, 0x53, 0x12, 0x86, 0x48, 0x90, +0x8A, 0x55, 0xEF, 0xF0, 0x90, 0x8A, 0x53, 0xA3, +0xE0, 0x24, 0x30, 0xF9, 0xE4, 0x34, 0xFC, 0xF1, +0xD3, 0x75, 0x16, 0x06, 0x7B, 0x01, 0x7A, 0x82, +0x79, 0x0A, 0x12, 0x98, 0x56, 0xB1, 0x29, 0x24, +0x36, 0xF9, 0xE4, 0x34, 0xFC, 0xF1, 0xD3, 0x75, +0x16, 0x04, 0xF1, 0xF2, 0x12, 0x98, 0x56, 0xB1, +0x29, 0xF1, 0xE2, 0xF1, 0xD3, 0x75, 0x16, 0x06, +0x7B, 0x01, 0x7A, 0x82, 0x79, 0x14, 0x12, 0x98, +0x56, 0xB1, 0x29, 0x24, 0x40, 0xF9, 0xE4, 0x34, +0xFC, 0xF1, 0xD3, 0x75, 0x16, 0x04, 0x7B, 0x01, +0x7A, 0x82, 0x79, 0x1A, 0x02, 0x2B, 0xED, 0x12, +0x82, 0xC3, 0x7E, 0x00, 0x74, 0x00, 0x2F, 0xF9, +0xE4, 0x34, 0xFC, 0x75, 0x13, 0x01, 0xF5, 0x14, +0x89, 0x15, 0x22, 0x7E, 0x00, 0x7F, 0x06, 0x02, +0x43, 0xD0, 0x24, 0x3A, 0xF9, 0xE4, 0x34, 0xFC, +0x22, 0x90, 0x89, 0x52, 0xE0, 0xFF, 0xC3, 0x22, +0x7D, 0x01, 0x7B, 0x01, 0x7A, 0x82, 0x79, 0x10, +0x22, 0x75, 0xE8, 0x03, 0x75, 0xA8, 0x84, 0x22, +0x90, 0x00, 0x80, 0xE0, 0x44, 0x80, 0xFD, 0x7F, +0x80, 0x12, 0x32, 0x1E, 0x90, 0xFD, 0x00, 0xE0, +0x54, 0xBF, 0xF0, 0x12, 0x8D, 0x24, 0x12, 0x32, +0x77, 0xF1, 0xE4, 0x12, 0x8D, 0x58, 0x7F, 0x01, +0x12, 0x47, 0x8C, 0x90, 0x84, 0x8E, 0x74, 0x02, +0xF0, 0xFF, 0x12, 0x47, 0x8C, 0x90, 0x84, 0x8E, +0xE0, 0x04, 0xF0, 0x12, 0x58, 0x42, 0x11, 0x5A, +0x90, 0x01, 0xCC, 0x74, 0x0F, 0xF0, 0x90, 0x00, +0x80, 0xE0, 0x44, 0x40, 0xFD, 0x7F, 0x80, 0x12, +0x32, 0x1E, 0x75, 0x20, 0xFF, 0x12, 0x67, 0xF9, +0xF1, 0xE5, 0x12, 0x8D, 0x5F, 0xE4, 0xFF, 0x02, +0x48, 0x15, 0x31, 0xEA, 0x12, 0x8B, 0x79, 0x11, +0x87, 0x12, 0x81, 0x92, 0x12, 0x7F, 0x92, 0x12, +0x92, 0x55, 0x90, 0x84, 0x9B, 0xE0, 0x54, 0x7F, +0xF0, 0x54, 0xBF, 0xF0, 0x54, 0xDF, 0xF0, 0x54, +0xF0, 0xF0, 0xE4, 0x90, 0x84, 0x9D, 0xF0, 0x90, +0x84, 0x9B, 0xE0, 0x54, 0xEF, 0xF0, 0x22, 0x7E, +0x00, 0x7F, 0xD7, 0x7D, 0x00, 0x7B, 0x01, 0x7A, +0x81, 0x79, 0x05, 0x12, 0x46, 0x4B, 0x90, 0x81, +0x09, 0x74, 0x02, 0xF0, 0x90, 0x81, 0x10, 0x14, +0xF0, 0xA3, 0xF0, 0xA3, 0x74, 0x10, 0xF0, 0x90, +0x81, 0x16, 0xE4, 0xF0, 0xA3, 0x74, 0x02, 0x31, +0xAD, 0x12, 0x91, 0x0F, 0xE4, 0xFD, 0xFF, 0x31, +0x45, 0x7D, 0x0C, 0x7F, 0x02, 0x31, 0x45, 0x31, +0x41, 0x90, 0x80, 0x07, 0xE0, 0xFF, 0xB4, 0x01, +0x08, 0x90, 0x81, 0x15, 0x74, 0x99, 0xF0, 0x80, +0x29, 0xEF, 0xB4, 0x03, 0x08, 0x90, 0x81, 0x15, +0x74, 0x90, 0xF0, 0x80, 0x1D, 0x90, 0x81, 0x15, +0x74, 0x40, 0xF0, 0x90, 0x00, 0x2C, 0xE0, 0x54, +0x0F, 0xFF, 0xBF, 0x05, 0x08, 0x90, 0x81, 0x27, +0x74, 0x02, 0xF0, 0x80, 0x05, 0xE4, 0x90, 0x81, +0x27, 0xF0, 0x90, 0x81, 0xDC, 0x74, 0x03, 0xF0, +0xA3, 0x74, 0x0F, 0xF0, 0xA3, 0xE0, 0x54, 0x01, +0x44, 0x28, 0xF0, 0xA3, 0x74, 0x07, 0x31, 0xAD, +0x7F, 0x01, 0x12, 0x91, 0x27, 0x90, 0x05, 0x58, +0x74, 0x02, 0xF0, 0x7E, 0x00, 0xFF, 0x7D, 0x00, +0x7B, 0x01, 0x7A, 0x81, 0x79, 0xE0, 0x12, 0x46, +0x4B, 0xF1, 0xBB, 0x90, 0x06, 0x0A, 0xE0, 0x54, +0xF8, 0xF0, 0x7B, 0x56, 0xE4, 0xFD, 0x7F, 0xFF, +0x12, 0x66, 0x73, 0xE4, 0x90, 0x81, 0xE2, 0xF0, +0x22, 0x7D, 0x0C, 0x7F, 0x01, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0xAC, 0x07, 0xEF, 0x14, +0x60, 0x15, 0x14, 0x60, 0x19, 0x24, 0x02, 0x70, +0x1A, 0xED, 0x54, 0x01, 0xFE, 0x90, 0x81, 0x05, +0xE0, 0x54, 0xFE, 0x4E, 0xF0, 0x80, 0x0C, 0x90, +0x81, 0x0D, 0xED, 0xF0, 0x80, 0x05, 0x90, 0x81, +0x0C, 0xED, 0xF0, 0x90, 0x00, 0x8F, 0xE0, 0x30, +0xE4, 0x2E, 0xEC, 0x14, 0x60, 0x07, 0x14, 0x60, +0x1D, 0x24, 0x02, 0x70, 0x23, 0x90, 0x81, 0x05, +0xE0, 0x54, 0x01, 0xC4, 0x33, 0x33, 0x33, 0x54, +0x80, 0xFF, 0x90, 0x81, 0x0D, 0xE0, 0x54, 0x7F, +0x4F, 0xFD, 0x7F, 0x88, 0x80, 0x07, 0x90, 0x81, +0x0C, 0xE0, 0xFD, 0x7F, 0x89, 0x12, 0x32, 0x1E, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xF0, 0x90, 0x81, +0x27, 0xE0, 0x24, 0x05, 0x90, 0x81, 0x22, 0xF0, +0xA3, 0x74, 0x10, 0xF0, 0x22, 0x71, 0x54, 0x70, +0x28, 0x90, 0x81, 0x06, 0xE0, 0x54, 0xFD, 0xF0, +0x7B, 0x2C, 0x12, 0x91, 0x08, 0x7D, 0x08, 0x7F, +0x01, 0x12, 0x67, 0x06, 0xBF, 0x01, 0x0D, 0x90, +0x81, 0x05, 0xE0, 0x44, 0x80, 0xF0, 0x7D, 0x0E, +0x7F, 0x01, 0x21, 0x45, 0x12, 0x8A, 0x30, 0x04, +0xF0, 0x22, 0xE4, 0xFD, 0xFF, 0x12, 0x98, 0x0B, +0xED, 0x70, 0x12, 0x51, 0x29, 0xC0, 0x83, 0xC0, +0x82, 0x51, 0x21, 0x80, 0x02, 0xC3, 0x33, 0xD8, +0xFC, 0xF4, 0x5E, 0x80, 0x0F, 0x51, 0x29, 0xC0, +0x83, 0xC0, 0x82, 0x51, 0x21, 0x80, 0x02, 0xC3, +0x33, 0xD8, 0xFC, 0x4E, 0xD0, 0x82, 0xD0, 0x83, +0xF0, 0x51, 0x34, 0x90, 0x81, 0x04, 0xEF, 0xF0, +0x22, 0xE0, 0xFE, 0x74, 0x01, 0xA8, 0x07, 0x08, +0x22, 0x74, 0xFC, 0x2E, 0xF5, 0x82, 0xE4, 0x34, +0x80, 0xF5, 0x83, 0x22, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x7D, 0x08, 0xED, 0x14, 0xF9, +0x24, 0xFC, 0x51, 0x2C, 0xE0, 0x60, 0x3A, 0x7C, +0x08, 0xEC, 0x14, 0x90, 0x8A, 0x5F, 0xF0, 0x74, +0xFC, 0x29, 0x51, 0x2C, 0xE0, 0xFB, 0x7A, 0x00, +0x90, 0x8A, 0x5F, 0x12, 0x97, 0x99, 0x80, 0x05, +0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, +0xEE, 0x5A, 0xFE, 0xEF, 0x5B, 0x4E, 0x60, 0x0F, +0xE9, 0x75, 0xF0, 0x08, 0xA4, 0xFF, 0x90, 0x8A, +0x5F, 0xE0, 0x2F, 0x04, 0xFF, 0x80, 0x06, 0xDC, +0xC8, 0xDD, 0xBA, 0x7F, 0x00, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0x12, 0x98, 0x0B, 0x51, 0x29, 0xE0, +0xFD, 0x7C, 0x00, 0x12, 0x97, 0x9B, 0x80, 0x05, +0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, +0xEE, 0x5C, 0xFE, 0xEF, 0x5D, 0x4E, 0x7F, 0x00, +0x60, 0x02, 0x7F, 0x01, 0x22, 0x8B, 0x52, 0x8A, +0x53, 0x89, 0x54, 0x12, 0x56, 0x95, 0xFF, 0xF5, +0x56, 0x12, 0x1F, 0xA4, 0xFE, 0xC3, 0x13, 0x30, +0xE0, 0x07, 0x12, 0x57, 0x75, 0xF5, 0x57, 0x80, +0x02, 0x8F, 0x57, 0x85, 0x56, 0x55, 0xE5, 0x55, +0xD3, 0x95, 0x57, 0x50, 0x23, 0xAB, 0x52, 0xAA, +0x53, 0xA9, 0x54, 0x12, 0x1F, 0xA4, 0x54, 0x01, +0xFD, 0xAF, 0x55, 0x31, 0xED, 0xAF, 0x55, 0x51, +0x8A, 0xEF, 0xAF, 0x55, 0x70, 0x04, 0xF1, 0xDA, +0x80, 0x02, 0xF1, 0xE3, 0x05, 0x55, 0x80, 0xD6, +0xE5, 0x56, 0x70, 0x14, 0xFF, 0x51, 0x8A, 0xEF, +0x70, 0x0E, 0x12, 0x80, 0x18, 0x71, 0x11, 0x12, +0x8E, 0x94, 0x54, 0xBF, 0xF0, 0x54, 0x7F, 0xF0, +0x22, 0xF1, 0xBB, 0x12, 0x66, 0x6E, 0x7D, 0x0C, +0x7F, 0x01, 0x21, 0x45, 0xEF, 0x60, 0x34, 0x71, +0x54, 0x70, 0x30, 0x90, 0x81, 0x06, 0xE0, 0x54, +0xFE, 0xF0, 0x7B, 0x2B, 0x7D, 0x0F, 0x7F, 0xFF, +0x12, 0x66, 0x73, 0x90, 0x06, 0x04, 0xE0, 0x54, +0xBF, 0xF0, 0x12, 0x67, 0x02, 0xBF, 0x01, 0x0D, +0x90, 0x81, 0x05, 0xE0, 0x44, 0x40, 0xF0, 0x7D, +0x06, 0x7F, 0x01, 0x21, 0x45, 0x12, 0x8A, 0x30, +0x74, 0x08, 0xF0, 0x22, 0xE4, 0xFF, 0x51, 0x8A, +0xEF, 0x64, 0x01, 0x22, 0x71, 0x54, 0x70, 0x11, +0x90, 0x81, 0x0A, 0xE0, 0x60, 0x0B, 0x90, 0x81, +0x0E, 0xE0, 0x20, 0xE4, 0x04, 0xD1, 0x79, 0x91, +0x2F, 0x22, 0x71, 0x54, 0x70, 0x1D, 0x90, 0x81, +0x0A, 0xE0, 0x60, 0x17, 0x90, 0x81, 0x0E, 0xE0, +0x20, 0xE4, 0x10, 0xD1, 0x79, 0xF0, 0x90, 0x81, +0x05, 0xE0, 0x12, 0x98, 0x37, 0x54, 0x07, 0x70, +0x02, 0xF1, 0x4D, 0x22, 0xE4, 0x90, 0x89, 0x07, +0xF0, 0x90, 0x81, 0x0A, 0xE0, 0x60, 0x24, 0x71, +0x54, 0x70, 0x20, 0xF1, 0xCB, 0xF0, 0x12, 0x97, +0x3F, 0x90, 0x89, 0x07, 0x74, 0x01, 0xF0, 0xE4, +0x90, 0x81, 0x11, 0xF0, 0x04, 0x60, 0x0C, 0x12, +0x97, 0x67, 0xE0, 0x20, 0xE2, 0x03, 0x12, 0x4D, +0xF6, 0x71, 0xF5, 0x22, 0xE4, 0xF5, 0x4E, 0x90, +0x81, 0x0A, 0xE0, 0x60, 0x27, 0x71, 0x54, 0x70, +0x23, 0x12, 0x97, 0x3F, 0xF1, 0xC3, 0x60, 0x09, +0x90, 0x81, 0x06, 0x12, 0x5F, 0xE2, 0x20, 0xE0, +0x03, 0x75, 0x4E, 0x01, 0xE5, 0x4E, 0x60, 0x0C, +0x12, 0x97, 0x67, 0xE0, 0x20, 0xE2, 0x03, 0x12, +0x4D, 0xF6, 0x71, 0xF5, 0x22, 0x90, 0x81, 0x0E, +0xE0, 0x44, 0x10, 0xF0, 0x90, 0x81, 0x13, 0xE0, +0x60, 0x04, 0x64, 0x01, 0x70, 0x11, 0xE4, 0xF5, +0x1D, 0x90, 0x81, 0x13, 0xE0, 0x91, 0xAF, 0x91, +0x37, 0x90, 0x81, 0x13, 0xE0, 0x80, 0x11, 0xE4, +0xF5, 0x1D, 0x91, 0xA5, 0x91, 0x37, 0x90, 0x81, +0x13, 0xE0, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0xFE, +0x91, 0xAF, 0x90, 0x81, 0x23, 0xF0, 0x22, 0xF0, +0xE4, 0xF5, 0x1D, 0x90, 0x81, 0xDD, 0xE0, 0xF5, +0x1E, 0xE4, 0xFB, 0xFD, 0x7F, 0x54, 0x7E, 0x01, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x8E, +0x19, 0x8F, 0x1A, 0xE5, 0x1E, 0x91, 0x95, 0x85, +0x19, 0x83, 0x85, 0x1A, 0x82, 0xF0, 0xE5, 0x1D, +0x91, 0x95, 0xFF, 0xE5, 0x1E, 0x13, 0x13, 0x13, +0x54, 0x1F, 0x4F, 0xA3, 0xF0, 0xEB, 0x91, 0x95, +0xFF, 0xE5, 0x1D, 0x13, 0x13, 0x13, 0x54, 0x1F, +0x4F, 0x91, 0x9C, 0xF0, 0xBD, 0x01, 0x0D, 0x85, +0x1A, 0x82, 0x8E, 0x83, 0xA3, 0xA3, 0xA3, 0x74, +0x03, 0xF0, 0x80, 0x06, 0x91, 0x9C, 0xA3, 0x74, +0x01, 0xF0, 0x91, 0x9C, 0xA3, 0x74, 0x05, 0xF0, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x54, 0x07, 0xC4, +0x33, 0x54, 0xE0, 0x22, 0x85, 0x1A, 0x82, 0x85, +0x19, 0x83, 0xA3, 0xA3, 0x22, 0x90, 0x81, 0x13, +0xE0, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0xFE, 0xFF, +0x90, 0x81, 0x12, 0xE0, 0x2F, 0x22, 0x90, 0x84, +0x8F, 0xE0, 0x30, 0xE0, 0x33, 0x71, 0x54, 0x70, +0x2F, 0x90, 0x8A, 0x67, 0xE0, 0x04, 0xF0, 0xE0, +0xB4, 0x0A, 0x0B, 0x90, 0x84, 0x91, 0xE0, 0x04, +0xF0, 0xE4, 0x90, 0x8A, 0x67, 0xF0, 0x90, 0x84, +0x91, 0xE0, 0xFF, 0x90, 0x84, 0x90, 0xE0, 0xD3, +0x9F, 0x50, 0x0D, 0x90, 0x84, 0x92, 0xE0, 0x70, +0x07, 0xE4, 0x90, 0x84, 0x91, 0xF0, 0xF1, 0xF6, +0x22, 0x90, 0x81, 0x06, 0xD1, 0x71, 0x30, 0xE0, +0x0C, 0xEF, 0xC4, 0x13, 0x13, 0x54, 0x03, 0x30, +0xE0, 0x03, 0x12, 0x4D, 0x69, 0x90, 0x81, 0x05, +0xF1, 0xEF, 0x30, 0xE0, 0x0A, 0xEF, 0x12, 0x98, +0x37, 0x54, 0x07, 0x70, 0x3F, 0x80, 0x3B, 0x90, +0x81, 0x13, 0xE0, 0x04, 0xF0, 0x90, 0x81, 0x0E, +0xE0, 0x54, 0xEF, 0xF0, 0x12, 0x97, 0xFF, 0x40, +0x29, 0x71, 0x54, 0x70, 0x27, 0xB1, 0x5D, 0xF1, +0x80, 0x70, 0x02, 0x80, 0x20, 0x90, 0x81, 0x14, +0xE0, 0x04, 0xF0, 0xE0, 0xD3, 0x94, 0x02, 0x40, +0x09, 0xB1, 0x55, 0xE4, 0x90, 0x81, 0x14, 0xF0, +0x80, 0x02, 0xF1, 0x57, 0xE4, 0x90, 0x81, 0x13, +0xF0, 0x22, 0xF1, 0x4D, 0x22, 0x90, 0x81, 0x06, +0xE0, 0x54, 0xFB, 0xF0, 0x22, 0x12, 0x97, 0xFF, +0x40, 0x2D, 0x90, 0x81, 0x24, 0xE0, 0x04, 0xF0, +0x90, 0x81, 0xDB, 0xE0, 0xFF, 0x90, 0x81, 0x24, +0xE0, 0xD3, 0x9F, 0x50, 0x1A, 0x90, 0x81, 0x1C, +0xE0, 0x04, 0xF0, 0x91, 0xA5, 0x90, 0x81, 0x23, +0x12, 0x7F, 0x7B, 0x12, 0x7F, 0x83, 0x90, 0x8A, +0x52, 0x74, 0x04, 0xF0, 0x12, 0x88, 0xF3, 0x22, +0x71, 0x54, 0x60, 0x02, 0xC1, 0x65, 0x90, 0x81, +0x0A, 0xE0, 0x70, 0x02, 0xC1, 0x65, 0x90, 0x06, +0xA9, 0xE0, 0xFF, 0x90, 0x05, 0x63, 0xE0, 0x90, +0x81, 0xCE, 0xF0, 0x90, 0x05, 0x62, 0xE0, 0x90, +0x81, 0xCF, 0xF0, 0x90, 0x05, 0x61, 0xE0, 0x90, +0x81, 0xD0, 0xF0, 0x90, 0x05, 0x60, 0xE0, 0x90, +0x81, 0xD1, 0xF0, 0xD1, 0x79, 0xF0, 0x90, 0x81, +0x0E, 0xE0, 0x54, 0xED, 0xF0, 0xD1, 0xF7, 0x90, +0x81, 0x08, 0xE0, 0xFF, 0xC4, 0x54, 0x0F, 0x64, +0x01, 0x70, 0x27, 0x90, 0x06, 0xAB, 0xE0, 0x90, +0x81, 0x11, 0xF0, 0x90, 0x06, 0xAA, 0xE0, 0x60, +0x05, 0xE0, 0x90, 0x81, 0x10, 0xF0, 0x90, 0x81, +0x11, 0xE0, 0xFF, 0x70, 0x08, 0x90, 0x81, 0x10, +0xE0, 0xFE, 0xFF, 0x80, 0x00, 0x90, 0x81, 0x11, +0xEF, 0xF0, 0x12, 0x7C, 0x73, 0xE4, 0x90, 0x81, +0x13, 0xF0, 0xA3, 0x12, 0x8A, 0x3A, 0x90, 0x81, +0x06, 0xD1, 0x71, 0x30, 0xE0, 0x4C, 0xEF, 0xC4, +0x13, 0x13, 0x54, 0x03, 0x20, 0xE0, 0x20, 0xD1, +0x66, 0x6F, 0x70, 0x3E, 0x90, 0x81, 0x06, 0xE0, +0x44, 0x40, 0xF0, 0xF1, 0xCB, 0xD1, 0x84, 0xF1, +0xDB, 0x12, 0x4D, 0x63, 0x12, 0x4D, 0x69, 0x90, +0x81, 0x11, 0xE0, 0x14, 0xF0, 0x80, 0x23, 0xF1, +0xC3, 0x64, 0x01, 0x70, 0x1D, 0xD1, 0x66, 0xFE, +0x6F, 0x60, 0x17, 0x90, 0x05, 0x73, 0xE0, 0xFF, +0xEE, 0x6F, 0x60, 0x0E, 0xF1, 0xEC, 0x30, 0xE0, +0x09, 0xEF, 0x54, 0xBF, 0xD1, 0x84, 0xD1, 0xE3, +0xD1, 0x8F, 0x12, 0x98, 0x84, 0x22, 0x90, 0x81, +0x10, 0xE0, 0xFF, 0xA3, 0xE0, 0x22, 0x90, 0x81, +0xE4, 0xE0, 0xFF, 0x13, 0x13, 0x13, 0x54, 0x1F, +0x22, 0x90, 0x01, 0x57, 0xE4, 0xF0, 0x90, 0x01, +0x3C, 0x74, 0x02, 0x22, 0xF0, 0x90, 0x01, 0x3F, +0x74, 0x10, 0xF0, 0xFD, 0x7F, 0x03, 0x22, 0x7D, +0x01, 0x7F, 0x02, 0xD1, 0x99, 0x7D, 0x02, 0x7F, +0x02, 0x74, 0x3D, 0x2F, 0xF8, 0xE6, 0x4D, 0xFE, +0xF6, 0x74, 0x30, 0x80, 0x47, 0x7B, 0x2D, 0x12, +0x81, 0xD9, 0x12, 0x66, 0x8F, 0x90, 0x01, 0x37, +0x74, 0x02, 0xF0, 0xFD, 0x7F, 0x03, 0xD1, 0x99, +0x12, 0x80, 0x7D, 0xE4, 0xFD, 0x7F, 0x01, 0x21, +0x45, 0x90, 0x81, 0x05, 0xE0, 0x54, 0xFB, 0xF0, +0xE4, 0x90, 0x81, 0x13, 0xF0, 0xA3, 0xF0, 0x90, +0x81, 0x0E, 0xF0, 0x90, 0x81, 0x06, 0xE0, 0x54, +0xF7, 0xF0, 0x54, 0xBF, 0xF0, 0xD1, 0x8F, 0x7D, +0x10, 0x7F, 0x03, 0x74, 0x45, 0x12, 0x98, 0x8C, +0xFE, 0xF6, 0x74, 0x38, 0x2F, 0xF5, 0x82, 0xE4, +0x34, 0x01, 0xF5, 0x83, 0xEE, 0xF0, 0x22, 0x90, +0x06, 0xA9, 0xE0, 0xF5, 0x4E, 0x54, 0xC0, 0x70, +0x07, 0xF1, 0x45, 0x54, 0xFD, 0xF0, 0x80, 0x45, +0xE5, 0x4E, 0x30, 0xE6, 0x1C, 0x90, 0x81, 0x0A, +0xE0, 0x64, 0x01, 0x70, 0x16, 0x90, 0x81, 0x0E, +0xE0, 0x44, 0x01, 0xF1, 0x7F, 0x64, 0x02, 0x60, +0x04, 0xF1, 0x9F, 0x80, 0x06, 0xF1, 0x57, 0x80, +0x02, 0xF1, 0x45, 0xE5, 0x4E, 0x90, 0x81, 0x0E, +0x30, 0xE7, 0x0D, 0xE0, 0x44, 0x02, 0x91, 0x2F, +0x90, 0x81, 0x05, 0xE0, 0x44, 0x04, 0xF0, 0x22, +0xE0, 0x54, 0xFD, 0xF0, 0x22, 0x90, 0x81, 0x0E, +0xE0, 0x54, 0xFE, 0xF0, 0x22, 0x90, 0x81, 0x0C, +0xE0, 0xFF, 0x7D, 0x01, 0x02, 0x4D, 0xFA, 0x12, +0x8E, 0x46, 0x90, 0x81, 0x0D, 0xE0, 0x64, 0x0C, +0x60, 0x06, 0x12, 0x66, 0x67, 0x12, 0x67, 0x02, +0x22, 0xE4, 0xFF, 0x51, 0x8A, 0xBF, 0x01, 0x0E, +0x90, 0x81, 0x0A, 0xE0, 0x60, 0x08, 0xF1, 0x45, +0x54, 0x07, 0x70, 0x02, 0xF1, 0x4D, 0x22, 0xF0, +0x90, 0x81, 0x08, 0xE0, 0x54, 0x0F, 0x22, 0xE4, +0xFF, 0x51, 0x8A, 0xBF, 0x01, 0x10, 0x90, 0x81, +0x0A, 0xE0, 0x60, 0x0A, 0xF1, 0x80, 0x64, 0x02, +0x60, 0x02, 0x80, 0x03, 0xF1, 0x57, 0x22, 0x90, +0x04, 0x1D, 0xE0, 0x70, 0x15, 0x90, 0x80, 0x0A, +0xE0, 0xFF, 0x90, 0x8A, 0x4A, 0x74, 0x09, 0xF0, +0x7B, 0x18, 0xE4, 0xFD, 0x12, 0x87, 0x18, 0x12, +0x65, 0x1C, 0x22, 0x90, 0x06, 0x04, 0xE0, 0x54, +0x7F, 0xF0, 0x22, 0x90, 0x81, 0x08, 0xE0, 0xC4, +0x54, 0x0F, 0x22, 0x90, 0x81, 0x10, 0xE0, 0x90, +0x05, 0x73, 0x22, 0xE4, 0xFD, 0xFF, 0x31, 0xED, +0xE4, 0xFF, 0x22, 0x74, 0x45, 0x2F, 0xF8, 0xE6, +0x4D, 0xC1, 0xE8, 0x22, 0x22, 0x90, 0x01, 0xC7, +0x74, 0xFE, 0xF0, 0x22, 0x90, 0x81, 0x06, 0xE0, +0xFF, 0x13, 0x13, 0x54, 0x3F, 0x22, 0x90, 0x84, +0x8F, 0xF1, 0xEF, 0x30, 0xE0, 0x0F, 0x7B, 0x00, +0x7A, 0x00, 0x79, 0x00, 0x12, 0x97, 0xE7, 0xA3, +0x04, 0xF0, 0x02, 0x65, 0x30, 0x7D, 0x08, 0x7F, +0x02, 0x02, 0x67, 0x06, 0x90, 0x84, 0x93, 0xE0, +0x30, 0xE0, 0x72, 0x90, 0x84, 0x97, 0xE0, 0x04, +0xF0, 0x90, 0x84, 0x9A, 0xE0, 0x64, 0x01, 0x70, +0x31, 0x90, 0x84, 0x93, 0x12, 0x6F, 0xEF, 0x30, +0xE0, 0x28, 0x90, 0x84, 0x99, 0xE0, 0x70, 0x22, +0x90, 0x84, 0x96, 0xE0, 0xFE, 0xA3, 0xE0, 0xC3, +0x9E, 0x40, 0x17, 0xEF, 0x13, 0x13, 0x13, 0x54, +0x1F, 0x30, 0xE0, 0x08, 0x12, 0x6F, 0xD3, 0x11, +0x8E, 0xF0, 0x80, 0x06, 0x11, 0x95, 0x11, 0x8E, +0xF0, 0x22, 0x90, 0x84, 0x97, 0xE0, 0xFF, 0x90, +0x84, 0x94, 0xE0, 0xD3, 0x9F, 0x50, 0x26, 0x90, +0x06, 0x92, 0xE0, 0x20, 0xE2, 0x10, 0x90, 0x84, +0x99, 0xE0, 0x70, 0x0A, 0x51, 0xC1, 0x90, 0x84, +0x92, 0xE0, 0x04, 0xF0, 0x80, 0x06, 0x90, 0x06, +0x92, 0x74, 0x04, 0xF0, 0xE4, 0x90, 0x84, 0x97, +0xF0, 0x90, 0x84, 0x99, 0xF0, 0x22, 0x90, 0x84, +0x93, 0xE0, 0x54, 0xFE, 0x22, 0x90, 0x01, 0xC7, +0x74, 0x10, 0xF0, 0x7F, 0x01, 0x90, 0x8A, 0x66, +0xEF, 0xF0, 0x90, 0x80, 0x07, 0xE0, 0x64, 0x02, +0x70, 0x22, 0x90, 0x8A, 0x66, 0xE0, 0xFD, 0x64, +0x01, 0x70, 0x35, 0x12, 0x5C, 0xE6, 0x90, 0x81, +0xE7, 0x12, 0x5F, 0xD7, 0x30, 0xE0, 0x09, 0x90, +0x01, 0x4D, 0xE0, 0x64, 0x80, 0xF0, 0x80, 0x20, +0xAF, 0x05, 0x80, 0x19, 0x90, 0x01, 0x00, 0x74, +0xFF, 0xF0, 0x7F, 0x64, 0x7E, 0x00, 0x12, 0x32, +0xAA, 0x90, 0x06, 0x90, 0xE0, 0x44, 0x01, 0xF0, +0x90, 0x8A, 0x66, 0xE0, 0xFF, 0x12, 0x8F, 0xBB, +0x11, 0x8E, 0xF0, 0x90, 0x81, 0xE3, 0xE0, 0x54, +0xBF, 0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x06, 0x31, 0xE0, 0x54, 0xEF, +0x44, 0x08, 0xF0, 0xED, 0x2F, 0xFF, 0xE4, 0x3E, +0xFE, 0x7C, 0x00, 0xEF, 0x24, 0x08, 0xFF, 0xEC, +0x3E, 0x90, 0x89, 0x32, 0xF0, 0xA3, 0xEF, 0xF0, +0x7E, 0x00, 0x7F, 0xE3, 0x7D, 0x00, 0x7B, 0x01, +0x7A, 0x82, 0x79, 0xF8, 0x12, 0x46, 0x4B, 0x90, +0x89, 0x33, 0xE0, 0x24, 0x01, 0x12, 0x5E, 0xD6, +0x90, 0x82, 0xF9, 0x51, 0x59, 0x24, 0x04, 0x12, +0x5E, 0xD6, 0x90, 0x82, 0xFC, 0x51, 0x59, 0x24, +0x05, 0x12, 0x5E, 0xD6, 0x90, 0x82, 0xFD, 0x51, +0x59, 0x24, 0x06, 0x12, 0x5E, 0xD6, 0x90, 0x82, +0xFE, 0x51, 0x59, 0x24, 0x07, 0x12, 0x5E, 0xD6, +0x90, 0x82, 0xFF, 0x51, 0x59, 0x24, 0x08, 0x12, +0x5E, 0xD6, 0x90, 0x83, 0x00, 0xEF, 0xF0, 0xE4, +0x90, 0x89, 0x31, 0xF0, 0x51, 0x6B, 0x94, 0x08, +0x50, 0x1D, 0x90, 0x89, 0x33, 0xE0, 0x24, 0x09, +0xFD, 0x90, 0x89, 0x32, 0xE0, 0x12, 0x5D, 0x6D, +0x90, 0x89, 0x31, 0xE0, 0x24, 0x01, 0xF5, 0x82, +0xE4, 0x34, 0x83, 0x51, 0x60, 0x80, 0xDD, 0xE4, +0x90, 0x89, 0x31, 0xF0, 0x51, 0x6B, 0x94, 0x02, +0x50, 0x1D, 0x90, 0x89, 0x33, 0xE0, 0x24, 0x61, +0xFD, 0x90, 0x89, 0x32, 0xE0, 0x12, 0x5D, 0x6D, +0x90, 0x89, 0x31, 0xE0, 0x24, 0x59, 0xF5, 0x82, +0xE4, 0x34, 0x83, 0x51, 0x60, 0x80, 0xDD, 0xE4, +0x90, 0x89, 0x31, 0xF0, 0x51, 0x6B, 0x94, 0x10, +0x50, 0x1D, 0x90, 0x89, 0x33, 0xE0, 0x24, 0x31, +0xFD, 0x90, 0x89, 0x32, 0xE0, 0x12, 0x5D, 0x6D, +0x90, 0x89, 0x31, 0xE0, 0x24, 0x29, 0xF5, 0x82, +0xE4, 0x34, 0x83, 0x51, 0x60, 0x80, 0xDD, 0xE4, +0x90, 0x89, 0x31, 0xF0, 0x90, 0x83, 0x5A, 0xE0, +0xFF, 0x90, 0x89, 0x31, 0xE0, 0xFE, 0xC3, 0x9F, +0x50, 0x24, 0x90, 0x89, 0x33, 0xE0, 0x24, 0x63, +0xFD, 0x90, 0x89, 0x32, 0xE0, 0x34, 0x00, 0xFC, +0xEE, 0x7E, 0x00, 0x2D, 0x12, 0x5D, 0x74, 0x90, +0x89, 0x31, 0xE0, 0x24, 0x5B, 0xF5, 0x82, 0xE4, +0x34, 0x83, 0x51, 0x60, 0x80, 0xCE, 0x90, 0x82, +0xFD, 0x12, 0x96, 0x6C, 0x90, 0x89, 0x2F, 0xEE, +0xF0, 0xA3, 0xEF, 0xF0, 0x30, 0xE3, 0x0C, 0x90, +0x01, 0xC7, 0x74, 0x03, 0xF0, 0x7F, 0x01, 0x11, +0x9D, 0x80, 0x1F, 0x7E, 0x00, 0x90, 0x89, 0x30, +0xE0, 0x54, 0x07, 0xFF, 0x64, 0x01, 0x60, 0x05, +0xEF, 0x64, 0x02, 0x70, 0x0D, 0xE4, 0xFD, 0x51, +0xCF, 0x90, 0x06, 0x31, 0xE0, 0x54, 0xF7, 0x44, +0x10, 0xF0, 0x7F, 0x00, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0xEF, 0xF0, 0x90, 0x89, 0x33, 0xE0, 0x22, +0xF5, 0x83, 0xEF, 0xF0, 0x90, 0x89, 0x31, 0xE0, +0x04, 0xF0, 0x22, 0x90, 0x89, 0x31, 0xE0, 0xFF, +0xC3, 0x22, 0x90, 0x84, 0x93, 0xE0, 0xFD, 0x30, +0xE0, 0x46, 0x90, 0x84, 0x98, 0xE0, 0xFC, 0x60, +0x3F, 0x12, 0x97, 0x9B, 0x80, 0x05, 0xC3, 0x33, +0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, 0x90, 0x04, +0xE0, 0xE0, 0xFB, 0xEF, 0x5B, 0x60, 0x0B, 0xE4, +0x90, 0x84, 0x98, 0xF0, 0x90, 0x84, 0x9A, 0x04, +0xF0, 0x22, 0x90, 0x84, 0x95, 0xE0, 0xD3, 0x9C, +0x50, 0x14, 0xED, 0x13, 0x13, 0x13, 0x54, 0x1F, +0x30, 0xE0, 0x05, 0x12, 0x6F, 0xD3, 0x80, 0x02, +0x11, 0x95, 0x11, 0x8E, 0xF0, 0x22, 0x51, 0xC1, +0x22, 0x7D, 0x08, 0x7F, 0x02, 0x12, 0x67, 0x06, +0x90, 0x84, 0x98, 0xE0, 0x04, 0xF0, 0x22, 0x90, +0x89, 0x34, 0x12, 0x94, 0xCB, 0xF1, 0xDF, 0x12, +0x57, 0xD7, 0xFF, 0x12, 0x95, 0x87, 0x12, 0x57, +0xD7, 0xFF, 0xA3, 0xE0, 0xFD, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x89, 0x37, 0x12, +0x94, 0xCB, 0x90, 0x89, 0x4F, 0x74, 0x18, 0xF0, +0x7E, 0x00, 0x7F, 0x80, 0x7D, 0x00, 0x7B, 0x01, +0x7A, 0x89, 0x79, 0x57, 0x12, 0x46, 0x4B, 0x90, +0x01, 0xC4, 0x74, 0xE5, 0xF0, 0x74, 0x72, 0xA3, +0xF0, 0x90, 0x84, 0x81, 0xE0, 0xFF, 0x12, 0x82, +0xC3, 0x90, 0x89, 0x4E, 0xEF, 0xF0, 0xF9, 0xE0, +0xFE, 0x24, 0x21, 0x12, 0x83, 0x63, 0x74, 0x41, +0xF0, 0xEE, 0x24, 0x20, 0xFD, 0xE4, 0x33, 0xFC, +0x90, 0x89, 0x4F, 0xE0, 0x7A, 0x00, 0x2D, 0xFE, +0xEA, 0x3C, 0x90, 0x89, 0x53, 0xF0, 0xA3, 0xCE, +0xF0, 0x74, 0x20, 0x29, 0x12, 0x87, 0xD4, 0x90, +0x89, 0x39, 0xE0, 0xFD, 0x12, 0x56, 0x9B, 0x12, +0x97, 0x2B, 0x90, 0x89, 0x53, 0xE0, 0xFF, 0xA3, +0xE0, 0x90, 0x89, 0x51, 0xCF, 0xF0, 0xA3, 0xEF, +0xF0, 0x90, 0x89, 0x57, 0x74, 0x01, 0xF0, 0xA3, +0x74, 0x03, 0xF0, 0xE4, 0xA3, 0xF0, 0xA3, 0x74, +0x5F, 0xF0, 0x90, 0x89, 0x53, 0xE4, 0x75, 0xF0, +0x04, 0x12, 0x43, 0xF6, 0x90, 0x82, 0xFC, 0xE0, +0xFF, 0x7E, 0x02, 0xB4, 0xFE, 0x02, 0x7E, 0xFE, +0x90, 0x89, 0x53, 0xA3, 0xE0, 0xFD, 0xB1, 0x48, +0xEE, 0xF0, 0x74, 0x00, 0x2D, 0xB1, 0x4A, 0xE0, +0x90, 0x89, 0x5B, 0xF0, 0x90, 0x89, 0x53, 0x12, +0x78, 0xE3, 0x90, 0x83, 0xF1, 0xE0, 0x90, 0x89, +0x37, 0xB4, 0x01, 0x0B, 0xE0, 0x44, 0x03, 0xFC, +0xA3, 0xE0, 0x44, 0x10, 0xFD, 0x80, 0x09, 0xE0, +0x44, 0x03, 0xFC, 0xA3, 0xE0, 0x44, 0x20, 0xFD, +0x90, 0x89, 0x55, 0xEC, 0xF0, 0xA3, 0xED, 0xF0, +0x90, 0x89, 0x37, 0xE0, 0x70, 0x04, 0xA3, 0xE0, +0x64, 0x01, 0x90, 0x89, 0x53, 0x70, 0x15, 0xB1, +0x45, 0x74, 0x03, 0xF1, 0x15, 0x74, 0x01, 0xF0, +0x90, 0x89, 0x5C, 0x74, 0x03, 0xF0, 0xA3, 0x74, +0x01, 0xF0, 0x80, 0x11, 0xB1, 0x45, 0x74, 0x03, +0xF1, 0x15, 0x74, 0x02, 0xF0, 0x90, 0x89, 0x5C, +0x04, 0xF0, 0xA3, 0x14, 0xF0, 0x12, 0x98, 0x17, +0xEF, 0x64, 0xFE, 0x90, 0x89, 0x53, 0x70, 0x23, +0xA3, 0xE0, 0x24, 0x00, 0xF1, 0xE8, 0xC0, 0x03, +0x8B, 0x13, 0x12, 0x98, 0x4C, 0xD0, 0x03, 0x12, +0x2B, 0xED, 0x75, 0x13, 0x01, 0x12, 0x98, 0x4C, +0x7B, 0x01, 0x7A, 0x89, 0x79, 0x5E, 0x12, 0x2B, +0xED, 0x80, 0x22, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, +0x24, 0x00, 0xF5, 0x82, 0x74, 0xFC, 0x3E, 0xF5, +0x83, 0xE4, 0xF0, 0x74, 0x01, 0x2F, 0xF5, 0x82, +0x74, 0xFC, 0x3E, 0xF5, 0x83, 0xE4, 0xF0, 0x90, +0x89, 0x5E, 0xF0, 0xA3, 0xF0, 0x12, 0x98, 0x17, +0xE4, 0x90, 0x89, 0x50, 0xF0, 0x12, 0x97, 0xB5, +0x90, 0x89, 0x53, 0xA3, 0xE0, 0xFD, 0xEF, 0x2D, +0xB1, 0x48, 0xEE, 0xF0, 0x12, 0x97, 0xB5, 0x74, +0x60, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, +0x83, 0xEE, 0x12, 0x98, 0x5D, 0xE0, 0xB4, 0x08, +0xDC, 0x12, 0x97, 0x35, 0x90, 0x89, 0x53, 0xE4, +0x75, 0xF0, 0x20, 0x12, 0x43, 0xF6, 0x90, 0x89, +0x53, 0x12, 0x7B, 0x74, 0x12, 0x97, 0x2B, 0x7B, +0x01, 0x7A, 0x89, 0x79, 0x57, 0x90, 0x89, 0xDE, +0x12, 0x44, 0x72, 0x90, 0x89, 0xE1, 0x74, 0x63, +0xF0, 0x7A, 0x89, 0x79, 0x3A, 0xA3, 0x12, 0x44, +0x72, 0x7A, 0x82, 0x79, 0xB8, 0x7D, 0x10, 0x12, +0x78, 0xEA, 0xE4, 0x90, 0x89, 0x50, 0xF0, 0x90, +0x89, 0x50, 0xE0, 0xFF, 0xC3, 0x94, 0x10, 0x50, +0x3C, 0x90, 0x89, 0x54, 0xE0, 0x2F, 0xFF, 0x90, +0x89, 0x53, 0xE0, 0x34, 0x00, 0xFE, 0x90, 0x89, +0xD7, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x84, 0x81, +0xE0, 0xFD, 0x12, 0x8E, 0xCA, 0x90, 0x89, 0x4E, +0xEF, 0xF0, 0x90, 0x89, 0x50, 0xE0, 0x24, 0x3A, +0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, +0xFF, 0x90, 0x89, 0x4E, 0xE0, 0xB1, 0x48, 0xEF, +0x12, 0x98, 0x5D, 0x80, 0xBA, 0x90, 0x04, 0x1D, +0xE0, 0x60, 0x21, 0x90, 0x05, 0x22, 0xE0, 0x90, +0x89, 0xD9, 0xF0, 0x7B, 0x1D, 0x12, 0x66, 0x89, +0xBF, 0x01, 0x03, 0x12, 0x85, 0xB8, 0x90, 0x89, +0xD9, 0xE0, 0xFD, 0x7B, 0x1E, 0xE4, 0xFF, 0x12, +0x66, 0x73, 0x80, 0x03, 0x12, 0x85, 0xB8, 0x12, +0x65, 0x1C, 0x90, 0x81, 0x0D, 0xE0, 0x70, 0x05, +0x7F, 0x01, 0x12, 0x4F, 0xDB, 0x74, 0xE5, 0x04, +0x90, 0x01, 0xC4, 0xF0, 0x74, 0x72, 0xA3, 0xF0, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xA3, 0xE0, 0xFE, +0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, +0x83, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x90, 0x84, 0xD1, 0xEC, 0xF0, 0xA3, 0xED, +0xF0, 0xA3, 0xEB, 0xF0, 0xAA, 0x07, 0x90, 0x84, +0xD8, 0x12, 0x20, 0xDA, 0x00, 0x00, 0x00, 0x00, +0x12, 0x98, 0x21, 0xEA, 0x24, 0xEF, 0x60, 0x30, +0x24, 0xD7, 0x70, 0x02, 0xC1, 0xA9, 0x24, 0x3A, +0x60, 0x02, 0xC1, 0xDC, 0xF1, 0xAE, 0x24, 0x0A, +0xF1, 0x00, 0xE4, 0xF0, 0xFE, 0x74, 0x00, 0x2F, +0x12, 0x98, 0x6D, 0x7D, 0x14, 0xD1, 0xF5, 0x7B, +0x00, 0x7A, 0x00, 0x79, 0x00, 0x12, 0x97, 0x7C, +0x7D, 0x14, 0x7C, 0x00, 0xE4, 0xFF, 0xC1, 0xA4, +0x90, 0x84, 0xD1, 0xE4, 0x75, 0xF0, 0x14, 0x12, +0x43, 0xF6, 0x90, 0x84, 0xD1, 0xA3, 0xE0, 0xFB, +0xFF, 0x24, 0x06, 0xFC, 0xE4, 0x33, 0x90, 0x84, +0xDC, 0xF0, 0xA3, 0xCC, 0xF0, 0x90, 0x84, 0xDC, +0xA3, 0xE0, 0xF1, 0x0A, 0xE4, 0xF0, 0x74, 0x04, +0x2F, 0xF1, 0xE0, 0xE0, 0xFE, 0xA9, 0x03, 0x74, +0x05, 0x29, 0xF1, 0xD7, 0x12, 0x81, 0xF8, 0xFE, +0x90, 0x84, 0xD6, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, +0x84, 0xD1, 0xE0, 0xFC, 0xA3, 0xE0, 0x2F, 0xFF, +0xEC, 0x3E, 0xFE, 0xD3, 0xEF, 0x94, 0x00, 0xEE, +0x94, 0x01, 0x90, 0x84, 0xD1, 0x40, 0x67, 0xE0, +0xFE, 0xA3, 0xE0, 0xFF, 0xE9, 0x7C, 0x00, 0x24, +0x00, 0xF9, 0xEC, 0x34, 0xFC, 0xFA, 0x7B, 0x01, +0xC3, 0xE4, 0x9F, 0xFD, 0x74, 0x01, 0x9E, 0xFC, +0xD1, 0xF7, 0x90, 0x84, 0xD3, 0xE0, 0x24, 0x01, +0xFF, 0xE4, 0x33, 0xA2, 0xE7, 0x13, 0xEF, 0x13, +0x90, 0xFD, 0x10, 0xF0, 0xF1, 0xD1, 0xC0, 0x00, +0xC0, 0x01, 0xC0, 0x02, 0xC0, 0x03, 0x7B, 0x01, +0x7A, 0xFC, 0x79, 0x00, 0x90, 0x84, 0xD1, 0x12, +0x7B, 0x6A, 0xE4, 0x9F, 0xFF, 0x74, 0x01, 0x9E, +0xFE, 0xF1, 0xB5, 0xC3, 0x9F, 0xFD, 0xEC, 0x9E, +0xFC, 0x12, 0x24, 0xE4, 0xD0, 0x03, 0xD0, 0x02, +0xD0, 0x01, 0xD0, 0x00, 0x12, 0x44, 0x0C, 0xD1, +0xFA, 0x12, 0x98, 0x21, 0x80, 0x0E, 0xA3, 0xE0, +0x7E, 0x00, 0x24, 0x00, 0x12, 0x98, 0x6D, 0xF1, +0xB5, 0xFD, 0xD1, 0xF7, 0x90, 0x84, 0xD1, 0x74, +0xFF, 0x75, 0xF0, 0xEC, 0x12, 0x43, 0xF6, 0xF1, +0xAE, 0x7E, 0x00, 0x24, 0x0C, 0xF9, 0xEE, 0x34, +0xFC, 0xFA, 0x7B, 0x01, 0xC0, 0x02, 0xC0, 0x01, +0x74, 0x10, 0x2F, 0xF9, 0xEE, 0x34, 0xFC, 0xFA, +0x12, 0x97, 0x7C, 0xF1, 0xB5, 0xFD, 0xD0, 0x01, +0xD0, 0x02, 0x7F, 0x11, 0x12, 0x1C, 0x34, 0x80, +0x2B, 0xF1, 0xAE, 0x24, 0x2A, 0xF1, 0x00, 0xE4, +0xF0, 0x74, 0x00, 0x2F, 0xF1, 0xE8, 0x7D, 0x48, +0xD1, 0xF5, 0xF1, 0xC6, 0x12, 0x44, 0x0C, 0xE4, +0xFD, 0xFC, 0xD1, 0xFA, 0xF1, 0xC6, 0x12, 0x44, +0x0C, 0xD1, 0xFA, 0x90, 0x84, 0xD8, 0x12, 0x44, +0x45, 0x12, 0x20, 0x9B, 0x90, 0x84, 0xD4, 0xEE, +0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x84, 0xD4, 0xE0, +0xFC, 0xA3, 0xE0, 0xFD, 0xEC, 0xFF, 0x90, 0x84, +0xDC, 0xB1, 0x45, 0xEF, 0xF1, 0x15, 0xED, 0xF0, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x7C, 0x00, 0x12, +0x24, 0xE4, 0x90, 0x84, 0xD8, 0x02, 0x20, 0xCE, +0xFD, 0xE4, 0x33, 0x90, 0x84, 0xDC, 0xF0, 0xA3, +0xED, 0xF0, 0xFE, 0x24, 0x00, 0xF5, 0x82, 0xE4, +0x34, 0xFC, 0xF5, 0x83, 0xE4, 0xF0, 0x74, 0x01, +0x2E, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, +0x22, 0xE4, 0xFD, 0xFC, 0x90, 0x84, 0x88, 0x12, +0x85, 0x84, 0xAB, 0x05, 0x74, 0x01, 0x2B, 0xF1, +0x19, 0xE0, 0xFE, 0x74, 0x00, 0x2B, 0xB1, 0x4A, +0xE0, 0x12, 0x93, 0x5F, 0x90, 0x84, 0x26, 0xF0, +0xA3, 0xEF, 0xF0, 0x74, 0x03, 0x2B, 0xF5, 0x82, +0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0xFE, 0x74, +0x02, 0x2B, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF1, +0xBD, 0x90, 0x84, 0x28, 0xF0, 0xA3, 0xEF, 0xF0, +0x74, 0x05, 0x2B, 0xF1, 0xD7, 0xE0, 0xFE, 0x74, +0x04, 0x2B, 0xF1, 0xE0, 0xF1, 0xBF, 0x90, 0x84, +0x2A, 0xF0, 0xA3, 0xEF, 0xF0, 0x74, 0x07, 0x2B, +0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, +0xFE, 0x74, 0x06, 0x2B, 0xF5, 0x82, 0xE4, 0x34, +0xFC, 0xF1, 0xBD, 0x90, 0x84, 0x2C, 0xF0, 0xA3, +0xEF, 0xF0, 0x74, 0x09, 0x2B, 0x12, 0x87, 0x98, +0xE0, 0xFE, 0x74, 0x08, 0x2B, 0x12, 0x87, 0x90, +0xE0, 0x24, 0x00, 0xFF, 0xEC, 0x3E, 0x90, 0x84, +0x2E, 0xF0, 0xA3, 0xEF, 0xF0, 0x22, 0x90, 0x84, +0xD1, 0xA3, 0xE0, 0xFF, 0x22, 0x90, 0x84, 0xD6, +0xE0, 0xFC, 0xA3, 0xE0, 0x22, 0xF5, 0x83, 0xE0, +0x24, 0x00, 0xFF, 0xEA, 0x3E, 0x22, 0x90, 0x84, +0xD8, 0x12, 0x44, 0x45, 0x78, 0x10, 0x12, 0x20, +0xA8, 0x90, 0x84, 0xD8, 0x02, 0x44, 0x51, 0xF5, +0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0x22, 0x22, +0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0x22, +0xF9, 0xE4, 0x34, 0xFC, 0xFA, 0x7B, 0x01, 0x22, +0xE4, 0x90, 0x89, 0x0E, 0xF0, 0xA3, 0xF0, 0xA3, +0xF0, 0x90, 0x89, 0x0E, 0xE0, 0x64, 0x01, 0xF0, +0x24, 0xF0, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x77, +0xA3, 0xF0, 0x90, 0x81, 0x0A, 0xE0, 0x60, 0x0F, +0x90, 0x81, 0x0D, 0xE0, 0xFF, 0x90, 0x81, 0x0C, +0xE0, 0x6F, 0x60, 0x03, 0x12, 0x6F, 0x4D, 0xC2, +0xAF, 0x12, 0x8D, 0x31, 0xBF, 0x01, 0x02, 0x11, +0x32, 0xD2, 0xAF, 0xF1, 0x7A, 0x12, 0x46, 0xC4, +0x80, 0xC7, 0x90, 0x81, 0x05, 0xE0, 0x30, 0xE0, +0x02, 0x11, 0x3C, 0x22, 0x90, 0x81, 0x0D, 0xE0, +0xFF, 0x60, 0x03, 0xB4, 0x08, 0x0E, 0x12, 0x90, +0x99, 0xBF, 0x01, 0x08, 0x11, 0x55, 0x90, 0x01, +0xE5, 0xE0, 0x04, 0xF0, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0xF1, 0x22, 0x11, 0x65, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xF1, 0xA4, 0x90, +0x81, 0x15, 0xE0, 0x20, 0xE0, 0x0C, 0x90, 0x00, +0x26, 0xE0, 0x54, 0x7F, 0xFD, 0x7F, 0x26, 0x12, +0x32, 0x1E, 0x90, 0x00, 0x08, 0xE0, 0x54, 0xEF, +0xFD, 0x7F, 0x08, 0x12, 0x32, 0x1E, 0xE4, 0xFF, +0x90, 0x89, 0x11, 0xD1, 0xC6, 0x90, 0x01, 0x09, +0xE0, 0x7F, 0x00, 0x30, 0xE7, 0x02, 0x7F, 0x01, +0x90, 0x89, 0x11, 0xE0, 0x6F, 0x60, 0x39, 0xC3, +0x90, 0x89, 0x13, 0xE0, 0x94, 0x88, 0x90, 0x89, +0x12, 0xE0, 0x94, 0x13, 0x40, 0x08, 0x90, 0x01, +0xC0, 0xE0, 0x44, 0x10, 0xF0, 0x22, 0x90, 0x89, +0x12, 0x11, 0xE3, 0x7F, 0x14, 0x7E, 0x00, 0x12, +0x32, 0xAA, 0xD3, 0x90, 0x89, 0x13, 0xE0, 0x94, +0x32, 0x90, 0x89, 0x12, 0xE0, 0x94, 0x00, 0x40, +0xBC, 0x90, 0x01, 0xC6, 0xE0, 0x30, 0xE0, 0xB5, +0x22, 0x7F, 0x01, 0x7E, 0x00, 0x12, 0x32, 0xAA, +0x90, 0x8A, 0x2A, 0xE4, 0x75, 0xF0, 0x01, 0x02, +0x43, 0xF6, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x90, 0x89, 0xDA, 0x12, 0x44, 0x72, 0x90, +0x89, 0xDD, 0xED, 0xF0, 0xE4, 0x90, 0x8A, 0x29, +0xF0, 0x90, 0x8A, 0x29, 0xE0, 0xFF, 0xC3, 0x94, +0x40, 0x50, 0x07, 0x51, 0xBF, 0x71, 0x47, 0xF0, +0x80, 0xEF, 0x12, 0x66, 0x5A, 0x71, 0x99, 0x51, +0xF2, 0x94, 0x40, 0x50, 0x0A, 0x51, 0xBF, 0xE0, +0x64, 0x36, 0xF0, 0x51, 0xB8, 0x80, 0xF0, 0x51, +0xA7, 0x90, 0x89, 0xE1, 0x71, 0x5F, 0x74, 0x80, +0x12, 0x1F, 0xFC, 0xEF, 0x75, 0xF0, 0x08, 0xA4, +0x24, 0x00, 0xFF, 0xE5, 0xF0, 0x34, 0x02, 0xFC, +0x90, 0x00, 0x7E, 0x12, 0x1F, 0xFC, 0xEF, 0x90, +0x00, 0x7F, 0x71, 0x7B, 0x71, 0x67, 0x94, 0xC0, +0xEE, 0x94, 0x00, 0x50, 0x5D, 0x71, 0x57, 0x50, +0x0D, 0x71, 0xAE, 0x24, 0xF2, 0xF9, 0xE4, 0x34, +0x89, 0xFA, 0x7B, 0x01, 0x80, 0x04, 0x71, 0xF6, +0x71, 0x4F, 0x71, 0x86, 0x51, 0xAD, 0x90, 0x01, +0x8C, 0xE0, 0x30, 0xE4, 0x0A, 0x51, 0xCA, 0x94, +0x03, 0x50, 0x04, 0x11, 0xD9, 0x80, 0xEF, 0x51, +0xE3, 0x40, 0x08, 0x90, 0x06, 0x31, 0xE0, 0x44, +0x01, 0x51, 0xDC, 0x90, 0x8A, 0x27, 0xE0, 0x54, +0x3F, 0x64, 0x30, 0x70, 0x19, 0x51, 0xAE, 0x90, +0x01, 0x8C, 0xE0, 0x20, 0xE5, 0x0A, 0x51, 0xCA, +0x94, 0x03, 0x50, 0x04, 0x11, 0xD9, 0x80, 0xEF, +0x51, 0xE3, 0x40, 0x02, 0x51, 0xD6, 0x71, 0x71, +0x80, 0x9A, 0x51, 0xF9, 0x7D, 0x84, 0x12, 0x2A, +0x8F, 0xE4, 0x90, 0x8A, 0x29, 0xF0, 0x90, 0x8A, +0x29, 0xE0, 0xFF, 0xC3, 0x94, 0x40, 0x50, 0x07, +0x51, 0xBF, 0x71, 0x47, 0xF0, 0x80, 0xEF, 0x12, +0x66, 0x5A, 0x71, 0x99, 0x51, 0xF2, 0x94, 0x40, +0x50, 0x0A, 0x51, 0xBF, 0xE0, 0x64, 0x5C, 0xF0, +0x51, 0xB8, 0x80, 0xF0, 0xE4, 0x90, 0x89, 0xE5, +0xF0, 0x71, 0x41, 0x90, 0x89, 0xE5, 0x71, 0x5F, +0x12, 0x1F, 0xBD, 0xFE, 0x51, 0xA7, 0x8F, 0x82, +0x75, 0x83, 0x00, 0xEE, 0x51, 0xB5, 0xE0, 0xB4, +0x14, 0xE7, 0x51, 0xA7, 0x90, 0x00, 0x14, 0x74, +0x80, 0x12, 0x1F, 0xFC, 0x90, 0x89, 0xE5, 0x74, +0x15, 0xF0, 0x51, 0xF2, 0x94, 0x3E, 0x50, 0x0C, +0x51, 0xA7, 0x8F, 0x82, 0x75, 0x83, 0x00, 0xE4, +0x51, 0xB5, 0x80, 0xEE, 0x51, 0xA7, 0x90, 0x00, +0x3E, 0x74, 0x02, 0x12, 0x1F, 0xFC, 0x90, 0x00, +0x3F, 0x74, 0xA0, 0x71, 0x7B, 0x71, 0x67, 0x94, +0x80, 0xEE, 0x94, 0x00, 0x50, 0x5D, 0x71, 0x57, +0x50, 0x0D, 0x71, 0xAE, 0x24, 0xF2, 0xF9, 0xE4, +0x34, 0x89, 0xFA, 0x7B, 0x01, 0x80, 0x04, 0x71, +0xF6, 0x71, 0x4F, 0x71, 0x86, 0x51, 0xAD, 0x90, +0x01, 0x8C, 0xE0, 0x30, 0xE4, 0x0A, 0x51, 0xCA, +0x94, 0x03, 0x50, 0x04, 0x11, 0xD9, 0x80, 0xEF, +0x51, 0xE3, 0x40, 0x08, 0x90, 0x06, 0x31, 0xE0, +0x44, 0x01, 0x51, 0xDC, 0x90, 0x8A, 0x27, 0xE0, +0x54, 0x3F, 0x64, 0x30, 0x70, 0x19, 0x51, 0xAE, +0x90, 0x01, 0x8C, 0xE0, 0x20, 0xE5, 0x0A, 0x51, +0xCA, 0x94, 0x03, 0x50, 0x04, 0x11, 0xD9, 0x80, +0xEF, 0x51, 0xE3, 0x40, 0x02, 0x51, 0xD6, 0x71, +0x71, 0x80, 0x9A, 0x51, 0xF9, 0x7D, 0x84, 0x12, +0x2A, 0x8F, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, +0x89, 0xDE, 0x02, 0x44, 0x69, 0xE4, 0x90, 0x8A, +0x2A, 0xF0, 0xA3, 0xF0, 0x22, 0x12, 0x1F, 0xFC, +0x90, 0x89, 0xE5, 0xE0, 0x04, 0xF0, 0x22, 0x74, +0xE6, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, +0x83, 0x22, 0xC3, 0x90, 0x8A, 0x2B, 0xE0, 0x94, +0xE8, 0x90, 0x8A, 0x2A, 0xE0, 0x22, 0x90, 0x06, +0x31, 0xE0, 0x44, 0x02, 0xF0, 0xEE, 0x90, 0x06, +0x36, 0xF0, 0x22, 0x90, 0x8A, 0x2A, 0xE0, 0xFE, +0xA3, 0xE0, 0xFF, 0xC3, 0x94, 0xE8, 0xEE, 0x94, +0x03, 0x22, 0x90, 0x89, 0xE5, 0xE0, 0xFF, 0xC3, +0x22, 0x90, 0x89, 0xE2, 0x12, 0x44, 0x69, 0xE9, +0x24, 0x10, 0xF9, 0xE4, 0x3A, 0xFA, 0x7D, 0x80, +0x12, 0x2A, 0x8F, 0x90, 0x89, 0xE2, 0x12, 0x44, +0x69, 0xE9, 0x24, 0x0C, 0xF9, 0xE4, 0x3A, 0xFA, +0x7D, 0x81, 0x12, 0x2A, 0x8F, 0x90, 0x89, 0xE2, +0x12, 0x44, 0x69, 0xE9, 0x24, 0x08, 0xF9, 0xE4, +0x3A, 0xFA, 0x7D, 0x82, 0x12, 0x2A, 0x8F, 0x90, +0x89, 0xE2, 0x12, 0x44, 0x69, 0xE9, 0x24, 0x04, +0xF9, 0xE4, 0x3A, 0xFA, 0x7D, 0x83, 0x12, 0x2A, +0x8F, 0x90, 0x89, 0xE2, 0x02, 0x44, 0x69, 0xE4, +0xF0, 0x90, 0x8A, 0x29, 0xE0, 0x04, 0x22, 0x24, +0xCC, 0xF9, 0xEA, 0x34, 0xFF, 0xFA, 0x22, 0xC3, +0xEF, 0x94, 0x40, 0xEE, 0x94, 0x00, 0x22, 0xE0, +0xFF, 0xF5, 0x82, 0x75, 0x83, 0x00, 0x22, 0x90, +0x8A, 0x26, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xC3, +0x22, 0x90, 0x8A, 0x26, 0xE4, 0x75, 0xF0, 0x10, +0x02, 0x43, 0xF6, 0x12, 0x1F, 0xFC, 0xE4, 0x90, +0x8A, 0x26, 0xF0, 0xA3, 0xF0, 0x22, 0xA3, 0xE0, +0x44, 0x8B, 0xFD, 0x12, 0x28, 0x08, 0x90, 0x8A, +0x28, 0xE0, 0x44, 0x90, 0x90, 0x01, 0x8C, 0xF0, +0x22, 0x90, 0x89, 0xDD, 0xE0, 0xF5, 0x16, 0x7B, +0x01, 0x7A, 0x89, 0x79, 0xE6, 0x12, 0x2B, 0xED, +0xE4, 0x90, 0x89, 0xE5, 0xF0, 0x22, 0xA3, 0x74, +0x40, 0xF0, 0x74, 0xE6, 0x2F, 0xF9, 0xE4, 0x34, +0x89, 0xFA, 0x7B, 0x01, 0x74, 0x40, 0x44, 0x88, +0xFD, 0x12, 0x28, 0x08, 0x90, 0x8A, 0x26, 0xA3, +0xE0, 0x24, 0xEA, 0xF9, 0xE4, 0x34, 0x89, 0xFA, +0x7B, 0x01, 0xA3, 0xE0, 0x44, 0x89, 0xFD, 0x12, +0x28, 0x08, 0x90, 0x8A, 0x26, 0xA3, 0xE0, 0x24, +0xEE, 0xF9, 0xE4, 0x34, 0x89, 0xFA, 0x7B, 0x01, +0xA3, 0xE0, 0x44, 0x8A, 0xFD, 0x12, 0x28, 0x08, +0x90, 0x8A, 0x26, 0xA3, 0xE0, 0x22, 0xE4, 0x90, +0x8A, 0x28, 0xF0, 0x90, 0x89, 0xDE, 0x12, 0x44, +0x69, 0x90, 0x8A, 0x26, 0xE0, 0xFE, 0xA3, 0xE0, +0x29, 0xF9, 0xEA, 0x3E, 0xFA, 0xE9, 0x24, 0xC0, +0xF9, 0xEA, 0x34, 0xFF, 0xFA, 0x74, 0x88, 0xFD, +0x12, 0x28, 0x08, 0x90, 0x89, 0xDE, 0x12, 0x44, +0x69, 0x90, 0x8A, 0x26, 0xE0, 0xFE, 0xA3, 0xE0, +0x29, 0xF9, 0xEA, 0x3E, 0xFA, 0xE9, 0x24, 0xC4, +0xF9, 0xEA, 0x34, 0xFF, 0xFA, 0xA3, 0xE0, 0x44, +0x89, 0xFD, 0x12, 0x28, 0x08, 0x90, 0x89, 0xDE, +0x12, 0x44, 0x69, 0x90, 0x8A, 0x26, 0xE0, 0xFE, +0xA3, 0xE0, 0x29, 0xF9, 0xEA, 0x3E, 0xFA, 0xE9, +0x24, 0xC8, 0xF9, 0xEA, 0x34, 0xFF, 0xFA, 0xA3, +0xE0, 0x44, 0x8A, 0xFD, 0x12, 0x28, 0x08, 0x90, +0x89, 0xDE, 0x12, 0x44, 0x69, 0x90, 0x8A, 0x26, +0xE0, 0xFE, 0xA3, 0xE0, 0x29, 0xF9, 0xEA, 0x3E, +0xFA, 0xE9, 0x22, 0x90, 0x81, 0xD2, 0x12, 0x44, +0x45, 0x90, 0x81, 0xCE, 0x12, 0x44, 0x51, 0xC3, +0x12, 0x44, 0x34, 0x50, 0x02, 0xA1, 0x21, 0x90, +0x81, 0xD2, 0x12, 0x44, 0x51, 0x90, 0x81, 0xCE, +0x12, 0x44, 0x45, 0x12, 0x44, 0x19, 0x78, 0x07, +0x12, 0x20, 0xA8, 0xC0, 0x07, 0x90, 0x81, 0xD6, +0xE0, 0xFB, 0xE4, 0xFA, 0xF9, 0xF8, 0xD0, 0x07, +0x12, 0x44, 0x19, 0xEE, 0x54, 0x07, 0xFE, 0xAD, +0x07, 0xAC, 0x06, 0x90, 0x81, 0x05, 0xE0, 0x30, +0xE0, 0x2E, 0xD1, 0x20, 0xC3, 0x33, 0xCE, 0x33, +0xCE, 0xD8, 0xF9, 0x2D, 0xFD, 0xEE, 0x3C, 0xFC, +0x90, 0x81, 0x27, 0xE0, 0x24, 0x05, 0xFF, 0xE4, +0x33, 0xFE, 0xEF, 0x78, 0x03, 0xC3, 0x33, 0xCE, +0x33, 0xCE, 0xD8, 0xF9, 0x2D, 0xFF, 0xEC, 0x3E, +0xCF, 0x24, 0xFA, 0xCF, 0x34, 0xFF, 0x80, 0x13, +0xD1, 0x20, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, +0xF9, 0x2D, 0xFF, 0xEE, 0x3C, 0xCF, 0x24, 0x10, +0xCF, 0x34, 0x00, 0x90, 0x89, 0x00, 0xF0, 0xA3, +0xEF, 0xF0, 0x90, 0x89, 0x00, 0x71, 0x6A, 0x94, +0xA0, 0xEE, 0x94, 0x00, 0x50, 0x13, 0x74, 0x28, +0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, +0xE0, 0x04, 0xF0, 0x90, 0x81, 0x20, 0xE0, 0x04, +0xF0, 0x90, 0x81, 0x20, 0xE0, 0xFF, 0xD3, 0x90, +0x81, 0xD9, 0xE0, 0x9F, 0x90, 0x81, 0xD8, 0xE0, +0x94, 0x00, 0x40, 0x02, 0xC1, 0x18, 0xE4, 0xFF, +0xFE, 0xD1, 0x32, 0xEF, 0xD3, 0x9D, 0x40, 0x07, +0x90, 0x89, 0x02, 0xEE, 0xF0, 0x80, 0x05, 0x0E, +0xEE, 0xB4, 0xA0, 0xED, 0xE4, 0xFF, 0xFE, 0xD1, +0x32, 0xC3, 0x90, 0x81, 0xD9, 0xE0, 0x9D, 0xFD, +0x90, 0x81, 0xD8, 0xE0, 0x94, 0x00, 0xFC, 0xEF, +0xD3, 0x9D, 0xE4, 0x9C, 0x40, 0x07, 0x90, 0x89, +0x03, 0xEE, 0xF0, 0x80, 0x05, 0x0E, 0xEE, 0xB4, +0xA0, 0xDD, 0x90, 0x89, 0x02, 0xE0, 0x90, 0x81, +0x25, 0xF0, 0x90, 0x89, 0x03, 0xE0, 0x90, 0x81, +0x26, 0xD1, 0x19, 0xC3, 0x94, 0x50, 0x40, 0x20, +0xEF, 0x24, 0xB0, 0x90, 0x81, 0x1D, 0xF0, 0xE4, +0x90, 0x81, 0x1C, 0xF0, 0xA3, 0xE0, 0x54, 0x07, +0x75, 0xF0, 0x80, 0xA4, 0xFF, 0x90, 0x81, 0xC8, +0xE5, 0xF0, 0xF0, 0xA3, 0xEF, 0xF0, 0x80, 0x10, +0xE4, 0x90, 0x81, 0x1D, 0xD1, 0x19, 0xC3, 0x74, +0x50, 0x9F, 0x90, 0x81, 0x1C, 0xF1, 0x7B, 0xF0, +0x90, 0x81, 0x25, 0x12, 0x4F, 0xF3, 0xF0, 0xA3, +0x12, 0x4F, 0xF3, 0xF0, 0x90, 0x81, 0x1D, 0x12, +0x4F, 0xF3, 0xF0, 0x90, 0x81, 0x1C, 0x12, 0x4F, +0xF3, 0xD1, 0x19, 0xA3, 0xE0, 0xC3, 0x9F, 0x90, +0x81, 0x23, 0xF0, 0x90, 0x81, 0x05, 0xE0, 0x30, +0xE0, 0x08, 0x90, 0x81, 0xD6, 0x12, 0x4F, 0xF3, +0x80, 0x04, 0x90, 0x81, 0xD7, 0xE0, 0x04, 0xFF, +0x90, 0x81, 0x23, 0xE0, 0x2F, 0xF0, 0x90, 0x81, +0x23, 0xE0, 0xC3, 0x94, 0x10, 0x50, 0x03, 0x74, +0x10, 0xF0, 0x90, 0x81, 0x23, 0xE0, 0x24, 0x02, +0xF1, 0x83, 0x90, 0x8A, 0x52, 0x74, 0x03, 0xF0, +0x12, 0x88, 0xF3, 0xE4, 0xFF, 0x12, 0x91, 0x27, +0x22, 0xF0, 0x90, 0x81, 0x25, 0xE0, 0xFF, 0x22, +0x90, 0x81, 0x22, 0xE0, 0xFF, 0xC3, 0x74, 0x0A, +0x9F, 0xFF, 0xE4, 0x94, 0x00, 0xFE, 0xEF, 0x78, +0x03, 0x22, 0x74, 0x28, 0x2E, 0xF5, 0x82, 0xE4, +0x34, 0x81, 0xF5, 0x83, 0xE0, 0x2F, 0xFF, 0x90, +0x81, 0xDA, 0xE0, 0xFD, 0x22, 0xE4, 0x90, 0x8A, +0x5C, 0xF0, 0xA3, 0xF0, 0x90, 0x02, 0x86, 0xE0, +0x20, 0xE1, 0x22, 0xC3, 0x90, 0x8A, 0x5D, 0xE0, +0x94, 0xD0, 0x90, 0x8A, 0x5C, 0xE0, 0x94, 0x07, +0x40, 0x0A, 0x90, 0x01, 0xC1, 0xE0, 0x44, 0x04, +0xF0, 0x7F, 0x00, 0x22, 0x90, 0x8A, 0x5C, 0x11, +0xE3, 0xD1, 0xBF, 0x80, 0xD7, 0x7F, 0x01, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, +0x8A, 0x43, 0xEE, 0xF0, 0xA3, 0xD1, 0xC6, 0x90, +0x8A, 0x43, 0xE0, 0xFE, 0xA3, 0xE0, 0xF5, 0x82, +0x8E, 0x83, 0xE0, 0x60, 0x23, 0xC3, 0x90, 0x8A, +0x46, 0xE0, 0x94, 0xE8, 0x90, 0x8A, 0x45, 0xE0, +0x94, 0x03, 0x40, 0x0B, 0x90, 0x01, 0xC0, 0xE0, +0x44, 0x80, 0xF0, 0x7F, 0x00, 0x80, 0x0B, 0x90, +0x8A, 0x45, 0x11, 0xE3, 0xD1, 0xBF, 0x80, 0xCF, +0x7F, 0x01, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x7F, +0x0A, 0x7E, 0x00, 0x02, 0x32, 0xAA, 0xEF, 0xF0, +0xE4, 0xA3, 0xF0, 0xA3, 0xF0, 0x22, 0xE4, 0xFB, +0xFA, 0xFD, 0x7F, 0x01, 0x12, 0x48, 0xC5, 0x90, +0x89, 0x14, 0xEF, 0xF0, 0x60, 0xF0, 0x90, 0x80, +0x01, 0xE0, 0xFF, 0x70, 0x04, 0xA3, 0xE0, 0x60, +0xE5, 0xC2, 0xAF, 0xEF, 0x30, 0xE1, 0x0A, 0x90, +0x80, 0x01, 0xE0, 0x54, 0xFD, 0xF0, 0x12, 0x8B, +0x14, 0xF1, 0x18, 0x30, 0xE2, 0x06, 0x54, 0xFB, +0xF0, 0x12, 0x8B, 0xE5, 0xF1, 0x18, 0x30, 0xE4, +0x0B, 0x54, 0xEF, 0xF0, 0xD1, 0x45, 0xBF, 0x01, +0x03, 0x12, 0x59, 0x8C, 0xD2, 0xAF, 0x80, 0xC6, +0xD2, 0xAF, 0xC2, 0xAF, 0x90, 0x80, 0x01, 0xE0, +0xFF, 0x22, 0x90, 0x81, 0x15, 0xE0, 0xFD, 0x7F, +0x93, 0x12, 0x32, 0x1E, 0x90, 0x81, 0x0B, 0xE0, +0x60, 0x12, 0x90, 0x01, 0x2F, 0xE0, 0x30, 0xE7, +0x05, 0x74, 0x10, 0xF0, 0x80, 0x06, 0x90, 0x01, +0x2F, 0x74, 0x90, 0xF0, 0x90, 0x00, 0x08, 0xE0, +0x44, 0x10, 0xFD, 0x7F, 0x08, 0x12, 0x32, 0x1E, +0x7F, 0x01, 0x11, 0x88, 0x90, 0x81, 0x15, 0xE0, +0x20, 0xE0, 0x0C, 0x90, 0x00, 0x26, 0xE0, 0x44, +0x80, 0xFD, 0x7F, 0x26, 0x12, 0x32, 0x1E, 0x90, +0x00, 0x90, 0xE0, 0x44, 0x01, 0xFD, 0x7F, 0x90, +0x12, 0x32, 0x1E, 0x7F, 0x14, 0x7E, 0x00, 0x02, +0x32, 0xAA, 0x22, 0xF0, 0xE4, 0x90, 0x81, 0xC8, +0xF0, 0xA3, 0x22, 0xF0, 0x90, 0x81, 0x1C, 0xE0, +0xFF, 0xA3, 0xE0, 0xFD, 0x90, 0x81, 0x23, 0xE0, +0xFB, 0x22, 0x90, 0x84, 0x8F, 0xE0, 0x54, 0xFE, +0xF0, 0x54, 0x7F, 0xF0, 0x54, 0xFB, 0xF0, 0xA3, +0x74, 0x0A, 0xC1, 0xC7, 0x90, 0x01, 0xC4, 0x74, +0xA4, 0xF0, 0x74, 0x7F, 0xA3, 0xF0, 0x90, 0x00, +0x90, 0xE0, 0x20, 0xE0, 0xF9, 0x74, 0xA4, 0x04, +0x90, 0x01, 0xC4, 0xF0, 0x74, 0x7F, 0xA3, 0xF0, +0x22, 0xAD, 0x07, 0x90, 0x84, 0x30, 0x11, 0xE3, +0x90, 0x84, 0x30, 0xE0, 0xFF, 0xAE, 0x05, 0x74, +0x04, 0x2E, 0x12, 0x77, 0xE0, 0xEF, 0xF0, 0x90, +0x84, 0x30, 0xA3, 0xE0, 0xFF, 0x74, 0x05, 0x2E, +0x12, 0x77, 0xD7, 0xEF, 0xF0, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x4B, 0xF2, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0xC0, 0x07, 0xC0, 0x05, +0x90, 0x8A, 0x2E, 0x12, 0x44, 0x45, 0x90, 0x84, +0xED, 0x12, 0x20, 0xCE, 0xD0, 0x05, 0xD0, 0x07, +0x12, 0x4D, 0x02, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, +0x01, 0x01, 0xE0, 0x44, 0x02, 0xF0, 0x90, 0x01, +0x00, 0x74, 0xFF, 0xF0, 0x90, 0x06, 0xB7, 0x74, +0x09, 0xF0, 0x90, 0x06, 0xB4, 0x74, 0x86, 0xF0, +0x31, 0xBA, 0xEC, 0x54, 0x7F, 0xFC, 0x90, 0x8A, +0x4B, 0x12, 0x20, 0xCE, 0x90, 0x8A, 0x4B, 0x12, +0x4C, 0xDA, 0x7F, 0x7C, 0x11, 0x74, 0x12, 0x20, +0xDA, 0xCC, 0xC0, 0x00, 0xC0, 0x11, 0x72, 0x12, +0x20, 0xDA, 0x00, 0xC0, 0x00, 0x14, 0x31, 0xC1, +0x12, 0x20, 0xDA, 0x00, 0x03, 0x3E, 0x60, 0xE4, +0xFD, 0xFF, 0x12, 0x7F, 0xF5, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0x7F, 0x8C, 0x7E, 0x08, 0x12, 0x2E, +0xA2, 0x90, 0x85, 0xBB, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0xE4, 0x90, 0x8A, 0x32, +0xF0, 0xA3, 0xF0, 0x12, 0x66, 0x8F, 0x90, 0x85, +0xBB, 0x12, 0x20, 0xDA, 0xCC, 0xF0, 0x00, 0xC0, +0x11, 0x72, 0x12, 0x20, 0xDA, 0x00, 0x00, 0x00, +0x14, 0x31, 0xC1, 0x12, 0x20, 0xDA, 0x00, 0x00, +0x00, 0x00, 0xE4, 0xFD, 0xFF, 0x12, 0x7F, 0xF5, +0x7F, 0xE8, 0x7E, 0x08, 0x12, 0x2D, 0x5C, 0xEF, +0x54, 0x0E, 0xFF, 0xE4, 0xFE, 0xED, 0x54, 0xF4, +0xFD, 0xEC, 0x54, 0x03, 0xFC, 0xE4, 0xFB, 0xFA, +0xF9, 0xF8, 0xC3, 0x12, 0x44, 0x34, 0x60, 0x1A, +0xD3, 0x31, 0x21, 0x94, 0x03, 0x40, 0x09, 0x90, +0x01, 0xC3, 0xE0, 0x44, 0x02, 0xF0, 0x80, 0x0A, +0xF1, 0x71, 0x90, 0x8A, 0x32, 0x12, 0x78, 0xE3, +0x80, 0xC6, 0xC3, 0x31, 0x21, 0x94, 0x03, 0x50, +0x19, 0x31, 0xBA, 0xEC, 0x44, 0x80, 0xFC, 0x90, +0x8A, 0x34, 0x12, 0x20, 0xCE, 0x90, 0x8A, 0x34, +0x12, 0x4C, 0xDA, 0x7F, 0x7C, 0x7E, 0x08, 0x12, +0x2E, 0xA2, 0x90, 0x01, 0x00, 0x74, 0x3F, 0xF0, +0xA3, 0xE0, 0x54, 0xFD, 0xF0, 0x90, 0x05, 0x53, +0xE0, 0x44, 0x20, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x90, 0x8A, 0x33, 0xE0, 0x94, 0xE8, 0x90, +0x8A, 0x32, 0xE0, 0x22, 0xEF, 0x60, 0x43, 0x90, +0x04, 0xEC, 0xE0, 0x54, 0xDD, 0xF0, 0x90, 0x84, +0x7E, 0xE0, 0xFF, 0x60, 0x02, 0x31, 0xE0, 0x90, +0x01, 0xC7, 0xE4, 0x31, 0xEF, 0xB1, 0x8D, 0x90, +0x06, 0x09, 0xE0, 0x54, 0xFE, 0xF0, 0x7B, 0x35, +0x31, 0xD9, 0x11, 0x7D, 0x90, 0x02, 0x86, 0xE0, +0x44, 0x04, 0xF0, 0xF1, 0x23, 0x31, 0xAD, 0x11, +0x18, 0x12, 0x66, 0x6E, 0xB1, 0xD7, 0x90, 0x01, +0x34, 0x74, 0x08, 0xF0, 0xFD, 0xE4, 0xFF, 0x02, +0x6E, 0x99, 0x90, 0x04, 0xEC, 0xE0, 0x44, 0x22, +0xF0, 0x7D, 0x08, 0xE4, 0xFF, 0x12, 0x4D, 0x6D, +0x90, 0x06, 0x90, 0xE0, 0x54, 0xF0, 0xF0, 0x90, +0x02, 0x86, 0xE0, 0x54, 0xFB, 0xF0, 0xD1, 0x0A, +0x31, 0xAE, 0x7E, 0x00, 0x7F, 0x27, 0x7D, 0x00, +0x7B, 0x01, 0x7A, 0x81, 0x79, 0xE3, 0x12, 0x46, +0x4B, 0x90, 0x06, 0x90, 0xE0, 0x44, 0x20, 0xF0, +0xD1, 0x35, 0x02, 0x58, 0xCC, 0x22, 0x90, 0x81, +0xE3, 0xF1, 0xA0, 0x30, 0xE0, 0x03, 0x12, 0x58, +0xCC, 0x22, 0x7F, 0x7C, 0x7E, 0x08, 0x02, 0x2D, +0x5C, 0x7F, 0x70, 0x7E, 0x0E, 0x12, 0x2E, 0xA2, +0x90, 0x8A, 0x2E, 0x22, 0x7B, 0x2F, 0x31, 0xD9, +0x11, 0x7D, 0x7D, 0x08, 0x7F, 0x01, 0x02, 0x69, +0x45, 0x7D, 0xFF, 0x7F, 0xFF, 0x02, 0x66, 0x73, +0x12, 0x67, 0xC7, 0x75, 0x16, 0x08, 0x7B, 0x01, +0x7A, 0x83, 0x79, 0xF2, 0x02, 0x2B, 0xED, 0xF0, +0x90, 0x01, 0x17, 0xE0, 0xFE, 0x90, 0x01, 0x16, +0xE0, 0x7C, 0x00, 0x24, 0x00, 0xFF, 0xEC, 0x3E, +0x22, 0x90, 0x84, 0x89, 0x51, 0xB9, 0xE0, 0xFE, +0x24, 0x20, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, +0x83, 0xE0, 0xFF, 0x74, 0x21, 0x2E, 0x71, 0x63, +0xE0, 0xFD, 0x90, 0x89, 0x19, 0xE0, 0x24, 0x24, +0xD1, 0x65, 0x90, 0x89, 0x19, 0xE0, 0x2F, 0x24, +0x28, 0xA3, 0xF0, 0xE0, 0xFD, 0x24, 0x04, 0x12, +0x77, 0xE0, 0xE0, 0xFE, 0x74, 0x05, 0x2D, 0x12, +0x77, 0xD7, 0x31, 0xF8, 0x90, 0x84, 0x30, 0xF0, +0xA3, 0xEF, 0xF0, 0x90, 0x89, 0x1A, 0xE0, 0x24, +0x0C, 0xF9, 0xE4, 0x34, 0xFC, 0x12, 0x67, 0xD3, +0x75, 0x16, 0x04, 0x7B, 0x01, 0x7A, 0x84, 0x79, +0x32, 0x12, 0x2B, 0xED, 0x90, 0x89, 0x1A, 0xE0, +0x24, 0x14, 0xF0, 0xE0, 0xFD, 0x24, 0x01, 0x12, +0x77, 0x19, 0xE0, 0xFE, 0x74, 0x00, 0x2D, 0x12, +0x75, 0x4A, 0x31, 0xF8, 0x90, 0x84, 0x36, 0xF0, +0xA3, 0xEF, 0xF0, 0x90, 0x84, 0x8A, 0x51, 0xB9, +0x90, 0x84, 0x2C, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, +0x4E, 0x60, 0x14, 0x90, 0x89, 0x19, 0xE0, 0x24, +0x00, 0x12, 0x67, 0xCF, 0x8F, 0x16, 0x7B, 0x01, +0x7A, 0x84, 0x79, 0x3A, 0x12, 0x2B, 0xED, 0x90, +0x84, 0x8B, 0x51, 0xB9, 0x24, 0x00, 0x12, 0x67, +0xCF, 0x90, 0x84, 0x2E, 0xA3, 0xE0, 0xF5, 0x16, +0x7B, 0x01, 0x7A, 0x84, 0x79, 0x5A, 0x02, 0x2B, +0xED, 0xE0, 0xFF, 0x51, 0xC3, 0x90, 0x89, 0x19, +0xEF, 0xF0, 0x22, 0xE4, 0xFE, 0xEF, 0xC3, 0x13, +0xFD, 0xEF, 0x30, 0xE0, 0x02, 0x7E, 0x80, 0x90, +0xFD, 0x10, 0xED, 0xF0, 0xAF, 0x06, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x8A, +0x48, 0xED, 0xF0, 0xA3, 0xEB, 0xF0, 0x90, 0x8A, +0x47, 0xEF, 0xF0, 0xE4, 0xFD, 0xFC, 0xB1, 0x86, +0x90, 0x8A, 0x47, 0xE0, 0x90, 0x04, 0x25, 0xF0, +0x90, 0x8A, 0x48, 0xE0, 0x60, 0x0E, 0x74, 0x0F, +0x2F, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, +0xE0, 0x44, 0x80, 0xF0, 0xAF, 0x05, 0x74, 0x08, +0x2F, 0xF1, 0x90, 0xE4, 0xF0, 0x74, 0x09, 0x2F, +0xF1, 0x98, 0xE0, 0x54, 0xF0, 0xF0, 0xAF, 0x05, +0x91, 0x34, 0xE0, 0x20, 0xE1, 0x15, 0x54, 0x01, +0xFE, 0x90, 0x8A, 0x49, 0xE0, 0x25, 0xE0, 0x25, +0xE0, 0xFB, 0xEE, 0x44, 0x02, 0x4B, 0xFE, 0x91, +0x34, 0xEE, 0xF0, 0x90, 0x8A, 0x4A, 0xE0, 0xFF, +0xAE, 0x05, 0x74, 0x1E, 0x2E, 0xF5, 0x82, 0xE4, +0x34, 0xFC, 0xF5, 0x83, 0xEF, 0xF0, 0x74, 0x21, +0x2E, 0x71, 0x63, 0xE0, 0x54, 0xF7, 0xF0, 0xAE, +0x04, 0xAF, 0x05, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x74, 0x21, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0xFC, +0xF5, 0x83, 0x22, 0x71, 0x98, 0x54, 0x3F, 0xF0, +0xBF, 0x01, 0x02, 0x80, 0x17, 0xEF, 0x70, 0x02, +0x80, 0x07, 0x90, 0x81, 0x0D, 0xE0, 0x30, 0xE3, +0x0B, 0x71, 0x60, 0xE0, 0x54, 0xEF, 0x71, 0x97, +0x44, 0x40, 0xF0, 0x22, 0x71, 0x60, 0xE0, 0x44, +0x10, 0x71, 0x97, 0x44, 0x80, 0xF0, 0x22, 0xF0, +0x74, 0x1F, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0xFC, +0xF5, 0x83, 0xE0, 0x22, 0x90, 0x80, 0x0B, 0xE0, +0xFF, 0x90, 0x8A, 0x3F, 0xE0, 0xFB, 0x90, 0x8A, +0x4A, 0x74, 0x0A, 0xF0, 0x7D, 0x01, 0x51, 0xD7, +0x90, 0x8A, 0x40, 0xEE, 0xF0, 0xFC, 0xA3, 0xEF, +0xF0, 0xFD, 0x90, 0x8A, 0x3E, 0xE0, 0xFF, 0x71, +0x6B, 0x90, 0x8A, 0x40, 0xE0, 0xFE, 0xA3, 0xE0, +0xFF, 0x90, 0x04, 0x80, 0xE0, 0x54, 0x0F, 0xFD, +0xAC, 0x07, 0x91, 0x47, 0x44, 0x01, 0xF0, 0x91, +0x47, 0x54, 0xFB, 0xF0, 0xAC, 0x07, 0x74, 0x16, +0x2C, 0x91, 0x37, 0xE0, 0x44, 0xFA, 0xF0, 0x74, +0x15, 0x2C, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, +0x83, 0xE0, 0x44, 0x1F, 0xF0, 0xAC, 0x07, 0x74, +0x06, 0x2C, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, +0x83, 0xE0, 0x44, 0x0F, 0xF0, 0x90, 0x04, 0x53, +0xE4, 0xF0, 0x90, 0x04, 0x52, 0xF0, 0x90, 0x04, +0x51, 0x74, 0xFF, 0xF0, 0x90, 0x04, 0x50, 0x74, +0xFD, 0xF0, 0x74, 0x14, 0x2C, 0x91, 0x3F, 0xE0, +0x54, 0xC0, 0x4D, 0xFD, 0x74, 0x14, 0x2F, 0x91, +0x3F, 0xED, 0xF0, 0x22, 0x74, 0x16, 0x2F, 0xF5, +0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0x22, 0xF5, +0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0x22, 0x74, +0x11, 0x2C, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, +0x83, 0xE0, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x12, 0x92, 0x0A, 0xFE, 0x90, 0x81, +0xE3, 0x12, 0x57, 0xBB, 0xF1, 0x88, 0xFF, 0x90, +0x81, 0xE3, 0xF1, 0xBA, 0x12, 0x57, 0xC9, 0xF1, +0x78, 0xFF, 0x90, 0x81, 0xE3, 0xB1, 0x50, 0x12, +0x57, 0xC9, 0xF1, 0x80, 0xFF, 0x90, 0x81, 0xE3, +0xF1, 0xB0, 0x12, 0x57, 0x74, 0xFF, 0x54, 0x01, +0xFE, 0x90, 0x81, 0xE5, 0xE0, 0x54, 0xFE, 0x4E, +0x12, 0x56, 0x94, 0xFE, 0x54, 0x01, 0xFD, 0x90, +0x81, 0xE4, 0xF1, 0xA8, 0x54, 0x04, 0xFE, 0xED, +0x54, 0xFB, 0x4E, 0x12, 0x56, 0x93, 0xFD, 0x54, +0x08, 0xFC, 0xEE, 0x54, 0xF7, 0x4C, 0xFE, 0x90, +0x81, 0xE4, 0xF0, 0xED, 0x54, 0x10, 0xFD, 0xEE, +0x54, 0xEF, 0x4D, 0x12, 0x56, 0x93, 0xFD, 0x54, +0x20, 0xFC, 0xEE, 0x54, 0xDF, 0x4C, 0x90, 0x81, +0xE4, 0xF0, 0xEF, 0x54, 0x10, 0xFF, 0xA3, 0xE0, +0x54, 0xEF, 0x4F, 0xFF, 0x12, 0x57, 0x74, 0xB1, +0x52, 0x90, 0x81, 0xE5, 0xF0, 0xED, 0x54, 0x02, +0xFF, 0x90, 0x81, 0xE4, 0xE0, 0x54, 0xFD, 0x4F, +0x31, 0xEF, 0xB1, 0x8D, 0x90, 0x81, 0xE3, 0xE0, +0xC3, 0x13, 0x54, 0x01, 0xFF, 0xF1, 0xC4, 0x90, +0x81, 0xE3, 0xE0, 0x13, 0x13, 0x54, 0x01, 0xFF, +0xB1, 0x9E, 0x90, 0x81, 0xE4, 0x12, 0x4F, 0xF3, +0x30, 0xE0, 0x1F, 0x90, 0x81, 0xE3, 0x12, 0x6E, +0x71, 0x20, 0xE0, 0x0E, 0xEF, 0xC3, 0x13, 0x20, +0xE0, 0x08, 0xE0, 0x13, 0x13, 0x54, 0x3F, 0x30, +0xE0, 0x04, 0x7F, 0x01, 0x80, 0x0E, 0x7F, 0x00, +0x80, 0x0A, 0x90, 0x81, 0xE3, 0xE0, 0x13, 0x13, +0x13, 0x54, 0x01, 0xFF, 0xB1, 0x5A, 0x90, 0x81, +0xE3, 0xE0, 0xC4, 0x13, 0x13, 0x54, 0x01, 0xFF, +0xB1, 0x95, 0x90, 0x81, 0xE3, 0xE0, 0x54, 0x01, +0xFF, 0x31, 0x2C, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0xF0, 0xEE, 0x54, 0x20, 0xFE, 0xEF, 0x54, 0xDF, +0x4E, 0x22, 0xE4, 0xFD, 0xFC, 0xEF, 0x60, 0x23, +0x90, 0x84, 0x82, 0xB1, 0x84, 0x74, 0x00, 0x2F, +0x12, 0x77, 0xE8, 0x90, 0x89, 0x19, 0x12, 0x44, +0x72, 0x90, 0x89, 0x19, 0x12, 0x66, 0x5D, 0x75, +0x16, 0x42, 0x7B, 0x01, 0x7A, 0x82, 0x79, 0xB6, +0x12, 0x2B, 0xED, 0x22, 0xE0, 0xFF, 0x51, 0xC3, +0x7C, 0x00, 0xAD, 0x07, 0x22, 0x90, 0x80, 0xFA, +0xF0, 0xA3, 0xEF, 0xF0, 0x22, 0xEF, 0x60, 0x05, +0x12, 0x77, 0x21, 0x51, 0x01, 0x22, 0xEF, 0x60, +0x07, 0x90, 0x84, 0x84, 0xE0, 0xFF, 0xB1, 0xA9, +0x22, 0x12, 0x67, 0xC7, 0x75, 0x16, 0x70, 0x7B, +0x01, 0x7A, 0x82, 0x79, 0x1E, 0x02, 0x2B, 0xED, +0x90, 0x84, 0x81, 0xE0, 0xFF, 0x90, 0x8A, 0x4A, +0x74, 0x08, 0xF0, 0x7B, 0x18, 0x7D, 0x01, 0x51, +0xD7, 0x90, 0x89, 0x4E, 0xEF, 0xF0, 0x90, 0x84, +0x81, 0xE0, 0x90, 0x04, 0x25, 0xF0, 0x22, 0xE4, +0xFF, 0x74, 0x18, 0xB1, 0xFF, 0x74, 0xF5, 0x2F, +0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, 0xEE, +0xF0, 0x74, 0x10, 0xB1, 0xFF, 0x74, 0xEF, 0x2F, +0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, 0xEE, +0xF0, 0x0F, 0xEF, 0xB4, 0x06, 0xDB, 0x22, 0x2F, +0xF5, 0x82, 0xE4, 0x34, 0x06, 0xF5, 0x83, 0xE0, +0xFE, 0x22, 0xD1, 0x35, 0x90, 0x84, 0x8D, 0xE0, +0xFF, 0x12, 0x94, 0x2C, 0x90, 0x01, 0x3F, 0x74, +0x04, 0xF0, 0x90, 0x80, 0x07, 0xE0, 0xFF, 0xB4, +0x01, 0x07, 0x90, 0xFD, 0x00, 0xE0, 0x54, 0xEF, +0xF0, 0xEF, 0xB4, 0x01, 0x07, 0x90, 0xFE, 0x10, +0xE0, 0x54, 0xFB, 0xF0, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0xE4, 0xFD, 0x7F, 0x8F, +0x12, 0x32, 0x1E, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0xA3, 0xE0, 0xFE, 0x24, 0x20, 0xF5, 0x82, 0xE4, +0x34, 0xFC, 0xF5, 0x83, 0xE0, 0xFF, 0x74, 0x21, +0x2E, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, +0xE0, 0xFD, 0x74, 0x24, 0x2E, 0xF5, 0x82, 0xE4, +0x34, 0xFC, 0xF5, 0x83, 0xE0, 0xFB, 0xE4, 0xFE, +0xEF, 0x30, 0xE7, 0x04, 0x7C, 0x02, 0x80, 0x02, +0xE4, 0xFC, 0xED, 0x30, 0xE6, 0x09, 0xAF, 0x03, +0x12, 0x93, 0xED, 0xAE, 0x07, 0x80, 0x02, 0xE4, +0xFE, 0xEC, 0x24, 0x18, 0x2E, 0xFF, 0x22, 0xE4, +0x90, 0x89, 0x03, 0xF0, 0xA3, 0xF0, 0x90, 0x06, +0x32, 0xE0, 0x44, 0x20, 0xF0, 0x12, 0x8E, 0x9C, +0xEF, 0x64, 0x01, 0x70, 0x6A, 0x90, 0x84, 0x89, +0xE0, 0xFF, 0x90, 0x8A, 0x4A, 0x74, 0x0D, 0xF0, +0x7B, 0x08, 0x7D, 0x01, 0xF1, 0x18, 0x90, 0x89, +0x00, 0xD1, 0x48, 0x90, 0x89, 0x02, 0xEF, 0xF0, +0x90, 0x89, 0x00, 0xF1, 0xD0, 0xE4, 0xFD, 0x12, +0x56, 0x9B, 0x90, 0x89, 0x02, 0xE0, 0xFF, 0x90, +0x89, 0x01, 0xE0, 0x2F, 0xFF, 0x90, 0x89, 0x00, +0xE0, 0x34, 0x00, 0xCF, 0x24, 0x28, 0xCF, 0x34, +0x00, 0xFE, 0x90, 0x89, 0x03, 0xF0, 0xA3, 0xEF, +0xF0, 0x12, 0x7F, 0xC1, 0xF1, 0x10, 0xFD, 0x90, +0x84, 0x89, 0xE0, 0xFB, 0xE4, 0xFF, 0x12, 0x75, +0x52, 0xF1, 0x10, 0xFD, 0x90, 0x84, 0x85, 0xE0, +0xFB, 0x7F, 0x11, 0x12, 0x75, 0x52, 0x12, 0x65, +0x1C, 0x90, 0x84, 0x38, 0x12, 0x78, 0xE3, 0x22, +0x90, 0x89, 0x03, 0xE0, 0xFC, 0xA3, 0xE0, 0x22, +0x51, 0xD7, 0x90, 0x89, 0x00, 0xEE, 0xF0, 0xA3, +0xEF, 0xF0, 0x22, 0x12, 0x93, 0xAE, 0xAD, 0x07, +0x90, 0x01, 0xC4, 0x74, 0x23, 0xF0, 0x74, 0x87, +0xA3, 0xF0, 0xED, 0x64, 0x01, 0x60, 0x1E, 0x12, +0x5C, 0xE6, 0xED, 0xB4, 0x02, 0x08, 0x90, 0x01, +0xC7, 0x74, 0x40, 0xF0, 0x80, 0x0A, 0xED, 0xB4, +0x04, 0x06, 0x90, 0x01, 0xC7, 0x74, 0x41, 0xF0, +0x7F, 0x01, 0x02, 0x70, 0x9D, 0x12, 0x92, 0x7D, +0x90, 0x02, 0x87, 0xE0, 0x70, 0xF7, 0x90, 0x06, +0x90, 0xE0, 0x44, 0x02, 0xF0, 0x74, 0x23, 0x04, +0x90, 0x01, 0xC4, 0xF0, 0x74, 0x87, 0xA3, 0xF0, +0x22, 0x7F, 0x32, 0x7E, 0x00, 0x02, 0x32, 0xAA, +0x54, 0x10, 0xFD, 0xEF, 0x54, 0xEF, 0x4D, 0x22, +0x54, 0x40, 0xFD, 0xEF, 0x54, 0xBF, 0x4D, 0x22, +0x54, 0x04, 0xFD, 0xEF, 0x54, 0xFB, 0x4D, 0x22, +0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0x22, +0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0x22, +0xE0, 0xFF, 0xC4, 0x13, 0x13, 0x54, 0x03, 0x22, +0xE0, 0x54, 0xFE, 0x4D, 0xFD, 0xF0, 0xEE, 0x22, +0xF0, 0xEE, 0x54, 0x80, 0xFE, 0xEF, 0x54, 0x7F, +0x4E, 0x22, 0xF0, 0xEE, 0x54, 0x08, 0xFE, 0xEF, +0x54, 0xF7, 0x4E, 0x22, 0xEF, 0x60, 0x08, 0x90, +0x84, 0x7F, 0xE0, 0xFF, 0x12, 0x67, 0x5E, 0x22, +0xA3, 0xE0, 0x24, 0x20, 0xF9, 0xE4, 0x34, 0xFC, +0xFA, 0x7B, 0x01, 0x22, 0x90, 0x8A, 0x5E, 0xEF, +0xF0, 0x7F, 0x02, 0x12, 0x48, 0x9E, 0x90, 0x80, +0x01, 0xE0, 0xFF, 0x90, 0x8A, 0x5E, 0xE0, 0xFE, +0xEF, 0x4E, 0x90, 0x80, 0x01, 0xF0, 0x22, 0x90, +0x02, 0x09, 0xE0, 0xF5, 0x52, 0x12, 0x1F, 0xA4, +0x25, 0x52, 0x90, 0x80, 0x09, 0x12, 0x56, 0x94, +0x25, 0x52, 0x90, 0x80, 0x0A, 0x12, 0x57, 0x74, +0x25, 0x52, 0x90, 0x80, 0x0B, 0x12, 0x57, 0xB4, +0x25, 0x52, 0x90, 0x80, 0x0C, 0x12, 0x55, 0x9B, +0x25, 0x52, 0x90, 0x80, 0x0D, 0xF0, 0x90, 0x00, +0x05, 0x12, 0x1F, 0xBD, 0x25, 0x52, 0x90, 0x80, +0x0E, 0x12, 0x57, 0xD0, 0x25, 0x52, 0x90, 0x80, +0x0F, 0xF0, 0x22, 0x12, 0x1F, 0xA4, 0x54, 0x01, +0xFF, 0x90, 0x84, 0xA0, 0xE0, 0x54, 0xFE, 0x4F, +0xF0, 0x22, 0x51, 0x1C, 0xFF, 0x54, 0x7F, 0x90, +0x81, 0x0A, 0xF0, 0xEF, 0x12, 0x5F, 0xD8, 0xA3, +0x12, 0x56, 0x94, 0xFD, 0x54, 0xF0, 0xC4, 0x54, +0x0F, 0xFF, 0x90, 0x81, 0x08, 0xE0, 0x54, 0xF0, +0x4F, 0x12, 0x57, 0xB4, 0xFC, 0x54, 0x01, 0x25, +0xE0, 0xFF, 0x90, 0x81, 0x05, 0xE0, 0x54, 0xFD, +0x4F, 0xF0, 0xEC, 0x54, 0x04, 0xC3, 0x13, 0xFF, +0x90, 0x81, 0x07, 0xE0, 0x54, 0xFD, 0x4F, 0xF0, +0xED, 0x54, 0x0F, 0xC4, 0x54, 0xF0, 0xFF, 0xA3, +0xE0, 0x54, 0x0F, 0x4F, 0x12, 0x57, 0x74, 0x90, +0x81, 0x09, 0x12, 0x55, 0x9B, 0xFD, 0x7F, 0x02, +0x12, 0x69, 0x45, 0x90, 0x89, 0x19, 0x12, 0x44, +0x69, 0x11, 0xBE, 0x51, 0x30, 0xF0, 0x90, 0x81, +0x0A, 0x51, 0x25, 0x90, 0x01, 0xBB, 0x12, 0x6F, +0x7F, 0x90, 0x01, 0xBE, 0xF0, 0x22, 0x90, 0x89, +0x1C, 0x12, 0x44, 0x72, 0x12, 0x6E, 0xC1, 0x90, +0x81, 0x0A, 0xE0, 0xFF, 0x12, 0x4D, 0x79, 0x90, +0x81, 0x0A, 0xE0, 0x60, 0x1D, 0x90, 0x89, 0x1C, +0x12, 0x44, 0x69, 0x12, 0x56, 0x95, 0x54, 0x0F, +0xFF, 0x12, 0x57, 0x75, 0xFD, 0x51, 0x45, 0x12, +0x7F, 0x84, 0x90, 0x8A, 0x52, 0x74, 0x01, 0xF0, +0x11, 0xF3, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0xAC, 0x07, 0x90, 0x81, 0x06, 0x12, +0x5F, 0xD7, 0x30, 0xE0, 0x02, 0x21, 0xA9, 0x90, +0x81, 0x05, 0xE0, 0x30, 0xE0, 0x16, 0x90, 0x81, +0x27, 0xE0, 0x24, 0x05, 0x90, 0x81, 0x1F, 0xF0, +0x90, 0x81, 0x27, 0xE0, 0x24, 0x03, 0x90, 0x81, +0x1E, 0xF0, 0x80, 0x0D, 0x90, 0x81, 0x1F, 0x74, +0x02, 0xF0, 0x90, 0x81, 0x1E, 0x14, 0xF0, 0x0B, +0x0B, 0x90, 0x81, 0x1E, 0xE0, 0xFA, 0x90, 0x81, +0x1D, 0xE0, 0xD3, 0x9A, 0x50, 0x12, 0x90, 0x81, +0x12, 0xEB, 0xF0, 0x90, 0x81, 0x1F, 0xE0, 0xC3, +0x9D, 0x2C, 0x90, 0x81, 0x22, 0xF0, 0x80, 0x18, +0xC3, 0xED, 0x9A, 0x2B, 0x90, 0x81, 0x12, 0xF0, +0x90, 0x81, 0x1E, 0xE0, 0xFF, 0xA3, 0xE0, 0xC3, +0x9F, 0x90, 0x81, 0x22, 0x12, 0x7F, 0x7B, 0xF0, +0x90, 0x81, 0x1F, 0x31, 0xB5, 0xFC, 0x90, 0x81, +0x22, 0x31, 0xBD, 0x40, 0x04, 0xEF, 0x24, 0x0A, +0xF0, 0x90, 0x81, 0x22, 0x31, 0xB5, 0xFC, 0x90, +0x81, 0x12, 0x31, 0xBD, 0x40, 0x04, 0xEF, 0x24, +0x0A, 0xF0, 0x90, 0x81, 0x22, 0xE0, 0xFF, 0x7E, +0x00, 0x90, 0x81, 0x16, 0xEE, 0xF0, 0xA3, 0xEF, +0xF0, 0x90, 0x05, 0x58, 0xE0, 0x6F, 0x70, 0x01, +0xE4, 0x60, 0x02, 0x51, 0x3B, 0x51, 0x14, 0x80, +0x07, 0x90, 0x81, 0x07, 0xE0, 0x44, 0x01, 0xF0, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xE0, 0xFF, 0x24, +0x0A, 0xFD, 0xE4, 0x33, 0x22, 0xE0, 0xD3, 0x9D, +0xEC, 0x64, 0x80, 0xF8, 0x74, 0x80, 0x98, 0x22, +0x51, 0xD3, 0x90, 0x89, 0x07, 0xEF, 0xF0, 0x30, +0xE0, 0x05, 0x7D, 0x01, 0xE4, 0x80, 0x02, 0xE4, +0xFD, 0xFF, 0x12, 0x69, 0x45, 0x90, 0x89, 0x07, +0xE0, 0x30, 0xE6, 0x11, 0x90, 0x01, 0x2F, 0xE0, +0x30, 0xE7, 0x04, 0xE4, 0xF0, 0x80, 0x06, 0x90, +0x01, 0x2F, 0x74, 0x80, 0xF0, 0x90, 0x81, 0x05, +0xE0, 0x90, 0x04, 0xEC, 0x30, 0xE0, 0x06, 0xE0, +0x54, 0xDD, 0xF0, 0x80, 0x04, 0xE0, 0x44, 0x22, +0xF0, 0x12, 0x7F, 0x84, 0x90, 0x8A, 0x52, 0x74, +0x02, 0xF0, 0x01, 0xF3, 0x90, 0x81, 0x07, 0xE0, +0x54, 0xFE, 0xF0, 0x22, 0x90, 0x89, 0x19, 0x12, +0x44, 0x72, 0x02, 0x1F, 0xA4, 0xE0, 0x90, 0x01, +0xBA, 0xF0, 0x90, 0x81, 0x0C, 0xE0, 0x22, 0xF0, +0x90, 0x01, 0xB9, 0x74, 0x01, 0xF0, 0x90, 0x01, +0xB8, 0x22, 0xF0, 0x90, 0x81, 0x16, 0xA3, 0xE0, +0x90, 0x05, 0x58, 0xF0, 0x22, 0xEF, 0x24, 0xFE, +0x60, 0x0B, 0x04, 0x70, 0x24, 0x90, 0x81, 0x10, +0x74, 0x02, 0xF0, 0x80, 0x13, 0xED, 0x70, 0x06, +0x90, 0x81, 0xDF, 0xE0, 0x80, 0x02, 0xED, 0x14, +0x90, 0x81, 0x10, 0xF0, 0x90, 0x81, 0x10, 0xE0, +0xA3, 0xF0, 0x90, 0x81, 0x06, 0xE0, 0x44, 0x08, +0xF0, 0x22, 0x90, 0x81, 0x05, 0x12, 0x87, 0xA0, +0x30, 0xE0, 0x1F, 0xEF, 0x54, 0xBF, 0xF0, 0x90, +0x04, 0xE0, 0xE0, 0x90, 0x81, 0x06, 0x30, 0xE0, +0x06, 0xE0, 0x44, 0x01, 0xF0, 0x80, 0x08, 0xE0, +0x54, 0xFE, 0x51, 0x2F, 0x74, 0x04, 0xF0, 0x12, +0x6F, 0x4D, 0xE4, 0xFF, 0x02, 0x72, 0x72, 0x90, +0x81, 0x05, 0xE0, 0xFF, 0x12, 0x5F, 0xD8, 0x30, +0xE0, 0x24, 0xEF, 0x54, 0x7F, 0xF0, 0x90, 0x04, +0xE0, 0xE0, 0x90, 0x81, 0x06, 0x30, 0xE1, 0x06, +0xE0, 0x44, 0x02, 0xF0, 0x80, 0x07, 0xE0, 0x54, +0xFD, 0x51, 0x2F, 0x04, 0xF0, 0x90, 0x81, 0x0A, +0xE0, 0x60, 0x03, 0x12, 0x6F, 0x4D, 0x7F, 0x01, +0x02, 0x72, 0x72, 0xE4, 0x90, 0x89, 0x09, 0xF0, +0xA3, 0xF0, 0x90, 0x00, 0x83, 0xE0, 0x90, 0x89, +0x08, 0xF0, 0x90, 0x00, 0x83, 0xE0, 0xFE, 0x90, +0x89, 0x08, 0xE0, 0xFF, 0xB5, 0x06, 0x01, 0x22, +0xC3, 0x90, 0x89, 0x0A, 0xE0, 0x94, 0x64, 0x90, +0x89, 0x09, 0xE0, 0x94, 0x00, 0x40, 0x0D, 0x90, +0x01, 0xC0, 0xE0, 0x44, 0x40, 0xF0, 0x90, 0x89, +0x08, 0xE0, 0xFF, 0x22, 0x90, 0x89, 0x09, 0x12, +0x78, 0xE3, 0x80, 0xC6, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x90, 0x80, 0x61, 0xE0, 0xFF, +0x90, 0x80, 0x60, 0xE0, 0xB5, 0x07, 0x04, 0x7F, +0x01, 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x70, 0x44, +0x90, 0x80, 0x60, 0xE0, 0xFE, 0x75, 0xF0, 0x08, +0x90, 0x80, 0x10, 0x12, 0x44, 0x5D, 0xE0, 0xFD, +0xEE, 0x75, 0xF0, 0x08, 0xA4, 0x24, 0x11, 0xF9, +0x74, 0x80, 0x35, 0xF0, 0xFA, 0x7B, 0x01, 0xAF, +0x05, 0x12, 0x55, 0x0E, 0x90, 0x80, 0x60, 0xE0, +0x04, 0xF0, 0xE0, 0x7F, 0x00, 0xB4, 0x0A, 0x02, +0x7F, 0x01, 0xEF, 0x60, 0x05, 0xE4, 0x90, 0x80, +0x60, 0xF0, 0x12, 0x50, 0xE3, 0x90, 0x80, 0x01, +0xE0, 0x44, 0x02, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0xE4, 0x90, 0x80, 0xF8, 0xF0, 0xA3, 0xF0, +0x90, 0x80, 0x60, 0xF0, 0xA3, 0xF0, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x89, +0x15, 0x12, 0x44, 0x72, 0x90, 0x8A, 0x57, 0xE0, +0xFF, 0x04, 0xF0, 0x90, 0x00, 0x01, 0xEF, 0x12, +0x1F, 0xFC, 0x7F, 0xAF, 0x7E, 0x01, 0x12, 0x7E, +0x78, 0xEF, 0x60, 0x34, 0x90, 0x89, 0x15, 0x12, +0x66, 0x5D, 0x90, 0x00, 0x0E, 0x12, 0x1F, 0xBD, +0x24, 0x02, 0xF5, 0x16, 0x7B, 0x01, 0x7A, 0x01, +0x79, 0xA0, 0x12, 0x2B, 0xED, 0x90, 0x89, 0x15, +0x12, 0x44, 0x69, 0x90, 0x00, 0x0E, 0x12, 0x1F, +0xBD, 0x90, 0x01, 0xAE, 0xF0, 0xA3, 0x74, 0xFF, +0xF0, 0x90, 0x01, 0xCB, 0xE0, 0x64, 0x80, 0xF0, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0xE4, 0xFF, 0x90, 0x80, +0xF9, 0xE0, 0xFE, 0x90, 0x80, 0xF8, 0xE0, 0xFD, +0xB5, 0x06, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, +0x00, 0xEE, 0x64, 0x01, 0x60, 0x45, 0x90, 0x01, +0xAF, 0xE0, 0x70, 0x0A, 0xED, 0x91, 0x50, 0xFA, +0x7B, 0x01, 0x71, 0x87, 0x7F, 0x01, 0xEF, 0x60, +0x32, 0x90, 0x80, 0xF8, 0xE0, 0x04, 0xF0, 0xE0, +0x7F, 0x00, 0xB4, 0x0A, 0x02, 0x7F, 0x01, 0xEF, +0x60, 0x05, 0xE4, 0x90, 0x80, 0xF8, 0xF0, 0x90, +0x80, 0xF9, 0xE0, 0xFF, 0x90, 0x80, 0xF8, 0xE0, +0xB5, 0x07, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, +0x00, 0xEF, 0x70, 0x07, 0x90, 0x80, 0x01, 0xE0, +0x44, 0x04, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x75, 0xF0, 0x0F, 0xA4, 0x24, 0x62, 0xF9, 0x74, +0x80, 0x35, 0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x90, 0x80, 0xF8, 0xE0, 0xFF, +0x70, 0x06, 0xA3, 0xE0, 0x64, 0x09, 0x60, 0x0A, +0xEF, 0x14, 0xFF, 0x90, 0x80, 0xF9, 0xE0, 0xB5, +0x07, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, +0xEF, 0x60, 0x09, 0x90, 0x01, 0xC1, 0xE0, 0x44, +0x02, 0xF0, 0x80, 0x2C, 0xC0, 0x01, 0x90, 0x80, +0xF9, 0xE0, 0x91, 0x50, 0xA8, 0x01, 0xFC, 0x7D, +0x01, 0xD0, 0x01, 0x7E, 0x00, 0x7F, 0x0F, 0x12, +0x43, 0xD0, 0x90, 0x80, 0xF9, 0xE0, 0x04, 0xF0, +0xE0, 0x7F, 0x00, 0xB4, 0x0A, 0x02, 0x7F, 0x01, +0xEF, 0x60, 0x05, 0xE4, 0x90, 0x80, 0xF9, 0xF0, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x01, 0x34, +0x74, 0xFF, 0x12, 0x58, 0xC4, 0x90, 0x01, 0x3C, +0x12, 0x58, 0xC4, 0xFD, 0x7F, 0x54, 0x12, 0x32, +0x1E, 0x7D, 0xFF, 0x7F, 0x55, 0x12, 0x32, 0x1E, +0x7D, 0xFF, 0x7F, 0x56, 0x12, 0x32, 0x1E, 0x7D, +0xFF, 0x7F, 0x57, 0x02, 0x32, 0x1E, 0x75, 0x3D, +0x10, 0xE4, 0xF5, 0x3E, 0x75, 0x3F, 0x07, 0x75, +0x40, 0x02, 0x90, 0x01, 0x30, 0xE5, 0x3D, 0xF0, +0xA3, 0xE5, 0x3E, 0xF0, 0xA3, 0xE5, 0x3F, 0xF0, +0xA3, 0xE5, 0x40, 0xF0, 0x22, 0x75, 0x45, 0x07, +0x75, 0x46, 0x01, 0x75, 0x47, 0x03, 0x75, 0x48, +0x62, 0x90, 0x01, 0x38, 0xE5, 0x45, 0xF0, 0xA3, +0xE5, 0x46, 0xF0, 0xA3, 0xE5, 0x47, 0xF0, 0xA3, +0xE5, 0x48, 0xF0, 0x22, 0x90, 0x01, 0x94, 0xE0, +0x44, 0x01, 0xF0, 0x90, 0x01, 0xC7, 0xE4, 0xF0, +0x22, 0x7F, 0x02, 0x90, 0x84, 0x8E, 0xE0, 0xFE, +0xEF, 0xC3, 0x9E, 0x50, 0x18, 0xEF, 0x25, 0xE0, +0x24, 0x81, 0xF8, 0xE6, 0x30, 0xE4, 0x0B, 0x90, +0x01, 0xB8, 0x74, 0x08, 0xF0, 0xA3, 0xF0, 0x7F, +0x00, 0x22, 0x0F, 0x80, 0xDE, 0x7F, 0x01, 0x22, +0xE4, 0x90, 0x80, 0x01, 0x02, 0x58, 0xC2, 0x90, +0x01, 0xE4, 0x74, 0x1C, 0xF0, 0xA3, 0xE4, 0xF0, +0x22, 0x90, 0x01, 0x34, 0xE0, 0x55, 0x3D, 0xF5, +0x41, 0xA3, 0xE0, 0x55, 0x3E, 0xF5, 0x42, 0xA3, +0xE0, 0x55, 0x3F, 0xF5, 0x43, 0xA3, 0xE0, 0x55, +0x40, 0xF5, 0x44, 0x90, 0x01, 0x34, 0xE5, 0x41, +0xF0, 0xA3, 0xE5, 0x42, 0xF0, 0xA3, 0xE5, 0x43, +0xF0, 0xA3, 0xE5, 0x44, 0xF0, 0x22, 0x90, 0x01, +0x3C, 0xE0, 0x55, 0x45, 0xF5, 0x49, 0xA3, 0xE0, +0x55, 0x46, 0xF5, 0x4A, 0xA3, 0xE0, 0x55, 0x47, +0xF5, 0x4B, 0xA3, 0xE0, 0x55, 0x48, 0xF5, 0x4C, +0x90, 0x01, 0x3C, 0xE5, 0x49, 0xF0, 0xA3, 0xE5, +0x4A, 0xF0, 0xA3, 0xE5, 0x4B, 0xF0, 0xA3, 0xE5, +0x4C, 0xF0, 0x53, 0x91, 0xDF, 0x22, 0x90, 0x81, +0xE3, 0xE0, 0x30, 0xE0, 0x05, 0x7F, 0x10, 0x12, +0x50, 0xCE, 0x22, 0x90, 0x01, 0xCF, 0xE0, 0x90, +0x8A, 0x61, 0xF0, 0xE0, 0xFF, 0x30, 0xE0, 0x07, +0x90, 0x01, 0xCF, 0xE0, 0x54, 0xFE, 0xF0, 0xEF, +0x30, 0xE5, 0x23, 0x90, 0x01, 0xCF, 0xE0, 0x54, +0xDF, 0xF0, 0x90, 0x01, 0x34, 0x74, 0x20, 0xF0, +0xE4, 0xF5, 0xA8, 0xF5, 0xE8, 0x12, 0x58, 0x9C, +0x90, 0x00, 0x03, 0xE0, 0x54, 0xFB, 0xFD, 0x7F, +0x03, 0x12, 0x32, 0x1E, 0x80, 0xFE, 0x22, 0x90, +0x84, 0x99, 0xE0, 0x04, 0xF0, 0x90, 0x81, 0x0D, +0xE0, 0x64, 0x02, 0x60, 0x03, 0x12, 0x6D, 0x90, +0x22, 0x90, 0x81, 0x0A, 0xE0, 0x60, 0x02, 0xD1, +0x2A, 0x22, 0x90, 0x81, 0x0A, 0xE0, 0x64, 0x01, +0x70, 0x13, 0x12, 0x6F, 0x80, 0x60, 0x05, 0x12, +0x66, 0x67, 0x80, 0x0A, 0x90, 0x81, 0x0D, 0xE0, +0x70, 0x03, 0x12, 0x4D, 0xF6, 0x22, 0x90, 0x81, +0x05, 0x12, 0x4F, 0xF3, 0x30, 0xE0, 0x05, 0x90, +0x01, 0x5B, 0xE4, 0xF0, 0x90, 0x06, 0x92, 0x74, +0x02, 0xF0, 0x90, 0x01, 0x3C, 0x74, 0x04, 0xF0, +0xE4, 0xF5, 0x1D, 0x90, 0x81, 0xDE, 0xE0, 0xC3, +0x13, 0x54, 0x7F, 0xF5, 0x1E, 0xE4, 0xFB, 0xFD, +0x7F, 0x58, 0x7E, 0x01, 0x12, 0x6C, 0x40, 0x90, +0x81, 0x05, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, +0x81, 0x0A, 0xE0, 0x60, 0x0E, 0x90, 0x06, 0x92, +0xE0, 0x30, 0xE1, 0x02, 0x80, 0xB8, 0xD1, 0x94, +0x12, 0x6F, 0x4D, 0x22, 0x90, 0x81, 0x05, 0xE0, +0x54, 0xF7, 0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x90, 0x04, 0x1D, 0xE0, 0x60, +0x1A, 0x90, 0x05, 0x22, 0xE0, 0x54, 0x90, 0x60, +0x07, 0x90, 0x01, 0xC0, 0xE0, 0x44, 0x08, 0xF0, +0x90, 0x01, 0xC6, 0xE0, 0x30, 0xE1, 0xE4, 0x7F, +0x00, 0x80, 0x02, 0x7F, 0x01, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0xC3, 0xEE, 0x94, 0x01, 0x40, 0x0A, +0x0D, 0xED, 0x13, 0x90, 0xFD, 0x10, 0xF0, 0xE4, +0x2F, 0xFF, 0x22, 0xC3, 0xEE, 0x94, 0x01, 0x40, +0x1E, 0x90, 0xFD, 0x11, 0xE0, 0xB5, 0x05, 0x14, +0x90, 0x01, 0x17, 0xE0, 0xB5, 0x05, 0x07, 0x90, +0xFD, 0x11, 0xE4, 0xF0, 0x80, 0x06, 0xED, 0x04, +0x90, 0xFD, 0x11, 0xF0, 0xE4, 0x2F, 0xFF, 0x22, +0xFF, 0xEE, 0x3C, 0xFE, 0x90, 0x89, 0x2B, 0xE0, +0xFD, 0xD1, 0xDB, 0x90, 0x89, 0x2C, 0xE0, 0x22, +0x12, 0x5F, 0xB3, 0xA3, 0xED, 0xF0, 0xE4, 0xA3, +0xF0, 0x90, 0x89, 0x2C, 0xE0, 0xFF, 0xC3, 0x94, +0x02, 0x50, 0x21, 0xF1, 0xB3, 0x12, 0x61, 0xA7, +0xFC, 0x7E, 0x00, 0xED, 0x2F, 0xF1, 0x00, 0x24, +0x5A, 0xF5, 0x82, 0xE4, 0x34, 0x84, 0x12, 0x5F, +0x9B, 0xB5, 0x06, 0x1D, 0x90, 0x89, 0x2C, 0xE0, +0x04, 0xF0, 0x80, 0xD5, 0x90, 0x06, 0x32, 0xE0, +0x44, 0x80, 0xF0, 0x90, 0x01, 0xC7, 0x74, 0x30, +0xF0, 0x7F, 0x01, 0x12, 0x70, 0x9D, 0x7F, 0x01, +0x22, 0x7F, 0x00, 0x22, 0x12, 0x5F, 0xB3, 0xA3, +0xED, 0xF0, 0x90, 0x84, 0x2C, 0xE0, 0x70, 0x02, +0xA3, 0xE0, 0x60, 0x33, 0xE4, 0x90, 0x89, 0x2C, +0xF0, 0x90, 0x89, 0x2C, 0xE0, 0xFE, 0xC3, 0x94, +0x02, 0x50, 0x27, 0xF1, 0xB3, 0x12, 0x61, 0xA7, +0xFC, 0xEE, 0x7E, 0x00, 0x2D, 0xF1, 0x00, 0x24, +0x3A, 0xF5, 0x82, 0xE4, 0x34, 0x84, 0x12, 0x5F, +0x9B, 0x6E, 0x60, 0x03, 0x7F, 0x00, 0x22, 0x90, +0x89, 0x2C, 0xE0, 0x04, 0xF0, 0x80, 0xD2, 0x7F, +0x00, 0x22, 0x90, 0x06, 0x32, 0xE0, 0x44, 0x40, +0xF0, 0xE4, 0x90, 0x84, 0x38, 0xF0, 0xA3, 0xF0, +0x7F, 0x01, 0x22, 0x90, 0x89, 0x2A, 0xE0, 0x24, +0x1C, 0xFD, 0x22, 0xEF, 0x64, 0x01, 0x70, 0x31, +0x90, 0x81, 0xE8, 0xE0, 0xFA, 0x54, 0x7F, 0xFF, +0x7E, 0x00, 0xC0, 0x07, 0x90, 0x81, 0xEA, 0xE0, +0x13, 0x13, 0x54, 0x01, 0xFD, 0x90, 0x81, 0xE9, +0xE0, 0xF9, 0xC3, 0x13, 0x54, 0x7F, 0xFB, 0xE9, +0x54, 0x01, 0x90, 0x89, 0x38, 0xF0, 0xEA, 0x12, +0x5F, 0xD8, 0xA3, 0xF0, 0xD0, 0x07, 0x12, 0x52, +0xBE, 0x22, 0x90, 0x04, 0x1A, 0xE0, 0xF4, 0x60, +0x03, 0x7F, 0x00, 0x22, 0x90, 0x04, 0x1B, 0xE0, +0x54, 0x07, 0x64, 0x07, 0x7F, 0x01, 0x60, 0x02, +0x7F, 0x00, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x12, 0x8F, 0xF2, 0xEF, 0x64, 0x01, +0x60, 0x05, 0x75, 0x58, 0x01, 0x80, 0x41, 0x90, +0x81, 0x0E, 0xE0, 0xFF, 0x54, 0x03, 0x60, 0x05, +0x75, 0x58, 0x02, 0x80, 0x33, 0xEF, 0x30, 0xE2, +0x05, 0x75, 0x58, 0x08, 0x80, 0x2A, 0x90, 0x81, +0x0E, 0xE0, 0x30, 0xE4, 0x05, 0x75, 0x58, 0x10, +0x80, 0x1E, 0x12, 0x6F, 0xEC, 0x20, 0xE0, 0x05, +0x75, 0x58, 0x20, 0x80, 0x13, 0x11, 0x7B, 0x8F, +0x59, 0xE5, 0x59, 0x64, 0x01, 0x60, 0x05, 0x85, +0x59, 0x58, 0x80, 0x04, 0x11, 0x73, 0x80, 0x0E, +0x90, 0x01, 0xB9, 0x74, 0x04, 0xF0, 0x90, 0x01, +0xB8, 0xE5, 0x58, 0xF0, 0x7F, 0x00, 0xD0, 0xD0, +0x92, 0xAF, 0x22, 0x90, 0x01, 0xB8, 0xE4, 0xF0, +0x7F, 0x01, 0x22, 0x90, 0x81, 0x0C, 0xE0, 0xD3, +0x94, 0x00, 0x40, 0x06, 0x75, 0x52, 0x04, 0x7F, +0xFF, 0x22, 0x90, 0x81, 0xE2, 0xE0, 0x60, 0x06, +0x75, 0x52, 0x80, 0x7F, 0xFF, 0x22, 0x7F, 0x01, +0x22, 0x90, 0x02, 0x87, 0xE0, 0x60, 0x02, 0x80, +0x08, 0x90, 0x01, 0x00, 0xE0, 0x64, 0x3F, 0x60, +0x05, 0x75, 0x51, 0x01, 0x80, 0x40, 0x90, 0x81, +0xE3, 0xE0, 0x30, 0xE0, 0x0B, 0x90, 0x02, 0x82, +0xE0, 0x60, 0x05, 0x75, 0x51, 0x02, 0x80, 0x2E, +0x90, 0x81, 0xEE, 0xE0, 0x30, 0xE0, 0x05, 0x75, +0x51, 0x08, 0x80, 0x22, 0x90, 0x02, 0x86, 0xE0, +0x20, 0xE1, 0x02, 0x80, 0x07, 0x90, 0x02, 0x86, +0xE0, 0x30, 0xE3, 0x05, 0x75, 0x51, 0x04, 0x80, +0x0D, 0x90, 0x04, 0x1D, 0xE0, 0x60, 0x05, 0x75, +0x51, 0x40, 0x80, 0x02, 0x80, 0x85, 0x90, 0x01, +0xB9, 0x74, 0x08, 0xF0, 0x90, 0x01, 0xB8, 0xE5, +0x51, 0xF0, 0x7F, 0x00, 0x22, 0x7B, 0x2E, 0x31, +0x08, 0x7D, 0x02, 0x7F, 0x01, 0x02, 0x69, 0x45, +0x7D, 0x6F, 0x7F, 0xFF, 0x02, 0x66, 0x73, 0x90, +0x81, 0xD6, 0x74, 0x18, 0xF0, 0xA3, 0x74, 0x03, +0xF0, 0xA3, 0xE4, 0xF0, 0xA3, 0x74, 0x64, 0xF0, +0xA3, 0x74, 0x05, 0xF0, 0xA3, 0xF0, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x8A, +0x64, 0xEF, 0xF0, 0x7E, 0x00, 0x7F, 0xA0, 0x7D, +0x00, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0x28, 0x12, +0x46, 0x4B, 0xE4, 0x90, 0x81, 0x21, 0xF0, 0x90, +0x81, 0x20, 0xF0, 0x90, 0x81, 0x24, 0xF0, 0x90, +0x8A, 0x64, 0xE0, 0xB4, 0x01, 0x09, 0x90, 0x81, +0x25, 0x74, 0x14, 0xF0, 0xE4, 0xA3, 0xF0, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x12, 0x80, 0x18, 0x12, +0x66, 0x6E, 0x7D, 0x0C, 0x7F, 0x01, 0x02, 0x69, +0x45, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x90, 0x8A, 0x65, 0xEF, 0xF0, 0xC3, 0x94, 0x02, +0x50, 0x44, 0x90, 0x80, 0x0B, 0xE0, 0xFF, 0x90, +0x04, 0x1C, 0xE0, 0x6F, 0x70, 0x38, 0x90, 0x81, +0x0D, 0xE0, 0x64, 0x0E, 0x70, 0x15, 0x90, 0x8A, +0x65, 0xE0, 0x70, 0x2A, 0x90, 0x81, 0x05, 0xE0, +0x54, 0x7F, 0xF0, 0x12, 0x6F, 0xBB, 0x12, 0x69, +0x41, 0x80, 0x18, 0x90, 0x81, 0x0D, 0xE0, 0x64, +0x06, 0x70, 0x13, 0x90, 0x8A, 0x65, 0xE0, 0x60, +0x0D, 0x31, 0xCB, 0x31, 0xD3, 0x90, 0x81, 0x0D, +0x74, 0x04, 0xF0, 0x12, 0x66, 0x6E, 0xD0, 0xD0, +0x92, 0xAF, 0x22, 0x90, 0x81, 0x05, 0xE0, 0x54, +0xBF, 0xF0, 0x22, 0x90, 0x06, 0x04, 0xE0, 0x44, +0x40, 0xF0, 0xE0, 0x44, 0x80, 0xF0, 0x22, 0x51, +0x0A, 0xFE, 0x90, 0x84, 0x8F, 0xE0, 0x54, 0xFE, +0x4E, 0xFE, 0xF0, 0xEF, 0x54, 0x04, 0xFF, 0xEE, +0x54, 0xFB, 0x4F, 0xF0, 0x12, 0x1F, 0xA4, 0xC3, +0x13, 0x30, 0xE0, 0x07, 0x12, 0x56, 0x95, 0x90, +0x84, 0x90, 0xF0, 0x22, 0x90, 0x89, 0x19, 0x12, +0x44, 0x69, 0x12, 0x1F, 0xA4, 0xFF, 0x54, 0x01, +0x22, 0x90, 0x89, 0x19, 0x12, 0x44, 0x72, 0x51, +0x55, 0x51, 0x04, 0xFE, 0x12, 0x70, 0x8E, 0x4E, +0xF0, 0xEF, 0xC3, 0x13, 0x30, 0xE0, 0x2D, 0x12, +0x56, 0x95, 0x90, 0x84, 0x94, 0x12, 0x57, 0x74, +0x90, 0x84, 0x95, 0xF0, 0x12, 0x1F, 0xA4, 0xFF, +0x54, 0x04, 0xFE, 0x90, 0x84, 0x93, 0xE0, 0x54, +0xFB, 0x12, 0x57, 0xB3, 0x90, 0x84, 0x96, 0xF0, +0xEF, 0x54, 0x08, 0xFF, 0x90, 0x84, 0x93, 0xE0, +0x54, 0xF7, 0x4F, 0xF0, 0x22, 0x7E, 0x00, 0x7F, +0x08, 0x7D, 0x00, 0x7B, 0x01, 0x7A, 0x84, 0x79, +0x93, 0x12, 0x46, 0x4B, 0x90, 0x84, 0x94, 0x74, +0x08, 0xF0, 0xA3, 0x74, 0x03, 0xF0, 0x22, 0x90, +0x02, 0x84, 0xEF, 0xF0, 0xEE, 0xA3, 0xF0, 0xA3, +0xE0, 0x44, 0x01, 0xF0, 0x22, 0x90, 0x01, 0x1F, +0xE0, 0xFE, 0x90, 0x01, 0x1E, 0x12, 0x81, 0xF8, +0x90, 0x89, 0x19, 0x71, 0x77, 0xE0, 0x90, 0x89, +0x1D, 0xF0, 0x90, 0x81, 0xE3, 0xE0, 0x20, 0xE0, +0x02, 0x61, 0x2F, 0x90, 0x89, 0x1D, 0xE0, 0xFF, +0xEC, 0xC3, 0x9F, 0x40, 0x02, 0x61, 0x2F, 0x90, +0x89, 0x19, 0xE0, 0xFA, 0xA3, 0xE0, 0xFB, 0x71, +0x7F, 0xAD, 0x07, 0x74, 0x02, 0x2D, 0x71, 0x9E, +0xF9, 0x71, 0x30, 0xFE, 0x74, 0x00, 0x2D, 0x12, +0x5F, 0xA2, 0x71, 0x5F, 0x54, 0x3F, 0x90, 0x89, +0x1B, 0xF0, 0xA3, 0xEF, 0xF0, 0x74, 0x03, 0x2D, +0x71, 0x87, 0xFF, 0x7E, 0x00, 0xAD, 0x01, 0xED, +0x24, 0x18, 0xFB, 0xEA, 0x33, 0xCB, 0x2F, 0xFF, +0xEE, 0x3B, 0x90, 0x89, 0x1B, 0x8F, 0xF0, 0x12, +0x43, 0xF6, 0x90, 0x89, 0x1B, 0xE0, 0xFE, 0xA3, +0xE0, 0xFF, 0x71, 0x3C, 0x90, 0x89, 0x1B, 0xEE, +0x71, 0x6F, 0xEE, 0x8F, 0xF0, 0x71, 0x67, 0xFE, +0xA3, 0xE0, 0xFF, 0xD3, 0x90, 0x89, 0x1A, 0xE0, +0x9F, 0x90, 0x89, 0x19, 0xE0, 0x9E, 0x40, 0x12, +0x90, 0x80, 0xFB, 0x71, 0x92, 0xC3, 0x90, 0x89, +0x1A, 0xE0, 0x9F, 0xF0, 0x90, 0x89, 0x19, 0xE0, +0x9E, 0xF0, 0x90, 0x89, 0x19, 0xE0, 0xFE, 0xA3, +0xE0, 0xFF, 0x51, 0x6F, 0x0C, 0x41, 0x9B, 0x22, +0x74, 0x01, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0xFB, +0xF5, 0x83, 0xE0, 0x22, 0x7D, 0x7F, 0xEF, 0x5D, +0xC3, 0x60, 0x0B, 0x71, 0x53, 0x5F, 0x24, 0x80, +0xFF, 0xE4, 0x3E, 0xFE, 0x80, 0x04, 0x71, 0x53, +0x5F, 0xFF, 0x22, 0x74, 0xFF, 0x9D, 0xFD, 0x74, +0xFF, 0x94, 0x00, 0x5E, 0xFE, 0xED, 0x22, 0x7A, +0x00, 0x24, 0x00, 0xFF, 0xEA, 0x3E, 0x22, 0x12, +0x43, 0xF6, 0x90, 0x80, 0xFA, 0xE0, 0x22, 0xF0, +0xA3, 0xEF, 0xF0, 0x90, 0x89, 0x19, 0x22, 0xF0, +0xA3, 0xEF, 0xF0, 0x90, 0x02, 0x87, 0x22, 0xEA, +0x90, 0xFD, 0x11, 0xF0, 0xAF, 0x03, 0x22, 0xF5, +0x82, 0xE4, 0x34, 0xFB, 0xF5, 0x83, 0xE0, 0x54, +0x03, 0x22, 0xE0, 0x24, 0x01, 0xFF, 0x90, 0x80, +0xFA, 0xE0, 0x34, 0x00, 0xFE, 0x22, 0xF5, 0x82, +0xE4, 0x34, 0xFB, 0xF5, 0x83, 0xE0, 0x54, 0x0F, +0x33, 0x33, 0x33, 0x54, 0xF8, 0x22, 0x90, 0x02, +0x86, 0xE0, 0x20, 0xE2, 0x03, 0x7F, 0x04, 0x22, +0x90, 0x02, 0x86, 0xE0, 0x7F, 0x01, 0x20, 0xE1, +0x02, 0x7F, 0x02, 0x22, 0x90, 0x81, 0xEE, 0xE0, +0x30, 0xE0, 0x0D, 0x90, 0x81, 0xE6, 0xE0, 0xC4, +0x54, 0x0F, 0x20, 0xE0, 0x03, 0x7F, 0x00, 0x22, +0x7F, 0x01, 0x22, 0xEF, 0x90, 0x01, 0xC7, 0xB4, +0xA0, 0x05, 0x74, 0x04, 0xF0, 0x80, 0x03, 0x74, +0x08, 0xF0, 0x02, 0x5C, 0xE6, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0xEF, 0x20, 0xE0, 0x05, +0x90, 0x84, 0x7C, 0x80, 0x03, 0x90, 0x84, 0x7D, +0xE0, 0x90, 0x84, 0x23, 0xF0, 0x90, 0x84, 0x23, +0xE0, 0x14, 0x60, 0x13, 0x14, 0x60, 0x14, 0x24, +0xFE, 0x60, 0x10, 0x14, 0x60, 0x09, 0x14, 0x60, +0x06, 0x24, 0x06, 0xE4, 0xFE, 0x80, 0x06, 0x7E, +0x04, 0x80, 0x02, 0x7E, 0x08, 0xAF, 0x06, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x90, 0x89, 0x1C, 0xEF, +0xF0, 0xE4, 0xFF, 0x74, 0xF2, 0x2F, 0xF5, 0x82, +0xE4, 0x34, 0x83, 0xF5, 0x83, 0xE0, 0xFE, 0x74, +0xA4, 0x12, 0x6E, 0xEC, 0x0F, 0xEF, 0xB4, 0x08, +0xEA, 0x90, 0x84, 0x22, 0xE0, 0x90, 0x04, 0x4C, +0xF0, 0x90, 0x84, 0x24, 0xE0, 0x90, 0x04, 0x4D, +0xF0, 0x75, 0x13, 0x01, 0x75, 0x14, 0x83, 0x75, +0x15, 0x01, 0x75, 0x16, 0x08, 0x7B, 0x01, 0x7A, +0x83, 0x79, 0xFA, 0x12, 0x2B, 0xED, 0x90, 0x84, +0x8D, 0xE0, 0x60, 0x22, 0x90, 0x89, 0x1C, 0xE0, +0xFF, 0x12, 0x82, 0xC3, 0x7E, 0x00, 0x74, 0x00, +0x2F, 0x12, 0x77, 0xE8, 0xC0, 0x03, 0x8B, 0x13, +0x75, 0x14, 0x83, 0x75, 0x15, 0xF2, 0x75, 0x16, +0x34, 0xD0, 0x03, 0x12, 0x2B, 0xED, 0x22, 0x90, +0x89, 0x56, 0x91, 0xCB, 0x2F, 0xFF, 0xE4, 0x3E, +0xCF, 0x24, 0x06, 0xCF, 0x12, 0x5E, 0xDB, 0xBF, +0x86, 0x1E, 0x90, 0x89, 0x58, 0xE0, 0xFF, 0x90, +0x89, 0x57, 0xE0, 0x2F, 0xFF, 0x90, 0x89, 0x56, +0xE0, 0x34, 0x00, 0xCF, 0x24, 0x07, 0xCF, 0x12, +0x5E, 0xDB, 0xBF, 0xDD, 0x03, 0x7F, 0x01, 0x22, +0x7F, 0x00, 0x22, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, +0xA3, 0xED, 0xF0, 0x22, 0x90, 0x89, 0x90, 0x12, +0x44, 0x72, 0x90, 0x89, 0x93, 0x12, 0x66, 0x5D, +0x75, 0x16, 0x10, 0x7B, 0x01, 0x7A, 0x82, 0x79, +0x8E, 0x12, 0x2B, 0xED, 0x90, 0x89, 0x90, 0x12, +0x66, 0x5D, 0x75, 0x16, 0x10, 0x7B, 0x01, 0x7A, +0x82, 0x79, 0x9E, 0x12, 0x2B, 0xED, 0x90, 0x89, +0x96, 0x12, 0x44, 0x45, 0x90, 0x82, 0xAE, 0x12, +0x20, 0xCE, 0x90, 0x89, 0x9A, 0xE0, 0x90, 0x82, +0xB5, 0xF0, 0x22, 0x12, 0x1F, 0xA4, 0x90, 0x84, +0x7C, 0x12, 0x56, 0x94, 0x90, 0x84, 0x7D, 0xF0, +0x22, 0xB1, 0x67, 0x90, 0x84, 0x85, 0x12, 0x56, +0x94, 0xFF, 0xED, 0x2F, 0x90, 0x84, 0x86, 0x12, +0x57, 0x74, 0xFF, 0xED, 0x2F, 0x90, 0x84, 0x87, +0x12, 0x57, 0xB4, 0xFF, 0xED, 0x2F, 0x90, 0x84, +0x88, 0x12, 0x55, 0x9B, 0xFF, 0xED, 0x2F, 0x90, +0x84, 0x89, 0xB1, 0x5C, 0x90, 0x84, 0x8A, 0x12, +0x57, 0xD0, 0xFF, 0xAE, 0x05, 0xED, 0x2F, 0x90, +0x84, 0x8B, 0xF0, 0x22, 0xF0, 0x90, 0x00, 0x05, +0x12, 0x1F, 0xBD, 0xFF, 0xED, 0x2F, 0x22, 0x90, +0x02, 0x09, 0xE0, 0xFD, 0x12, 0x1F, 0xA4, 0xFE, +0xAF, 0x05, 0xED, 0x2E, 0x22, 0xB1, 0x67, 0x90, +0x84, 0x8C, 0x12, 0x56, 0x94, 0xFF, 0xAE, 0x05, +0xED, 0x2F, 0x90, 0x84, 0x8D, 0xF0, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x84, +0x7D, 0xE0, 0xFD, 0xB4, 0x02, 0x07, 0xD1, 0x64, +0x74, 0x08, 0xF0, 0x80, 0x09, 0xED, 0xB4, 0x04, +0x05, 0xD1, 0x64, 0x74, 0x10, 0xF0, 0xEF, 0x64, +0x02, 0x4E, 0x60, 0x08, 0xEF, 0x64, 0x01, 0x4E, +0x60, 0x02, 0xC1, 0x5F, 0x90, 0x82, 0xF9, 0xE0, +0xFF, 0x64, 0xFE, 0x70, 0x02, 0xC1, 0x5F, 0xEF, +0x64, 0x02, 0x60, 0x07, 0xEF, 0x64, 0x03, 0x60, +0x02, 0xC1, 0x5F, 0x90, 0x83, 0x59, 0xD1, 0x6C, +0x90, 0x89, 0x82, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, +0x7E, 0x00, 0x7F, 0x28, 0x7D, 0x00, 0x7B, 0x01, +0x7A, 0x89, 0x79, 0x58, 0x12, 0x46, 0x4B, 0x7B, +0x01, 0x7A, 0x83, 0x79, 0x5B, 0x90, 0x86, 0x67, +0x12, 0x44, 0x72, 0x7A, 0x89, 0x79, 0x58, 0x90, +0x86, 0x6A, 0x12, 0x44, 0x72, 0x7A, 0x82, 0x79, +0xC8, 0x7D, 0x03, 0x12, 0x02, 0x00, 0x75, 0x13, +0x01, 0x75, 0x14, 0x89, 0x75, 0x15, 0x60, 0x75, +0x16, 0x20, 0x7B, 0x01, 0x7A, 0x89, 0x79, 0x37, +0x12, 0x2B, 0xED, 0x90, 0x89, 0x5E, 0xE0, 0x54, +0x03, 0x90, 0x89, 0x57, 0xF0, 0xC3, 0x94, 0x04, +0x50, 0x1C, 0xE0, 0x90, 0x84, 0x22, 0xF0, 0x75, +0x13, 0x01, 0x75, 0x14, 0x89, 0x75, 0x15, 0x37, +0x75, 0x16, 0x20, 0x7B, 0x01, 0x7A, 0x84, 0x79, +0x02, 0x12, 0x2B, 0xED, 0x80, 0x06, 0x90, 0x84, +0x22, 0x74, 0x05, 0xF0, 0x90, 0x89, 0x57, 0xE0, +0xFF, 0x90, 0x84, 0x7D, 0xE0, 0xFD, 0x7B, 0x01, +0x7A, 0x89, 0x79, 0x37, 0x12, 0x58, 0xEA, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x90, 0x89, 0x80, 0x74, +0x80, 0xF0, 0xA3, 0x22, 0xE0, 0xFE, 0xA3, 0xE0, +0xFD, 0xED, 0xFF, 0x22, 0x90, 0x84, 0xF8, 0xED, +0xF0, 0x90, 0x84, 0xF5, 0x12, 0x44, 0x72, 0x12, +0x57, 0xB5, 0x90, 0x84, 0xFC, 0xF0, 0x90, 0x84, +0xF5, 0x12, 0x66, 0x5D, 0x75, 0x16, 0x03, 0x7B, +0x01, 0x7A, 0x84, 0x79, 0xF9, 0x12, 0x2B, 0xED, +0x90, 0x84, 0xF8, 0xE0, 0x70, 0x2E, 0xFF, 0xD1, +0xCD, 0xE0, 0xB4, 0xFF, 0x06, 0xD1, 0xCD, 0xE4, +0xF0, 0x80, 0x07, 0xD1, 0xCD, 0xE0, 0x04, 0xF0, +0x80, 0x05, 0x0F, 0xEF, 0xB4, 0x03, 0xE8, 0x75, +0x13, 0x01, 0x75, 0x14, 0x84, 0x75, 0x15, 0xF9, +0x75, 0x16, 0x03, 0x90, 0x84, 0xF5, 0x12, 0x44, +0x69, 0x12, 0x2B, 0xED, 0x22, 0x74, 0xF9, 0x2F, +0xF5, 0x82, 0xE4, 0x34, 0x84, 0xF5, 0x83, 0x22, +0x74, 0x10, 0x2F, 0xF9, 0xE4, 0x34, 0xFB, 0xA8, +0x01, 0xFC, 0x7D, 0x01, 0x7B, 0x01, 0x7A, 0x84, +0x79, 0x32, 0xD1, 0xF3, 0x7F, 0x01, 0x60, 0x02, +0x7F, 0x00, 0x22, 0x7E, 0x00, 0x7F, 0x04, 0x12, +0x46, 0x27, 0xEF, 0x22, 0xAD, 0x07, 0xAB, 0x05, +0x74, 0x17, 0x2B, 0xF5, 0x82, 0xE4, 0x34, 0xFB, +0xF5, 0x83, 0xE0, 0xFE, 0x74, 0x16, 0x2B, 0xF5, +0x82, 0xE4, 0x34, 0xFB, 0xF5, 0x83, 0x12, 0x81, +0xF8, 0xFE, 0x90, 0x84, 0x36, 0xE0, 0x6E, 0x70, +0x03, 0xA3, 0xE0, 0x6F, 0x7F, 0x01, 0x60, 0x02, +0x7F, 0x00, 0x22, 0x90, 0x89, 0x53, 0xE4, 0x75, +0xF0, 0x08, 0x12, 0x43, 0xF6, 0x90, 0x89, 0x53, +0xE4, 0x75, 0xF0, 0x08, 0x02, 0x43, 0xF6, 0x90, +0x05, 0x63, 0xE0, 0x90, 0x81, 0xD2, 0xF0, 0x90, +0x05, 0x62, 0xE0, 0x90, 0x81, 0xD3, 0xF0, 0x90, +0x05, 0x61, 0xE0, 0x90, 0x81, 0xD4, 0xF0, 0x90, +0x05, 0x60, 0xE0, 0x90, 0x81, 0xD5, 0xF0, 0x90, +0x81, 0x06, 0xE0, 0x44, 0x80, 0xF0, 0x22, 0x90, +0x81, 0xC9, 0xE0, 0x24, 0x01, 0xFF, 0x90, 0x81, +0xC8, 0xE0, 0x34, 0x00, 0xFE, 0x12, 0x32, 0xAA, +0x90, 0x81, 0x0D, 0x22, 0x90, 0x86, 0x55, 0x12, +0x44, 0x72, 0x90, 0x84, 0xD8, 0x12, 0x44, 0x45, +0x90, 0x86, 0x58, 0x02, 0x20, 0xCE, 0xF5, 0x83, +0xEF, 0xF0, 0x90, 0x89, 0x52, 0xE0, 0x04, 0xF0, +0x22, 0xE0, 0xFF, 0x74, 0x01, 0x7E, 0x00, 0xA8, +0x07, 0x08, 0x22, 0x2F, 0xF5, 0x82, 0x74, 0x01, +0x3E, 0xF5, 0x83, 0xE0, 0xFF, 0x90, 0x80, 0x61, +0xE0, 0x75, 0xF0, 0x08, 0x22, 0x90, 0x89, 0x50, +0xE0, 0xFF, 0x24, 0x01, 0xF5, 0x82, 0xE4, 0x34, +0x83, 0xF5, 0x83, 0xE0, 0xFE, 0x22, 0x24, 0x40, +0xF9, 0xE4, 0x34, 0xFC, 0xFA, 0x7B, 0x01, 0x22, +0x12, 0x44, 0x5D, 0xE5, 0x82, 0x29, 0xF5, 0x82, +0xE4, 0x35, 0x83, 0xF5, 0x83, 0xEF, 0xF0, 0x22, +0x7E, 0x00, 0x7F, 0x04, 0x02, 0x43, 0xD0, 0x90, +0x84, 0xA4, 0x12, 0x44, 0x72, 0xE4, 0x90, 0x84, +0xA7, 0xF0, 0x22, 0x7B, 0x01, 0x7A, 0x83, 0x79, +0xF2, 0x90, 0x8A, 0x3B, 0xE0, 0xFD, 0x22, 0x90, +0x81, 0xDC, 0xE0, 0xFF, 0x90, 0x81, 0x13, 0xE0, +0xD3, 0x9F, 0x22, 0xEF, 0x13, 0x13, 0x13, 0x54, +0x1F, 0xFE, 0xEF, 0x54, 0x07, 0xFF, 0x22, 0x90, +0x89, 0x53, 0xE4, 0x75, 0xF0, 0x02, 0x02, 0x43, +0xF6, 0x90, 0x84, 0xD3, 0xE0, 0xC3, 0x13, 0x90, +0xFD, 0x10, 0xF0, 0x22, 0x7D, 0x01, 0x7E, 0x00, +0x7F, 0x10, 0x12, 0x46, 0x27, 0xEF, 0x22, 0x54, +0xFB, 0xF0, 0x90, 0x81, 0x0E, 0xE0, 0x54, 0xFD, +0xF0, 0x22, 0x24, 0x28, 0xF9, 0xE4, 0x34, 0xFC, +0xFA, 0x7B, 0x01, 0x22, 0x75, 0x14, 0x82, 0x75, +0x15, 0xFF, 0x75, 0x16, 0x02, 0x22, 0x12, 0x2B, +0xED, 0x90, 0x8A, 0x53, 0x22, 0xF0, 0x90, 0x89, +0x50, 0xE0, 0x04, 0xF0, 0x22, 0x24, 0x04, 0xF5, +0x82, 0xE4, 0x34, 0xFB, 0x22, 0xF9, 0xEE, 0x34, +0xFC, 0xFA, 0x7B, 0x01, 0x22, 0x90, 0x82, 0x1E, +0x12, 0x44, 0x5D, 0xE0, 0x22, 0x7E, 0x00, 0x7F, +0x10, 0x02, 0x43, 0xD0, 0x90, 0x81, 0x06, 0xE0, +0x44, 0x04, 0xF0, 0x22, 0x2F, 0xF8, 0xE6, 0xFE, +0xED, 0xF4, 0x5E, 0x22, 0xCD, 0x91 +}; + +u32 array_length_mp_8188e_s_fw_wowlan = 22710; + +#endif /*CONFIG_WOWLAN*/ + +#endif /* end of LOAD_FW_HEADER_FROM_DRIVER */ + +#endif /* end of CONFIG_SFW_SUPPORTED */ diff --git a/drivers/staging/rtl8188eu/hal/hal8188e_s_fw.h b/drivers/staging/rtl8188eu/hal/hal8188e_s_fw.h new file mode 100644 index 000000000000..71b0ecac0c01 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal8188e_s_fw.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef _FW_HEADER_8188E_S_H +#define _FW_HEADER_8188E_S_H + +#ifdef CONFIG_SFW_SUPPORTED + +#ifdef LOAD_FW_HEADER_FROM_DRIVER +#if defined(CONFIG_AP_WOWLAN) +extern u8 array_mp_8188e_s_fw_ap[16054]; +extern u32 array_length_mp_8188e_s_fw_ap; +#endif + +extern u8 array_mp_8188e_s_fw_nic[19206]; +extern u32 array_length_mp_8188e_s_fw_nic; +#ifdef CONFIG_WOWLAN +extern u8 array_mp_8188e_s_fw_wowlan[22710]; +extern u32 array_length_mp_8188e_s_fw_wowlan; +#endif /*CONFIG_WOWLAN*/ +#endif /* end of LOAD_FW_HEADER_FROM_DRIVER */ +#endif /* end of CONFIG_SFW_SUPPORTED */ + +#endif + diff --git a/drivers/staging/rtl8188eu/hal/hal8188e_t_fw.c b/drivers/staging/rtl8188eu/hal/hal8188e_t_fw.c new file mode 100644 index 000000000000..6c5d7dd2278e --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal8188e_t_fw.c @@ -0,0 +1,7730 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#include "drv_types.h" +#include "hal8188e_t_fw.h" + +#ifdef LOAD_FW_HEADER_FROM_DRIVER + +#if (defined(CONFIG_AP_WOWLAN)) + +u8 array_mp_8188e_t_fw_ap[] = { +0xE1, 0x88, 0x20, 0x00, 0x1C, 0x00, 0x00, 0x00, +0x05, 0x05, 0x14, 0x27, 0x6E, 0x3C, 0x00, 0x00, +0xA5, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x02, 0x45, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xC1, 0x84, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xA1, 0xFB, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xE1, 0xF3, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xC2, 0xAF, 0x80, 0xFE, 0x32, 0x12, 0x41, 0x04, +0x85, 0xD0, 0x0B, 0x75, 0xD0, 0x08, 0xAA, 0xE0, +0xC2, 0x8C, 0xE5, 0x8A, 0x24, 0x67, 0xF5, 0x8A, +0xE5, 0x8C, 0x34, 0x79, 0xF5, 0x8C, 0xD2, 0x8C, +0xEC, 0x24, 0x87, 0xF8, 0xE6, 0xBC, 0x02, 0x02, +0x74, 0xFF, 0xC3, 0x95, 0x81, 0xB4, 0x40, 0x00, +0x40, 0xCE, 0x79, 0x03, 0x78, 0x80, 0x16, 0xE6, +0x08, 0x70, 0x0B, 0xC2, 0xAF, 0xE6, 0x30, 0xE1, +0x03, 0x44, 0x18, 0xF6, 0xD2, 0xAF, 0x08, 0xD9, +0xED, 0xEA, 0x8B, 0xD0, 0x22, 0xE5, 0x0C, 0xFF, +0x23, 0x24, 0x81, 0xF8, 0x0F, 0x08, 0x08, 0xBF, +0x03, 0x04, 0x7F, 0x00, 0x78, 0x81, 0xE6, 0x30, +0xE4, 0xF2, 0x00, 0xE5, 0x0C, 0xC3, 0x9F, 0x50, +0x20, 0x05, 0x0C, 0x74, 0x86, 0x25, 0x0C, 0xF8, +0xE6, 0xFD, 0xA6, 0x81, 0x08, 0xE6, 0xAE, 0x0C, +0xBE, 0x02, 0x02, 0x74, 0xFF, 0xCD, 0xF8, 0xE8, +0x6D, 0x60, 0xE0, 0x08, 0xE6, 0xC0, 0xE0, 0x80, +0xF6, 0xE5, 0x0C, 0xD3, 0x9F, 0x40, 0x27, 0xE5, +0x0C, 0x24, 0x87, 0xF8, 0xE6, 0xAE, 0x0C, 0xBE, +0x02, 0x02, 0x74, 0xFF, 0xFD, 0x18, 0xE6, 0xCD, +0xF8, 0xE5, 0x81, 0x6D, 0x60, 0x06, 0xD0, 0xE0, +0xF6, 0x18, 0x80, 0xF5, 0xE5, 0x0C, 0x24, 0x86, +0xC8, 0xF6, 0x15, 0x0C, 0x80, 0xD3, 0xE5, 0x0C, +0x23, 0x24, 0x81, 0xF8, 0x7F, 0x04, 0xC2, 0xAF, +0xE6, 0x30, 0xE0, 0x03, 0x10, 0xE2, 0x0C, 0x7F, +0x00, 0x30, 0xE1, 0x07, 0x30, 0xE3, 0x04, 0x7F, +0x08, 0x54, 0xF4, 0x54, 0x7C, 0xC6, 0xD2, 0xAF, +0x54, 0x80, 0x42, 0x07, 0x22, 0x78, 0x86, 0xA6, +0x81, 0x74, 0x02, 0x60, 0x06, 0xFF, 0x08, 0x76, +0xFF, 0xDF, 0xFB, 0x7F, 0x03, 0xE4, 0x78, 0x80, +0xF6, 0x08, 0xF6, 0x08, 0xDF, 0xFA, 0x78, 0x81, +0x76, 0x30, 0x90, 0x45, 0xF5, 0x74, 0x01, 0x93, +0xC0, 0xE0, 0xE4, 0x93, 0xC0, 0xE0, 0x43, 0x89, +0x01, 0x75, 0x8A, 0x60, 0x75, 0x8C, 0x79, 0xD2, +0x8C, 0xD2, 0xAF, 0x22, 0x02, 0xEF, 0xD3, 0x94, +0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, 0x74, 0x81, +0x2F, 0x2F, 0xF8, 0xE6, 0x20, 0xE5, 0xF4, 0xC2, +0xAF, 0xE6, 0x44, 0x30, 0xF6, 0xD2, 0xAF, 0xAE, +0x0C, 0xEE, 0xC3, 0x9F, 0x50, 0x21, 0x0E, 0x74, +0x86, 0x2E, 0xF8, 0xE6, 0xF9, 0x08, 0xE6, 0x18, +0xBE, 0x02, 0x02, 0x74, 0xFF, 0xFD, 0xED, 0x69, +0x60, 0x09, 0x09, 0xE7, 0x19, 0x19, 0xF7, 0x09, +0x09, 0x80, 0xF3, 0x16, 0x16, 0x80, 0xDA, 0xEE, +0xD3, 0x9F, 0x40, 0x04, 0x05, 0x81, 0x05, 0x81, +0xEE, 0xD3, 0x9F, 0x40, 0x22, 0x74, 0x86, 0x2E, +0xF8, 0x08, 0xE6, 0xF9, 0xEE, 0xB5, 0x0C, 0x02, +0xA9, 0x81, 0x18, 0x06, 0x06, 0xE6, 0xFD, 0xED, +0x69, 0x60, 0x09, 0x19, 0x19, 0xE7, 0x09, 0x09, +0xF7, 0x19, 0x80, 0xF3, 0x1E, 0x80, 0xD9, 0xEF, +0x24, 0x86, 0xF8, 0xE6, 0x04, 0xF8, 0xEF, 0x2F, +0x04, 0x90, 0x45, 0xF5, 0x93, 0xF6, 0x08, 0xEF, +0x2F, 0x93, 0xF6, 0x7F, 0x00, 0x22, 0xEF, 0xD3, +0x94, 0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, 0xEF, +0x23, 0x24, 0x81, 0xF8, 0xE6, 0x30, 0xE5, 0xF4, +0xC2, 0xAF, 0xE6, 0x54, 0x8C, 0xF6, 0xD2, 0xAF, +0xE5, 0x0C, 0xB5, 0x07, 0x0A, 0x74, 0x86, 0x2F, +0xF8, 0xE6, 0xF5, 0x81, 0x02, 0x41, 0x4D, 0x50, +0x2E, 0x74, 0x87, 0x2F, 0xF8, 0xE6, 0xBF, 0x02, +0x02, 0x74, 0xFF, 0xFD, 0x18, 0xE6, 0xF9, 0x74, +0x86, 0x2F, 0xF8, 0xFB, 0xE6, 0xFC, 0xE9, 0x6C, +0x60, 0x08, 0xA8, 0x05, 0xE7, 0xF6, 0x1D, 0x19, +0x80, 0xF4, 0xA8, 0x03, 0xA6, 0x05, 0x1F, 0xE5, +0x0C, 0xB5, 0x07, 0xE3, 0x7F, 0x00, 0x22, 0x74, +0x87, 0x2F, 0xF8, 0xE6, 0xFD, 0x18, 0x86, 0x01, +0x0F, 0x74, 0x86, 0x2F, 0xF8, 0xA6, 0x01, 0x08, +0x86, 0x04, 0xE5, 0x0C, 0xB5, 0x07, 0x02, 0xAC, +0x81, 0xED, 0x6C, 0x60, 0x08, 0x0D, 0x09, 0xA8, +0x05, 0xE6, 0xF7, 0x80, 0xF4, 0xE5, 0x0C, 0xB5, +0x07, 0xDE, 0x89, 0x81, 0x7F, 0x00, 0x22, 0xEF, +0xD3, 0x94, 0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, +0xEF, 0x23, 0x24, 0x81, 0xF8, 0xC2, 0xAF, 0xE6, +0x30, 0xE5, 0x05, 0x30, 0xE0, 0x02, 0xD2, 0xE4, +0xD2, 0xE2, 0xC6, 0xD2, 0xAF, 0x7F, 0x00, 0x30, +0xE2, 0x01, 0x0F, 0x02, 0x41, 0x4C, 0x8F, 0xF0, +0xE4, 0xFF, 0xFE, 0xE5, 0x0C, 0x23, 0x24, 0x80, +0xF8, 0xC2, 0xA9, 0x30, 0xF7, 0x0D, 0x7F, 0x08, +0xE6, 0x60, 0x0B, 0x2D, 0xF6, 0x60, 0x30, 0x50, +0x2E, 0x80, 0x07, 0x30, 0xF1, 0x06, 0xED, 0xF6, +0x60, 0x25, 0x7E, 0x02, 0x08, 0x30, 0xF0, 0x10, +0xC2, 0xAF, 0xE6, 0x10, 0xE7, 0x23, 0x0E, 0x30, +0xE2, 0x0C, 0xD2, 0xAF, 0x7F, 0x04, 0x80, 0x12, +0xC2, 0xAF, 0xE6, 0x10, 0xE7, 0x13, 0x54, 0xEC, +0x4E, 0xF6, 0xD2, 0xAF, 0x02, 0x41, 0x4D, 0x7F, +0x08, 0x08, 0xEF, 0x44, 0x83, 0xF4, 0xC2, 0xAF, +0x56, 0xC6, 0xD2, 0xAF, 0x54, 0x80, 0x4F, 0xFF, +0x22, 0xE7, 0x09, 0xF6, 0x08, 0xDF, 0xFA, 0x80, +0x46, 0xE7, 0x09, 0xF2, 0x08, 0xDF, 0xFA, 0x80, +0x3E, 0x88, 0x82, 0x8C, 0x83, 0xE7, 0x09, 0xF0, +0xA3, 0xDF, 0xFA, 0x80, 0x32, 0xE3, 0x09, 0xF6, +0x08, 0xDF, 0xFA, 0x80, 0x78, 0xE3, 0x09, 0xF2, +0x08, 0xDF, 0xFA, 0x80, 0x70, 0x88, 0x82, 0x8C, +0x83, 0xE3, 0x09, 0xF0, 0xA3, 0xDF, 0xFA, 0x80, +0x64, 0x89, 0x82, 0x8A, 0x83, 0xE0, 0xA3, 0xF6, +0x08, 0xDF, 0xFA, 0x80, 0x58, 0x89, 0x82, 0x8A, +0x83, 0xE0, 0xA3, 0xF2, 0x08, 0xDF, 0xFA, 0x80, +0x4C, 0x80, 0xD2, 0x80, 0xFA, 0x80, 0xC6, 0x80, +0xD4, 0x80, 0x69, 0x80, 0xF2, 0x80, 0x33, 0x80, +0x10, 0x80, 0xA6, 0x80, 0xEA, 0x80, 0x9A, 0x80, +0xA8, 0x80, 0xDA, 0x80, 0xE2, 0x80, 0xCA, 0x80, +0x33, 0x89, 0x82, 0x8A, 0x83, 0xEC, 0xFA, 0xE4, +0x93, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, 0xC5, +0x83, 0xCC, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, +0xCC, 0xC5, 0x83, 0xCC, 0xDF, 0xE9, 0xDE, 0xE7, +0x80, 0x0D, 0x89, 0x82, 0x8A, 0x83, 0xE4, 0x93, +0xA3, 0xF6, 0x08, 0xDF, 0xF9, 0xEC, 0xFA, 0xA9, +0xF0, 0xED, 0xFB, 0x22, 0x89, 0x82, 0x8A, 0x83, +0xEC, 0xFA, 0xE0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, +0xCC, 0xC5, 0x83, 0xCC, 0xF0, 0xA3, 0xC8, 0xC5, +0x82, 0xC8, 0xCC, 0xC5, 0x83, 0xCC, 0xDF, 0xEA, +0xDE, 0xE8, 0x80, 0xDB, 0x89, 0x82, 0x8A, 0x83, +0xE4, 0x93, 0xA3, 0xF2, 0x08, 0xDF, 0xF9, 0x80, +0xCC, 0x88, 0xF0, 0xEF, 0x60, 0x01, 0x0E, 0x4E, +0x60, 0xC3, 0x88, 0xF0, 0xED, 0x24, 0x02, 0xB4, +0x04, 0x00, 0x50, 0xB9, 0xF5, 0x82, 0xEB, 0x24, +0x02, 0xB4, 0x04, 0x00, 0x50, 0xAF, 0x23, 0x23, +0x45, 0x82, 0x23, 0x90, 0x43, 0xF9, 0x73, 0xC5, +0xF0, 0xF8, 0xA3, 0xE0, 0x28, 0xF0, 0xC5, 0xF0, +0xF8, 0xE5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, +0x83, 0xE0, 0x38, 0xF0, 0x22, 0xEF, 0x4B, 0xFF, +0xEE, 0x4A, 0xFE, 0xED, 0x49, 0xFD, 0xEC, 0x48, +0xFC, 0x22, 0xEB, 0x9F, 0xF5, 0xF0, 0xEA, 0x9E, +0x42, 0xF0, 0xE9, 0x9D, 0x42, 0xF0, 0xE8, 0x9C, +0x45, 0xF0, 0x22, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, +0xA3, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x22, 0xA4, +0x25, 0x82, 0xF5, 0x82, 0xE5, 0xF0, 0x35, 0x83, +0xF5, 0x83, 0x22, 0xE0, 0xFB, 0xA3, 0xE0, 0xFA, +0xA3, 0xE0, 0xF9, 0x22, 0xEB, 0xF0, 0xA3, 0xEA, +0xF0, 0xA3, 0xE9, 0xF0, 0x22, 0xD0, 0x83, 0xD0, +0x82, 0xF8, 0xE4, 0x93, 0x70, 0x12, 0x74, 0x01, +0x93, 0x70, 0x0D, 0xA3, 0xA3, 0x93, 0xF8, 0x74, +0x01, 0x93, 0xF5, 0x82, 0x88, 0x83, 0xE4, 0x73, +0x74, 0x02, 0x93, 0x68, 0x60, 0xEF, 0xA3, 0xA3, +0xA3, 0x80, 0xDF, 0xEF, 0x4E, 0x60, 0x12, 0xEF, +0x60, 0x01, 0x0E, 0xED, 0xBB, 0x01, 0x0B, 0x89, +0x82, 0x8A, 0x83, 0xF0, 0xA3, 0xDF, 0xFC, 0xDE, +0xFA, 0x22, 0x89, 0xF0, 0x50, 0x07, 0xF7, 0x09, +0xDF, 0xFC, 0xA9, 0xF0, 0x22, 0xBB, 0xFE, 0xFC, +0xF3, 0x09, 0xDF, 0xFC, 0xA9, 0xF0, 0x22, 0x02, +0x45, 0x8D, 0x02, 0x41, 0xDD, 0xE4, 0x93, 0xA3, +0xF8, 0xE4, 0x93, 0xA3, 0x40, 0x03, 0xF6, 0x80, +0x01, 0xF2, 0x08, 0xDF, 0xF4, 0x80, 0x29, 0xE4, +0x93, 0xA3, 0xF8, 0x54, 0x07, 0x24, 0x0C, 0xC8, +0xC3, 0x33, 0xC4, 0x54, 0x0F, 0x44, 0x20, 0xC8, +0x83, 0x40, 0x04, 0xF4, 0x56, 0x80, 0x01, 0x46, +0xF6, 0xDF, 0xE4, 0x80, 0x0B, 0x01, 0x02, 0x04, +0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x45, 0xD2, +0xE4, 0x7E, 0x01, 0x93, 0x60, 0xBC, 0xA3, 0xFF, +0x54, 0x3F, 0x30, 0xE5, 0x09, 0x54, 0x1F, 0xFE, +0xE4, 0x93, 0xA3, 0x60, 0x01, 0x0E, 0xCF, 0x54, +0xC0, 0x25, 0xE0, 0x60, 0xA8, 0x40, 0xB8, 0xE4, +0x93, 0xA3, 0xFA, 0xE4, 0x93, 0xA3, 0xF8, 0xE4, +0x93, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCA, 0xC5, +0x83, 0xCA, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, +0xCA, 0xC5, 0x83, 0xCA, 0xDF, 0xE9, 0xDE, 0xE7, +0x80, 0xBE, 0x41, 0x82, 0xB4, 0x00, 0x41, 0x82, +0xB5, 0x00, 0x41, 0x82, 0xC2, 0x00, 0x41, 0x82, +0xC5, 0x00, 0x44, 0x82, 0x86, 0x41, 0x4E, 0x59, +0x00, 0x44, 0x82, 0x82, 0x61, 0x6E, 0x79, 0x00, +0x41, 0x82, 0xC6, 0x00, 0x00, 0x57, 0xFC, 0x58, +0xFD, 0x5F, 0xE3, 0xC0, 0xE0, 0xC0, 0xF0, 0xC0, +0x83, 0xC0, 0x82, 0xC0, 0xD0, 0x75, 0xD0, 0x00, +0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x02, 0xC0, 0x03, +0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, +0x90, 0x01, 0xC4, 0x74, 0xFB, 0xF0, 0x74, 0x45, +0xA3, 0xF0, 0xD1, 0x4A, 0x74, 0xFB, 0x04, 0x90, +0x01, 0xC4, 0xF0, 0x74, 0x45, 0xA3, 0xF0, 0xD0, +0x07, 0xD0, 0x06, 0xD0, 0x05, 0xD0, 0x04, 0xD0, +0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0xD0, +0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0, +0xE0, 0x32, 0x90, 0x00, 0x54, 0xE0, 0x55, 0x35, +0xF5, 0x39, 0xA3, 0xE0, 0x55, 0x36, 0xF5, 0x3A, +0xA3, 0xE0, 0x55, 0x37, 0xF5, 0x3B, 0xA3, 0xE0, +0x55, 0x38, 0xF5, 0x3C, 0xAD, 0x39, 0x7F, 0x54, +0x12, 0x32, 0x1E, 0xAD, 0x3A, 0x7F, 0x55, 0x12, +0x32, 0x1E, 0xAD, 0x3B, 0x7F, 0x56, 0x12, 0x32, +0x1E, 0xAD, 0x3C, 0x7F, 0x57, 0x12, 0x32, 0x1E, +0x53, 0x91, 0xEF, 0x22, 0xC0, 0xE0, 0xC0, 0xF0, +0xC0, 0x83, 0xC0, 0x82, 0xC0, 0xD0, 0x75, 0xD0, +0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x02, 0xC0, +0x03, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, +0x07, 0x90, 0x01, 0xC4, 0x74, 0x84, 0xF0, 0x74, +0x46, 0xA3, 0xF0, 0x12, 0x70, 0x04, 0xE5, 0x41, +0x30, 0xE3, 0x02, 0xF1, 0x51, 0xE5, 0x41, 0x30, +0xE4, 0x02, 0xF1, 0x2D, 0xE5, 0x43, 0x30, 0xE0, +0x03, 0x12, 0x54, 0xEB, 0xE5, 0x43, 0x30, 0xE1, +0x03, 0x12, 0x68, 0x7D, 0xE5, 0x43, 0x30, 0xE2, +0x02, 0xF1, 0x5D, 0xE5, 0x43, 0x30, 0xE3, 0x03, +0x12, 0x4F, 0xCE, 0xE5, 0x43, 0x30, 0xE4, 0x03, +0x12, 0x6A, 0xA0, 0xE5, 0x43, 0x30, 0xE5, 0x02, +0xF1, 0xC9, 0xE5, 0x43, 0x30, 0xE6, 0x03, 0x12, +0x59, 0x4A, 0xE5, 0x43, 0x30, 0xE7, 0x02, 0xF1, +0x6F, 0xE5, 0x44, 0x30, 0xE0, 0x02, 0xF1, 0x40, +0xE5, 0x44, 0x30, 0xE1, 0x02, 0xF1, 0x48, 0x74, +0x84, 0x04, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x46, +0xA3, 0xF0, 0xD0, 0x07, 0xD0, 0x06, 0xD0, 0x05, +0xD0, 0x04, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, +0xD0, 0x00, 0xD0, 0xD0, 0xD0, 0x82, 0xD0, 0x83, +0xD0, 0xF0, 0xD0, 0xE0, 0x32, 0x12, 0x5C, 0xD8, +0x7F, 0x02, 0x8F, 0x0F, 0x7F, 0x02, 0x71, 0x27, +0x90, 0x80, 0x01, 0xE0, 0x45, 0x0F, 0xF0, 0x22, +0xF1, 0x80, 0xBF, 0x03, 0x02, 0xF1, 0x88, 0x22, +0x90, 0x81, 0x30, 0xE0, 0x60, 0x02, 0xF1, 0x90, +0x22, 0x90, 0x80, 0xFC, 0xE0, 0x30, 0xE0, 0x04, +0x7F, 0x20, 0xF1, 0x32, 0x22, 0x90, 0x81, 0xA7, +0xE0, 0x04, 0xF0, 0x90, 0x81, 0x33, 0xE0, 0x64, +0x02, 0x60, 0x03, 0x12, 0x69, 0x14, 0x22, 0xF1, +0xEB, 0x90, 0x05, 0x50, 0xE0, 0x44, 0x01, 0xF0, +0xF1, 0x80, 0xBF, 0x03, 0x02, 0xF1, 0x88, 0x22, +0x90, 0x01, 0x02, 0xE0, 0x54, 0x03, 0xFF, 0x22, +0x90, 0x05, 0x21, 0xE0, 0x54, 0x7F, 0xF0, 0x22, +0x90, 0x81, 0x30, 0xE0, 0x64, 0x01, 0x70, 0x15, +0xF1, 0xE4, 0x60, 0x08, 0xF1, 0xAE, 0x12, 0x4C, +0x7F, 0x02, 0x5B, 0x92, 0x90, 0x81, 0x33, 0xE0, +0x70, 0x03, 0x12, 0x49, 0xED, 0x22, 0xE4, 0xFD, +0x7F, 0x0C, 0x02, 0x49, 0xF1, 0x12, 0x5B, 0x92, +0x90, 0x81, 0x33, 0xE0, 0x64, 0x0C, 0x60, 0x08, +0xF1, 0xAE, 0x12, 0x4C, 0x7F, 0x12, 0x5E, 0xE9, +0x22, 0xE4, 0xFF, 0x12, 0x4E, 0x80, 0xBF, 0x01, +0x11, 0x90, 0x81, 0x30, 0xE0, 0x60, 0x0B, 0xF1, +0xE4, 0x64, 0x02, 0x60, 0x03, 0x02, 0x72, 0x16, +0xF1, 0xB5, 0x22, 0xF0, 0x90, 0x81, 0x2E, 0xE0, +0x54, 0x0F, 0x22, 0xE4, 0xF5, 0x4E, 0xF5, 0x4F, +0xF5, 0x50, 0x22, 0xC0, 0xE0, 0xC0, 0xF0, 0xC0, +0x83, 0xC0, 0x82, 0xC0, 0xD0, 0x75, 0xD0, 0x00, +0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x02, 0xC0, 0x03, +0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, +0x90, 0x01, 0xC4, 0x74, 0xF3, 0xF0, 0x74, 0x47, +0xA3, 0xF0, 0x12, 0x70, 0x31, 0xE5, 0x49, 0x30, +0xE1, 0x02, 0x11, 0xCF, 0xE5, 0x49, 0x30, 0xE2, +0x03, 0x12, 0x59, 0xBB, 0xE5, 0x49, 0x30, 0xE3, +0x03, 0x12, 0x6D, 0x9D, 0xE5, 0x49, 0x30, 0xE4, +0x03, 0x12, 0x6B, 0x59, 0xE5, 0x4A, 0x30, 0xE0, +0x03, 0x12, 0x6C, 0x6C, 0xE5, 0x4B, 0x30, 0xE5, +0x03, 0x12, 0x6B, 0x35, 0xE5, 0x4C, 0x30, 0xE1, +0x05, 0x7F, 0x04, 0x12, 0x47, 0x32, 0xE5, 0x4C, +0x30, 0xE4, 0x02, 0x11, 0x93, 0xE5, 0x4C, 0x30, +0xE5, 0x03, 0x12, 0x5C, 0xB4, 0xE5, 0x4C, 0x30, +0xE6, 0x03, 0x12, 0x5C, 0x3E, 0x74, 0xF3, 0x04, +0x90, 0x01, 0xC4, 0xF0, 0x74, 0x47, 0xA3, 0xF0, +0xD0, 0x07, 0xD0, 0x06, 0xD0, 0x05, 0xD0, 0x04, +0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, +0xD0, 0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, +0xD0, 0xE0, 0x32, 0x12, 0x6E, 0x2E, 0xF1, 0xB5, +0x7F, 0x01, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x90, 0x81, 0x2D, 0xE0, 0xFE, 0xC3, 0x13, +0x30, 0xE0, 0x1F, 0x90, 0x82, 0x69, 0x74, 0x1E, +0xF0, 0x90, 0x82, 0x77, 0x74, 0x01, 0xF0, 0x90, +0x82, 0x6B, 0xEF, 0xF0, 0x7B, 0x01, 0x7A, 0x82, +0x79, 0x69, 0x12, 0x60, 0xAB, 0x7F, 0x04, 0x12, +0x47, 0x32, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, +0x81, 0x30, 0xE0, 0x60, 0x03, 0x12, 0x69, 0xF5, +0x90, 0x81, 0x94, 0xE0, 0x30, 0xE0, 0x49, 0xC4, +0x54, 0x0F, 0x20, 0xE0, 0x17, 0xE4, 0xF5, 0x1D, +0x90, 0x81, 0x96, 0x31, 0x30, 0x91, 0x7D, 0xF1, +0xE5, 0x30, 0xE0, 0x06, 0x7D, 0x0C, 0x7F, 0x01, +0x71, 0xE8, 0xE1, 0xF3, 0x90, 0x81, 0x94, 0xE0, +0xC4, 0x54, 0x0F, 0x30, 0xE0, 0x22, 0xE4, 0xF5, +0x1D, 0x90, 0x81, 0x97, 0x31, 0x30, 0x90, 0x81, +0x94, 0xE0, 0x54, 0xEF, 0xF0, 0xE0, 0xC3, 0x13, +0x30, 0xE0, 0x06, 0x7D, 0x04, 0x7F, 0x01, 0x61, +0xE8, 0x7B, 0x31, 0xF1, 0xED, 0x12, 0x64, 0x11, +0x22, 0xF0, 0xE4, 0xF5, 0x1D, 0x90, 0x81, 0x8E, +0xE0, 0xF5, 0x1E, 0xE4, 0xFB, 0xFD, 0x7F, 0x54, +0x7E, 0x01, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x8E, 0x19, 0x8F, 0x1A, 0xE5, 0x1E, 0x54, +0x07, 0xC4, 0x33, 0x54, 0xE0, 0x85, 0x19, 0x83, +0x85, 0x1A, 0x82, 0xF0, 0xE5, 0x1D, 0x31, 0x9A, +0xE5, 0x1E, 0x13, 0x13, 0x13, 0x54, 0x1F, 0x4F, +0xA3, 0xF0, 0xEB, 0x31, 0x9A, 0xE5, 0x1D, 0x13, +0x13, 0x13, 0x54, 0x1F, 0x4F, 0x31, 0x91, 0xF0, +0xBD, 0x01, 0x0D, 0x85, 0x1A, 0x82, 0x8E, 0x83, +0xA3, 0xA3, 0xA3, 0x74, 0x03, 0xF0, 0x80, 0x06, +0x31, 0x91, 0xA3, 0x74, 0x01, 0xF0, 0x31, 0x91, +0xA3, 0x74, 0x05, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x85, 0x1A, 0x82, 0x85, 0x19, 0x83, 0xA3, +0xA3, 0x22, 0x54, 0x07, 0xC4, 0x33, 0x54, 0xE0, +0xFF, 0x22, 0x90, 0x81, 0x34, 0xE0, 0x44, 0x10, +0xF0, 0x90, 0x81, 0x39, 0xE0, 0x60, 0x04, 0x64, +0x01, 0x70, 0x15, 0xE4, 0xF5, 0x1D, 0x90, 0x81, +0x39, 0xE0, 0xFF, 0x90, 0x81, 0x38, 0xE0, 0x2F, +0x31, 0x31, 0x90, 0x81, 0x39, 0xE0, 0x80, 0x11, +0xE4, 0xF5, 0x1D, 0x12, 0x7C, 0x46, 0xFF, 0x90, +0x81, 0x38, 0xE0, 0x2F, 0x31, 0x31, 0x12, 0x7C, +0x46, 0xFF, 0x90, 0x81, 0x38, 0xE0, 0x2F, 0x90, +0x81, 0x49, 0xF0, 0x90, 0x81, 0x33, 0xE0, 0x20, +0xE2, 0x02, 0x31, 0xED, 0x22, 0x7D, 0x01, 0x7F, +0x04, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x90, 0x82, 0xC1, 0xED, 0xF0, 0x90, 0x81, 0x2B, +0xE0, 0xFE, 0xC4, 0x13, 0x13, 0x54, 0x03, 0x30, +0xE0, 0x02, 0x61, 0x39, 0xEE, 0x12, 0x5C, 0x37, +0x30, 0xE0, 0x02, 0x61, 0x39, 0x90, 0x81, 0x33, +0xE0, 0xFE, 0x6F, 0x70, 0x02, 0x61, 0x39, 0xEF, +0x70, 0x02, 0x41, 0xAD, 0x24, 0xFE, 0x70, 0x02, +0x41, 0xE7, 0x24, 0xFE, 0x60, 0x47, 0x24, 0xFC, +0x70, 0x02, 0x61, 0x22, 0x24, 0xFC, 0x60, 0x02, +0x61, 0x32, 0xEE, 0xB4, 0x0E, 0x02, 0x71, 0x95, +0x90, 0x81, 0x33, 0xE0, 0x70, 0x04, 0x7F, 0x01, +0x71, 0xD5, 0x90, 0x81, 0x33, 0xE0, 0xB4, 0x06, +0x02, 0x71, 0xB2, 0x90, 0x81, 0x33, 0xE0, 0xB4, +0x04, 0x0D, 0x90, 0x82, 0xC1, 0xE0, 0xFF, 0x60, +0x04, 0xB1, 0xD5, 0x80, 0x02, 0xB1, 0xAE, 0x90, +0x81, 0x33, 0xE0, 0x64, 0x08, 0x60, 0x02, 0x61, +0x32, 0xB1, 0x49, 0x61, 0x32, 0x90, 0x81, 0x33, +0xE0, 0x70, 0x04, 0x7F, 0x01, 0x71, 0xD5, 0x90, +0x81, 0x33, 0xE0, 0xB4, 0x06, 0x02, 0x71, 0xB2, +0x90, 0x81, 0x33, 0xE0, 0xB4, 0x0E, 0x07, 0x71, +0x3E, 0xBF, 0x01, 0x02, 0x71, 0x95, 0x90, 0x81, +0x33, 0xE0, 0x64, 0x0C, 0x60, 0x02, 0x61, 0x32, +0x71, 0x3E, 0xEF, 0x64, 0x01, 0x60, 0x02, 0x61, +0x32, 0x91, 0x50, 0x61, 0x32, 0x90, 0x81, 0x33, +0xE0, 0xB4, 0x0E, 0x07, 0x71, 0x3E, 0xBF, 0x01, +0x02, 0x71, 0x95, 0x90, 0x81, 0x33, 0xE0, 0xB4, +0x06, 0x02, 0x71, 0xB2, 0x90, 0x81, 0x33, 0xE0, +0xB4, 0x0C, 0x07, 0x71, 0x3E, 0xBF, 0x01, 0x02, +0x91, 0x50, 0x90, 0x81, 0x33, 0xE0, 0x64, 0x04, +0x70, 0x58, 0x12, 0x6C, 0x06, 0xEF, 0x64, 0x01, +0x70, 0x50, 0x12, 0x64, 0xC5, 0x80, 0x4B, 0x90, +0x81, 0x33, 0xE0, 0xB4, 0x0E, 0x07, 0x71, 0x3E, +0xBF, 0x01, 0x02, 0x71, 0x95, 0x90, 0x81, 0x33, +0xE0, 0xB4, 0x06, 0x02, 0x71, 0xB2, 0x90, 0x81, +0x33, 0xE0, 0xB4, 0x0C, 0x07, 0x71, 0x3E, 0xBF, +0x01, 0x02, 0x91, 0x50, 0x90, 0x81, 0x33, 0xE0, +0x70, 0x04, 0x7F, 0x01, 0x71, 0xD5, 0x90, 0x81, +0x33, 0xE0, 0xB4, 0x04, 0x15, 0x12, 0x72, 0xCC, +0x80, 0x10, 0x90, 0x81, 0x33, 0xE0, 0xB4, 0x0C, +0x09, 0x12, 0x69, 0xEB, 0x30, 0xE0, 0x03, 0x12, +0x65, 0x90, 0x90, 0x81, 0x33, 0x12, 0x7C, 0x39, +0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x6D, 0x84, +0xEF, 0x64, 0x01, 0x60, 0x05, 0x75, 0x1F, 0x01, +0x80, 0x30, 0x12, 0x6D, 0x69, 0x30, 0xE0, 0x05, +0x75, 0x1F, 0x02, 0x80, 0x25, 0x90, 0x81, 0x32, +0xE0, 0xD3, 0x94, 0x04, 0x40, 0x05, 0x75, 0x1F, +0x08, 0x80, 0x17, 0x90, 0x81, 0x94, 0xE0, 0x30, +0xE0, 0x0B, 0xC4, 0x54, 0x0F, 0x30, 0xE0, 0x05, +0x75, 0x1F, 0x11, 0x80, 0x05, 0x12, 0x6D, 0x48, +0x80, 0x0E, 0x90, 0x01, 0xB9, 0x74, 0x02, 0xF0, +0x90, 0x01, 0xB8, 0xE5, 0x1F, 0xF0, 0x7F, 0x00, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x81, 0x2C, +0xE0, 0xC3, 0x13, 0x20, 0xE0, 0x04, 0x7D, 0x0C, +0x80, 0x05, 0x12, 0x73, 0x6C, 0x7D, 0x04, 0x7F, +0x01, 0x71, 0xE8, 0xE4, 0xFB, 0xFD, 0x7F, 0xFF, +0x81, 0x84, 0x90, 0x81, 0x2C, 0xE0, 0x90, 0x06, +0x04, 0x20, 0xE0, 0x08, 0xE0, 0x44, 0x40, 0xF0, +0x7D, 0x04, 0x80, 0x06, 0xE0, 0x54, 0x7F, 0xF0, +0x7D, 0x0C, 0x7F, 0x01, 0x71, 0xE8, 0xE4, 0xFB, +0xFD, 0x7F, 0xFF, 0x81, 0x84, 0x90, 0x82, 0xC0, +0xEF, 0xF0, 0xB1, 0x51, 0x90, 0x82, 0xC0, 0xE0, +0x60, 0x02, 0x91, 0x7F, 0x7D, 0x04, 0x7F, 0x01, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xAC, +0x07, 0xEF, 0x14, 0x60, 0x15, 0x14, 0x60, 0x19, +0x24, 0x02, 0x70, 0x1A, 0xED, 0x54, 0x01, 0xFE, +0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFE, 0x4E, 0xF0, +0x80, 0x0C, 0x90, 0x81, 0x33, 0xED, 0xF0, 0x80, +0x05, 0x90, 0x81, 0x32, 0xED, 0xF0, 0x90, 0x00, +0x8F, 0xE0, 0x30, 0xE4, 0x2E, 0xEC, 0x14, 0x60, +0x07, 0x14, 0x60, 0x1D, 0x24, 0x02, 0x70, 0x23, +0x90, 0x81, 0x2B, 0xE0, 0x54, 0x01, 0xC4, 0x33, +0x33, 0x33, 0x54, 0x80, 0xFF, 0x90, 0x81, 0x33, +0xE0, 0x54, 0x7F, 0x4F, 0xFD, 0x7F, 0x88, 0x80, +0x07, 0x90, 0x81, 0x32, 0xE0, 0xFD, 0x7F, 0x89, +0x12, 0x32, 0x1E, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0xF1, 0xC6, 0x70, 0x28, 0x90, 0x81, 0x2C, 0xE0, +0x54, 0xFD, 0xF0, 0x7B, 0x2C, 0x12, 0x72, 0xD7, +0x7D, 0x08, 0x7F, 0x01, 0x12, 0x5E, 0xED, 0xBF, +0x01, 0x0D, 0x90, 0x81, 0x2B, 0xE0, 0x44, 0x80, +0xF0, 0x7D, 0x0E, 0x7F, 0x01, 0x61, 0xE8, 0x12, +0x5E, 0x0F, 0x04, 0xF0, 0x22, 0xB1, 0x51, 0xE4, +0xFB, 0xFD, 0x7F, 0xFF, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x90, 0x05, 0x22, 0xED, 0xF0, +0x90, 0x80, 0x05, 0xEB, 0xF0, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0x7E, 0x00, 0x7F, 0x62, 0x7D, 0x00, +0x7B, 0x01, 0x7A, 0x81, 0x79, 0x2B, 0x12, 0x45, +0x23, 0x90, 0x81, 0x2F, 0x74, 0x02, 0xF0, 0x90, +0x81, 0x36, 0x14, 0xF0, 0xA3, 0xF0, 0xA3, 0x74, +0x10, 0xF0, 0x90, 0x81, 0x3C, 0xE4, 0xF0, 0xA3, +0x74, 0x05, 0x12, 0x7C, 0x1C, 0xE4, 0xFD, 0xFF, +0x71, 0xE8, 0x7D, 0x0C, 0x7F, 0x02, 0x71, 0xE8, +0x7D, 0x0C, 0x7F, 0x01, 0x71, 0xE8, 0x90, 0x80, +0x07, 0xE0, 0xFF, 0xB4, 0x01, 0x08, 0x90, 0x81, +0x3B, 0x74, 0x99, 0xF0, 0x80, 0x29, 0xEF, 0xB4, +0x03, 0x08, 0x90, 0x81, 0x3B, 0x74, 0x90, 0xF0, +0x80, 0x1D, 0x90, 0x81, 0x3B, 0x74, 0x40, 0xF0, +0x90, 0x00, 0x2C, 0xE0, 0x54, 0x0F, 0xFF, 0xBF, +0x05, 0x08, 0x90, 0x81, 0x4D, 0x74, 0x02, 0xF0, +0x80, 0x05, 0xE4, 0x90, 0x81, 0x4D, 0xF0, 0x90, +0x81, 0x8D, 0x74, 0x02, 0xF0, 0xA3, 0x74, 0x0F, +0xF0, 0xA3, 0xE0, 0x54, 0x01, 0x44, 0x28, 0xF0, +0xA3, 0x74, 0x07, 0x12, 0x7C, 0x1C, 0x7E, 0x00, +0x7F, 0x02, 0x7D, 0x00, 0x7B, 0x01, 0x7A, 0x81, +0x79, 0x91, 0x12, 0x45, 0x23, 0x12, 0x73, 0x5C, +0x12, 0x7C, 0x63, 0x7B, 0x56, 0xE4, 0xFD, 0x7F, +0xFF, 0x91, 0x84, 0xE4, 0x90, 0x81, 0x93, 0xF0, +0x22, 0x91, 0x7D, 0x7D, 0x0C, 0x7F, 0x01, 0x61, +0xE8, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x90, 0x01, 0x01, 0xE0, 0x44, 0x02, 0xF0, 0x90, +0x01, 0x00, 0x74, 0xFF, 0xF0, 0x90, 0x06, 0xB7, +0x74, 0x09, 0xF0, 0x90, 0x06, 0xB4, 0x74, 0x86, +0xF0, 0x12, 0x65, 0x6E, 0x54, 0x7F, 0xFC, 0x90, +0x82, 0xA9, 0x12, 0x20, 0xCE, 0x90, 0x82, 0xA9, +0x12, 0x63, 0x80, 0x7F, 0x7C, 0x12, 0x64, 0xBC, +0x12, 0x20, 0xDA, 0xCC, 0xC0, 0x00, 0xC0, 0x12, +0x64, 0xBA, 0x12, 0x20, 0xDA, 0x00, 0xC0, 0x00, +0x14, 0x12, 0x65, 0x77, 0x12, 0x20, 0xDA, 0x00, +0x03, 0x3E, 0x60, 0xE4, 0xFD, 0xFF, 0x12, 0x65, +0x4C, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x12, 0x73, +0x5C, 0x91, 0x7F, 0x7D, 0x0C, 0x7F, 0x01, 0x61, +0xE8, 0x90, 0x81, 0x94, 0xE0, 0x30, 0xE0, 0x14, +0x90, 0x01, 0x57, 0xE4, 0xF0, 0x91, 0x7D, 0xF1, +0xE5, 0x30, 0xE0, 0x06, 0x7D, 0x0C, 0x7F, 0x01, +0x71, 0xE8, 0xF1, 0xF3, 0x22, 0xEF, 0x60, 0x33, +0xF1, 0xC6, 0x70, 0x2F, 0x90, 0x81, 0x2C, 0xE0, +0x54, 0xFE, 0xF0, 0x7B, 0x2B, 0x7D, 0x0F, 0x7F, +0xFF, 0x91, 0x84, 0x90, 0x06, 0x04, 0xE0, 0x54, +0xBF, 0xF0, 0x12, 0x5E, 0xE9, 0xBF, 0x01, 0x0D, +0x90, 0x81, 0x2B, 0xE0, 0x44, 0x40, 0xF0, 0x7D, +0x06, 0x7F, 0x01, 0x61, 0xE8, 0x12, 0x5E, 0x0F, +0x74, 0x08, 0xF0, 0x22, 0xEF, 0x70, 0x38, 0x7D, +0x78, 0x7F, 0x02, 0x12, 0x69, 0x0A, 0x7D, 0x02, +0x7F, 0x03, 0x12, 0x69, 0x0A, 0x7D, 0xC8, 0x7F, +0x02, 0x12, 0x6A, 0x79, 0x12, 0x6A, 0xC3, 0xF0, +0xE4, 0xFF, 0xD1, 0x80, 0xEF, 0x70, 0x0C, 0xB1, +0x51, 0xB1, 0xAE, 0x12, 0x73, 0x64, 0x54, 0x7F, +0xF0, 0x80, 0x06, 0x7D, 0x01, 0x7F, 0x0C, 0x31, +0xF1, 0x12, 0x5F, 0xD3, 0x02, 0x7C, 0x63, 0x90, +0x01, 0x36, 0x74, 0x78, 0xF0, 0xA3, 0x74, 0x02, +0xF0, 0x7D, 0x78, 0xFF, 0xF1, 0xB9, 0x7D, 0x02, +0x7F, 0x03, 0xF1, 0xB9, 0x90, 0x06, 0x0A, 0xE0, +0x44, 0x07, 0x12, 0x67, 0xAA, 0xE4, 0xFF, 0xD1, +0x80, 0xBF, 0x01, 0x10, 0x12, 0x6A, 0x62, 0x90, +0x81, 0x33, 0xE0, 0x20, 0xE2, 0x09, 0x7D, 0x01, +0x7F, 0x04, 0x21, 0xF1, 0x12, 0x67, 0x7D, 0x22, +0x12, 0x6C, 0xFD, 0xFE, 0xEF, 0x54, 0x07, 0xFF, +0x74, 0x22, 0x2E, 0x12, 0x6F, 0x96, 0xFD, 0x7C, +0x00, 0x12, 0x5E, 0x06, 0x80, 0x05, 0xC3, 0x33, +0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, 0xEE, 0x5C, +0xFE, 0xEF, 0x5D, 0x4E, 0x7F, 0x00, 0x60, 0x02, +0x7F, 0x01, 0x22, 0x8B, 0x55, 0x8A, 0x56, 0x89, +0x57, 0x12, 0x57, 0x38, 0xFF, 0xF5, 0x59, 0x12, +0x1F, 0xA4, 0xFE, 0xC3, 0x13, 0x30, 0xE0, 0x07, +0x12, 0x57, 0x92, 0xF5, 0x5A, 0x80, 0x02, 0x8F, +0x5A, 0x85, 0x59, 0x58, 0xE5, 0x58, 0xD3, 0x95, +0x5A, 0x50, 0x25, 0xAB, 0x55, 0xAA, 0x56, 0xA9, +0x57, 0x12, 0x1F, 0xA4, 0x54, 0x01, 0xFD, 0xAF, +0x58, 0x12, 0x53, 0x0C, 0xAF, 0x58, 0xD1, 0x80, +0xEF, 0xAF, 0x58, 0x70, 0x05, 0x12, 0x68, 0x03, +0x80, 0x02, 0xF1, 0xEC, 0x05, 0x58, 0x80, 0xD4, +0xE5, 0x59, 0x70, 0x13, 0xFF, 0xD1, 0x80, 0xEF, +0x70, 0x0D, 0xB1, 0x51, 0xB1, 0xAE, 0x12, 0x5F, +0xD3, 0x54, 0xBF, 0xF0, 0x54, 0x7F, 0xF0, 0x22, +0x90, 0x81, 0xCD, 0x12, 0x44, 0xF4, 0x90, 0x81, +0xCC, 0xEF, 0xF0, 0x12, 0x44, 0xFD, 0x4F, 0x4F, +0x00, 0x4F, 0x54, 0x01, 0x4F, 0x58, 0x03, 0x4F, +0x5D, 0x04, 0x4F, 0x62, 0x08, 0x4F, 0x67, 0x09, +0x4F, 0x6C, 0x0A, 0x4F, 0x71, 0x12, 0x4F, 0x76, +0x13, 0x4F, 0x7B, 0x14, 0x4F, 0x80, 0x20, 0x4F, +0x85, 0x25, 0x4F, 0x8A, 0x26, 0x4F, 0x8F, 0xC2, +0x4F, 0x94, 0xC4, 0x00, 0x00, 0x4F, 0x99, 0xF1, +0xA9, 0x02, 0x57, 0x98, 0xF1, 0xA9, 0xC1, 0xAB, +0xF1, 0xA9, 0x02, 0x73, 0x78, 0xF1, 0xA9, 0x02, +0x57, 0x3E, 0xF1, 0xA9, 0x02, 0x56, 0x1D, 0xF1, +0xA9, 0x02, 0x65, 0x9E, 0xF1, 0xA9, 0x02, 0x65, +0xB6, 0xF1, 0xA9, 0x02, 0x61, 0xC1, 0xF1, 0xA9, +0x02, 0x5B, 0xBE, 0xF1, 0xA9, 0x02, 0x65, 0xC2, +0xF1, 0xA9, 0x02, 0x5E, 0x19, 0xF1, 0xA9, 0x02, +0x65, 0xD1, 0xF1, 0xA9, 0x02, 0x65, 0xD9, 0xF1, +0xA9, 0x02, 0x67, 0xD0, 0xF1, 0xA9, 0x02, 0x67, +0xD8, 0x90, 0x01, 0xC0, 0xE0, 0x44, 0x01, 0xF0, +0x90, 0x81, 0xCC, 0xE0, 0x90, 0x01, 0xC2, 0xF0, +0x22, 0x90, 0x81, 0xCD, 0x02, 0x44, 0xEB, 0x7D, +0x01, 0x7F, 0x02, 0xF1, 0xB9, 0x7D, 0x02, 0x7F, +0x02, 0x74, 0x3D, 0x2F, 0xF8, 0xE6, 0x4D, 0xFE, +0xF6, 0x74, 0x30, 0x02, 0x6A, 0x81, 0xE4, 0xFF, +0xD1, 0x80, 0xEF, 0x64, 0x01, 0x22, 0xF1, 0xC6, +0x70, 0x12, 0x90, 0x81, 0x30, 0xE0, 0x60, 0x0C, +0x90, 0x81, 0x34, 0xE0, 0x20, 0xE4, 0x05, 0x12, +0x6A, 0xC3, 0x31, 0x29, 0x22, 0x90, 0x81, 0x94, +0xE0, 0xC3, 0x13, 0x22, 0x22, 0x7D, 0xFF, 0x7F, +0xFF, 0x81, 0x84, 0x90, 0x81, 0x94, 0xE0, 0x44, +0x10, 0xF0, 0x22, 0x90, 0x00, 0xF7, 0xE0, 0x20, +0xE7, 0x09, 0xE0, 0x7F, 0x01, 0x20, 0xE6, 0x0C, +0x7F, 0x02, 0x22, 0x90, 0x00, 0xF7, 0xE0, 0x30, +0xE6, 0x02, 0x7F, 0x03, 0x22, 0x12, 0x4F, 0xFB, +0x90, 0x80, 0x07, 0xEF, 0xF0, 0x11, 0x36, 0x90, +0x01, 0x64, 0x74, 0x01, 0xF0, 0x90, 0x00, 0x12, +0xE0, 0x54, 0xC7, 0x44, 0x20, 0xFD, 0x7F, 0x12, +0x12, 0x32, 0x1E, 0x02, 0x2D, 0xA7, 0x90, 0x00, +0x08, 0xE0, 0x54, 0xEF, 0xF0, 0x11, 0x6F, 0x11, +0xA7, 0x12, 0x6F, 0x9F, 0x12, 0x6F, 0xBE, 0xE4, +0xF5, 0x35, 0xF5, 0x37, 0xF5, 0x36, 0xF5, 0x37, +0x75, 0x38, 0x80, 0xAD, 0x35, 0x7F, 0x50, 0x12, +0x32, 0x1E, 0xAD, 0x36, 0x7F, 0x51, 0x12, 0x32, +0x1E, 0xAD, 0x37, 0x7F, 0x52, 0x12, 0x32, 0x1E, +0xAD, 0x38, 0x7F, 0x53, 0x02, 0x32, 0x1E, 0x90, +0x01, 0x30, 0xE4, 0x11, 0x9F, 0x90, 0x01, 0x38, +0x11, 0x9F, 0xFD, 0x7F, 0x50, 0x12, 0x32, 0x1E, +0xE4, 0xFD, 0x7F, 0x51, 0x12, 0x32, 0x1E, 0xE4, +0xFD, 0x7F, 0x52, 0x12, 0x32, 0x1E, 0xE4, 0xFD, +0x7F, 0x53, 0x02, 0x32, 0x1E, 0xE4, 0x90, 0x81, +0xD8, 0xF0, 0x90, 0x82, 0x43, 0xF0, 0xA3, 0xF0, +0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0x22, 0x90, +0x01, 0x34, 0x74, 0xFF, 0x11, 0x9F, 0x90, 0x01, +0x3C, 0x11, 0x9F, 0xFD, 0x7F, 0x54, 0x12, 0x32, +0x1E, 0x7D, 0xFF, 0x7F, 0x55, 0x12, 0x32, 0x1E, +0x7D, 0xFF, 0x7F, 0x56, 0x12, 0x32, 0x1E, 0x7D, +0xFF, 0x7F, 0x57, 0x02, 0x32, 0x1E, 0x90, 0x80, +0xFC, 0xE0, 0x54, 0xFE, 0x71, 0x6B, 0x90, 0x80, +0xFC, 0xE0, 0x54, 0xFD, 0xF0, 0x54, 0xFB, 0xF0, +0x54, 0xF7, 0xF0, 0x54, 0xEF, 0xF0, 0xE4, 0x90, +0x80, 0xFF, 0x11, 0x9D, 0x11, 0xA0, 0x90, 0x81, +0x1E, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0x22, 0x90, +0x82, 0x53, 0x51, 0xC8, 0xE4, 0x11, 0xA0, 0xFC, +0xA3, 0xF0, 0x31, 0xA4, 0x90, 0x82, 0x58, 0xEF, +0xF0, 0x51, 0x7F, 0xA3, 0xE0, 0x04, 0xFD, 0x31, +0xA4, 0xAC, 0x07, 0x90, 0x82, 0x58, 0xE0, 0x30, +0xE7, 0x08, 0x90, 0x82, 0x56, 0x74, 0x02, 0xF0, +0x80, 0x05, 0xE4, 0x90, 0x82, 0x56, 0xF0, 0xEC, +0x30, 0xE6, 0x34, 0x51, 0x7F, 0x7D, 0x02, 0x31, +0xA4, 0xEF, 0x54, 0x70, 0xC4, 0x54, 0x0F, 0x90, +0x82, 0x59, 0xF0, 0x14, 0x60, 0x11, 0x14, 0x60, +0x16, 0x24, 0xFE, 0x60, 0x12, 0x14, 0x60, 0x07, +0x14, 0x60, 0x04, 0x24, 0x06, 0x80, 0x10, 0x90, +0x82, 0x57, 0x74, 0x04, 0xF0, 0x80, 0x0D, 0x90, +0x82, 0x57, 0x74, 0x08, 0xF0, 0x80, 0x05, 0xE4, +0x90, 0x82, 0x57, 0xF0, 0x90, 0x82, 0x56, 0xE0, +0x24, 0x18, 0xFF, 0xA3, 0xE0, 0x2F, 0xFF, 0x22, +0x90, 0x82, 0x4F, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, +0xA3, 0xED, 0xF0, 0x11, 0xF7, 0x90, 0x82, 0x52, +0xEF, 0xF0, 0x90, 0x82, 0x51, 0xE0, 0xFD, 0x90, +0x82, 0x50, 0xE0, 0x2D, 0xFD, 0x90, 0x82, 0x4F, +0xE0, 0x34, 0x00, 0xFC, 0x7E, 0x00, 0xED, 0x2F, +0xFF, 0xEE, 0x3C, 0xCF, 0x24, 0x06, 0xCF, 0x34, +0x00, 0xFE, 0xE4, 0xFD, 0xAB, 0x07, 0xAA, 0x06, +0xED, 0x2B, 0xFB, 0xE4, 0x3A, 0xFA, 0xC3, 0x90, +0x80, 0xFB, 0xE0, 0x9B, 0x90, 0x80, 0xFA, 0xE0, +0x9A, 0x50, 0x0A, 0xA3, 0x12, 0x7C, 0x2C, 0xEB, +0x9F, 0xFB, 0xEA, 0x9E, 0xFA, 0xEA, 0x90, 0xFD, +0x11, 0xF0, 0xAF, 0x03, 0x74, 0x00, 0x2F, 0x12, +0x7C, 0x51, 0xFF, 0x22, 0x31, 0x70, 0xEF, 0x64, +0x08, 0x70, 0x34, 0x51, 0x12, 0x24, 0x07, 0x31, +0x9E, 0xEF, 0x70, 0x2B, 0x51, 0x12, 0x24, 0x1D, +0x31, 0x9E, 0xBF, 0x44, 0x0B, 0x51, 0x12, 0x24, +0x1F, 0x31, 0x9E, 0xEF, 0x64, 0x43, 0x60, 0x14, +0x51, 0x12, 0x24, 0x1D, 0x31, 0x9E, 0xEF, 0x64, +0x43, 0x70, 0x0C, 0x51, 0x12, 0x24, 0x1F, 0x31, +0x9E, 0xBF, 0x44, 0x03, 0x7F, 0x01, 0x22, 0x7F, +0x00, 0x22, 0x90, 0x82, 0x51, 0xE0, 0xFF, 0x90, +0x82, 0x50, 0xE0, 0x2F, 0xFF, 0x90, 0x82, 0x4F, +0xE0, 0x34, 0x00, 0xFE, 0x90, 0x82, 0x52, 0xE0, +0x7C, 0x00, 0x2F, 0xFF, 0xEC, 0x3E, 0xCF, 0x22, +0x31, 0x70, 0xEF, 0x64, 0x08, 0x70, 0x20, 0x51, +0x12, 0x24, 0x07, 0x31, 0x9E, 0xEF, 0x64, 0x06, +0x70, 0x15, 0x51, 0x12, 0x24, 0x0E, 0x31, 0x9E, +0xEF, 0x70, 0x0C, 0x51, 0x12, 0x24, 0x0F, 0x31, +0x9E, 0xBF, 0x01, 0x03, 0x7F, 0x01, 0x22, 0x7F, +0x00, 0x22, 0x24, 0x0A, 0xFC, 0xED, 0x2C, 0xFD, +0x31, 0xA4, 0x90, 0x81, 0xD0, 0xA3, 0xE0, 0xFE, +0x90, 0x81, 0xD6, 0xE0, 0x2E, 0x24, 0x24, 0xF5, +0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xEF, 0xF0, +0x90, 0x81, 0xD6, 0xE0, 0x04, 0xF0, 0x22, 0x90, +0x82, 0x53, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x22, +0x90, 0x82, 0x4F, 0x51, 0xC8, 0x31, 0xA4, 0xEF, +0x54, 0x0C, 0x64, 0x08, 0x70, 0x2F, 0x90, 0x82, +0x52, 0xF0, 0x90, 0x82, 0x52, 0xE0, 0xFD, 0xC3, +0x94, 0x06, 0x50, 0x21, 0x90, 0x82, 0x4F, 0xE0, +0xFE, 0xA3, 0xE0, 0xFF, 0xA3, 0xE0, 0x24, 0x10, +0xFC, 0xED, 0x2C, 0xFD, 0x31, 0xA4, 0xEF, 0xF4, +0x60, 0x03, 0x7F, 0x01, 0x22, 0x90, 0x82, 0x52, +0xE0, 0x04, 0xF0, 0x80, 0xD5, 0x7F, 0x00, 0x22, +0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xA3, 0xED, 0xF0, +0x22, 0xFD, 0x31, 0xA4, 0x90, 0x81, 0xD7, 0xE0, +0x22, 0x24, 0x1A, 0xFC, 0xED, 0x2C, 0xFD, 0x31, +0xA4, 0x90, 0x81, 0xD6, 0xE0, 0x24, 0xEE, 0xF5, +0x82, 0xE4, 0x34, 0x81, 0x22, 0x71, 0x09, 0x12, +0x67, 0xED, 0x12, 0x4C, 0x9A, 0x12, 0x72, 0xE9, +0x71, 0x5B, 0x12, 0x73, 0xD8, 0x11, 0xCE, 0x12, +0x72, 0xAF, 0x90, 0x81, 0xA9, 0x74, 0x01, 0xF0, +0x22, 0xE4, 0xFD, 0xFF, 0x12, 0x6C, 0xFD, 0xFE, +0xEF, 0x54, 0x07, 0xFF, 0xED, 0x70, 0x14, 0x71, +0x52, 0xF5, 0x83, 0xC0, 0x83, 0xC0, 0x82, 0x71, +0x4A, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xF4, +0x5E, 0x80, 0x11, 0x71, 0x52, 0xF5, 0x83, 0xC0, +0x83, 0xC0, 0x82, 0x71, 0x4A, 0x80, 0x02, 0xC3, +0x33, 0xD8, 0xFC, 0x4E, 0xD0, 0x82, 0xD0, 0x83, +0xF0, 0x12, 0x6F, 0x42, 0x90, 0x81, 0x2A, 0xEF, +0xF0, 0x22, 0xE0, 0xFE, 0x74, 0x01, 0xA8, 0x07, +0x08, 0x22, 0x74, 0x22, 0x2E, 0xF5, 0x82, 0xE4, +0x34, 0x81, 0x22, 0x90, 0x81, 0x9D, 0xE0, 0x54, +0xFE, 0xF0, 0x54, 0x7F, 0xF0, 0x54, 0xFB, 0xF0, +0xA3, 0x74, 0x0A, 0xF0, 0xE4, 0xA3, 0xF0, 0xA3, +0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x90, 0x82, 0xA1, 0xEE, 0xF0, 0xA3, 0xEF, +0x71, 0x6B, 0x90, 0x82, 0xA1, 0xE0, 0xFE, 0xA3, +0xE0, 0xF5, 0x82, 0x8E, 0x83, 0xE0, 0x60, 0x23, +0xC3, 0x90, 0x82, 0xA4, 0xE0, 0x94, 0xE8, 0x90, +0x82, 0xA3, 0xE0, 0x94, 0x03, 0x40, 0x0B, 0x90, +0x01, 0xC0, 0xE0, 0x44, 0x80, 0xF0, 0x7F, 0x00, +0x80, 0x0B, 0x90, 0x82, 0xA3, 0x71, 0xBD, 0xF1, +0x2E, 0x80, 0xCF, 0x7F, 0x01, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0x90, 0x82, 0x4D, 0xE4, 0x75, 0xF0, +0x01, 0x02, 0x44, 0x9F, 0x90, 0x81, 0xC8, 0xEF, +0x71, 0x6B, 0x90, 0x01, 0x09, 0xE0, 0x7F, 0x00, +0x30, 0xE7, 0x02, 0x7F, 0x01, 0x90, 0x81, 0xC8, +0xE0, 0x6F, 0x60, 0x35, 0xC3, 0x90, 0x81, 0xCA, +0xE0, 0x94, 0x88, 0x90, 0x81, 0xC9, 0xE0, 0x94, +0x13, 0x40, 0x08, 0x90, 0x01, 0xC0, 0xE0, 0x44, +0x10, 0xF0, 0x22, 0x90, 0x81, 0xC9, 0x71, 0xBD, +0x12, 0x58, 0xAF, 0xD3, 0x90, 0x81, 0xCA, 0xE0, +0x94, 0x32, 0x90, 0x81, 0xC9, 0xE0, 0x94, 0x00, +0x40, 0xC0, 0x90, 0x01, 0xC6, 0xE0, 0x30, 0xE0, +0xB9, 0x22, 0xE4, 0xFD, 0xFB, 0xFA, 0xF1, 0x27, +0x30, 0xE0, 0x74, 0x90, 0x00, 0xB6, 0xE0, 0xFC, +0x90, 0x00, 0xBF, 0xE0, 0xFE, 0x90, 0x00, 0xBE, +0xE0, 0x24, 0x00, 0xFB, 0xEA, 0x3E, 0xFA, 0xC4, +0xF8, 0x54, 0xF0, 0xC8, 0xEB, 0xC4, 0x54, 0x0F, +0x48, 0x54, 0x1E, 0xFF, 0xEC, 0xC4, 0x54, 0x01, +0x4F, 0x90, 0x81, 0xB0, 0xF0, 0x12, 0x7C, 0x0B, +0xEC, 0x30, 0xE4, 0x0A, 0x90, 0x81, 0x14, 0xE0, +0xFD, 0x12, 0x6B, 0x2D, 0x80, 0x35, 0xEB, 0x30, +0xE5, 0x09, 0x90, 0x81, 0x15, 0x91, 0xDC, 0x04, +0xF0, 0x80, 0x28, 0xEB, 0x30, 0xE6, 0x0A, 0x90, +0x81, 0x16, 0x91, 0xDC, 0x74, 0x02, 0xF0, 0x80, +0x1A, 0xEB, 0x30, 0xE7, 0x0A, 0x90, 0x81, 0x17, +0x91, 0xDC, 0x74, 0x03, 0xF0, 0x80, 0x0C, 0xEA, +0x30, 0xE0, 0x08, 0x90, 0x81, 0x18, 0x91, 0xDC, +0x74, 0x04, 0xF0, 0xAF, 0x05, 0x80, 0x56, 0x90, +0x81, 0x07, 0xE0, 0xFD, 0x7C, 0x00, 0xA3, 0xE0, +0xFE, 0xA3, 0xE0, 0xFF, 0x12, 0x20, 0x30, 0xED, +0x4C, 0x70, 0x05, 0x90, 0x81, 0x14, 0x80, 0x2A, +0xED, 0x64, 0x01, 0x4C, 0x70, 0x05, 0x90, 0x81, +0x15, 0x80, 0x1F, 0xED, 0x64, 0x02, 0x4C, 0x70, +0x05, 0x90, 0x81, 0x16, 0x80, 0x14, 0xED, 0x64, +0x03, 0x4C, 0x70, 0x05, 0x90, 0x81, 0x17, 0x80, +0x09, 0xED, 0x64, 0x04, 0x4C, 0x70, 0x0C, 0x90, +0x81, 0x18, 0xE0, 0xFF, 0x91, 0xE5, 0x90, 0x81, +0x08, 0x71, 0xBD, 0x22, 0xE0, 0xFD, 0x90, 0x81, +0x08, 0xE4, 0xF0, 0xA3, 0x22, 0x90, 0x04, 0x24, +0xEF, 0xF0, 0x22, 0x12, 0x47, 0xEB, 0xB1, 0x51, +0xE4, 0xFF, 0x12, 0x48, 0x9A, 0x90, 0x80, 0xFC, +0xE0, 0x30, 0xE0, 0x02, 0x91, 0x12, 0x02, 0x4D, +0xB9, 0x12, 0x72, 0x39, 0x90, 0x81, 0x3B, 0xE0, +0x20, 0xE0, 0x0C, 0x90, 0x00, 0x26, 0xE0, 0x54, +0x7F, 0xFD, 0x7F, 0x26, 0x12, 0x32, 0x1E, 0x90, +0x00, 0x08, 0xE0, 0x54, 0xEF, 0xFD, 0x7F, 0x08, +0x12, 0x32, 0x1E, 0xE4, 0xFF, 0x61, 0xC4, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x72, +0x56, 0xB1, 0x01, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x90, 0x81, 0x33, 0xE0, 0xFF, 0x60, 0x03, 0xB4, +0x08, 0x0E, 0x12, 0x6E, 0xFC, 0xBF, 0x01, 0x08, +0xB1, 0x27, 0x90, 0x01, 0xE5, 0xE0, 0x04, 0xF0, +0x22, 0xE4, 0xF5, 0x51, 0x90, 0x81, 0x30, 0xE0, +0x60, 0x1D, 0x12, 0x4F, 0xC6, 0x70, 0x18, 0x12, +0x6D, 0x60, 0x60, 0x09, 0x90, 0x81, 0x2C, 0x12, +0x5F, 0xDB, 0x20, 0xE0, 0x03, 0x75, 0x51, 0x01, +0xE5, 0x51, 0x60, 0x03, 0x12, 0x49, 0xA2, 0x22, +0xE4, 0x90, 0x82, 0xBA, 0xF0, 0xA3, 0xF0, 0x90, +0x02, 0x86, 0xE0, 0x20, 0xE1, 0x22, 0xC3, 0x90, +0x82, 0xBB, 0xE0, 0x94, 0xD0, 0x90, 0x82, 0xBA, +0xE0, 0x94, 0x07, 0x40, 0x0A, 0x90, 0x01, 0xC1, +0xE0, 0x44, 0x04, 0xF0, 0x7F, 0x00, 0x22, 0x90, +0x82, 0xBA, 0x71, 0xBD, 0xF1, 0x2E, 0x80, 0xD7, +0x7F, 0x01, 0x22, 0x90, 0x01, 0x17, 0xE0, 0xFE, +0x90, 0x01, 0x16, 0x12, 0x7C, 0x5A, 0x90, 0x80, +0xFA, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x02, 0x86, +0xE0, 0x44, 0x04, 0xF1, 0xEC, 0x30, 0xE0, 0x2B, +0x90, 0x01, 0xC7, 0xE4, 0xF0, 0xB1, 0x78, 0x90, +0x80, 0xFC, 0xE0, 0xBF, 0x01, 0x05, 0x54, 0xEF, +0xF0, 0x80, 0x03, 0x44, 0x10, 0xF0, 0x90, 0x80, +0xFF, 0xE0, 0xFF, 0x60, 0x0E, 0xE4, 0xF5, 0x1D, +0x8F, 0x1E, 0xFB, 0xFD, 0x7F, 0x5C, 0x7E, 0x01, +0x12, 0x49, 0x3A, 0x90, 0x80, 0xFC, 0xE0, 0x44, +0x01, 0xF0, 0x7D, 0x08, 0xE4, 0xFF, 0x12, 0x4F, +0xB9, 0x90, 0x05, 0x52, 0xE0, 0x54, 0x07, 0x04, +0x90, 0x81, 0x07, 0x71, 0x6B, 0x90, 0x04, 0x22, +0xE0, 0x54, 0xEF, 0xF0, 0xF1, 0x27, 0x30, 0xE0, +0x03, 0x12, 0x7C, 0x0B, 0x22, 0x12, 0x67, 0x8D, +0xFC, 0x54, 0x02, 0xFE, 0x90, 0x80, 0xFC, 0xE0, +0x54, 0xFD, 0x4E, 0xF0, 0xE0, 0xFF, 0xC3, 0x13, +0x30, 0xE0, 0x08, 0xF1, 0x21, 0xF1, 0x83, 0x90, +0x80, 0xFF, 0xF0, 0xEC, 0x30, 0xE0, 0x18, 0xB1, +0xAB, 0x90, 0x01, 0xC7, 0xE4, 0xF0, 0x90, 0x80, +0x07, 0xE0, 0x64, 0x01, 0x70, 0x2E, 0x90, 0xFE, +0x10, 0xE0, 0x44, 0x04, 0xF0, 0x80, 0x25, 0x12, +0x6A, 0x75, 0x90, 0x01, 0x3C, 0xE0, 0x30, 0xE4, +0x03, 0x74, 0x10, 0xF0, 0x90, 0x01, 0x63, 0xE4, +0xF0, 0x12, 0x6A, 0xFA, 0xF1, 0x27, 0x30, 0xE0, +0x0B, 0x90, 0x02, 0x86, 0xE0, 0x30, 0xE2, 0x04, +0xE0, 0x54, 0xFB, 0xF0, 0x90, 0x81, 0xD0, 0xF1, +0x35, 0x90, 0x80, 0xFD, 0xF1, 0x91, 0x90, 0x80, +0xFE, 0xF1, 0xEC, 0x30, 0xE0, 0x28, 0xF1, 0x21, +0x12, 0x67, 0xB5, 0x90, 0x80, 0xFC, 0x12, 0x67, +0x96, 0x4E, 0xF1, 0xD8, 0x90, 0x81, 0x00, 0xF0, +0x70, 0x03, 0x74, 0x14, 0xF0, 0xF1, 0x21, 0x90, +0x00, 0x05, 0x12, 0x1F, 0xBD, 0x90, 0x81, 0x01, +0xF1, 0xDF, 0x90, 0x81, 0x02, 0xF0, 0x90, 0x80, +0xFD, 0xE0, 0x54, 0x01, 0x90, 0x81, 0x0A, 0xF0, +0x90, 0x80, 0xFD, 0xE0, 0x54, 0x02, 0x90, 0x81, +0x0B, 0xF0, 0x90, 0x80, 0xFD, 0xE0, 0x54, 0x04, +0x90, 0x81, 0x0C, 0xF0, 0x90, 0x80, 0xFD, 0xE0, +0x54, 0x08, 0x90, 0x81, 0x0D, 0xF0, 0x90, 0x80, +0xFD, 0xE0, 0x54, 0x10, 0x90, 0x81, 0x0E, 0xF0, +0x90, 0x80, 0xFE, 0xE0, 0x54, 0x01, 0x90, 0x81, +0x0F, 0xF0, 0x90, 0x80, 0xFE, 0xE0, 0x54, 0x02, +0x90, 0x81, 0x10, 0xF0, 0x90, 0x80, 0xFE, 0xE0, +0x54, 0x04, 0x90, 0x81, 0x11, 0xF0, 0x90, 0x80, +0xFE, 0xE0, 0x54, 0x08, 0x90, 0x81, 0x12, 0xF0, +0x90, 0x80, 0xFE, 0xE0, 0x54, 0x10, 0x90, 0x81, +0x13, 0xF0, 0x22, 0x90, 0x81, 0xD0, 0x12, 0x44, +0xF4, 0x90, 0x81, 0xD0, 0x02, 0x44, 0xEB, 0x90, +0x80, 0xFC, 0xE0, 0xC3, 0x13, 0x22, 0x7F, 0x0A, +0x7E, 0x00, 0x02, 0x32, 0xAA, 0x12, 0x44, 0xEB, +0x90, 0x00, 0x01, 0x02, 0x1F, 0xBD, 0x90, 0x81, +0xD0, 0x12, 0x44, 0xF4, 0x12, 0x73, 0xD8, 0xF1, +0x21, 0x12, 0x73, 0x98, 0xF1, 0x89, 0x4E, 0xF0, +0xEF, 0xC3, 0x13, 0x30, 0xE0, 0x2B, 0xF1, 0x38, +0x90, 0x81, 0xA2, 0xF1, 0x91, 0x90, 0x81, 0xA3, +0xF0, 0x12, 0x1F, 0xA4, 0xFF, 0x54, 0x04, 0xFE, +0x90, 0x81, 0xA1, 0xE0, 0x54, 0xFB, 0x4E, 0xF1, +0x82, 0x90, 0x81, 0xA4, 0xF0, 0xEF, 0x54, 0x08, +0xFF, 0x90, 0x81, 0xA1, 0xE0, 0x54, 0xF7, 0x4F, +0xF0, 0x22, 0xF0, 0x90, 0x00, 0x03, 0x02, 0x1F, +0xBD, 0x90, 0x81, 0xA1, 0xE0, 0x54, 0xFE, 0x22, +0x4F, 0xF0, 0x90, 0x00, 0x02, 0x02, 0x1F, 0xBD, +0x90, 0x02, 0x09, 0xE0, 0xF5, 0x55, 0x12, 0x1F, +0xA4, 0x25, 0x55, 0x90, 0x80, 0x09, 0xF0, 0xF1, +0x38, 0x25, 0x55, 0x90, 0x80, 0x0A, 0xF1, 0x91, +0x25, 0x55, 0x90, 0x80, 0x0B, 0xF1, 0x82, 0x25, +0x55, 0x90, 0x80, 0x0C, 0xF1, 0xD8, 0x25, 0x55, +0x90, 0x80, 0x0D, 0xF0, 0x90, 0x00, 0x05, 0x12, +0x1F, 0xBD, 0x25, 0x55, 0x90, 0x80, 0x0E, 0xF1, +0xDF, 0x25, 0x55, 0x90, 0x80, 0x0F, 0xF0, 0x22, +0xF0, 0x90, 0x00, 0x04, 0x02, 0x1F, 0xBD, 0xF0, +0x90, 0x00, 0x06, 0x02, 0x1F, 0xBD, 0xE4, 0x90, +0x80, 0x01, 0x01, 0x9D, 0xF0, 0x90, 0x80, 0xFC, +0xE0, 0xFF, 0xC3, 0x13, 0x22, 0x75, 0xE8, 0x03, +0x75, 0xA8, 0x84, 0x22, 0x90, 0x00, 0x80, 0xE0, +0x44, 0x80, 0xFD, 0x7F, 0x80, 0x12, 0x32, 0x1E, +0x90, 0xFD, 0x00, 0xE0, 0x54, 0xBF, 0xF0, 0x11, +0xC0, 0x12, 0x32, 0x77, 0x11, 0xCD, 0x12, 0x57, +0xE6, 0x7F, 0x01, 0x12, 0x42, 0x15, 0x90, 0x81, +0x9C, 0x74, 0x02, 0xF0, 0xFF, 0x12, 0x42, 0x15, +0x90, 0x81, 0x9C, 0xE0, 0x04, 0xF0, 0x12, 0x50, +0x15, 0x12, 0x52, 0xED, 0x90, 0x01, 0xCC, 0x74, +0x0F, 0xF0, 0x90, 0x00, 0x80, 0xE0, 0x44, 0x40, +0xFD, 0x7F, 0x80, 0x12, 0x32, 0x1E, 0x75, 0x20, +0xFF, 0x12, 0x57, 0xF5, 0x11, 0x55, 0x11, 0xB6, +0xE4, 0xFF, 0x02, 0x42, 0x9E, 0xE4, 0x90, 0x81, +0xC3, 0xF0, 0xA3, 0xF0, 0x90, 0x01, 0x98, 0xE0, +0x7F, 0x00, 0x30, 0xE4, 0x02, 0x7F, 0x01, 0xEF, +0x64, 0x01, 0x60, 0x3C, 0xC3, 0x90, 0x81, 0xC4, +0xE0, 0x94, 0x88, 0x90, 0x81, 0xC3, 0xE0, 0x94, +0x13, 0x40, 0x0F, 0x90, 0x01, 0xC1, 0xE0, 0x44, +0x10, 0xF0, 0x90, 0x01, 0xC7, 0x74, 0xFD, 0xF0, +0x80, 0x1E, 0x90, 0x81, 0xC3, 0x12, 0x53, 0xBD, +0x11, 0xAF, 0xD3, 0x90, 0x81, 0xC4, 0xE0, 0x94, +0x32, 0x90, 0x81, 0xC3, 0xE0, 0x94, 0x00, 0x40, +0xBB, 0x90, 0x01, 0xC6, 0xE0, 0x30, 0xE3, 0xB4, +0x90, 0x01, 0xC7, 0x74, 0xFE, 0xF0, 0x22, 0x7F, +0x14, 0x7E, 0x00, 0x02, 0x32, 0xAA, 0x90, 0x01, +0xE4, 0x74, 0x1C, 0xF0, 0xA3, 0xE4, 0xF0, 0x22, +0x90, 0x01, 0x94, 0xE0, 0x44, 0x01, 0xF0, 0x90, +0x01, 0xC7, 0xE4, 0xF0, 0x22, 0x90, 0x01, 0x01, +0xE0, 0x44, 0x04, 0xF0, 0x90, 0x01, 0x9C, 0x74, +0x7E, 0xF0, 0xA3, 0x74, 0x92, 0xF0, 0xA3, 0x74, +0xA0, 0xF0, 0xA3, 0x74, 0x24, 0xF0, 0x90, 0x01, +0x9B, 0x74, 0x49, 0xF0, 0x90, 0x01, 0x9A, 0x74, +0xE0, 0xF0, 0x90, 0x01, 0x99, 0xE4, 0xF0, 0x90, +0x01, 0x98, 0x04, 0xF0, 0x22, 0xE4, 0x90, 0x81, +0xC5, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0x90, 0x81, +0xC5, 0xE0, 0x64, 0x01, 0xF0, 0x24, 0xFD, 0x90, +0x01, 0xC4, 0xF0, 0x74, 0x58, 0xA3, 0xF0, 0x90, +0x81, 0x30, 0xE0, 0x60, 0x0E, 0x90, 0x81, 0x33, +0xE0, 0xFF, 0x90, 0x81, 0x32, 0xE0, 0x6F, 0x60, +0x02, 0x31, 0x40, 0xC2, 0xAF, 0x12, 0x6F, 0xDD, +0xBF, 0x01, 0x03, 0x12, 0x72, 0xDE, 0xD2, 0xAF, +0x31, 0x3F, 0x12, 0x41, 0x4D, 0x80, 0xC7, 0x22, +0x90, 0x81, 0x32, 0xE0, 0xFF, 0x7D, 0x01, 0x02, +0x49, 0xF1, 0xE4, 0xFF, 0x12, 0x4E, 0x80, 0xBF, +0x01, 0x0E, 0x90, 0x81, 0x30, 0xE0, 0x60, 0x08, +0x31, 0x61, 0x54, 0x07, 0x70, 0x02, 0x31, 0x40, +0x22, 0x90, 0x81, 0x34, 0xE0, 0x54, 0xFE, 0xF0, +0x22, 0x90, 0x06, 0xA9, 0xE0, 0xF5, 0x4E, 0x54, +0xC0, 0x70, 0x07, 0x31, 0x61, 0x54, 0xFD, 0xF0, +0x80, 0xC6, 0xE5, 0x4E, 0x30, 0xE6, 0x1F, 0x90, +0x81, 0x30, 0xE0, 0x64, 0x01, 0x70, 0x19, 0x90, +0x81, 0x34, 0xE0, 0x44, 0x01, 0x12, 0x47, 0xE3, +0x64, 0x02, 0x60, 0x05, 0x12, 0x72, 0x16, 0x80, +0x07, 0x12, 0x47, 0xB5, 0x80, 0x02, 0x31, 0x61, +0xE5, 0x4E, 0x90, 0x81, 0x34, 0x30, 0xE7, 0x0E, +0xE0, 0x44, 0x02, 0x12, 0x49, 0x29, 0x90, 0x81, +0x2B, 0xE0, 0x44, 0x04, 0xF0, 0x22, 0xE0, 0x54, +0xFD, 0xF0, 0x22, 0x90, 0x81, 0x30, 0xE0, 0x60, +0x0F, 0x90, 0x06, 0x92, 0xE0, 0x30, 0xE1, 0x04, +0x71, 0x92, 0x80, 0x04, 0xF1, 0xD3, 0x31, 0x40, +0x90, 0x81, 0xAA, 0x91, 0x35, 0x30, 0xE0, 0x19, +0xEF, 0xC4, 0x54, 0x0F, 0x30, 0xE0, 0x02, 0xF1, +0x82, 0x90, 0x81, 0xAB, 0xE0, 0x30, 0xE0, 0x09, +0x71, 0x64, 0x20, 0xE0, 0x02, 0x7D, 0x01, 0x31, +0xF2, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x90, 0x82, 0xB9, 0xED, 0xF0, 0x90, 0x82, +0xB8, 0xEF, 0xF0, 0xD3, 0x94, 0x07, 0x50, 0x4B, +0x51, 0xC3, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, +0xF4, 0xFF, 0x90, 0x00, 0x47, 0xE0, 0x5F, 0xFD, +0x7F, 0x47, 0x51, 0xBD, 0x80, 0x02, 0xC3, 0x33, +0xD8, 0xFC, 0xFF, 0x90, 0x00, 0x46, 0xE0, 0x4F, +0xFD, 0x7F, 0x46, 0x71, 0x7D, 0x60, 0x10, 0x51, +0xC0, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xFF, +0x90, 0x00, 0x45, 0xE0, 0x4F, 0x80, 0x0F, 0x51, +0xC0, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xF4, +0xFF, 0x90, 0x00, 0x45, 0xE0, 0x5F, 0xFD, 0x7F, +0x45, 0x80, 0x62, 0x90, 0x82, 0xB8, 0xE0, 0x24, +0xF8, 0xF0, 0xE0, 0x24, 0x04, 0x51, 0xC4, 0x80, +0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xF4, 0xFF, 0x90, +0x00, 0x43, 0xE0, 0x5F, 0xFD, 0x7F, 0x43, 0x51, +0xBD, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xFF, +0x90, 0x00, 0x43, 0xE0, 0x4F, 0xFD, 0x7F, 0x43, +0x71, 0x7D, 0x60, 0x19, 0x90, 0x82, 0xB8, 0xE0, +0x24, 0x04, 0x51, 0xC4, 0x80, 0x02, 0xC3, 0x33, +0xD8, 0xFC, 0xFF, 0x90, 0x00, 0x42, 0xE0, 0x4F, +0xFD, 0x7F, 0x42, 0x80, 0x18, 0x90, 0x82, 0xB8, +0xE0, 0x24, 0x04, 0x51, 0xC4, 0x80, 0x02, 0xC3, +0x33, 0xD8, 0xFC, 0xF4, 0xFF, 0x90, 0x00, 0x42, +0xE0, 0x5F, 0xFD, 0x7F, 0x42, 0x12, 0x32, 0x1E, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x12, 0x32, 0x1E, +0x90, 0x82, 0xB8, 0xE0, 0xFF, 0x74, 0x01, 0xA8, +0x07, 0x08, 0x22, 0xAD, 0x07, 0x90, 0x81, 0xAC, +0xE0, 0x75, 0xF0, 0x20, 0xA4, 0xFF, 0x90, 0x82, +0x96, 0xE5, 0xF0, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, +0x81, 0xAD, 0xE0, 0x75, 0xF0, 0x08, 0xA4, 0xAE, +0xF0, 0x90, 0x82, 0x98, 0xF0, 0xEE, 0xA3, 0xF0, +0x71, 0x75, 0x90, 0x82, 0x9A, 0xF0, 0xEE, 0xA3, +0xF0, 0xED, 0x64, 0x01, 0x60, 0x5E, 0x90, 0x81, +0xAA, 0xE0, 0xFE, 0x91, 0x37, 0x30, 0xE0, 0x54, +0xEE, 0x71, 0x69, 0x20, 0xE0, 0x02, 0x7D, 0x01, +0x71, 0x5D, 0xFE, 0x54, 0x0F, 0xFF, 0xEE, 0xC4, +0x13, 0x13, 0x54, 0x01, 0xFD, 0x71, 0x5D, 0xC4, +0x13, 0x54, 0x07, 0x30, 0xE0, 0x21, 0xA3, 0xE0, +0x30, 0xE0, 0x0D, 0x90, 0x82, 0x9B, 0xE0, 0xF5, +0x1D, 0x90, 0x82, 0x9A, 0x71, 0x85, 0x80, 0x0F, +0x71, 0x75, 0xFF, 0x12, 0x32, 0xAA, 0x71, 0x64, +0x20, 0xE0, 0x02, 0x7D, 0x01, 0x31, 0xF2, 0x90, +0x81, 0xAA, 0xE0, 0xC4, 0x54, 0x0F, 0x30, 0xE0, +0x0B, 0x90, 0x82, 0x99, 0xE0, 0xF5, 0x1D, 0x90, +0x82, 0x98, 0x71, 0x85, 0x22, 0x31, 0xF2, 0x90, +0x81, 0xAA, 0xE0, 0x22, 0x90, 0x81, 0xAA, 0xE0, +0xFE, 0x54, 0x0F, 0xFF, 0xEE, 0xC4, 0x13, 0x13, +0x54, 0x03, 0x7D, 0x00, 0x22, 0x90, 0x82, 0x96, +0xE0, 0xFE, 0xA3, 0xE0, 0x22, 0x12, 0x32, 0x1E, +0x90, 0x82, 0xB9, 0xE0, 0x22, 0xE0, 0xF5, 0x1E, +0xE4, 0xFB, 0xFD, 0x7F, 0x58, 0x7E, 0x01, 0x02, +0x49, 0x3A, 0x12, 0x6D, 0x69, 0x30, 0xE0, 0x05, +0x90, 0x01, 0x5B, 0xE4, 0xF0, 0x90, 0x06, 0x92, +0x74, 0x02, 0xF0, 0x90, 0x01, 0x3C, 0x74, 0x04, +0xF0, 0xE4, 0xF5, 0x1D, 0x90, 0x81, 0x8F, 0xE0, +0xC3, 0x13, 0x54, 0x7F, 0x71, 0x86, 0x90, 0x81, +0x2B, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x12, 0x1F, +0xA4, 0xFF, 0x54, 0x80, 0xFE, 0x90, 0x81, 0xAA, +0xE0, 0x54, 0x7F, 0x4E, 0xFE, 0xF0, 0xEF, 0x54, +0x40, 0xFF, 0xEE, 0x54, 0xBF, 0x4F, 0xFF, 0xF0, +0x12, 0x1F, 0xA4, 0xFE, 0x54, 0x20, 0xFD, 0xEF, +0x54, 0xDF, 0x4D, 0xFF, 0x90, 0x81, 0xAA, 0xF0, +0xEE, 0x54, 0x10, 0xFE, 0xEF, 0x54, 0xEF, 0x4E, +0xFF, 0xF0, 0x12, 0x1F, 0xA4, 0x54, 0x0F, 0xFE, +0xEF, 0x54, 0xF0, 0x4E, 0x90, 0x81, 0xAA, 0xF0, +0x12, 0x57, 0x38, 0xFF, 0x54, 0x7F, 0x90, 0x81, +0xAC, 0xF0, 0xEF, 0x54, 0x80, 0x91, 0x37, 0xFF, +0x90, 0x81, 0xAB, 0xE0, 0x54, 0xFE, 0x12, 0x57, +0x90, 0x90, 0x81, 0xAD, 0x12, 0x57, 0x82, 0x54, +0x01, 0x25, 0xE0, 0xFF, 0x90, 0x81, 0xAB, 0xE0, +0x54, 0xFD, 0x4F, 0xF0, 0x71, 0x64, 0x20, 0xE0, +0x02, 0x7D, 0x01, 0x21, 0xF2, 0xE0, 0xFF, 0xC4, +0x13, 0x13, 0x13, 0x54, 0x01, 0x22, 0x90, 0x81, +0x2B, 0x91, 0x35, 0x30, 0xE0, 0x1D, 0xEF, 0x54, +0x7F, 0xB1, 0xFB, 0x30, 0xE1, 0x06, 0xE0, 0x44, +0x02, 0xF0, 0x80, 0x07, 0xE0, 0x54, 0xFD, 0xD1, +0x0E, 0x04, 0xF0, 0x90, 0x81, 0x30, 0xE0, 0x60, +0x02, 0x31, 0x40, 0x7F, 0x01, 0x90, 0x81, 0xA1, +0xE0, 0xFD, 0x30, 0xE0, 0x46, 0x90, 0x81, 0xA6, +0xE0, 0xFC, 0x60, 0x3F, 0xD1, 0x06, 0x80, 0x05, +0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, +0x90, 0x04, 0xE0, 0xE0, 0xFB, 0xEF, 0x5B, 0x60, +0x0B, 0xE4, 0x90, 0x81, 0xA6, 0xF0, 0x90, 0x81, +0xA8, 0x04, 0xF0, 0x22, 0x90, 0x81, 0xA3, 0xE0, +0xD3, 0x9C, 0x50, 0x15, 0xED, 0x13, 0x13, 0x13, +0x54, 0x1F, 0x30, 0xE0, 0x05, 0x12, 0x67, 0xFB, +0x80, 0x02, 0xD1, 0x89, 0x12, 0x57, 0x89, 0xF0, +0x22, 0xD1, 0xDC, 0x22, 0x90, 0x81, 0x2B, 0xF1, +0xDB, 0x30, 0xE0, 0x18, 0xEF, 0x54, 0xBF, 0xB1, +0xFB, 0x30, 0xE0, 0x06, 0xE0, 0x44, 0x01, 0xF0, +0x80, 0x08, 0xE0, 0x54, 0xFE, 0xD1, 0x0E, 0x74, +0x04, 0xF0, 0x31, 0x40, 0xE4, 0xFF, 0x80, 0x8D, +0x90, 0x01, 0xCC, 0xE0, 0x54, 0x0F, 0x90, 0x82, +0xB6, 0xF0, 0x90, 0x82, 0xB6, 0xE0, 0xFD, 0x70, +0x02, 0xA1, 0xD0, 0x90, 0x80, 0x60, 0xE0, 0xFF, +0x70, 0x06, 0xA3, 0xE0, 0x64, 0x09, 0x60, 0x0A, +0xEF, 0x14, 0xFF, 0x90, 0x80, 0x61, 0xE0, 0xB5, +0x07, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, +0xEF, 0x60, 0x08, 0x90, 0x01, 0xC1, 0xE0, 0x44, +0x01, 0xF0, 0x22, 0x90, 0x82, 0xB4, 0xD1, 0x04, +0x80, 0x05, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, +0xF9, 0xFF, 0xEF, 0x5D, 0x70, 0x02, 0xA1, 0xB2, +0xE4, 0x90, 0x82, 0xB7, 0xF0, 0x90, 0x82, 0xB7, +0xE0, 0xF9, 0xC3, 0x94, 0x04, 0x50, 0x31, 0xB1, +0xD1, 0xA4, 0xFF, 0xE9, 0xFD, 0x7C, 0x00, 0x2F, +0xFF, 0xEC, 0x35, 0xF0, 0xFE, 0x74, 0xD0, 0xB1, +0xE9, 0x90, 0x80, 0x10, 0xB1, 0xD9, 0xB1, 0xD1, +0xA4, 0x2D, 0xFF, 0xEC, 0x35, 0xF0, 0xFE, 0x74, +0xF0, 0xB1, 0xE9, 0x90, 0x80, 0x14, 0xB1, 0xD9, +0x90, 0x82, 0xB7, 0xE0, 0x04, 0xF0, 0x80, 0xC5, +0x90, 0x82, 0xB6, 0xE0, 0xFF, 0x90, 0x82, 0xB4, +0xE0, 0xFE, 0x74, 0x01, 0xA8, 0x06, 0x08, 0x80, +0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xF4, 0x5F, 0x90, +0x82, 0xB6, 0xF0, 0x90, 0x82, 0xB4, 0x51, 0xC3, +0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0x90, 0x01, +0xCC, 0xF0, 0x90, 0x82, 0xB4, 0xE0, 0x04, 0xF0, +0xE0, 0x54, 0x03, 0xF0, 0x90, 0x80, 0x61, 0xF1, +0xC5, 0xB4, 0x0A, 0x02, 0x7F, 0x01, 0xEF, 0x70, +0x02, 0x81, 0xE2, 0xE4, 0x90, 0x80, 0x61, 0xF0, +0x81, 0xE2, 0x90, 0x01, 0xC0, 0xE0, 0x44, 0x02, +0xF0, 0x90, 0x82, 0xB4, 0xE0, 0x44, 0x80, 0x90, +0x00, 0x8A, 0xF0, 0xB1, 0xD1, 0x90, 0x01, 0xD0, +0x12, 0x44, 0xDF, 0xE0, 0x90, 0x01, 0xC3, 0xF0, +0x22, 0x90, 0x82, 0xB4, 0xE0, 0x75, 0xF0, 0x04, +0x22, 0x12, 0x44, 0xDF, 0xE5, 0x82, 0x29, 0xF5, +0x82, 0xE4, 0x35, 0x83, 0xF5, 0x83, 0xEF, 0xF0, +0x22, 0x2F, 0xF5, 0x82, 0x74, 0x01, 0x3E, 0xF5, +0x83, 0xE0, 0xFF, 0x90, 0x80, 0x61, 0xE0, 0x75, +0xF0, 0x08, 0x22, 0xF0, 0x90, 0x04, 0xE0, 0xE0, +0x90, 0x81, 0x2C, 0x22, 0xE0, 0xFF, 0x74, 0x01, +0x7E, 0x00, 0xA8, 0x07, 0x08, 0x22, 0xF0, 0x90, +0x01, 0xB9, 0x74, 0x01, 0xF0, 0x90, 0x01, 0xB8, +0x22, 0x12, 0x67, 0x8D, 0xFF, 0x54, 0x7F, 0x90, +0x81, 0x30, 0xF0, 0xEF, 0x91, 0x37, 0xA3, 0xF0, +0x12, 0x57, 0x38, 0xFD, 0x54, 0xF0, 0xC4, 0x54, +0x0F, 0xFF, 0x90, 0x81, 0x2E, 0xE0, 0x54, 0xF0, +0x4F, 0x12, 0x57, 0x82, 0xFC, 0x54, 0x01, 0x25, +0xE0, 0xFF, 0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFD, +0x4F, 0xF0, 0xEC, 0x54, 0x04, 0xC3, 0x13, 0xFF, +0x90, 0x81, 0x2D, 0xE0, 0x54, 0xFD, 0x4F, 0xF0, +0xED, 0x54, 0x0F, 0xC4, 0x54, 0xF0, 0xFF, 0xA3, +0xE0, 0x54, 0x0F, 0x12, 0x57, 0x90, 0x90, 0x81, +0x2F, 0x12, 0x57, 0xD8, 0xFD, 0x7F, 0x02, 0x12, +0x4B, 0xE8, 0x12, 0x57, 0x21, 0x12, 0x6D, 0xFC, +0xD1, 0x0F, 0xF0, 0x90, 0x81, 0x30, 0x12, 0x7C, +0x39, 0x12, 0x47, 0xE3, 0x90, 0x01, 0xBE, 0xF0, +0x22, 0x90, 0x01, 0xC7, 0x74, 0x10, 0xF0, 0x7F, +0x01, 0x80, 0x0B, 0x12, 0x6A, 0xFA, 0x90, 0x01, +0xC7, 0x74, 0x66, 0xF0, 0xE4, 0xFF, 0x90, 0x82, +0xC4, 0xEF, 0xF0, 0x90, 0x80, 0x07, 0xE0, 0xB4, +0x02, 0x12, 0x90, 0x82, 0xC4, 0xE0, 0xFF, 0x64, +0x01, 0x60, 0x24, 0x90, 0x01, 0x4D, 0xE0, 0x64, +0x80, 0xF0, 0x80, 0x19, 0x90, 0x01, 0x00, 0x74, +0xFF, 0xF0, 0x7F, 0x64, 0x7E, 0x00, 0x12, 0x32, +0xAA, 0x90, 0x06, 0x90, 0xE0, 0x44, 0x01, 0xF0, +0x90, 0x82, 0xC4, 0xE0, 0xFF, 0x51, 0xCB, 0x12, +0x57, 0x89, 0xF0, 0x22, 0x7D, 0x08, 0x7F, 0x02, +0xD1, 0xED, 0x90, 0x81, 0xA6, 0xE0, 0x04, 0xF0, +0x22, 0x7D, 0x08, 0xE4, 0xFF, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x82, 0x9C, 0xEF, +0xF0, 0xA3, 0xED, 0xF0, 0x90, 0x80, 0x03, 0xE0, +0x04, 0xF0, 0x90, 0x04, 0x1D, 0xE0, 0x60, 0x28, +0x90, 0x05, 0x22, 0xE0, 0x90, 0x82, 0xA0, 0xF0, +0x7B, 0x26, 0xF1, 0xCC, 0x12, 0x64, 0xE1, 0xEF, +0x64, 0x01, 0x70, 0x03, 0x12, 0x71, 0x5F, 0x90, +0x82, 0xA0, 0xE0, 0xFD, 0x7B, 0x27, 0xE4, 0xFF, +0x12, 0x4C, 0x84, 0x12, 0x72, 0xFA, 0x80, 0x06, +0x12, 0x72, 0xFA, 0x12, 0x71, 0x5F, 0xF1, 0xBE, +0x7F, 0x01, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xF1, +0x6A, 0x54, 0x3F, 0xF0, 0xBF, 0x01, 0x02, 0x80, +0x16, 0xEF, 0x70, 0x02, 0x80, 0x07, 0x90, 0x81, +0x33, 0xE0, 0x30, 0xE3, 0x0A, 0xF1, 0x76, 0x54, +0xEF, 0xF1, 0x69, 0x44, 0x40, 0xF0, 0x22, 0xF1, +0x76, 0x44, 0x10, 0xF1, 0x69, 0x44, 0x80, 0xF0, +0x22, 0xF0, 0x74, 0x1F, 0x2D, 0xF5, 0x82, 0xE4, +0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x22, 0x74, 0x21, +0x2D, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, +0xE0, 0x22, 0xE4, 0x90, 0x81, 0xB6, 0xF0, 0x90, +0x81, 0xB4, 0x74, 0x14, 0xF0, 0x90, 0x81, 0xC2, +0x74, 0x01, 0xF0, 0xFB, 0x7A, 0x81, 0x79, 0xB4, +0x12, 0x60, 0xAB, 0x7F, 0x04, 0x90, 0x82, 0xBC, +0xEF, 0xF0, 0x7F, 0x02, 0x12, 0x43, 0x27, 0x90, +0x80, 0x01, 0xE0, 0xFF, 0x90, 0x82, 0xBC, 0xE0, +0xFE, 0xEF, 0x4E, 0x90, 0x80, 0x01, 0xF0, 0x22, +0x7D, 0x08, 0x7F, 0x02, 0xC1, 0xED, 0x90, 0x04, +0x1F, 0x74, 0x20, 0xF0, 0x22, 0xE0, 0x04, 0xF0, +0xE0, 0x7F, 0x00, 0x22, 0x7D, 0xFF, 0xE4, 0xFF, +0x02, 0x4C, 0x84, 0x90, 0x81, 0x2B, 0xE0, 0x54, +0xF7, 0xF0, 0x22, 0xE0, 0xFF, 0xC4, 0x13, 0x13, +0x54, 0x03, 0x22, 0xE4, 0xFB, 0xFA, 0xFD, 0x7F, +0x01, 0x12, 0x43, 0x4E, 0x90, 0x81, 0xCB, 0xEF, +0xF0, 0x60, 0xF0, 0x90, 0x80, 0x01, 0xE0, 0xFF, +0x70, 0x04, 0xA3, 0xE0, 0x60, 0xE5, 0xC2, 0xAF, +0xEF, 0x30, 0xE1, 0x09, 0x90, 0x80, 0x01, 0xE0, +0x54, 0xFD, 0xF0, 0x31, 0xD4, 0x11, 0x2E, 0xFF, +0x30, 0xE2, 0x05, 0x54, 0xFB, 0xF0, 0x11, 0x37, +0x11, 0x2E, 0xFF, 0x30, 0xE5, 0x0C, 0x54, 0xDF, +0xF0, 0x12, 0x55, 0x78, 0xBF, 0x01, 0x03, 0x12, +0x74, 0x57, 0xD2, 0xAF, 0x80, 0xC5, 0xD2, 0xAF, +0xC2, 0xAF, 0x90, 0x80, 0x01, 0xE0, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xE4, 0xFF, +0x90, 0x80, 0xF9, 0xE0, 0xFE, 0x90, 0x80, 0xF8, +0xE0, 0xFD, 0xB5, 0x06, 0x04, 0x7E, 0x01, 0x80, +0x02, 0x7E, 0x00, 0xEE, 0x64, 0x01, 0x60, 0x42, +0x90, 0x01, 0xAF, 0xE0, 0x70, 0x0A, 0xED, 0x11, +0x9F, 0xFA, 0x7B, 0x01, 0x51, 0x36, 0x7F, 0x01, +0xEF, 0x60, 0x2F, 0x90, 0x80, 0xF8, 0x12, 0x5F, +0xC5, 0xB4, 0x0A, 0x02, 0x7F, 0x01, 0xEF, 0x60, +0x05, 0xE4, 0x90, 0x80, 0xF8, 0xF0, 0x90, 0x80, +0xF9, 0xE0, 0xFF, 0x90, 0x80, 0xF8, 0xE0, 0xB5, +0x07, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, +0xEF, 0x70, 0x07, 0x90, 0x80, 0x01, 0xE0, 0x44, +0x04, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x75, +0xF0, 0x0F, 0xA4, 0x24, 0x62, 0xF9, 0x74, 0x80, +0x35, 0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x80, 0xF8, 0xE0, 0xFF, 0x70, +0x06, 0xA3, 0xE0, 0x64, 0x09, 0x60, 0x0A, 0xEF, +0x14, 0xFF, 0x90, 0x80, 0xF9, 0xE0, 0xB5, 0x07, +0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xEF, +0x60, 0x09, 0x90, 0x01, 0xC1, 0xE0, 0x44, 0x02, +0xF0, 0x80, 0x29, 0xC0, 0x01, 0x90, 0x80, 0xF9, +0xE0, 0x11, 0x9F, 0xA8, 0x01, 0xFC, 0x7D, 0x01, +0xD0, 0x01, 0x7E, 0x00, 0x7F, 0x0F, 0x12, 0x44, +0x79, 0x90, 0x80, 0xF9, 0x12, 0x5F, 0xC5, 0xB4, +0x0A, 0x02, 0x7F, 0x01, 0xEF, 0x60, 0x05, 0xE4, +0x90, 0x80, 0xF9, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x90, 0x81, 0xDB, 0x74, 0x12, 0xF0, 0x90, +0x81, 0xE9, 0x74, 0x05, 0xF0, 0x90, 0x81, 0xDD, +0xEF, 0xF0, 0xA3, 0xED, 0xF0, 0xA3, 0xEB, 0xF0, +0x90, 0x81, 0xD9, 0xE0, 0x90, 0x81, 0xE0, 0xF0, +0x90, 0x81, 0xDA, 0xE0, 0x90, 0x81, 0xE1, 0xF0, +0x7B, 0x01, 0x7A, 0x81, 0x79, 0xDB, 0x11, 0xAB, +0x7F, 0x04, 0x02, 0x5F, 0x9D, 0x31, 0xBA, 0x7F, +0xF5, 0x7E, 0x00, 0x12, 0x2B, 0x27, 0xBF, 0x01, +0x06, 0x90, 0x81, 0xD0, 0xE0, 0xA3, 0xF0, 0x31, +0xBA, 0x7F, 0xF6, 0x7E, 0x00, 0x12, 0x2B, 0x27, +0xBF, 0x01, 0x08, 0x90, 0x81, 0xD0, 0xE0, 0x90, +0x81, 0xD2, 0xF0, 0x31, 0xBA, 0x7F, 0xF4, 0x7E, +0x00, 0x12, 0x2B, 0x27, 0xBF, 0x01, 0x08, 0x90, +0x81, 0xD0, 0xE0, 0x90, 0x81, 0xD3, 0xF0, 0x31, +0xBA, 0x7F, 0xF3, 0x7E, 0x00, 0x12, 0x2B, 0x27, +0xBF, 0x01, 0x08, 0x90, 0x81, 0xD0, 0xE0, 0x90, +0x81, 0xD4, 0xF0, 0x31, 0xBA, 0x7F, 0xF2, 0x7E, +0x00, 0x12, 0x2B, 0x27, 0xBF, 0x01, 0x08, 0x90, +0x81, 0xD0, 0xE0, 0x90, 0x81, 0xD5, 0xF0, 0x90, +0x81, 0xD1, 0xE0, 0xFF, 0xA3, 0xE0, 0xFD, 0xA3, +0xE0, 0xFB, 0xA3, 0xE0, 0x90, 0x81, 0xD9, 0xF0, +0x90, 0x81, 0xD5, 0xE0, 0x90, 0x81, 0xDA, 0xF0, +0x21, 0x09, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0xD0, +0x22, 0x12, 0x1F, 0xA4, 0xFF, 0x90, 0x81, 0x21, +0xF0, 0xBF, 0x01, 0x07, 0x31, 0x3D, 0xE4, 0x90, +0x81, 0x21, 0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x90, 0x80, 0x61, 0xE0, 0xFF, +0x90, 0x80, 0x60, 0xE0, 0xB5, 0x07, 0x04, 0x7F, +0x01, 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x70, 0x41, +0x90, 0x80, 0x60, 0xE0, 0xFE, 0x75, 0xF0, 0x08, +0x90, 0x80, 0x10, 0x12, 0x44, 0xDF, 0xE0, 0xFD, +0xEE, 0x75, 0xF0, 0x08, 0xA4, 0x24, 0x11, 0xF9, +0x74, 0x80, 0x35, 0xF0, 0xFA, 0x7B, 0x01, 0xAF, +0x05, 0x12, 0x4F, 0x10, 0x90, 0x80, 0x60, 0x12, +0x5F, 0xC5, 0xB4, 0x0A, 0x02, 0x7F, 0x01, 0xEF, +0x60, 0x05, 0xE4, 0x90, 0x80, 0x60, 0xF0, 0x12, +0x5C, 0xD8, 0x90, 0x80, 0x01, 0xE0, 0x44, 0x02, +0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x81, 0xCC, +0x12, 0x44, 0xF4, 0x90, 0x82, 0xB5, 0xE0, 0xFF, +0x04, 0xF0, 0x90, 0x00, 0x01, 0xEF, 0x12, 0x1F, +0xFC, 0x7F, 0xAF, 0x7E, 0x01, 0x12, 0x53, 0x72, +0xEF, 0x60, 0x3A, 0x90, 0x81, 0xCC, 0x12, 0x44, +0xEB, 0x8B, 0x13, 0x8A, 0x14, 0x89, 0x15, 0x90, +0x00, 0x0E, 0x12, 0x1F, 0xBD, 0x24, 0x02, 0xF5, +0x16, 0x7B, 0x01, 0x7A, 0x01, 0x79, 0xA0, 0x12, +0x2B, 0xED, 0x90, 0x81, 0xCC, 0x12, 0x44, 0xEB, +0x90, 0x00, 0x0E, 0x12, 0x1F, 0xBD, 0x90, 0x01, +0xAE, 0xF0, 0xA3, 0x74, 0xFF, 0xF0, 0x90, 0x01, +0xCB, 0xE0, 0x64, 0x80, 0xF0, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0x90, 0x82, 0x5A, 0xEF, 0xF0, 0xA3, +0xED, 0xF0, 0xA3, 0x12, 0x20, 0xDA, 0x00, 0x00, +0x00, 0x00, 0xE4, 0x90, 0x82, 0x68, 0xF0, 0x7F, +0x24, 0x7E, 0x08, 0x12, 0x2D, 0x5C, 0x90, 0x82, +0x60, 0x12, 0x20, 0xCE, 0x90, 0x82, 0x5A, 0xE0, +0xFB, 0x70, 0x08, 0x90, 0x82, 0x60, 0x12, 0x44, +0xD3, 0x80, 0x06, 0xEB, 0x71, 0x89, 0x12, 0x2D, +0x5C, 0x90, 0x82, 0x64, 0x12, 0x20, 0xCE, 0x90, +0x82, 0x5B, 0xE0, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, +0x78, 0x17, 0x91, 0x05, 0x90, 0x82, 0x64, 0x12, +0x44, 0xD3, 0xED, 0x54, 0x7F, 0xFD, 0xEC, 0x54, +0x80, 0xFC, 0x12, 0x44, 0xB5, 0xEC, 0x44, 0x80, +0xFC, 0x90, 0x82, 0x64, 0x12, 0x20, 0xCE, 0x71, +0x9C, 0x54, 0x7F, 0xFC, 0x71, 0x83, 0x71, 0xA4, +0x71, 0x89, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x82, +0x64, 0x71, 0x80, 0xD0, 0x07, 0xD0, 0x06, 0x12, +0x2E, 0xA2, 0x71, 0x9C, 0x44, 0x80, 0xFC, 0x71, +0x83, 0x71, 0xA4, 0x70, 0x04, 0x7F, 0x20, 0x80, +0x09, 0x90, 0x82, 0x5A, 0xE0, 0xB4, 0x01, 0x16, +0x7F, 0x28, 0x7E, 0x08, 0x12, 0x2D, 0x5C, 0x78, +0x08, 0x12, 0x20, 0xA8, 0xEF, 0x54, 0x01, 0xFF, +0xE4, 0x90, 0x82, 0x68, 0xEF, 0xF0, 0x90, 0x82, +0x68, 0xE0, 0x90, 0x82, 0x5A, 0x60, 0x0E, 0xE0, +0x75, 0xF0, 0x08, 0xA4, 0x24, 0x66, 0xF5, 0x82, +0xE4, 0x34, 0x87, 0x80, 0x0C, 0xE0, 0x75, 0xF0, +0x08, 0xA4, 0x24, 0x64, 0xF5, 0x82, 0xE4, 0x34, +0x87, 0x71, 0x94, 0x12, 0x2D, 0x5C, 0xED, 0x54, +0x0F, 0xFD, 0xE4, 0xFC, 0x90, 0x82, 0x5C, 0x12, +0x20, 0xCE, 0x90, 0x82, 0x5C, 0x02, 0x44, 0xD3, +0x12, 0x44, 0xD3, 0x90, 0x85, 0xBB, 0x02, 0x20, +0xCE, 0x75, 0xF0, 0x08, 0xA4, 0x24, 0x62, 0xF5, +0x82, 0xE4, 0x34, 0x87, 0xF5, 0x83, 0xE0, 0xFE, +0xA3, 0xE0, 0xFF, 0x22, 0x90, 0x82, 0x60, 0x12, +0x44, 0xD3, 0xEC, 0x22, 0x7F, 0x24, 0x7E, 0x08, +0x12, 0x2E, 0xA2, 0x90, 0x82, 0x5A, 0xE0, 0x22, +0x90, 0x82, 0x78, 0xEF, 0xF0, 0xAB, 0x05, 0x90, +0x82, 0x7E, 0x12, 0x20, 0xDA, 0x00, 0x00, 0x00, +0x00, 0xAF, 0x03, 0xE4, 0xFC, 0xFD, 0xFE, 0x78, +0x14, 0x91, 0x05, 0x90, 0x82, 0x7A, 0x12, 0x44, +0xD3, 0xED, 0x54, 0x0F, 0xFD, 0xE4, 0xFC, 0x12, +0x44, 0xB5, 0xEC, 0x54, 0x0F, 0xFC, 0x90, 0x82, +0x7E, 0x12, 0x20, 0xCE, 0x90, 0x82, 0x78, 0xE0, +0x75, 0xF0, 0x08, 0xA4, 0x24, 0x60, 0xF5, 0x82, +0xE4, 0x34, 0x87, 0x71, 0x94, 0xC0, 0x06, 0xC0, +0x07, 0x90, 0x82, 0x7E, 0x71, 0x80, 0xD0, 0x07, +0xD0, 0x06, 0x02, 0x2E, 0xA2, 0x12, 0x20, 0xBB, +0xA8, 0x04, 0xA9, 0x05, 0xAA, 0x06, 0xAB, 0x07, +0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0xE4, 0x90, 0x82, 0x90, 0xF0, 0xA3, 0xF0, 0x91, +0xE1, 0x90, 0x85, 0xBB, 0x12, 0x20, 0xDA, 0xCC, +0xF0, 0x00, 0xC0, 0x91, 0xBA, 0x12, 0x20, 0xDA, +0x00, 0x00, 0x00, 0x14, 0xB1, 0x77, 0x12, 0x20, +0xDA, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xFD, 0xFF, +0xB1, 0x4C, 0x7F, 0xE8, 0x7E, 0x08, 0x12, 0x2D, +0x5C, 0xEF, 0x54, 0x0E, 0xFF, 0xE4, 0xFE, 0xED, +0x54, 0xF4, 0xFD, 0xEC, 0x54, 0x03, 0xFC, 0xE4, +0xFB, 0xFA, 0xF9, 0xF8, 0xC3, 0x12, 0x44, 0xC2, +0x60, 0x18, 0xD3, 0x91, 0xAD, 0x40, 0x09, 0x90, +0x01, 0xC3, 0xE0, 0x44, 0x02, 0xF0, 0x80, 0x0A, +0xB1, 0x45, 0x90, 0x82, 0x90, 0x12, 0x53, 0xBD, +0x80, 0xC8, 0xC3, 0x91, 0xAD, 0x50, 0x17, 0xB1, +0x6E, 0x44, 0x80, 0xFC, 0x90, 0x82, 0x92, 0x12, +0x20, 0xCE, 0x90, 0x82, 0x92, 0x71, 0x80, 0x7F, +0x7C, 0x7E, 0x08, 0x12, 0x2E, 0xA2, 0x90, 0x01, +0x00, 0x74, 0x3F, 0xF0, 0xA3, 0xE0, 0x54, 0xFD, +0xF0, 0x90, 0x05, 0x53, 0xE0, 0x44, 0x20, 0xF0, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x82, 0x91, +0xE0, 0x94, 0xE8, 0x90, 0x82, 0x90, 0xE0, 0x94, +0x03, 0x22, 0x7F, 0x8C, 0x7E, 0x08, 0x12, 0x2E, +0xA2, 0x90, 0x85, 0xBB, 0x22, 0x7B, 0x2D, 0x12, +0x4F, 0xED, 0x91, 0xE1, 0x90, 0x01, 0x37, 0x74, +0x02, 0xF0, 0xFD, 0x7F, 0x03, 0x12, 0x4F, 0xB9, +0x91, 0x11, 0xE4, 0xFD, 0x7F, 0x01, 0x02, 0x4B, +0xE8, 0xE4, 0x90, 0x82, 0xB1, 0xF0, 0xA3, 0xF0, +0x90, 0x05, 0x22, 0xE0, 0x90, 0x82, 0xB3, 0xF0, +0x7B, 0x47, 0x12, 0x5F, 0xCC, 0x90, 0x05, 0xF8, +0xE0, 0x70, 0x1B, 0xA3, 0xE0, 0x70, 0x17, 0xA3, +0xE0, 0x70, 0x13, 0xA3, 0xE0, 0x70, 0x0F, 0x90, +0x82, 0xB3, 0xE0, 0xFD, 0x7B, 0x48, 0xE4, 0xFF, +0x12, 0x4C, 0x84, 0x7F, 0x01, 0x22, 0xD3, 0x90, +0x82, 0xB2, 0xE0, 0x94, 0xE8, 0x90, 0x82, 0xB1, +0xE0, 0x94, 0x03, 0x40, 0x16, 0x90, 0x01, 0xC0, +0xE0, 0x44, 0x20, 0xF0, 0x90, 0x82, 0xB3, 0xE0, +0xFD, 0x7B, 0x5B, 0xE4, 0xFF, 0x12, 0x4C, 0x84, +0x7F, 0x00, 0x22, 0xB1, 0x45, 0x90, 0x82, 0xB1, +0x12, 0x53, 0xBD, 0x80, 0xB0, 0x7F, 0x32, 0x7E, +0x00, 0x02, 0x32, 0xAA, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0xC0, 0x07, 0xC0, 0x05, 0x90, +0x82, 0x8C, 0x12, 0x44, 0xD3, 0x90, 0x82, 0x7A, +0x12, 0x20, 0xCE, 0xD0, 0x05, 0xD0, 0x07, 0x71, +0xB0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x7F, 0x7C, +0x7E, 0x08, 0x12, 0x2D, 0x5C, 0xEC, 0x22, 0x7F, +0x70, 0x7E, 0x0E, 0x12, 0x2E, 0xA2, 0x90, 0x82, +0x8C, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x51, 0x9A, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x7B, 0x2F, 0x12, 0x4F, 0xED, 0x91, 0x11, 0x7D, +0x08, 0x7F, 0x01, 0x02, 0x4B, 0xE8, 0x12, 0x57, +0x1B, 0xB1, 0xAA, 0x7A, 0x81, 0x79, 0x14, 0x02, +0x2B, 0xED, 0x8B, 0x13, 0x8A, 0x14, 0x89, 0x15, +0x75, 0x16, 0x05, 0x7B, 0x01, 0x22, 0x12, 0x57, +0x1B, 0xB1, 0xAA, 0x7A, 0x81, 0x79, 0x19, 0x02, +0x2B, 0xED, 0x12, 0x1F, 0xA4, 0x54, 0x01, 0xFF, +0x90, 0x81, 0xAF, 0xE0, 0x54, 0xFE, 0x4F, 0xF0, +0x22, 0x12, 0x1F, 0xA4, 0x90, 0x81, 0x93, 0xF0, +0x22, 0xF1, 0x8D, 0xFF, 0x54, 0x01, 0xFE, 0x90, +0x81, 0x94, 0xF1, 0x85, 0x54, 0x02, 0xFF, 0xEE, +0x54, 0xFD, 0x4F, 0xFF, 0xF0, 0xF1, 0xB5, 0x90, +0x81, 0x94, 0xF1, 0x96, 0x4E, 0xFF, 0xF0, 0x12, +0x1F, 0xA4, 0x54, 0x10, 0x25, 0xE0, 0x25, 0xE0, +0xFE, 0xEF, 0x54, 0xBF, 0x4E, 0x90, 0x81, 0x94, +0xF0, 0x90, 0x05, 0x52, 0xE0, 0x54, 0x07, 0xFF, +0x90, 0x81, 0xD0, 0x60, 0x13, 0x12, 0x57, 0x35, +0xFD, 0x90, 0x05, 0x56, 0xE0, 0xC3, 0x9D, 0x90, +0x81, 0x96, 0xF0, 0xA3, 0xED, 0xF0, 0x80, 0x23, +0x12, 0x57, 0x35, 0xFB, 0xFF, 0x90, 0x05, 0x54, +0xE0, 0xC3, 0x9F, 0xFF, 0xE4, 0x94, 0x00, 0xFE, +0x7C, 0x00, 0x7D, 0x05, 0x12, 0x20, 0x30, 0x90, +0x81, 0x96, 0xEF, 0xF0, 0xEB, 0x75, 0xF0, 0x05, +0x84, 0xA3, 0xF0, 0x12, 0x57, 0x21, 0x12, 0x1F, +0xA4, 0x20, 0xE0, 0x0A, 0x12, 0x4C, 0x7D, 0x90, +0x01, 0x57, 0xE4, 0xF0, 0x80, 0x0A, 0x7D, 0x0C, +0x7F, 0x01, 0x12, 0x4B, 0xE8, 0x12, 0x4F, 0xF3, +0xF1, 0x9F, 0x20, 0xE0, 0x04, 0xEF, 0x44, 0x20, +0xF0, 0x12, 0x4F, 0xE5, 0x30, 0xE0, 0x17, 0x90, +0x81, 0x30, 0x74, 0x01, 0xF0, 0xE4, 0x90, 0x81, +0x32, 0xF0, 0xF1, 0x7D, 0xF1, 0xC2, 0x90, 0x82, +0xB0, 0x74, 0x06, 0xF0, 0x80, 0x18, 0xE4, 0x90, +0x81, 0x30, 0xF0, 0x90, 0x81, 0x32, 0x74, 0x0C, +0xF0, 0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFE, 0xF0, +0xA3, 0xE0, 0x54, 0xFB, 0xF0, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xAC, 0x07, 0x90, +0x81, 0x2C, 0xE0, 0x12, 0x5C, 0x37, 0x30, 0xE0, +0x02, 0xE1, 0x66, 0x90, 0x81, 0x2B, 0xE0, 0x30, +0xE0, 0x16, 0x90, 0x81, 0x4D, 0xE0, 0x24, 0x05, +0x90, 0x81, 0x45, 0xF0, 0x90, 0x81, 0x4D, 0xE0, +0x24, 0x03, 0x90, 0x81, 0x44, 0xF0, 0x80, 0x0E, +0x90, 0x81, 0x45, 0x74, 0x05, 0xF0, 0x90, 0x81, +0x44, 0x14, 0xF0, 0x04, 0x2B, 0xFB, 0x90, 0x81, +0x44, 0xE0, 0xFA, 0x90, 0x81, 0x43, 0xE0, 0xD3, +0x9A, 0x50, 0x0E, 0x90, 0x81, 0x38, 0xEB, 0xF0, +0x90, 0x81, 0x45, 0xE0, 0xC3, 0x9D, 0x2C, 0x80, +0x11, 0xC3, 0xED, 0x9A, 0x2B, 0x90, 0x81, 0x38, +0xF0, 0x90, 0x81, 0x44, 0xE0, 0xFF, 0xA3, 0xE0, +0xC3, 0x9F, 0x90, 0x81, 0x48, 0xF0, 0x90, 0x81, +0x45, 0xE0, 0xFF, 0x24, 0x0A, 0xFD, 0xE4, 0x33, +0xFC, 0x90, 0x81, 0x48, 0xF1, 0x72, 0x40, 0x04, +0xEF, 0x24, 0x0A, 0xF0, 0x90, 0x81, 0x48, 0xE0, +0xFF, 0x24, 0x23, 0xFD, 0xE4, 0x33, 0xFC, 0x90, +0x81, 0x38, 0xF1, 0x72, 0x40, 0x04, 0xEF, 0x24, +0x23, 0xF0, 0x90, 0x81, 0x48, 0xE0, 0xFF, 0x7E, +0x00, 0x90, 0x81, 0x3C, 0xEE, 0xF0, 0xA3, 0xEF, +0xF0, 0x90, 0x05, 0x58, 0xE0, 0x6F, 0x70, 0x01, +0xE4, 0x60, 0x02, 0xF1, 0xAB, 0x90, 0x81, 0x2D, +0xE0, 0x54, 0xFE, 0xF0, 0x80, 0x07, 0x90, 0x81, +0x2D, 0xE0, 0x44, 0x01, 0xF0, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0xE0, 0xD3, 0x9D, 0xEC, 0x64, 0x80, +0xF8, 0x74, 0x80, 0x98, 0x22, 0x90, 0x81, 0x2C, +0xE0, 0x44, 0x04, 0xF0, 0x22, 0xE0, 0x54, 0xFE, +0x4E, 0xFE, 0xF0, 0xEF, 0x22, 0x90, 0x81, 0xD0, +0x12, 0x44, 0xF4, 0x02, 0x1F, 0xA4, 0xF0, 0xEE, +0x54, 0x08, 0xFE, 0xEF, 0x54, 0xF7, 0x22, 0x90, +0x81, 0x94, 0xE0, 0xFF, 0x13, 0x13, 0x13, 0x54, +0x1F, 0x22, 0xF0, 0x90, 0x81, 0x3C, 0xA3, 0xE0, +0x90, 0x05, 0x58, 0xF0, 0x22, 0x12, 0x1F, 0xA4, +0xFE, 0x54, 0x04, 0xFD, 0xEF, 0x54, 0xFB, 0x4D, +0xFF, 0x22, 0x90, 0x81, 0x42, 0xE0, 0xFF, 0xA3, +0xE0, 0xFD, 0x90, 0x81, 0x49, 0xE0, 0xFB, 0x22, +0x12, 0x1F, 0xA4, 0x90, 0x81, 0xA9, 0xF0, 0x22, +0x12, 0x1F, 0xA4, 0x90, 0x81, 0x1E, 0xF0, 0x12, +0x57, 0x38, 0x90, 0x81, 0x1F, 0x12, 0x57, 0x91, +0x90, 0x81, 0x20, 0xF0, 0x22, 0xE4, 0x90, 0x80, +0xF8, 0xF0, 0xA3, 0xF0, 0x90, 0x80, 0x60, 0xF0, +0xA3, 0xF0, 0x22, 0xE4, 0xFD, 0xFF, 0x12, 0x53, +0x0C, 0xE4, 0xFF, 0x22, 0x90, 0x81, 0xA1, 0xE0, +0x30, 0xE0, 0x71, 0x90, 0x81, 0xA5, 0xE0, 0x04, +0xF0, 0x90, 0x81, 0xA8, 0xE0, 0x64, 0x01, 0x70, +0x2F, 0x90, 0x81, 0xA1, 0x31, 0xEE, 0x30, 0xE0, +0x27, 0x90, 0x81, 0xA7, 0xE0, 0x70, 0x21, 0x90, +0x81, 0xA4, 0xE0, 0xFE, 0xA3, 0xE0, 0xC3, 0x9E, +0x40, 0x16, 0x91, 0xFD, 0x30, 0xE0, 0x09, 0x12, +0x67, 0xFB, 0x12, 0x57, 0x89, 0xF0, 0x80, 0x08, +0x12, 0x5E, 0x89, 0x12, 0x57, 0x89, 0xF0, 0x22, +0x90, 0x81, 0xA5, 0xE0, 0xFF, 0x90, 0x81, 0xA2, +0xE0, 0xD3, 0x9F, 0x50, 0x27, 0x90, 0x06, 0x92, +0xE0, 0x20, 0xE2, 0x11, 0x90, 0x81, 0xA7, 0xE0, +0x70, 0x0B, 0x12, 0x5E, 0xDC, 0x90, 0x81, 0xA0, +0xE0, 0x04, 0xF0, 0x80, 0x06, 0x90, 0x06, 0x92, +0x74, 0x04, 0xF0, 0xE4, 0x90, 0x81, 0xA5, 0xF0, +0x90, 0x81, 0xA7, 0xF0, 0x22, 0x12, 0x47, 0xEB, +0x90, 0x81, 0x30, 0xE0, 0x60, 0x2A, 0x90, 0x81, +0x2C, 0xB1, 0x6C, 0x30, 0xE0, 0x0B, 0x90, 0x01, +0x3B, 0xE0, 0x30, 0xE4, 0x04, 0x31, 0x06, 0x31, +0x00, 0x90, 0x82, 0xBE, 0xE0, 0x04, 0xF0, 0xE0, +0xC3, 0x94, 0x80, 0x40, 0x0B, 0x90, 0x01, 0x98, +0xE0, 0x54, 0xFE, 0xF0, 0xE0, 0x44, 0x01, 0xF0, +0x12, 0x47, 0x80, 0xBF, 0x03, 0x14, 0x90, 0x81, +0xA9, 0xE0, 0xB4, 0x01, 0x0D, 0x90, 0x01, 0xB8, +0xE0, 0x04, 0xF0, 0x90, 0x05, 0x21, 0xE0, 0x44, +0x80, 0xF0, 0x11, 0x04, 0xD1, 0xBF, 0xE4, 0x90, +0x81, 0xA0, 0xF0, 0x51, 0xCE, 0x90, 0x81, 0x94, +0xE0, 0x30, 0xE0, 0x0C, 0xE4, 0xF5, 0x1D, 0x90, +0x81, 0x96, 0x12, 0x49, 0x30, 0x12, 0x4F, 0xF3, +0x90, 0x80, 0x07, 0xE0, 0xB4, 0x01, 0x10, 0x12, +0x67, 0x9F, 0x20, 0xE0, 0x0A, 0xEF, 0xC4, 0x13, +0x54, 0x07, 0x30, 0xE0, 0x02, 0xD1, 0x83, 0x22, +0x7D, 0x01, 0x7F, 0x02, 0x80, 0x04, 0x7D, 0x02, +0x7F, 0x02, 0x74, 0x3D, 0x51, 0x98, 0xFE, 0xF6, +0x74, 0x30, 0x41, 0x81, 0x90, 0x05, 0x62, 0xE0, +0xFE, 0x90, 0x05, 0x61, 0xE0, 0xFD, 0xED, 0x78, +0x02, 0xCE, 0xC3, 0x13, 0xCE, 0x13, 0xD8, 0xF9, +0xFF, 0x90, 0x81, 0xB0, 0xEE, 0xF0, 0xA3, 0xEF, +0xF0, 0x12, 0x4F, 0xC6, 0x60, 0x02, 0x21, 0xD7, +0x90, 0x81, 0x30, 0xE0, 0x70, 0x02, 0x21, 0xD7, +0xB1, 0x60, 0x64, 0x01, 0x70, 0x22, 0x90, 0x06, +0xAB, 0xE0, 0x90, 0x81, 0x37, 0xF0, 0x90, 0x06, +0xAA, 0xE0, 0x90, 0x81, 0x36, 0xF0, 0xA3, 0xE0, +0xFF, 0x70, 0x08, 0x90, 0x81, 0x36, 0xE0, 0xFE, +0xFF, 0x80, 0x00, 0x90, 0x81, 0x37, 0xEF, 0xF0, +0xE4, 0x90, 0x81, 0x39, 0xF0, 0xA3, 0x12, 0x67, +0xAA, 0x51, 0xC3, 0x51, 0x6C, 0x54, 0xEF, 0xF0, +0x12, 0x59, 0x69, 0x90, 0x81, 0x2C, 0x12, 0x67, +0xA2, 0x30, 0xE0, 0x50, 0xEF, 0xC4, 0x13, 0x13, +0x54, 0x03, 0x20, 0xE0, 0x1E, 0x31, 0xD8, 0x6F, +0x70, 0x42, 0x90, 0x81, 0x2C, 0xE0, 0x44, 0x40, +0xF0, 0xB1, 0x58, 0x31, 0xE0, 0x51, 0x90, 0x31, +0x00, 0x31, 0x06, 0x90, 0x81, 0x37, 0xE0, 0x14, +0xF0, 0x80, 0x29, 0x90, 0x81, 0x2E, 0xE0, 0xC4, +0x54, 0x0F, 0x64, 0x01, 0x70, 0x1E, 0x31, 0xD8, +0xFE, 0x6F, 0x60, 0x18, 0x90, 0x05, 0x73, 0xE0, +0xFF, 0xEE, 0x6F, 0x60, 0x0F, 0x31, 0xEB, 0x30, +0xE0, 0x0A, 0xEF, 0x54, 0xBF, 0x31, 0xE0, 0x51, +0x79, 0x12, 0x4F, 0xAF, 0x12, 0x67, 0x7D, 0x22, +0x90, 0x81, 0x36, 0xE0, 0xFF, 0xA3, 0xE0, 0x22, +0xF0, 0x90, 0x01, 0x3F, 0x74, 0x10, 0xF0, 0xFD, +0x7F, 0x03, 0x22, 0x90, 0x81, 0x2C, 0xE0, 0xFF, +0x13, 0x13, 0x54, 0x3F, 0x22, 0x90, 0x81, 0x2C, +0x12, 0x67, 0xA2, 0x30, 0xE0, 0x0B, 0xEF, 0xC4, +0x13, 0x13, 0x54, 0x03, 0x30, 0xE0, 0x02, 0x31, +0x06, 0x90, 0x81, 0x2B, 0x31, 0xEE, 0x30, 0xE0, +0x09, 0xEF, 0x51, 0x6A, 0x54, 0x07, 0x70, 0x49, +0x80, 0x44, 0x90, 0x81, 0x39, 0xE0, 0x04, 0xF0, +0x90, 0x81, 0x34, 0xE0, 0x54, 0xEF, 0xF0, 0x90, +0x81, 0x8D, 0xE0, 0xFF, 0x90, 0x81, 0x39, 0xE0, +0xD3, 0x9F, 0x40, 0x2A, 0x12, 0x4F, 0xC6, 0x70, +0x28, 0x12, 0x47, 0xE4, 0x70, 0x02, 0x80, 0x22, +0x90, 0x81, 0x3A, 0xE0, 0x04, 0xF0, 0xE0, 0xD3, +0x94, 0x02, 0x40, 0x09, 0x51, 0x62, 0xE4, 0x90, +0x81, 0x3A, 0xF0, 0x80, 0x03, 0x12, 0x47, 0xB5, +0xE4, 0x90, 0x81, 0x39, 0xF0, 0x22, 0x12, 0x59, +0x40, 0x22, 0x90, 0x81, 0x2C, 0xE0, 0x54, 0xFB, +0xF0, 0x22, 0x54, 0xFB, 0xF0, 0x90, 0x81, 0x34, +0xE0, 0x54, 0xFD, 0xF0, 0x22, 0x7D, 0x10, 0xE4, +0xFF, 0x74, 0x45, 0x51, 0x98, 0xFE, 0xF6, 0x74, +0x38, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x01, 0xF5, +0x83, 0xEE, 0xF0, 0x22, 0x7D, 0x10, 0xE4, 0xFF, +0x74, 0x45, 0x2F, 0xF8, 0xE6, 0x4D, 0x80, 0xE5, +0x2F, 0xF8, 0xE6, 0xFE, 0xED, 0xF4, 0x5E, 0x22, +0x12, 0x4F, 0xC6, 0x70, 0x1D, 0x90, 0x81, 0x30, +0xE0, 0x60, 0x17, 0x90, 0x81, 0x34, 0xE0, 0x20, +0xE4, 0x10, 0x51, 0xC3, 0xF0, 0x90, 0x81, 0x2B, +0xE0, 0x51, 0x6A, 0x54, 0x07, 0x70, 0x03, 0x12, +0x59, 0x40, 0x22, 0x90, 0x01, 0x57, 0xE4, 0xF0, +0x90, 0x01, 0x3C, 0x74, 0x02, 0x22, 0x12, 0x57, +0xED, 0x30, 0xE0, 0x25, 0xEF, 0x30, 0xE0, 0x21, +0x13, 0x13, 0x13, 0x54, 0x1F, 0x30, 0xE0, 0x19, +0x90, 0x81, 0x00, 0xE0, 0x70, 0x0D, 0x51, 0xFA, +0x90, 0x01, 0xC7, 0x74, 0x66, 0xF0, 0xE4, 0xFF, +0x02, 0x5E, 0x9E, 0x90, 0x81, 0x00, 0xE0, 0x14, +0xF0, 0x22, 0xE4, 0x90, 0x82, 0x4F, 0xF0, 0x90, +0x80, 0xFC, 0xE0, 0xFE, 0x54, 0x01, 0x90, 0x82, +0x4F, 0xF0, 0xEE, 0x54, 0xFE, 0x90, 0x80, 0xFC, +0xF0, 0x7D, 0x08, 0xE4, 0xFF, 0x31, 0x0A, 0x90, +0x82, 0x4F, 0xE0, 0x60, 0x10, 0x90, 0x02, 0x09, +0xE0, 0x90, 0x04, 0x24, 0xF0, 0x90, 0x02, 0x09, +0xE0, 0x90, 0x04, 0x25, 0xF0, 0xE4, 0x90, 0x81, +0x08, 0xF0, 0xA3, 0xF0, 0x22, 0x71, 0xA8, 0x90, +0x81, 0xB4, 0xEE, 0xF0, 0xA3, 0xEF, 0x12, 0x57, +0xEC, 0x30, 0xE0, 0x14, 0x90, 0x81, 0xB5, 0xE0, +0x20, 0xE0, 0x0D, 0x51, 0xFA, 0x90, 0x02, 0x86, +0xE0, 0x30, 0xE2, 0x04, 0xE0, 0x54, 0xFB, 0xF0, +0x22, 0x12, 0x4F, 0xE5, 0x30, 0xE0, 0x0A, 0x30, +0xE0, 0x45, 0x90, 0x81, 0x2B, 0xE0, 0x30, 0xE0, +0x3E, 0x90, 0x81, 0x1E, 0xE0, 0x60, 0x2E, 0x90, +0x01, 0x63, 0xE4, 0xF0, 0x90, 0x81, 0x1F, 0xE0, +0x60, 0x08, 0xF5, 0x2D, 0xE4, 0xF5, 0x2E, 0xFB, +0x80, 0x10, 0x90, 0x81, 0x20, 0xE0, 0xFB, 0x60, +0x07, 0xE4, 0xF5, 0x2D, 0xF5, 0x2E, 0x80, 0x02, +0xB1, 0x50, 0x7D, 0x01, 0x7F, 0x60, 0x7E, 0x01, +0x12, 0x31, 0x21, 0x80, 0x07, 0x51, 0x75, 0x90, +0x01, 0x63, 0xE4, 0xF0, 0x12, 0x5E, 0x96, 0x22, +0xE4, 0x90, 0x81, 0xB8, 0xF0, 0xA3, 0xF0, 0x90, +0x00, 0x9E, 0xE0, 0x90, 0x81, 0xBA, 0xF0, 0x90, +0x00, 0x9F, 0xE0, 0x90, 0x81, 0xBB, 0xF0, 0xE0, +0xFD, 0xFE, 0x90, 0x81, 0xBA, 0xE0, 0xFC, 0xFB, +0xEB, 0xFF, 0x90, 0x81, 0xB6, 0xEE, 0xF0, 0xA3, +0xEF, 0xF0, 0x90, 0x00, 0x9E, 0xE0, 0xFF, 0xEC, +0xB5, 0x07, 0x09, 0xA3, 0xE0, 0xFF, 0xED, 0xB5, +0x07, 0x02, 0x80, 0x11, 0xC3, 0x90, 0x81, 0xB9, +0xE0, 0x94, 0x64, 0x90, 0x81, 0xB8, 0xE0, 0x94, +0x00, 0x40, 0x0B, 0xB1, 0x40, 0x90, 0x81, 0xB6, +0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x22, 0x90, 0x81, +0xB8, 0x12, 0x53, 0xBD, 0x80, 0xA9, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xB1, 0x84, 0xEF, +0x64, 0x01, 0x60, 0x05, 0x75, 0x0D, 0x01, 0x80, +0x40, 0x90, 0x81, 0x34, 0xE0, 0xFF, 0x54, 0x03, +0x60, 0x05, 0x75, 0x0D, 0x02, 0x80, 0x32, 0xEF, +0x30, 0xE2, 0x05, 0x75, 0x0D, 0x08, 0x80, 0x29, +0x90, 0x81, 0x34, 0xE0, 0x30, 0xE4, 0x05, 0x75, +0x0D, 0x10, 0x80, 0x1D, 0x31, 0xEB, 0x20, 0xE0, +0x05, 0x75, 0x0D, 0x20, 0x80, 0x13, 0xB1, 0xB9, +0x8F, 0x0E, 0xE5, 0x0E, 0x64, 0x01, 0x60, 0x05, +0x85, 0x0E, 0x0D, 0x80, 0x04, 0xB1, 0x48, 0x80, +0x0E, 0x90, 0x01, 0xB9, 0x74, 0x04, 0xF0, 0x90, +0x01, 0xB8, 0xE5, 0x0D, 0xF0, 0x7F, 0x00, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0xB1, 0x04, 0x90, 0x81, +0xB4, 0xEF, 0xF0, 0x30, 0xE0, 0x05, 0x7D, 0x01, +0xE4, 0x80, 0x02, 0xE4, 0xFD, 0xFF, 0x12, 0x4B, +0xE8, 0x90, 0x81, 0xB4, 0xE0, 0x30, 0xE6, 0x11, +0x90, 0x01, 0x2F, 0xE0, 0x30, 0xE7, 0x04, 0xE4, +0xF0, 0x80, 0x06, 0x90, 0x01, 0x2F, 0x74, 0x80, +0xF0, 0x90, 0x81, 0x2B, 0xE0, 0x30, 0xE0, 0x2E, +0x91, 0xF5, 0x30, 0xE1, 0x0D, 0xE0, 0x44, 0x04, +0xF0, 0x90, 0x04, 0xEC, 0xE0, 0x54, 0xFD, 0xF0, +0x80, 0x04, 0xE0, 0x54, 0xFB, 0xF0, 0x91, 0xF5, +0x30, 0xE5, 0x0D, 0xE0, 0x44, 0x08, 0xF0, 0x90, +0x04, 0xEC, 0xE0, 0x54, 0xDF, 0xF0, 0x80, 0x21, +0xE0, 0x54, 0xF7, 0xF0, 0x80, 0x1B, 0x90, 0x81, +0x2D, 0x31, 0xEE, 0x30, 0xE0, 0x07, 0x90, 0x04, +0xEC, 0xE0, 0x44, 0x02, 0xF0, 0x91, 0xFD, 0x30, +0xE0, 0x07, 0x90, 0x04, 0xEC, 0xE0, 0x44, 0x20, +0xF0, 0x12, 0x67, 0xC2, 0x90, 0x82, 0xB0, 0x74, +0x02, 0xF0, 0x02, 0x66, 0xA6, 0x90, 0x04, 0xEC, +0xE0, 0x90, 0x81, 0x2D, 0x22, 0xEF, 0x13, 0x13, +0x13, 0x54, 0x1F, 0x22, 0xE4, 0x90, 0x81, 0xB6, +0xF0, 0xA3, 0xF0, 0x90, 0x00, 0x83, 0xE0, 0x90, +0x81, 0xB5, 0xF0, 0x90, 0x00, 0x83, 0xE0, 0xFE, +0x90, 0x81, 0xB5, 0xE0, 0xFF, 0xB5, 0x06, 0x01, +0x22, 0xC3, 0x90, 0x81, 0xB7, 0xE0, 0x94, 0x64, +0x90, 0x81, 0xB6, 0xE0, 0x94, 0x00, 0x40, 0x08, +0xB1, 0x40, 0x90, 0x81, 0xB5, 0xE0, 0xFF, 0x22, +0x90, 0x81, 0xB6, 0x12, 0x53, 0xBD, 0x80, 0xCB, +0x90, 0x01, 0xC0, 0xE0, 0x44, 0x40, 0xF0, 0x22, +0x90, 0x01, 0xB8, 0xE4, 0xF0, 0x7F, 0x01, 0x22, +0x75, 0x2D, 0x20, 0xE4, 0xF5, 0x2E, 0xFB, 0x22, +0x90, 0x81, 0x36, 0xE0, 0x90, 0x05, 0x73, 0x22, +0x90, 0x81, 0x2E, 0xE0, 0xFF, 0xC4, 0x54, 0x0F, +0x22, 0x90, 0x81, 0x2B, 0xE0, 0x13, 0x13, 0x13, +0x54, 0x1F, 0x22, 0x90, 0x80, 0xFF, 0xE0, 0x60, +0x08, 0x90, 0x80, 0xFC, 0xE0, 0x44, 0x10, 0xF0, +0x22, 0x02, 0x5E, 0x93, 0x90, 0x04, 0x1A, 0xE0, +0xF4, 0x60, 0x03, 0x7F, 0x00, 0x22, 0x90, 0x04, +0x1B, 0xE0, 0x54, 0x07, 0x64, 0x07, 0x7F, 0x01, +0x60, 0x02, 0x7F, 0x00, 0x22, 0x12, 0x57, 0xED, +0x30, 0xE0, 0x15, 0xE4, 0x90, 0x80, 0xFF, 0xF0, +0x90, 0x80, 0xFC, 0xE0, 0x30, 0xE0, 0x09, 0xC4, +0x54, 0x0F, 0x30, 0xE0, 0x03, 0x12, 0x5E, 0x93, +0x22, 0x90, 0x81, 0x32, 0xE0, 0xD3, 0x94, 0x00, +0x40, 0x06, 0x75, 0x55, 0x04, 0x7F, 0xFF, 0x22, +0x90, 0x81, 0x93, 0xE0, 0x60, 0x06, 0x75, 0x55, +0x80, 0x7F, 0xFF, 0x22, 0x7F, 0x01, 0x22, 0x90, +0x81, 0x2B, 0xE0, 0x54, 0xFB, 0xF0, 0xE4, 0x90, +0x81, 0x39, 0xF0, 0xA3, 0xF0, 0x90, 0x81, 0x34, +0xF0, 0x90, 0x81, 0x2C, 0xE0, 0x54, 0xF7, 0xF0, +0x54, 0xBF, 0xF0, 0x12, 0x4F, 0xAF, 0x7D, 0x10, +0x7F, 0x03, 0x41, 0x79, 0x90, 0x81, 0xD3, 0x12, +0x44, 0xF4, 0xB1, 0xD7, 0x90, 0x81, 0x30, 0xE0, +0xFF, 0x12, 0x4E, 0x0C, 0x90, 0x81, 0x30, 0xE0, +0x60, 0x1B, 0x90, 0x81, 0xD3, 0x12, 0x57, 0x35, +0x54, 0x0F, 0xFF, 0x12, 0x57, 0x92, 0xFD, 0xD1, +0x56, 0x12, 0x67, 0xC2, 0x90, 0x82, 0xB0, 0x74, +0x01, 0xF0, 0x12, 0x66, 0xA6, 0x22, 0xE4, 0x90, +0x81, 0xB4, 0xF0, 0x90, 0x81, 0x30, 0xE0, 0x60, +0x1C, 0xE4, 0xFF, 0x12, 0x4E, 0x80, 0xBF, 0x01, +0x14, 0xB1, 0x58, 0xF0, 0x90, 0x81, 0xB4, 0x74, +0x01, 0xF0, 0xE4, 0x90, 0x81, 0x37, 0xF0, 0x04, +0x60, 0x03, 0x12, 0x49, 0xA2, 0x22, 0xEF, 0x24, +0xFE, 0x60, 0x0B, 0x04, 0x70, 0x24, 0x90, 0x81, +0x36, 0x74, 0x02, 0xF0, 0x80, 0x13, 0xED, 0x70, +0x06, 0x90, 0x81, 0x90, 0xE0, 0x80, 0x02, 0xED, +0x14, 0x90, 0x81, 0x36, 0xF0, 0x90, 0x81, 0x36, +0xE0, 0xA3, 0xF0, 0x90, 0x81, 0x2C, 0xE0, 0x44, +0x08, 0xF0, 0x22, 0x90, 0x81, 0x94, 0xE0, 0x30, +0xE0, 0x34, 0xC4, 0x13, 0x54, 0x07, 0x30, 0xE0, +0x2D, 0x90, 0x82, 0xC2, 0xE0, 0x04, 0xF0, 0xE0, +0xD3, 0x94, 0xC8, 0x40, 0x21, 0x90, 0x81, 0x94, +0xE0, 0x54, 0xDF, 0xF0, 0xE4, 0x90, 0x82, 0xC2, +0xF0, 0x90, 0x81, 0x94, 0xE0, 0x13, 0x30, 0xE0, +0x0D, 0x90, 0x81, 0x2B, 0xE0, 0x44, 0x01, 0xF0, +0x90, 0x81, 0x3B, 0x74, 0xD0, 0xF0, 0x22, 0x90, +0x81, 0x9D, 0xE0, 0x30, 0xE0, 0x35, 0x12, 0x4F, +0xC6, 0x70, 0x30, 0x90, 0x82, 0xC5, 0xE0, 0x04, +0xF0, 0xE0, 0xB4, 0x0A, 0x0B, 0x90, 0x81, 0x9F, +0xE0, 0x04, 0xF0, 0xE4, 0x90, 0x82, 0xC5, 0xF0, +0x90, 0x81, 0x9F, 0xE0, 0xFF, 0x90, 0x81, 0x9E, +0xE0, 0xD3, 0x9F, 0x50, 0x0E, 0x90, 0x81, 0xA0, +0xE0, 0x70, 0x08, 0xE4, 0x90, 0x81, 0x9F, 0xF0, +0x12, 0x5F, 0xB8, 0x22, 0x90, 0x02, 0x87, 0xE0, +0x60, 0x02, 0x80, 0x08, 0x90, 0x01, 0x00, 0xE0, +0x64, 0x3F, 0x60, 0x05, 0x75, 0x54, 0x01, 0x80, +0x22, 0x90, 0x02, 0x96, 0xE0, 0x60, 0x05, 0x75, +0x54, 0x10, 0x80, 0x17, 0x90, 0x02, 0x86, 0xE0, +0x20, 0xE1, 0x02, 0x80, 0x07, 0x90, 0x02, 0x86, +0xE0, 0x30, 0xE3, 0x05, 0x75, 0x54, 0x04, 0x80, +0x02, 0xA1, 0x48, 0x90, 0x01, 0xB9, 0x74, 0x08, +0xF0, 0x90, 0x01, 0xB8, 0xE5, 0x54, 0xF0, 0x7F, +0x00, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x7D, 0x08, 0xED, 0x14, 0xF9, 0x24, 0x22, +0xF1, 0x96, 0x60, 0x39, 0x7C, 0x08, 0xEC, 0x14, +0x90, 0x82, 0xBD, 0xF0, 0x74, 0x22, 0x29, 0xF1, +0x96, 0xFB, 0x7A, 0x00, 0x90, 0x82, 0xBD, 0x12, +0x5E, 0x04, 0x80, 0x05, 0xC3, 0x33, 0xCE, 0x33, +0xCE, 0xD8, 0xF9, 0xFF, 0xEE, 0x5A, 0xFE, 0xEF, +0x5B, 0x4E, 0x60, 0x0F, 0xE9, 0x75, 0xF0, 0x08, +0xA4, 0xFF, 0x90, 0x82, 0xBD, 0xE0, 0x2F, 0x04, +0xFF, 0x80, 0x06, 0xDC, 0xC9, 0xDD, 0xBC, 0x7F, +0x00, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xF5, 0x82, +0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0, 0x22, 0x75, +0x3D, 0x10, 0xE4, 0xF5, 0x3E, 0x75, 0x3F, 0x87, +0x75, 0x40, 0x03, 0x90, 0x01, 0x30, 0xE5, 0x3D, +0xF0, 0xA3, 0xE5, 0x3E, 0xF0, 0xA3, 0xE5, 0x3F, +0xF0, 0xA3, 0xE5, 0x40, 0xF0, 0x22, 0x75, 0x45, +0x0F, 0x75, 0x46, 0x01, 0x75, 0x47, 0x23, 0x75, +0x48, 0x62, 0x90, 0x01, 0x38, 0xE5, 0x45, 0xF0, +0xA3, 0xE5, 0x46, 0xF0, 0xA3, 0xE5, 0x47, 0xF0, +0xA3, 0xE5, 0x48, 0xF0, 0x22, 0x7F, 0x02, 0x90, +0x81, 0x9C, 0xE0, 0xFE, 0xEF, 0xC3, 0x9E, 0x50, +0x18, 0xEF, 0x25, 0xE0, 0x24, 0x81, 0xF8, 0xE6, +0x30, 0xE4, 0x0B, 0x90, 0x01, 0xB8, 0x74, 0x08, +0xF0, 0xA3, 0xF0, 0x7F, 0x00, 0x22, 0x0F, 0x80, +0xDE, 0x7F, 0x01, 0x22, 0x90, 0x01, 0x34, 0xE0, +0x55, 0x3D, 0xF5, 0x41, 0xA3, 0xE0, 0x55, 0x3E, +0xF5, 0x42, 0xA3, 0xE0, 0x55, 0x3F, 0xF5, 0x43, +0xA3, 0xE0, 0x55, 0x40, 0xF5, 0x44, 0x90, 0x01, +0x34, 0xE5, 0x41, 0xF0, 0xA3, 0xE5, 0x42, 0xF0, +0xA3, 0xE5, 0x43, 0xF0, 0xA3, 0xE5, 0x44, 0xF0, +0x22, 0x90, 0x01, 0x3C, 0xE0, 0x55, 0x45, 0xF5, +0x49, 0xA3, 0xE0, 0x55, 0x46, 0xF5, 0x4A, 0xA3, +0xE0, 0x55, 0x47, 0xF5, 0x4B, 0xA3, 0xE0, 0x55, +0x48, 0xF5, 0x4C, 0x90, 0x01, 0x3C, 0xE5, 0x49, +0xF0, 0xA3, 0xE5, 0x4A, 0xF0, 0xA3, 0xE5, 0x4B, +0xF0, 0xA3, 0xE5, 0x4C, 0xF0, 0x53, 0x91, 0xDF, +0x22, 0x90, 0x01, 0xCF, 0xE0, 0x90, 0x82, 0xBF, +0xF0, 0xE0, 0xFF, 0x30, 0xE0, 0x07, 0x90, 0x01, +0xCF, 0xE0, 0x54, 0xFE, 0xF0, 0xEF, 0x30, 0xE5, +0x23, 0x90, 0x01, 0xCF, 0xE0, 0x54, 0xDF, 0xF0, +0x90, 0x01, 0x34, 0x74, 0x20, 0xF0, 0xE4, 0xF5, +0xA8, 0xF5, 0xE8, 0x12, 0x50, 0x6F, 0x90, 0x00, +0x03, 0xE0, 0x54, 0xFB, 0xFD, 0x7F, 0x03, 0x12, +0x32, 0x1E, 0x80, 0xFE, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x82, 0xA6, 0xED, +0xF0, 0xA3, 0xEB, 0xF0, 0x90, 0x82, 0xA5, 0xEF, +0xF0, 0xE4, 0xFD, 0xFC, 0x31, 0x40, 0x7C, 0x00, +0xAD, 0x07, 0x90, 0x82, 0xA5, 0xE0, 0x90, 0x04, +0x25, 0xF0, 0x90, 0x82, 0xA6, 0xE0, 0x60, 0x0E, +0x74, 0x0F, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0xFC, +0xF5, 0x83, 0xE0, 0x44, 0x80, 0xF0, 0xAF, 0x05, +0x74, 0x08, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0xFC, +0xF5, 0x83, 0xE4, 0xF0, 0x74, 0x09, 0x2F, 0xF5, +0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x54, +0xF0, 0xF0, 0xAF, 0x05, 0x31, 0x54, 0xE0, 0x20, +0xE1, 0x15, 0x54, 0x01, 0xFE, 0x90, 0x82, 0xA7, +0xE0, 0x25, 0xE0, 0x25, 0xE0, 0xFB, 0xEE, 0x44, +0x02, 0x4B, 0xFE, 0x31, 0x54, 0xEE, 0xF0, 0x90, +0x82, 0xA8, 0xE0, 0xFF, 0xAE, 0x05, 0x74, 0x1E, +0x2E, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, +0xEF, 0xF0, 0x74, 0x21, 0x2E, 0x12, 0x5F, 0x79, +0x54, 0xF7, 0xF0, 0xAE, 0x04, 0xAF, 0x05, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x74, 0x2F, 0x2E, 0xF5, +0x82, 0xE4, 0x34, 0x82, 0xF5, 0x83, 0xE0, 0xFF, +0xE4, 0xFE, 0xEF, 0xC3, 0x13, 0xFD, 0xEF, 0x30, +0xE0, 0x02, 0x7E, 0x80, 0x90, 0xFD, 0x10, 0xED, +0xF0, 0xAF, 0x06, 0x22, 0x74, 0x16, 0x2F, 0xF5, +0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0x22, 0x90, +0x80, 0x0B, 0xE0, 0xFF, 0x90, 0x82, 0x9D, 0xE0, +0xFB, 0x90, 0x82, 0xA8, 0x74, 0x0A, 0xF0, 0x7D, +0x01, 0x11, 0x9D, 0x90, 0x82, 0x9E, 0xEE, 0xF0, +0xFC, 0xA3, 0xEF, 0xF0, 0xFD, 0x90, 0x82, 0x9C, +0xE0, 0xFF, 0x12, 0x5F, 0x3F, 0x90, 0x82, 0x9E, +0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x04, 0x80, +0xE0, 0x54, 0x0F, 0xFD, 0xAC, 0x07, 0x31, 0xF8, +0x44, 0x01, 0xF0, 0x31, 0xF8, 0x54, 0xFB, 0xF0, +0xAC, 0x07, 0x74, 0x16, 0x2C, 0x31, 0x57, 0xE0, +0x44, 0xFA, 0xF0, 0x74, 0x15, 0x2C, 0xF5, 0x82, +0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x1F, +0xF0, 0xAC, 0x07, 0x74, 0x06, 0x2C, 0xF5, 0x82, +0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x0F, +0xF0, 0x90, 0x04, 0x53, 0xE4, 0xF0, 0x90, 0x04, +0x52, 0xF0, 0x90, 0x04, 0x51, 0x74, 0xFF, 0xF0, +0x90, 0x04, 0x50, 0x74, 0xFD, 0xF0, 0x74, 0x14, +0x2C, 0x31, 0xF0, 0xE0, 0x54, 0xC0, 0x4D, 0xFD, +0x74, 0x14, 0x2F, 0x31, 0xF0, 0xED, 0xF0, 0x22, +0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0x22, +0x74, 0x11, 0x2C, 0xF5, 0x82, 0xE4, 0x34, 0xFC, +0xF5, 0x83, 0xE0, 0x22, 0x7D, 0x01, 0x11, 0x9D, +0x90, 0x81, 0xD0, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, +0xE4, 0x90, 0x81, 0xD6, 0xF0, 0x22, 0x90, 0x04, +0x1D, 0xE0, 0x70, 0x1C, 0x90, 0x80, 0x0A, 0xE0, +0xFF, 0x90, 0x82, 0xA8, 0x74, 0x09, 0xF0, 0x7B, +0x18, 0xE4, 0xFD, 0x11, 0x9D, 0x90, 0x81, 0xB2, +0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x12, 0x5F, 0xBE, +0x22, 0x90, 0x01, 0xC4, 0x74, 0x39, 0xF0, 0x74, +0x72, 0xA3, 0xF0, 0x90, 0x00, 0x90, 0xE0, 0x20, +0xE0, 0xF9, 0x74, 0x39, 0x04, 0x90, 0x01, 0xC4, +0xF0, 0x74, 0x72, 0xA3, 0xF0, 0x22, 0x90, 0x81, +0x3B, 0xE0, 0xFD, 0x7F, 0x93, 0x12, 0x32, 0x1E, +0x90, 0x81, 0x31, 0xE0, 0x60, 0x12, 0x90, 0x01, +0x2F, 0xE0, 0x30, 0xE7, 0x05, 0x74, 0x10, 0xF0, +0x80, 0x06, 0x90, 0x01, 0x2F, 0x74, 0x90, 0xF0, +0x90, 0x00, 0x08, 0xE0, 0x44, 0x10, 0xFD, 0x7F, +0x08, 0x12, 0x32, 0x1E, 0x7F, 0x01, 0x12, 0x53, +0xC4, 0x90, 0x81, 0x3B, 0xE0, 0x20, 0xE0, 0x0C, +0x90, 0x00, 0x26, 0xE0, 0x44, 0x80, 0xFD, 0x7F, +0x26, 0x12, 0x32, 0x1E, 0x90, 0x00, 0x90, 0xE0, +0x44, 0x01, 0xFD, 0x7F, 0x90, 0x12, 0x32, 0x1E, +0x7F, 0x14, 0x7E, 0x00, 0x02, 0x32, 0xAA, 0x90, +0x81, 0xAA, 0xE0, 0x54, 0x7F, 0xF0, 0x54, 0xBF, +0xF0, 0x54, 0xDF, 0xF0, 0x54, 0xF0, 0xF0, 0xE4, +0x90, 0x81, 0xAC, 0xF0, 0x90, 0x81, 0xAA, 0xE0, +0x54, 0xEF, 0xF0, 0x22, 0x7B, 0x2E, 0x51, 0xD7, +0x7D, 0x02, 0x7F, 0x01, 0x02, 0x4B, 0xE8, 0x7D, +0x6F, 0x7F, 0xFF, 0x02, 0x4C, 0x84, 0x90, 0x81, +0x2B, 0xE0, 0x30, 0xE0, 0x03, 0x12, 0x55, 0x38, +0x22, 0x90, 0x81, 0x94, 0xE0, 0x54, 0xFE, 0xF0, +0x54, 0xFD, 0xF0, 0x54, 0xEF, 0xF0, 0x44, 0x08, +0xF0, 0x22, 0x90, 0x82, 0x9C, 0xE0, 0xFF, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x82, +0xC3, 0xEF, 0xF0, 0xC3, 0x94, 0x02, 0x50, 0x47, +0x90, 0x80, 0x0B, 0xE0, 0xFF, 0x90, 0x04, 0x1C, +0xE0, 0x6F, 0x70, 0x3B, 0x90, 0x81, 0x33, 0xE0, +0x64, 0x0E, 0x70, 0x18, 0x90, 0x82, 0xC3, 0xE0, +0x70, 0x2D, 0x90, 0x81, 0x2B, 0xE0, 0x54, 0x7F, +0xF0, 0x71, 0x5C, 0x7D, 0x0C, 0x7F, 0x01, 0x12, +0x4B, 0xE8, 0x80, 0x18, 0x90, 0x81, 0x33, 0xE0, +0x64, 0x06, 0x70, 0x13, 0x90, 0x82, 0xC3, 0xE0, +0x60, 0x0D, 0x71, 0x64, 0x71, 0x6C, 0x90, 0x81, +0x33, 0x74, 0x04, 0xF0, 0x12, 0x4C, 0x7F, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x90, 0x06, 0x04, 0xE0, +0x54, 0x7F, 0xF0, 0x22, 0x90, 0x81, 0x2B, 0xE0, +0x54, 0xBF, 0xF0, 0x22, 0x90, 0x06, 0x04, 0xE0, +0x44, 0x40, 0xF0, 0xE0, 0x44, 0x80, 0xF0, 0x22, +0x71, 0x98, 0x90, 0x81, 0x9D, 0x12, 0x67, 0x85, +0x54, 0x04, 0xFF, 0xEE, 0x54, 0xFB, 0x4F, 0xF0, +0x12, 0x1F, 0xA4, 0xC3, 0x13, 0x30, 0xE0, 0x07, +0x12, 0x57, 0x38, 0x90, 0x81, 0x9E, 0xF0, 0x22, +0x12, 0x1F, 0xA4, 0xFF, 0x54, 0x01, 0xFE, 0x22, +0x90, 0x81, 0xCC, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, +0x90, 0x02, 0x84, 0xEF, 0xF0, 0xEE, 0xA3, 0xF0, +0xA3, 0xE0, 0x44, 0x01, 0xF0, 0x22, 0x7D, 0x7F, +0xEF, 0x5D, 0xC3, 0x60, 0x0A, 0x71, 0xCB, 0x24, +0x80, 0xFF, 0xE4, 0x3E, 0xFE, 0x80, 0x03, 0x71, +0xCB, 0xFF, 0x22, 0x74, 0xFF, 0x9D, 0xFD, 0x74, +0xFF, 0x94, 0x00, 0x5E, 0xFE, 0xED, 0x5F, 0x22, +0x7E, 0x00, 0x7F, 0x08, 0x7D, 0x00, 0x7B, 0x01, +0x7A, 0x81, 0x79, 0xA1, 0x12, 0x45, 0x23, 0x90, +0x81, 0xA2, 0x74, 0x08, 0xF0, 0xA3, 0x74, 0x03, +0xF0, 0x22, 0x90, 0x82, 0x4F, 0x12, 0x44, 0xF4, +0xE4, 0xFF, 0x90, 0x82, 0x55, 0xE0, 0xFE, 0xEF, +0xC3, 0x9E, 0x50, 0x1E, 0x90, 0x82, 0x52, 0x12, +0x44, 0xEB, 0x8F, 0x82, 0x91, 0x3B, 0xFE, 0x90, +0x82, 0x4F, 0x12, 0x44, 0xEB, 0x8F, 0x82, 0x91, +0x3B, 0x6E, 0x60, 0x03, 0x7F, 0x00, 0x22, 0x0F, +0x80, 0xD8, 0x7F, 0x01, 0x22, 0x75, 0xF0, 0x03, +0xA4, 0x24, 0x20, 0xF5, 0x82, 0xE4, 0x34, 0x82, +0xF5, 0x83, 0x12, 0x44, 0xEB, 0x90, 0x81, 0xD6, +0xE0, 0xF5, 0x82, 0x75, 0x83, 0x00, 0x02, 0x1F, +0xBD, 0x74, 0x03, 0xF0, 0x7A, 0x82, 0x79, 0x86, +0x71, 0xF2, 0xEF, 0x22, 0x74, 0x03, 0xF0, 0x7A, +0x82, 0x79, 0x82, 0x71, 0xF2, 0xEF, 0x22, 0x12, +0x57, 0x27, 0x30, 0xE0, 0x0A, 0xE0, 0xC4, 0x54, +0x0F, 0x30, 0xE0, 0x03, 0x02, 0x7B, 0x0A, 0x90, +0x81, 0x19, 0xE0, 0x90, 0x82, 0x2F, 0xF0, 0x90, +0x81, 0x1A, 0xE0, 0x90, 0x82, 0x30, 0xF0, 0x90, +0x81, 0x1B, 0xE0, 0x90, 0x82, 0x31, 0xF0, 0x90, +0x81, 0x1C, 0xE0, 0x90, 0x82, 0x32, 0xF0, 0x90, +0x81, 0x1D, 0xE0, 0x90, 0x82, 0x33, 0xF0, 0x90, +0x81, 0x0A, 0xE0, 0x90, 0x82, 0x34, 0xF0, 0x90, +0x81, 0x0B, 0xE0, 0x90, 0x82, 0x35, 0xF0, 0x90, +0x81, 0x0C, 0xE0, 0x90, 0x82, 0x36, 0xF0, 0x90, +0x81, 0x0D, 0xE0, 0x90, 0x82, 0x37, 0xF0, 0x90, +0x81, 0x0E, 0xE0, 0x90, 0x82, 0x38, 0xF0, 0x90, +0x81, 0x0F, 0xE0, 0x90, 0x82, 0x39, 0xF0, 0x90, +0x81, 0x10, 0xE0, 0x90, 0x82, 0x3A, 0xF0, 0x90, +0x81, 0x11, 0xE0, 0x90, 0x82, 0x3B, 0xF0, 0x90, +0x81, 0x12, 0xE0, 0x90, 0x82, 0x3C, 0xF0, 0x90, +0x81, 0x13, 0xE0, 0x90, 0x82, 0x3D, 0xF0, 0x12, +0x50, 0x95, 0x90, 0x81, 0xD7, 0xF0, 0x12, 0x7B, +0x2C, 0x50, 0x05, 0x12, 0x7B, 0x18, 0x80, 0xF6, +0x90, 0x01, 0x1F, 0xE0, 0xFE, 0x90, 0x01, 0x1E, +0x12, 0x7C, 0x5A, 0x90, 0x81, 0xCC, 0xF0, 0xA3, +0x12, 0x7B, 0x94, 0x12, 0x7B, 0x2C, 0x50, 0x57, +0x31, 0x34, 0x90, 0x81, 0xD7, 0xE0, 0xFE, 0x24, +0x3E, 0xF5, 0x82, 0xE4, 0x34, 0x82, 0x12, 0x7B, +0xFB, 0x24, 0x45, 0xF5, 0x82, 0xE4, 0x34, 0xFC, +0xF5, 0x83, 0xE0, 0xFF, 0x74, 0xD9, 0x2E, 0xF5, +0x82, 0xE4, 0x34, 0x81, 0x12, 0x7B, 0xFB, 0x24, +0x46, 0xF9, 0xE4, 0x34, 0xFC, 0xFA, 0x7B, 0x01, +0xEE, 0x12, 0x7B, 0x9D, 0x12, 0x44, 0xF4, 0x12, +0x7B, 0xFF, 0x24, 0x30, 0xF9, 0xE4, 0x34, 0xFC, +0xFA, 0xEE, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0x20, +0xF5, 0x82, 0xE4, 0x34, 0x82, 0xF5, 0x83, 0x12, +0x44, 0xF4, 0x12, 0x7B, 0x25, 0x80, 0xA4, 0x90, +0x02, 0x87, 0xE0, 0x70, 0x03, 0x02, 0x7B, 0x0A, +0x90, 0x80, 0xFC, 0xE0, 0x20, 0xE0, 0x03, 0x02, +0x7B, 0x0A, 0xC3, 0x13, 0x30, 0xE0, 0x0A, 0xE0, +0xC4, 0x54, 0x0F, 0x30, 0xE0, 0x03, 0x02, 0x7B, +0x0A, 0xE4, 0x90, 0x82, 0x48, 0x12, 0x50, 0x9D, +0x90, 0x81, 0xCC, 0xE0, 0xFF, 0xA3, 0xE0, 0xA3, +0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x81, 0xCE, +0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEC, 0x90, 0xFD, +0x11, 0xF0, 0x74, 0x01, 0x2D, 0xF5, 0x82, 0xE4, +0x34, 0xFB, 0xF5, 0x83, 0xE0, 0xFE, 0x74, 0x00, +0x2D, 0x12, 0x7C, 0x51, 0x7A, 0x00, 0x24, 0x00, +0xFF, 0xEA, 0x3E, 0x54, 0x3F, 0x90, 0x81, 0xD0, +0xF0, 0xA3, 0xEF, 0xF0, 0x74, 0x02, 0x2D, 0xF5, +0x82, 0xE4, 0x34, 0xFB, 0xF5, 0x83, 0xE0, 0x54, +0x0F, 0x33, 0x33, 0x33, 0x54, 0xF8, 0x90, 0x81, +0xD3, 0xF0, 0xFC, 0x74, 0x07, 0x2D, 0xF5, 0x82, +0xE4, 0x34, 0xFB, 0xF5, 0x83, 0xE0, 0x54, 0xC0, +0x90, 0x81, 0xD5, 0xF0, 0xEC, 0x24, 0x18, 0x90, +0x81, 0xD2, 0xF0, 0xFD, 0x90, 0x81, 0xCE, 0xE0, +0xFE, 0xA3, 0xE0, 0xFF, 0x12, 0x51, 0xA4, 0xEF, +0x54, 0xFC, 0x90, 0x81, 0xD4, 0xF0, 0x90, 0x81, +0xD3, 0xE0, 0x24, 0x18, 0xFF, 0xE4, 0x33, 0x90, +0x81, 0xD0, 0x8F, 0xF0, 0x12, 0x44, 0x9F, 0x90, +0x81, 0xD0, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x71, +0xB6, 0x90, 0x81, 0xCC, 0xEE, 0x8F, 0xF0, 0x12, +0x44, 0x9F, 0x90, 0x80, 0xFA, 0xE0, 0xFE, 0xA3, +0xE0, 0xFF, 0x90, 0x81, 0xCC, 0xE0, 0xFC, 0xA3, +0xE0, 0xFD, 0xD3, 0x9F, 0xEC, 0x9E, 0x40, 0x12, +0x90, 0x80, 0xFB, 0x12, 0x7C, 0x2C, 0xED, 0x9F, +0xFF, 0xEC, 0x9E, 0x90, 0x81, 0xCC, 0xF0, 0xA3, +0xEF, 0xF0, 0x12, 0x57, 0x27, 0x20, 0xE0, 0x03, +0x02, 0x78, 0x99, 0xE4, 0x90, 0x81, 0xD8, 0xF0, +0x90, 0x81, 0xD7, 0xF0, 0x12, 0x7B, 0x2C, 0x50, +0x37, 0x31, 0x34, 0xE4, 0x90, 0x81, 0xD6, 0xF0, +0x12, 0x7B, 0x4C, 0x94, 0x06, 0x50, 0x15, 0x12, +0x7B, 0x0B, 0x24, 0x04, 0xFC, 0xED, 0x2C, 0x12, +0x52, 0xD1, 0x91, 0x25, 0xB5, 0x07, 0x05, 0x12, +0x52, 0x78, 0x80, 0xE4, 0x90, 0x81, 0xD6, 0xE0, +0xB4, 0x06, 0x08, 0x90, 0x81, 0xD8, 0x74, 0x01, +0xF0, 0x80, 0x05, 0x12, 0x7B, 0x25, 0x80, 0xC4, +0x90, 0x81, 0xD4, 0xE0, 0x24, 0x60, 0x70, 0x03, +0x02, 0x78, 0x44, 0x24, 0xFC, 0x70, 0x03, 0x02, +0x78, 0x44, 0x24, 0xF4, 0x70, 0x03, 0x02, 0x78, +0x39, 0x24, 0xF0, 0x70, 0x03, 0x02, 0x78, 0x44, +0x24, 0x80, 0x60, 0x03, 0x02, 0x78, 0x58, 0x12, +0x7B, 0x0B, 0x24, 0x18, 0xFD, 0x12, 0x51, 0xA4, +0xEF, 0x60, 0x03, 0x02, 0x79, 0xF3, 0x12, 0x7B, +0x0B, 0x24, 0x19, 0xFD, 0x12, 0x51, 0xA4, 0x90, +0x81, 0xED, 0x51, 0x0E, 0x12, 0x7B, 0x47, 0x9F, +0x50, 0x0B, 0x12, 0x7B, 0x0B, 0x12, 0x52, 0xD9, +0x12, 0x52, 0x74, 0x80, 0xEF, 0x90, 0x81, 0xED, +0xE0, 0x70, 0x02, 0xE1, 0x87, 0xE4, 0x90, 0x81, +0xD7, 0xF0, 0x12, 0x7B, 0x2C, 0x50, 0x67, 0x31, +0x34, 0x12, 0x7B, 0xBB, 0x70, 0x1E, 0x12, 0x7B, +0x9C, 0x12, 0x44, 0xEB, 0xC0, 0x03, 0xC0, 0x02, +0xC0, 0x01, 0x12, 0x7B, 0x53, 0xED, 0xF0, 0xD0, +0x01, 0xD0, 0x02, 0xD0, 0x03, 0x71, 0xF2, 0xEF, +0x60, 0x02, 0x80, 0x28, 0x90, 0x81, 0xED, 0xE0, +0x64, 0x03, 0x70, 0x2D, 0x12, 0x7B, 0x53, 0x91, +0x41, 0x70, 0x07, 0x12, 0x7B, 0x53, 0x91, 0x4C, +0x60, 0x1A, 0x12, 0x7B, 0xAB, 0x60, 0x02, 0x80, +0x06, 0x12, 0x7B, 0x6A, 0xE0, 0x60, 0x05, 0x74, +0x48, 0x2F, 0x80, 0x10, 0x12, 0x7B, 0x39, 0x74, +0x01, 0xF0, 0x80, 0x0D, 0x12, 0x7B, 0x63, 0x80, +0x03, 0x12, 0x7B, 0x63, 0x12, 0x7B, 0x3F, 0xE4, +0xF0, 0x12, 0x7B, 0x25, 0x80, 0x94, 0x90, 0x82, +0x48, 0xE0, 0x70, 0x57, 0xA3, 0xE0, 0x70, 0x53, +0xA3, 0xE0, 0x70, 0x4F, 0xA3, 0xE0, 0x70, 0x4B, +0xA3, 0xE0, 0x70, 0x47, 0x02, 0x79, 0xF3, 0xE4, +0x90, 0x81, 0xD7, 0xF0, 0x12, 0x7B, 0x2C, 0x50, +0x21, 0x74, 0x34, 0x2E, 0x12, 0x7B, 0x71, 0xE0, +0x60, 0x0A, 0x74, 0x48, 0x2E, 0x12, 0x7B, 0x3F, +0xE4, 0xF0, 0x80, 0x09, 0x74, 0x48, 0x2E, 0x12, +0x7B, 0x3F, 0x74, 0x01, 0xF0, 0x12, 0x7B, 0x25, +0x80, 0xDA, 0x90, 0x82, 0x48, 0xE0, 0x70, 0x13, +0xA3, 0xE0, 0x70, 0x0F, 0xA3, 0xE0, 0x70, 0x0B, +0xA3, 0xE0, 0x70, 0x07, 0xA3, 0xE0, 0x70, 0x03, +0x02, 0x79, 0xF3, 0xE4, 0x90, 0x81, 0xD7, 0xF0, +0x12, 0x7B, 0x2C, 0x40, 0x03, 0x02, 0x79, 0xF3, +0x31, 0x34, 0x12, 0x7B, 0x39, 0xE0, 0x60, 0x55, +0x90, 0x81, 0x94, 0xE0, 0x30, 0xE0, 0x06, 0xC4, +0x54, 0x0F, 0x30, 0xE0, 0x48, 0x12, 0x7B, 0x79, +0x90, 0x04, 0x1D, 0xE0, 0x60, 0x1B, 0xD3, 0x90, +0x82, 0x4E, 0xE0, 0x94, 0x28, 0x90, 0x82, 0x4D, +0xE0, 0x94, 0x00, 0x50, 0x0C, 0x7F, 0xFA, 0x7E, +0x00, 0x12, 0x32, 0xAA, 0x12, 0x53, 0xBA, 0x80, +0xDF, 0x90, 0x04, 0x1D, 0xE0, 0x70, 0x1E, 0x71, +0x81, 0x74, 0x0A, 0xF0, 0xE4, 0xFB, 0x12, 0x72, +0x04, 0x71, 0x4C, 0x94, 0x06, 0x50, 0x07, 0x71, +0x0B, 0x12, 0x52, 0x5A, 0x80, 0xF3, 0x12, 0x5F, +0xBE, 0x90, 0x06, 0x35, 0xF0, 0x71, 0x25, 0x80, +0x97, 0x90, 0x81, 0xD8, 0xE0, 0xB4, 0x01, 0x02, +0x80, 0x4F, 0x61, 0x04, 0x90, 0x81, 0xD8, 0xE0, +0xB4, 0x01, 0x0B, 0x90, 0x80, 0xFC, 0x12, 0x69, +0xEE, 0x30, 0xE0, 0x02, 0x80, 0x3B, 0x61, 0x04, +0x90, 0x81, 0xD5, 0xE0, 0x70, 0x12, 0x90, 0x81, +0xD8, 0xE0, 0xB4, 0x01, 0x0B, 0x90, 0x80, 0xFC, +0xE0, 0x13, 0x13, 0x54, 0x3F, 0x20, 0xE0, 0x02, +0x61, 0x04, 0x71, 0x0B, 0xFD, 0x12, 0x52, 0x88, +0xEF, 0x60, 0x02, 0x80, 0x14, 0x71, 0x0B, 0xFD, +0x12, 0x52, 0x30, 0xEF, 0x60, 0x02, 0x80, 0x09, +0x71, 0x0B, 0xFD, 0x12, 0x51, 0xD4, 0xEF, 0x60, +0x06, 0x12, 0x6D, 0x73, 0x02, 0x75, 0x5F, 0x61, +0x04, 0x90, 0x81, 0xD4, 0xE0, 0x24, 0xC0, 0x60, +0x02, 0x21, 0xFF, 0x71, 0x0B, 0x24, 0x18, 0xFD, +0x12, 0x51, 0xA4, 0xEF, 0x60, 0x02, 0x21, 0xF3, +0x71, 0x0B, 0x24, 0x19, 0xFD, 0x12, 0x51, 0xA4, +0x90, 0x81, 0xED, 0x12, 0x72, 0x0E, 0x71, 0x47, +0x9F, 0x50, 0x0A, 0x71, 0x0B, 0x12, 0x52, 0xD9, +0x12, 0x52, 0x74, 0x80, 0xF1, 0x90, 0x81, 0xED, +0xE0, 0x70, 0x02, 0x21, 0x55, 0xE4, 0x90, 0x81, +0xD7, 0xF0, 0x71, 0x2C, 0x50, 0x5F, 0x12, 0x71, +0x34, 0x71, 0xBB, 0x70, 0x1D, 0x71, 0x9C, 0x12, +0x44, 0xEB, 0xC0, 0x03, 0xC0, 0x02, 0xC0, 0x01, +0x71, 0x53, 0xED, 0xF0, 0xD0, 0x01, 0xD0, 0x02, +0xD0, 0x03, 0x12, 0x73, 0xF2, 0xEF, 0x60, 0x02, +0x80, 0x26, 0x90, 0x81, 0xED, 0xE0, 0x64, 0x03, +0x70, 0x29, 0x71, 0x53, 0x12, 0x74, 0x41, 0x70, +0x07, 0x71, 0x53, 0x12, 0x74, 0x4C, 0x60, 0x17, +0x71, 0xAB, 0x60, 0x02, 0x80, 0x05, 0x71, 0x6A, +0xE0, 0x60, 0x05, 0x74, 0x48, 0x2F, 0x80, 0x0D, +0x71, 0x39, 0x74, 0x01, 0xF0, 0x80, 0x0A, 0x71, +0x63, 0x80, 0x02, 0x71, 0x63, 0x71, 0x3F, 0xE4, +0xF0, 0x71, 0x25, 0x80, 0x9D, 0x90, 0x82, 0x48, +0xE0, 0x70, 0x4E, 0xA3, 0xE0, 0x70, 0x4A, 0xA3, +0xE0, 0x70, 0x46, 0xA3, 0xE0, 0x70, 0x42, 0xA3, +0xE0, 0x70, 0x3E, 0x21, 0xF3, 0xE4, 0x90, 0x81, +0xD7, 0xF0, 0x71, 0x2C, 0x50, 0x1D, 0x74, 0x34, +0x2E, 0x71, 0x71, 0xE0, 0x60, 0x09, 0x74, 0x48, +0x2E, 0x71, 0x3F, 0xE4, 0xF0, 0x80, 0x08, 0x74, +0x48, 0x2E, 0x71, 0x3F, 0x74, 0x01, 0xF0, 0x71, +0x25, 0x80, 0xDF, 0x90, 0x82, 0x48, 0xE0, 0x70, +0x10, 0xA3, 0xE0, 0x70, 0x0C, 0xA3, 0xE0, 0x70, +0x08, 0xA3, 0xE0, 0x70, 0x04, 0xA3, 0xE0, 0x60, +0x62, 0xE4, 0x90, 0x81, 0xD7, 0xF0, 0x71, 0x2C, +0x50, 0x59, 0x12, 0x71, 0x34, 0x71, 0x39, 0xE0, +0x60, 0x4D, 0x90, 0x81, 0x94, 0xE0, 0x30, 0xE0, +0x06, 0xC4, 0x54, 0x0F, 0x30, 0xE0, 0x40, 0x71, +0x79, 0x90, 0x04, 0x1D, 0xE0, 0x60, 0x14, 0xD3, +0x90, 0x82, 0x4E, 0xE0, 0x94, 0xE8, 0x90, 0x82, +0x4D, 0xE0, 0x94, 0x03, 0x50, 0x05, 0x12, 0x53, +0xBA, 0x80, 0xE6, 0x90, 0x04, 0x1D, 0xE0, 0x70, +0x1E, 0x71, 0x81, 0x74, 0x06, 0xF0, 0x7B, 0x08, +0x12, 0x72, 0x04, 0x71, 0x4C, 0x94, 0x06, 0x50, +0x07, 0x71, 0x0B, 0x12, 0x52, 0x5A, 0x80, 0xF3, +0x12, 0x5F, 0xBE, 0x90, 0x06, 0x35, 0xF0, 0x71, +0x25, 0x80, 0xA3, 0x12, 0x73, 0xA0, 0x90, 0x06, +0x36, 0x74, 0xDD, 0xF0, 0x02, 0x75, 0x5F, 0x90, +0x81, 0xD5, 0xE0, 0x60, 0x02, 0x61, 0x04, 0x71, +0x0B, 0x24, 0x16, 0xFD, 0x12, 0x51, 0xA4, 0x90, +0x06, 0x34, 0xEF, 0xF0, 0x71, 0x0B, 0x24, 0x17, +0xFD, 0x12, 0x51, 0xA4, 0x90, 0x06, 0x37, 0x71, +0x94, 0x71, 0x2C, 0x50, 0x34, 0x12, 0x71, 0x34, +0xE4, 0x90, 0x81, 0xD6, 0xF0, 0x71, 0x4C, 0x94, +0x06, 0x50, 0x22, 0x71, 0x0B, 0x24, 0x04, 0x2D, +0x12, 0x52, 0xD1, 0xFE, 0x12, 0x74, 0x25, 0x6F, +0x60, 0x0E, 0x74, 0x43, 0x2E, 0xF5, 0x82, 0xE4, +0x34, 0x82, 0xF5, 0x83, 0xE4, 0xF0, 0x80, 0x05, +0x12, 0x52, 0x78, 0x80, 0xD8, 0x71, 0x25, 0x80, +0xC8, 0x90, 0x82, 0x43, 0xE0, 0x64, 0x01, 0x60, +0x17, 0xA3, 0xE0, 0x64, 0x01, 0x60, 0x11, 0xA3, +0xE0, 0x64, 0x01, 0x60, 0x0B, 0xA3, 0xE0, 0x64, +0x01, 0x60, 0x05, 0xA3, 0xE0, 0xB4, 0x01, 0x06, +0x90, 0x81, 0xD8, 0x74, 0x01, 0xF0, 0x90, 0x81, +0xD8, 0xE0, 0x64, 0x01, 0x70, 0x6F, 0x12, 0x6A, +0xFA, 0x12, 0x4F, 0xE5, 0x30, 0xE0, 0x0D, 0xE0, +0xC3, 0x13, 0x30, 0xE0, 0x40, 0x90, 0x81, 0x2B, +0xE0, 0x30, 0xE0, 0x39, 0x12, 0x5E, 0x96, 0x90, +0x81, 0x1E, 0xE0, 0x70, 0x03, 0x02, 0x75, 0x5F, +0x90, 0x01, 0x3C, 0xE0, 0x30, 0xE4, 0x03, 0x74, +0x10, 0xF0, 0x12, 0x6A, 0x8C, 0x90, 0x81, 0x1F, +0xE0, 0x60, 0x07, 0xF5, 0x2D, 0xE4, 0xF5, 0x2E, +0x80, 0x26, 0x90, 0x81, 0x20, 0xE0, 0x60, 0x08, +0xFB, 0xE4, 0xF5, 0x2D, 0xF5, 0x2E, 0x80, 0x19, +0x12, 0x6D, 0x50, 0x80, 0x14, 0x90, 0x01, 0x3C, +0xE0, 0x30, 0xE4, 0x03, 0x74, 0x10, 0xF0, 0x12, +0x6A, 0x8C, 0xE4, 0xF5, 0x2D, 0x75, 0x2E, 0x9C, +0xFB, 0x7D, 0x01, 0x7F, 0x60, 0x7E, 0x01, 0x12, +0x31, 0x21, 0x02, 0x75, 0x5F, 0x12, 0x50, 0x95, +0x90, 0x81, 0xD7, 0xF0, 0x71, 0x2C, 0x50, 0x04, +0x71, 0x18, 0x80, 0xF8, 0x12, 0x73, 0xA0, 0x02, +0x75, 0x5F, 0x22, 0x90, 0x81, 0xCE, 0xE0, 0xFE, +0xA3, 0xE0, 0xFF, 0x90, 0x81, 0xD2, 0xE0, 0x22, +0x74, 0x43, 0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x82, +0xF5, 0x83, 0x74, 0x01, 0xF0, 0x90, 0x81, 0xD7, +0xE0, 0x04, 0xF0, 0x22, 0x90, 0x81, 0x07, 0xE0, +0xFF, 0x90, 0x81, 0xD7, 0xE0, 0xFE, 0xC3, 0x9F, +0x22, 0x90, 0x81, 0xD7, 0xE0, 0x24, 0x48, 0xF5, +0x82, 0xE4, 0x34, 0x82, 0xF5, 0x83, 0x22, 0x90, +0x81, 0xED, 0xE0, 0xFF, 0x90, 0x81, 0xD6, 0xE0, +0xFD, 0xC3, 0x22, 0x7B, 0x01, 0x7A, 0x81, 0x79, +0xEE, 0x90, 0x82, 0x52, 0x12, 0x44, 0xF4, 0x90, +0x82, 0x55, 0x22, 0x90, 0x81, 0xD7, 0xE0, 0x24, +0x48, 0x22, 0x90, 0x81, 0xD7, 0xE0, 0xFF, 0x24, +0x34, 0xF5, 0x82, 0xE4, 0x34, 0x82, 0xF5, 0x83, +0x22, 0xE4, 0x90, 0x82, 0x4D, 0xF0, 0xA3, 0xF0, +0x22, 0x90, 0x81, 0xD7, 0xE0, 0x24, 0x2F, 0xF5, +0x82, 0xE4, 0x34, 0x82, 0xF5, 0x83, 0xE0, 0xFF, +0x90, 0x82, 0xA8, 0x22, 0xEF, 0xF0, 0xE4, 0x90, +0x81, 0xD7, 0xF0, 0x22, 0xEF, 0x75, 0xF0, 0x03, +0xA4, 0x24, 0xDE, 0xF5, 0x82, 0xE4, 0x34, 0x81, +0xF5, 0x83, 0x22, 0x90, 0x81, 0xD7, 0xE0, 0xFF, +0x24, 0x39, 0xF5, 0x82, 0xE4, 0x34, 0x82, 0xF5, +0x83, 0xE0, 0x22, 0x90, 0x81, 0xD7, 0xE0, 0xFF, +0x24, 0xD9, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, +0x83, 0xE0, 0xFE, 0x90, 0x81, 0xED, 0xE0, 0xFD, +0xEE, 0x6D, 0x22, 0xEF, 0x30, 0xE7, 0x04, 0x7E, +0x02, 0x80, 0x02, 0xE4, 0xFE, 0xED, 0x30, 0xE6, +0x12, 0xEB, 0x20, 0xE0, 0x07, 0x90, 0x81, 0x01, +0xE0, 0xFC, 0x80, 0x09, 0x90, 0x81, 0x02, 0xE0, +0xFC, 0x80, 0x02, 0xE4, 0xFC, 0xEE, 0x24, 0x18, +0x2C, 0xFF, 0x22, 0xF5, 0x83, 0xEF, 0xF0, 0x74, +0x3E, 0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x82, 0xF5, +0x83, 0xE0, 0x22, 0x90, 0x00, 0xB6, 0x74, 0x10, +0xF0, 0x90, 0x00, 0xBE, 0x74, 0xE0, 0xF0, 0xA3, +0x74, 0x01, 0xF0, 0x22, 0xF0, 0x90, 0x81, 0x4D, +0xE0, 0x24, 0x05, 0x90, 0x81, 0x48, 0xF0, 0xA3, +0x74, 0x10, 0xF0, 0x22, 0xE0, 0x24, 0x01, 0xFF, +0x90, 0x80, 0xFA, 0xE0, 0x34, 0x00, 0xFE, 0xC3, +0x22, 0xE0, 0x90, 0x01, 0xBA, 0xF0, 0x90, 0x81, +0x32, 0xE0, 0x90, 0x01, 0xBB, 0x22, 0x90, 0x81, +0x39, 0xE0, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0xFE, +0x22, 0xF5, 0x82, 0xE4, 0x34, 0xFB, 0xF5, 0x83, +0xE0, 0x22, 0xE0, 0x7C, 0x00, 0x24, 0x00, 0xFF, +0xEC, 0x3E, 0x22, 0x90, 0x06, 0x0A, 0xE0, 0x54, +0xF8, 0xF0, 0x22, 0x00, 0xBB, 0x50 +}; + +u32 array_length_mp_8188e_t_fw_ap = 15502; + +#endif /*defined(CONFIG_AP_WOWLAN)*/ + +u8 array_mp_8188e_t_fw_nic[] = { +0xE1, 0x88, 0x10, 0x00, 0x1C, 0x00, 0x00, 0x00, +0x05, 0x05, 0x14, 0x27, 0x7E, 0x3B, 0x00, 0x00, +0xA5, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x02, 0x45, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xC1, 0xBE, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xC1, 0x35, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xE1, 0xF6, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xC2, 0xAF, 0x80, 0xFE, 0x32, 0x12, 0x41, 0x04, +0x85, 0xD0, 0x0B, 0x75, 0xD0, 0x08, 0xAA, 0xE0, +0xC2, 0x8C, 0xE5, 0x8A, 0x24, 0x67, 0xF5, 0x8A, +0xE5, 0x8C, 0x34, 0x79, 0xF5, 0x8C, 0xD2, 0x8C, +0xEC, 0x24, 0x87, 0xF8, 0xE6, 0xBC, 0x02, 0x02, +0x74, 0xFF, 0xC3, 0x95, 0x81, 0xB4, 0x40, 0x00, +0x40, 0xCE, 0x79, 0x03, 0x78, 0x80, 0x16, 0xE6, +0x08, 0x70, 0x0B, 0xC2, 0xAF, 0xE6, 0x30, 0xE1, +0x03, 0x44, 0x18, 0xF6, 0xD2, 0xAF, 0x08, 0xD9, +0xED, 0xEA, 0x8B, 0xD0, 0x22, 0xE5, 0x0C, 0xFF, +0x23, 0x24, 0x81, 0xF8, 0x0F, 0x08, 0x08, 0xBF, +0x03, 0x04, 0x7F, 0x00, 0x78, 0x81, 0xE6, 0x30, +0xE4, 0xF2, 0x00, 0xE5, 0x0C, 0xC3, 0x9F, 0x50, +0x20, 0x05, 0x0C, 0x74, 0x86, 0x25, 0x0C, 0xF8, +0xE6, 0xFD, 0xA6, 0x81, 0x08, 0xE6, 0xAE, 0x0C, +0xBE, 0x02, 0x02, 0x74, 0xFF, 0xCD, 0xF8, 0xE8, +0x6D, 0x60, 0xE0, 0x08, 0xE6, 0xC0, 0xE0, 0x80, +0xF6, 0xE5, 0x0C, 0xD3, 0x9F, 0x40, 0x27, 0xE5, +0x0C, 0x24, 0x87, 0xF8, 0xE6, 0xAE, 0x0C, 0xBE, +0x02, 0x02, 0x74, 0xFF, 0xFD, 0x18, 0xE6, 0xCD, +0xF8, 0xE5, 0x81, 0x6D, 0x60, 0x06, 0xD0, 0xE0, +0xF6, 0x18, 0x80, 0xF5, 0xE5, 0x0C, 0x24, 0x86, +0xC8, 0xF6, 0x15, 0x0C, 0x80, 0xD3, 0xE5, 0x0C, +0x23, 0x24, 0x81, 0xF8, 0x7F, 0x04, 0xC2, 0xAF, +0xE6, 0x30, 0xE0, 0x03, 0x10, 0xE2, 0x0C, 0x7F, +0x00, 0x30, 0xE1, 0x07, 0x30, 0xE3, 0x04, 0x7F, +0x08, 0x54, 0xF4, 0x54, 0x7C, 0xC6, 0xD2, 0xAF, +0x54, 0x80, 0x42, 0x07, 0x22, 0x78, 0x86, 0xA6, +0x81, 0x74, 0x02, 0x60, 0x06, 0xFF, 0x08, 0x76, +0xFF, 0xDF, 0xFB, 0x7F, 0x03, 0xE4, 0x78, 0x80, +0xF6, 0x08, 0xF6, 0x08, 0xDF, 0xFA, 0x78, 0x81, +0x76, 0x30, 0x90, 0x46, 0x2F, 0x74, 0x01, 0x93, +0xC0, 0xE0, 0xE4, 0x93, 0xC0, 0xE0, 0x43, 0x89, +0x01, 0x75, 0x8A, 0x60, 0x75, 0x8C, 0x79, 0xD2, +0x8C, 0xD2, 0xAF, 0x22, 0x02, 0xEF, 0xD3, 0x94, +0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, 0x74, 0x81, +0x2F, 0x2F, 0xF8, 0xE6, 0x20, 0xE5, 0xF4, 0xC2, +0xAF, 0xE6, 0x44, 0x30, 0xF6, 0xD2, 0xAF, 0xAE, +0x0C, 0xEE, 0xC3, 0x9F, 0x50, 0x21, 0x0E, 0x74, +0x86, 0x2E, 0xF8, 0xE6, 0xF9, 0x08, 0xE6, 0x18, +0xBE, 0x02, 0x02, 0x74, 0xFF, 0xFD, 0xED, 0x69, +0x60, 0x09, 0x09, 0xE7, 0x19, 0x19, 0xF7, 0x09, +0x09, 0x80, 0xF3, 0x16, 0x16, 0x80, 0xDA, 0xEE, +0xD3, 0x9F, 0x40, 0x04, 0x05, 0x81, 0x05, 0x81, +0xEE, 0xD3, 0x9F, 0x40, 0x22, 0x74, 0x86, 0x2E, +0xF8, 0x08, 0xE6, 0xF9, 0xEE, 0xB5, 0x0C, 0x02, +0xA9, 0x81, 0x18, 0x06, 0x06, 0xE6, 0xFD, 0xED, +0x69, 0x60, 0x09, 0x19, 0x19, 0xE7, 0x09, 0x09, +0xF7, 0x19, 0x80, 0xF3, 0x1E, 0x80, 0xD9, 0xEF, +0x24, 0x86, 0xF8, 0xE6, 0x04, 0xF8, 0xEF, 0x2F, +0x04, 0x90, 0x46, 0x2F, 0x93, 0xF6, 0x08, 0xEF, +0x2F, 0x93, 0xF6, 0x7F, 0x00, 0x22, 0xEF, 0xD3, +0x94, 0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, 0xEF, +0x23, 0x24, 0x81, 0xF8, 0xE6, 0x30, 0xE5, 0xF4, +0xC2, 0xAF, 0xE6, 0x54, 0x8C, 0xF6, 0xD2, 0xAF, +0xE5, 0x0C, 0xB5, 0x07, 0x0A, 0x74, 0x86, 0x2F, +0xF8, 0xE6, 0xF5, 0x81, 0x02, 0x41, 0x4D, 0x50, +0x2E, 0x74, 0x87, 0x2F, 0xF8, 0xE6, 0xBF, 0x02, +0x02, 0x74, 0xFF, 0xFD, 0x18, 0xE6, 0xF9, 0x74, +0x86, 0x2F, 0xF8, 0xFB, 0xE6, 0xFC, 0xE9, 0x6C, +0x60, 0x08, 0xA8, 0x05, 0xE7, 0xF6, 0x1D, 0x19, +0x80, 0xF4, 0xA8, 0x03, 0xA6, 0x05, 0x1F, 0xE5, +0x0C, 0xB5, 0x07, 0xE3, 0x7F, 0x00, 0x22, 0x74, +0x87, 0x2F, 0xF8, 0xE6, 0xFD, 0x18, 0x86, 0x01, +0x0F, 0x74, 0x86, 0x2F, 0xF8, 0xA6, 0x01, 0x08, +0x86, 0x04, 0xE5, 0x0C, 0xB5, 0x07, 0x02, 0xAC, +0x81, 0xED, 0x6C, 0x60, 0x08, 0x0D, 0x09, 0xA8, +0x05, 0xE6, 0xF7, 0x80, 0xF4, 0xE5, 0x0C, 0xB5, +0x07, 0xDE, 0x89, 0x81, 0x7F, 0x00, 0x22, 0xEF, +0xD3, 0x94, 0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, +0xEF, 0x23, 0x24, 0x81, 0xF8, 0xC2, 0xAF, 0xE6, +0x30, 0xE5, 0x05, 0x30, 0xE0, 0x02, 0xD2, 0xE4, +0xD2, 0xE2, 0xC6, 0xD2, 0xAF, 0x7F, 0x00, 0x30, +0xE2, 0x01, 0x0F, 0x02, 0x41, 0x4C, 0x8F, 0xF0, +0xE4, 0xFF, 0xFE, 0xE5, 0x0C, 0x23, 0x24, 0x80, +0xF8, 0xC2, 0xA9, 0x30, 0xF7, 0x0D, 0x7F, 0x08, +0xE6, 0x60, 0x0B, 0x2D, 0xF6, 0x60, 0x30, 0x50, +0x2E, 0x80, 0x07, 0x30, 0xF1, 0x06, 0xED, 0xF6, +0x60, 0x25, 0x7E, 0x02, 0x08, 0x30, 0xF0, 0x10, +0xC2, 0xAF, 0xE6, 0x10, 0xE7, 0x23, 0x0E, 0x30, +0xE2, 0x0C, 0xD2, 0xAF, 0x7F, 0x04, 0x80, 0x12, +0xC2, 0xAF, 0xE6, 0x10, 0xE7, 0x13, 0x54, 0xEC, +0x4E, 0xF6, 0xD2, 0xAF, 0x02, 0x41, 0x4D, 0x7F, +0x08, 0x08, 0xEF, 0x44, 0x83, 0xF4, 0xC2, 0xAF, +0x56, 0xC6, 0xD2, 0xAF, 0x54, 0x80, 0x4F, 0xFF, +0x22, 0xE7, 0x09, 0xF6, 0x08, 0xDF, 0xFA, 0x80, +0x46, 0xE7, 0x09, 0xF2, 0x08, 0xDF, 0xFA, 0x80, +0x3E, 0x88, 0x82, 0x8C, 0x83, 0xE7, 0x09, 0xF0, +0xA3, 0xDF, 0xFA, 0x80, 0x32, 0xE3, 0x09, 0xF6, +0x08, 0xDF, 0xFA, 0x80, 0x78, 0xE3, 0x09, 0xF2, +0x08, 0xDF, 0xFA, 0x80, 0x70, 0x88, 0x82, 0x8C, +0x83, 0xE3, 0x09, 0xF0, 0xA3, 0xDF, 0xFA, 0x80, +0x64, 0x89, 0x82, 0x8A, 0x83, 0xE0, 0xA3, 0xF6, +0x08, 0xDF, 0xFA, 0x80, 0x58, 0x89, 0x82, 0x8A, +0x83, 0xE0, 0xA3, 0xF2, 0x08, 0xDF, 0xFA, 0x80, +0x4C, 0x80, 0xD2, 0x80, 0xFA, 0x80, 0xC6, 0x80, +0xD4, 0x80, 0x69, 0x80, 0xF2, 0x80, 0x33, 0x80, +0x10, 0x80, 0xA6, 0x80, 0xEA, 0x80, 0x9A, 0x80, +0xA8, 0x80, 0xDA, 0x80, 0xE2, 0x80, 0xCA, 0x80, +0x33, 0x89, 0x82, 0x8A, 0x83, 0xEC, 0xFA, 0xE4, +0x93, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, 0xC5, +0x83, 0xCC, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, +0xCC, 0xC5, 0x83, 0xCC, 0xDF, 0xE9, 0xDE, 0xE7, +0x80, 0x0D, 0x89, 0x82, 0x8A, 0x83, 0xE4, 0x93, +0xA3, 0xF6, 0x08, 0xDF, 0xF9, 0xEC, 0xFA, 0xA9, +0xF0, 0xED, 0xFB, 0x22, 0x89, 0x82, 0x8A, 0x83, +0xEC, 0xFA, 0xE0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, +0xCC, 0xC5, 0x83, 0xCC, 0xF0, 0xA3, 0xC8, 0xC5, +0x82, 0xC8, 0xCC, 0xC5, 0x83, 0xCC, 0xDF, 0xEA, +0xDE, 0xE8, 0x80, 0xDB, 0x89, 0x82, 0x8A, 0x83, +0xE4, 0x93, 0xA3, 0xF2, 0x08, 0xDF, 0xF9, 0x80, +0xCC, 0x88, 0xF0, 0xEF, 0x60, 0x01, 0x0E, 0x4E, +0x60, 0xC3, 0x88, 0xF0, 0xED, 0x24, 0x02, 0xB4, +0x04, 0x00, 0x50, 0xB9, 0xF5, 0x82, 0xEB, 0x24, +0x02, 0xB4, 0x04, 0x00, 0x50, 0xAF, 0x23, 0x23, +0x45, 0x82, 0x23, 0x90, 0x43, 0xF9, 0x73, 0xC5, +0xF0, 0xF8, 0xA3, 0xE0, 0x28, 0xF0, 0xC5, 0xF0, +0xF8, 0xE5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, +0x83, 0xE0, 0x38, 0xF0, 0x22, 0xC3, 0xEF, 0x9B, +0xFF, 0xEE, 0x9A, 0xFE, 0xED, 0x99, 0xFD, 0xEC, +0x98, 0xFC, 0x22, 0xEF, 0x5B, 0xFF, 0xEE, 0x5A, +0xFE, 0xED, 0x59, 0xFD, 0xEC, 0x58, 0xFC, 0x22, +0xEF, 0x4B, 0xFF, 0xEE, 0x4A, 0xFE, 0xED, 0x49, +0xFD, 0xEC, 0x48, 0xFC, 0x22, 0xEB, 0x9F, 0xF5, +0xF0, 0xEA, 0x9E, 0x42, 0xF0, 0xE9, 0x9D, 0x42, +0xF0, 0xE8, 0x9C, 0x45, 0xF0, 0x22, 0xE0, 0xFC, +0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3, 0xE0, +0xFF, 0x22, 0xE2, 0xFC, 0x08, 0xE2, 0xFD, 0x08, +0xE2, 0xFE, 0x08, 0xE2, 0xFF, 0x22, 0xE0, 0xF8, +0xA3, 0xE0, 0xF9, 0xA3, 0xE0, 0xFA, 0xA3, 0xE0, +0xFB, 0x22, 0xE2, 0xFB, 0x08, 0xE2, 0xF9, 0x08, +0xE2, 0xFA, 0x08, 0xE2, 0xCB, 0xF8, 0x22, 0xEC, +0xF2, 0x08, 0xED, 0xF2, 0x08, 0xEE, 0xF2, 0x08, +0xEF, 0xF2, 0x22, 0xA4, 0x25, 0x82, 0xF5, 0x82, +0xE5, 0xF0, 0x35, 0x83, 0xF5, 0x83, 0x22, 0xE0, +0xFB, 0xA3, 0xE0, 0xFA, 0xA3, 0xE0, 0xF9, 0x22, +0xEB, 0xF0, 0xA3, 0xEA, 0xF0, 0xA3, 0xE9, 0xF0, +0x22, 0xD0, 0x83, 0xD0, 0x82, 0xF8, 0xE4, 0x93, +0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0D, 0xA3, +0xA3, 0x93, 0xF8, 0x74, 0x01, 0x93, 0xF5, 0x82, +0x88, 0x83, 0xE4, 0x73, 0x74, 0x02, 0x93, 0x68, +0x60, 0xEF, 0xA3, 0xA3, 0xA3, 0x80, 0xDF, 0xEF, +0x4E, 0x60, 0x12, 0xEF, 0x60, 0x01, 0x0E, 0xED, +0xBB, 0x01, 0x0B, 0x89, 0x82, 0x8A, 0x83, 0xF0, +0xA3, 0xDF, 0xFC, 0xDE, 0xFA, 0x22, 0x89, 0xF0, +0x50, 0x07, 0xF7, 0x09, 0xDF, 0xFC, 0xA9, 0xF0, +0x22, 0xBB, 0xFE, 0xFC, 0xF3, 0x09, 0xDF, 0xFC, +0xA9, 0xF0, 0x22, 0x02, 0x45, 0xD9, 0x02, 0x41, +0xDD, 0xE4, 0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, +0x40, 0x03, 0xF6, 0x80, 0x01, 0xF2, 0x08, 0xDF, +0xF4, 0x80, 0x29, 0xE4, 0x93, 0xA3, 0xF8, 0x54, +0x07, 0x24, 0x0C, 0xC8, 0xC3, 0x33, 0xC4, 0x54, +0x0F, 0x44, 0x20, 0xC8, 0x83, 0x40, 0x04, 0xF4, +0x56, 0x80, 0x01, 0x46, 0xF6, 0xDF, 0xE4, 0x80, +0x0B, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, +0x80, 0x90, 0x46, 0x1E, 0xE4, 0x7E, 0x01, 0x93, +0x60, 0xBC, 0xA3, 0xFF, 0x54, 0x3F, 0x30, 0xE5, +0x09, 0x54, 0x1F, 0xFE, 0xE4, 0x93, 0xA3, 0x60, +0x01, 0x0E, 0xCF, 0x54, 0xC0, 0x25, 0xE0, 0x60, +0xA8, 0x40, 0xB8, 0xE4, 0x93, 0xA3, 0xFA, 0xE4, +0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0xC8, 0xC5, +0x82, 0xC8, 0xCA, 0xC5, 0x83, 0xCA, 0xF0, 0xA3, +0xC8, 0xC5, 0x82, 0xC8, 0xCA, 0xC5, 0x83, 0xCA, +0xDF, 0xE9, 0xDE, 0xE7, 0x80, 0xBE, 0x41, 0x82, +0xA5, 0x00, 0x41, 0x82, 0xA6, 0x00, 0x41, 0x82, +0xB0, 0x00, 0x41, 0x82, 0xB2, 0x00, 0x00, 0x50, +0xF6, 0x61, 0x1E, 0x67, 0xDE, 0xC0, 0xE0, 0xC0, +0xF0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0xD0, 0x75, +0xD0, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x02, +0xC0, 0x03, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, +0xC0, 0x07, 0x90, 0x01, 0xC4, 0x74, 0x35, 0xF0, +0x74, 0x46, 0xA3, 0xF0, 0xD1, 0x84, 0x74, 0x35, +0x04, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x46, 0xA3, +0xF0, 0xD0, 0x07, 0xD0, 0x06, 0xD0, 0x05, 0xD0, +0x04, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, +0x00, 0xD0, 0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, +0xF0, 0xD0, 0xE0, 0x32, 0x90, 0x00, 0x54, 0xE0, +0x55, 0x35, 0xF5, 0x39, 0xA3, 0xE0, 0x55, 0x36, +0xF5, 0x3A, 0xA3, 0xE0, 0x55, 0x37, 0xF5, 0x3B, +0xA3, 0xE0, 0x55, 0x38, 0xF5, 0x3C, 0xAD, 0x39, +0x7F, 0x54, 0x12, 0x32, 0x1E, 0xAD, 0x3A, 0x7F, +0x55, 0x12, 0x32, 0x1E, 0xAD, 0x3B, 0x7F, 0x56, +0x12, 0x32, 0x1E, 0xAD, 0x3C, 0x7F, 0x57, 0x12, +0x32, 0x1E, 0x53, 0x91, 0xEF, 0x22, 0xC0, 0xE0, +0xC0, 0xF0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0xD0, +0x75, 0xD0, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, +0x02, 0xC0, 0x03, 0xC0, 0x04, 0xC0, 0x05, 0xC0, +0x06, 0xC0, 0x07, 0x90, 0x01, 0xC4, 0x74, 0xBE, +0xF0, 0x74, 0x46, 0xA3, 0xF0, 0x12, 0x75, 0x11, +0xE5, 0x41, 0x30, 0xE4, 0x02, 0xF1, 0x5A, 0xE5, +0x41, 0x30, 0xE6, 0x03, 0x12, 0x75, 0x6E, 0xE5, +0x43, 0x30, 0xE0, 0x03, 0x12, 0x6B, 0x93, 0xE5, +0x43, 0x30, 0xE1, 0x03, 0x12, 0x55, 0xC7, 0xE5, +0x43, 0x30, 0xE2, 0x03, 0x12, 0x75, 0x7B, 0xE5, +0x43, 0x30, 0xE3, 0x02, 0xF1, 0x6D, 0xE5, 0x43, +0x30, 0xE4, 0x02, 0xF1, 0xB0, 0xE5, 0x43, 0x30, +0xE5, 0x03, 0x12, 0x75, 0x9E, 0xE5, 0x43, 0x30, +0xE6, 0x02, 0xF1, 0xDE, 0xE5, 0x44, 0x30, 0xE1, +0x03, 0x12, 0x75, 0xBA, 0x74, 0xBE, 0x04, 0x90, +0x01, 0xC4, 0xF0, 0x74, 0x46, 0xA3, 0xF0, 0xD0, +0x07, 0xD0, 0x06, 0xD0, 0x05, 0xD0, 0x04, 0xD0, +0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0xD0, +0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0, +0xE0, 0x32, 0x12, 0x68, 0x7D, 0x7F, 0x02, 0x8F, +0x0F, 0x7F, 0x02, 0x71, 0x27, 0x90, 0x80, 0x3C, +0xE0, 0x45, 0x0F, 0xF0, 0x22, 0xF1, 0x84, 0x70, +0x12, 0x90, 0x81, 0x4B, 0xE0, 0x60, 0x0C, 0x90, +0x81, 0x4F, 0xE0, 0x20, 0xE4, 0x05, 0xF1, 0xD3, +0x12, 0x48, 0xFB, 0x22, 0xE4, 0xFF, 0xF1, 0x8C, +0xEF, 0x64, 0x01, 0x22, 0x12, 0x7B, 0x2D, 0x12, +0x51, 0xB6, 0xE0, 0xFD, 0x7C, 0x00, 0x12, 0x6B, +0x30, 0x80, 0x05, 0xC3, 0x33, 0xCE, 0x33, 0xCE, +0xD8, 0xF9, 0xFF, 0xEE, 0x5C, 0xFE, 0xEF, 0x5D, +0x4E, 0x7F, 0x00, 0x60, 0x02, 0x7F, 0x01, 0x22, +0xF1, 0x84, 0x70, 0x1E, 0x90, 0x81, 0x4B, 0xE0, +0x60, 0x18, 0x90, 0x81, 0x4F, 0xE0, 0x20, 0xE4, +0x11, 0xF1, 0xD3, 0xF0, 0x90, 0x81, 0x46, 0xE0, +0x12, 0x67, 0x97, 0x54, 0x07, 0x70, 0x03, 0x12, +0x61, 0x68, 0x22, 0x90, 0x01, 0x57, 0xE4, 0xF0, +0x90, 0x01, 0x3C, 0x74, 0x02, 0x22, 0xE4, 0xFF, +0xF1, 0x8C, 0xBF, 0x01, 0x10, 0x90, 0x81, 0x4B, +0xE0, 0x60, 0x0A, 0x12, 0x63, 0x7F, 0x54, 0x07, +0x70, 0x03, 0x12, 0x61, 0x68, 0x22, 0xC0, 0xE0, +0xC0, 0xF0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0xD0, +0x75, 0xD0, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, +0x02, 0xC0, 0x03, 0xC0, 0x04, 0xC0, 0x05, 0xC0, +0x06, 0xC0, 0x07, 0x90, 0x01, 0xC4, 0x74, 0xF6, +0xF0, 0x74, 0x47, 0xA3, 0xF0, 0x12, 0x75, 0x3E, +0xE5, 0x49, 0x30, 0xE1, 0x02, 0x11, 0x9E, 0xE5, +0x49, 0x30, 0xE2, 0x03, 0x12, 0x61, 0x7D, 0xE5, +0x4A, 0x30, 0xE0, 0x03, 0x12, 0x6D, 0xC3, 0xE5, +0x4A, 0x30, 0xE4, 0x03, 0x12, 0x76, 0xE7, 0xE5, +0x4B, 0x30, 0xE1, 0x03, 0x12, 0x6C, 0x2E, 0xE5, +0x4B, 0x30, 0xE0, 0x03, 0x12, 0x6E, 0x60, 0xE5, +0x4B, 0x30, 0xE4, 0x02, 0xF1, 0xF1, 0xE5, 0x4C, +0x30, 0xE1, 0x05, 0x7F, 0x04, 0x12, 0x47, 0x5F, +0xE5, 0x4C, 0x30, 0xE4, 0x03, 0x12, 0x6B, 0x6C, +0xE5, 0x4C, 0x30, 0xE5, 0x03, 0x12, 0x62, 0x6E, +0xE5, 0x4C, 0x30, 0xE6, 0x03, 0x12, 0x62, 0x96, +0x74, 0xF6, 0x04, 0x90, 0x01, 0xC4, 0xF0, 0x74, +0x47, 0xA3, 0xF0, 0xD0, 0x07, 0xD0, 0x06, 0xD0, +0x05, 0xD0, 0x04, 0xD0, 0x03, 0xD0, 0x02, 0xD0, +0x01, 0xD0, 0x00, 0xD0, 0xD0, 0xD0, 0x82, 0xD0, +0x83, 0xD0, 0xF0, 0xD0, 0xE0, 0x32, 0x90, 0x81, +0x4B, 0xE0, 0x60, 0x03, 0x12, 0x63, 0xF2, 0x90, +0x81, 0xAF, 0xE0, 0x30, 0xE0, 0x49, 0xC4, 0x54, +0x0F, 0x20, 0xE0, 0x17, 0xE4, 0xF5, 0x1D, 0x90, +0x81, 0xB1, 0x31, 0x02, 0xB1, 0x15, 0x12, 0x67, +0xC9, 0x30, 0xE0, 0x02, 0x31, 0xCA, 0x12, 0x67, +0xC2, 0xF0, 0x22, 0x90, 0x81, 0xAF, 0xE0, 0xC4, +0x54, 0x0F, 0x30, 0xE0, 0x22, 0xE4, 0xF5, 0x1D, +0x90, 0x81, 0xB2, 0x31, 0x02, 0x90, 0x81, 0xAF, +0xE0, 0x54, 0xEF, 0xF0, 0xE0, 0xC3, 0x13, 0x30, +0xE0, 0x06, 0x7D, 0x04, 0x7F, 0x01, 0x21, 0xCE, +0x7B, 0x31, 0xF1, 0x9C, 0x12, 0x57, 0xE3, 0x22, +0xE0, 0x44, 0x02, 0xF0, 0xE4, 0xF5, 0x1D, 0x90, +0x81, 0xA9, 0xE0, 0xF5, 0x1E, 0xE4, 0xFB, 0xFD, +0x7F, 0x54, 0x7E, 0x01, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x8E, 0x19, 0x8F, 0x1A, 0xE5, +0x1E, 0x31, 0x61, 0x85, 0x19, 0x83, 0x85, 0x1A, +0x82, 0xF0, 0xE5, 0x1D, 0x31, 0x61, 0xFF, 0xE5, +0x1E, 0x13, 0x13, 0x13, 0x54, 0x1F, 0x4F, 0xA3, +0xF0, 0xEB, 0x31, 0x61, 0xFF, 0xE5, 0x1D, 0x13, +0x13, 0x13, 0x54, 0x1F, 0x4F, 0x31, 0x68, 0xF0, +0xBD, 0x01, 0x0D, 0x85, 0x1A, 0x82, 0x8E, 0x83, +0xA3, 0xA3, 0xA3, 0x74, 0x03, 0xF0, 0x80, 0x06, +0x31, 0x68, 0xA3, 0x74, 0x01, 0xF0, 0x31, 0x68, +0xA3, 0x74, 0x05, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x54, 0x07, 0xC4, 0x33, 0x54, 0xE0, 0x22, +0x85, 0x1A, 0x82, 0x85, 0x19, 0x83, 0xA3, 0xA3, +0x22, 0x90, 0x81, 0x4F, 0xE0, 0x44, 0x10, 0xF0, +0x90, 0x81, 0x54, 0xE0, 0x60, 0x04, 0x64, 0x01, +0x70, 0x11, 0xE4, 0xF5, 0x1D, 0x90, 0x81, 0x54, +0xE0, 0x31, 0xBF, 0x31, 0x03, 0x90, 0x81, 0x54, +0xE0, 0x80, 0x11, 0xE4, 0xF5, 0x1D, 0x31, 0xB5, +0x31, 0x03, 0x90, 0x81, 0x54, 0xE0, 0x75, 0xF0, +0x03, 0xA4, 0x24, 0xFE, 0x31, 0xBF, 0x90, 0x81, +0x64, 0xF0, 0x90, 0x81, 0x4E, 0xE0, 0x20, 0xE2, +0x03, 0x12, 0x67, 0xD7, 0x22, 0x90, 0x81, 0x54, +0xE0, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0xFE, 0xFF, +0x90, 0x81, 0x53, 0xE0, 0x2F, 0x22, 0xE0, 0x54, +0x7F, 0xF0, 0x7D, 0x0C, 0x7F, 0x01, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xAC, 0x07, 0xEF, +0x14, 0x60, 0x15, 0x14, 0x60, 0x19, 0x24, 0x02, +0x70, 0x1A, 0xED, 0x54, 0x01, 0xFE, 0x90, 0x81, +0x46, 0xE0, 0x54, 0xFE, 0x4E, 0xF0, 0x80, 0x0C, +0x90, 0x81, 0x4E, 0xED, 0xF0, 0x80, 0x05, 0x90, +0x81, 0x4D, 0xED, 0xF0, 0x90, 0x00, 0x8F, 0xE0, +0x30, 0xE4, 0x2E, 0xEC, 0x14, 0x60, 0x07, 0x14, +0x60, 0x1D, 0x24, 0x02, 0x70, 0x23, 0x90, 0x81, +0x46, 0xE0, 0x54, 0x01, 0xC4, 0x33, 0x33, 0x33, +0x54, 0x80, 0xFF, 0x90, 0x81, 0x4E, 0xE0, 0x54, +0x7F, 0x4F, 0xFD, 0x7F, 0x88, 0x80, 0x07, 0x90, +0x81, 0x4D, 0xE0, 0xFD, 0x7F, 0x89, 0x12, 0x32, +0x1E, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x7E, 0x00, +0x7F, 0x62, 0x7D, 0x00, 0x7B, 0x01, 0x7A, 0x81, +0x79, 0x46, 0x12, 0x45, 0x6F, 0x12, 0x7B, 0x13, +0x12, 0x45, 0x6F, 0x90, 0x81, 0x4A, 0x74, 0x02, +0xF0, 0x90, 0x81, 0x51, 0x14, 0xF0, 0xA3, 0xF0, +0xA3, 0x74, 0x10, 0xF0, 0x90, 0x81, 0x57, 0xE4, +0xF0, 0xA3, 0x74, 0x02, 0x51, 0xF8, 0xF0, 0x12, +0x77, 0xDC, 0xE4, 0xFD, 0xFF, 0x31, 0xCE, 0x7D, +0x0C, 0x7F, 0x02, 0x31, 0xCE, 0x31, 0xCA, 0x90, +0x80, 0x42, 0xE0, 0xFF, 0xB4, 0x01, 0x08, 0x90, +0x81, 0x56, 0x74, 0x99, 0xF0, 0x80, 0x29, 0xEF, +0xB4, 0x03, 0x08, 0x90, 0x81, 0x56, 0x74, 0x90, +0xF0, 0x80, 0x1D, 0x90, 0x81, 0x56, 0x74, 0x40, +0xF0, 0x90, 0x00, 0x2C, 0xE0, 0x54, 0x0F, 0xFF, +0xBF, 0x05, 0x08, 0x90, 0x81, 0x68, 0x74, 0x02, +0xF0, 0x80, 0x05, 0xE4, 0x90, 0x81, 0x68, 0xF0, +0x90, 0x81, 0xA8, 0x74, 0x02, 0xF0, 0xA3, 0x74, +0x0F, 0xF0, 0xA3, 0xE0, 0x54, 0x01, 0x44, 0x28, +0xF0, 0xA3, 0x74, 0x07, 0x51, 0xF8, 0xF0, 0x7F, +0x01, 0x12, 0x79, 0x8B, 0x90, 0x05, 0x58, 0x74, +0x02, 0xF0, 0x7E, 0x00, 0xFF, 0x7D, 0x00, 0x7B, +0x01, 0x7A, 0x81, 0x79, 0xAC, 0x12, 0x45, 0x6F, +0x12, 0x7B, 0x4D, 0x90, 0x06, 0x0A, 0xE0, 0x54, +0xF8, 0xF0, 0x7B, 0x56, 0xE4, 0xFD, 0x7F, 0xFF, +0xB1, 0x1C, 0xE4, 0x90, 0x81, 0xAE, 0xF0, 0x22, +0xF0, 0x90, 0x81, 0x68, 0xE0, 0x24, 0x04, 0x90, +0x81, 0x63, 0xF0, 0xA3, 0x74, 0x10, 0x22, 0x90, +0x82, 0xAD, 0xEF, 0xF0, 0xB1, 0x77, 0x90, 0x82, +0xAD, 0xE0, 0x60, 0x02, 0xB1, 0x17, 0x7D, 0x04, +0xD1, 0x2F, 0x74, 0x04, 0xF0, 0x22, 0xFD, 0x7F, +0x0C, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x90, 0x82, 0xAE, 0xED, 0xF0, 0x90, 0x81, 0x46, +0xE0, 0xFE, 0xC4, 0x13, 0x13, 0x54, 0x03, 0x30, +0xE0, 0x02, 0x81, 0x69, 0xEE, 0x12, 0x67, 0x7E, +0x30, 0xE0, 0x02, 0x81, 0x69, 0x90, 0x81, 0x4E, +0xE0, 0xFE, 0x6F, 0x70, 0x02, 0x81, 0x69, 0xEF, +0x70, 0x02, 0x61, 0xDD, 0x24, 0xFE, 0x70, 0x02, +0x81, 0x16, 0x24, 0xFE, 0x60, 0x47, 0x24, 0xFC, +0x70, 0x02, 0x81, 0x51, 0x24, 0xFC, 0x60, 0x02, +0x81, 0x62, 0xEE, 0xB4, 0x0E, 0x02, 0x91, 0xEC, +0x90, 0x81, 0x4E, 0xE0, 0x70, 0x04, 0x7F, 0x01, +0x71, 0x07, 0x90, 0x81, 0x4E, 0xE0, 0xB4, 0x06, +0x02, 0x91, 0xC5, 0x90, 0x81, 0x4E, 0xE0, 0xB4, +0x04, 0x0D, 0x90, 0x82, 0xAE, 0xE0, 0xFF, 0x60, +0x04, 0xB1, 0xF6, 0x80, 0x02, 0xB1, 0x61, 0x90, +0x81, 0x4E, 0xE0, 0x64, 0x08, 0x60, 0x02, 0x81, +0x62, 0xB1, 0x6C, 0x81, 0x62, 0x90, 0x81, 0x4E, +0xE0, 0x70, 0x04, 0x7F, 0x01, 0x71, 0x07, 0x90, +0x81, 0x4E, 0xE0, 0xB4, 0x06, 0x02, 0x91, 0xC5, +0x90, 0x81, 0x4E, 0xE0, 0xB4, 0x0E, 0x07, 0x91, +0x6E, 0xBF, 0x01, 0x02, 0x91, 0xEC, 0x90, 0x81, +0x4E, 0xE0, 0x64, 0x0C, 0x60, 0x02, 0x81, 0x62, +0x91, 0x6E, 0xEF, 0x64, 0x01, 0x60, 0x02, 0x81, +0x62, 0xB1, 0x32, 0x81, 0x62, 0x90, 0x81, 0x4E, +0xE0, 0xB4, 0x0E, 0x07, 0x91, 0x6E, 0xBF, 0x01, +0x02, 0x91, 0xEC, 0x90, 0x81, 0x4E, 0xE0, 0xB4, +0x06, 0x02, 0x91, 0xC5, 0x90, 0x81, 0x4E, 0xE0, +0xB4, 0x0C, 0x07, 0x91, 0x6E, 0xBF, 0x01, 0x02, +0xB1, 0x32, 0x90, 0x81, 0x4E, 0xE0, 0x64, 0x04, +0x70, 0x58, 0x12, 0x76, 0x09, 0xEF, 0x64, 0x01, +0x70, 0x50, 0xF1, 0xD0, 0x80, 0x4C, 0x90, 0x81, +0x4E, 0xE0, 0xB4, 0x0E, 0x07, 0x91, 0x6E, 0xBF, +0x01, 0x02, 0x91, 0xEC, 0x90, 0x81, 0x4E, 0xE0, +0xB4, 0x06, 0x02, 0x91, 0xC5, 0x90, 0x81, 0x4E, +0xE0, 0xB4, 0x0C, 0x07, 0x91, 0x6E, 0xBF, 0x01, +0x02, 0xB1, 0x32, 0x90, 0x81, 0x4E, 0xE0, 0x70, +0x04, 0x7F, 0x01, 0x71, 0x07, 0x90, 0x81, 0x4E, +0xE0, 0xB4, 0x04, 0x16, 0x12, 0x77, 0xC6, 0x80, +0x11, 0x90, 0x81, 0x4E, 0xE0, 0xB4, 0x0C, 0x0A, +0x12, 0x65, 0xB9, 0x54, 0x3F, 0x30, 0xE0, 0x02, +0xD1, 0x37, 0x90, 0x81, 0x4E, 0x12, 0x7B, 0x20, +0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x75, 0xF0, +0xEF, 0x64, 0x01, 0x60, 0x05, 0x75, 0x1F, 0x01, +0x80, 0x30, 0x12, 0x7B, 0x43, 0x30, 0xE0, 0x05, +0x75, 0x1F, 0x02, 0x80, 0x25, 0x90, 0x81, 0x4D, +0xE0, 0xD3, 0x94, 0x04, 0x40, 0x05, 0x75, 0x1F, +0x08, 0x80, 0x17, 0x90, 0x81, 0xAF, 0xE0, 0x30, +0xE0, 0x0B, 0xC4, 0x54, 0x0F, 0x30, 0xE0, 0x05, +0x75, 0x1F, 0x11, 0x80, 0x05, 0x12, 0x76, 0x72, +0x80, 0x0E, 0x90, 0x01, 0xB9, 0x74, 0x02, 0xF0, +0x90, 0x01, 0xB8, 0xE5, 0x1F, 0xF0, 0x7F, 0x00, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x81, 0x47, +0xE0, 0x90, 0x06, 0x04, 0x20, 0xE0, 0x07, 0xE0, +0x44, 0x40, 0xF1, 0xA2, 0x80, 0x0F, 0x31, 0xC6, +0x90, 0x05, 0x27, 0xE0, 0x54, 0x7F, 0xF0, 0x90, +0x81, 0x45, 0x74, 0x0C, 0xF0, 0xE4, 0xFB, 0xFD, +0x7F, 0xFF, 0x80, 0x30, 0x90, 0x81, 0x47, 0xE0, +0xC3, 0x13, 0x20, 0xE0, 0x04, 0x31, 0xCA, 0x80, +0x15, 0x12, 0x7B, 0x64, 0xE0, 0x44, 0x80, 0xF1, +0xA2, 0x90, 0x05, 0x27, 0xE0, 0x44, 0x80, 0xF0, +0x90, 0x81, 0x45, 0x74, 0x04, 0xF0, 0xE4, 0xFB, +0xFD, 0x7F, 0xFF, 0x80, 0x07, 0xB1, 0x77, 0xE4, +0xFB, 0xFD, 0x7F, 0xFF, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x90, 0x05, 0x22, 0xED, 0xF0, +0x90, 0x80, 0x40, 0xEB, 0xF0, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0x12, 0x47, 0x84, 0x70, 0x29, 0x90, +0x81, 0x47, 0xE0, 0x54, 0xFD, 0xF0, 0x7B, 0x2C, +0x12, 0x7B, 0x55, 0x7D, 0x08, 0x7F, 0x01, 0xD1, +0xC7, 0xBF, 0x01, 0x0F, 0x90, 0x81, 0x46, 0xE0, +0x44, 0x80, 0xF0, 0x7D, 0x0E, 0xD1, 0x2F, 0x74, +0x0E, 0xF0, 0x22, 0x12, 0x62, 0xC5, 0x04, 0xF0, +0x22, 0x12, 0x7B, 0x4D, 0xB1, 0x17, 0x7D, 0x0C, +0x7F, 0x01, 0x21, 0xCE, 0xB1, 0x15, 0x31, 0xCA, +0x90, 0x81, 0x45, 0x74, 0x0C, 0xF0, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x01, +0x01, 0xE0, 0x44, 0x02, 0xF0, 0x90, 0x01, 0x00, +0x74, 0xFF, 0xF0, 0x90, 0x06, 0xB7, 0x74, 0x09, +0xF0, 0x90, 0x06, 0xB4, 0x74, 0x86, 0xF0, 0x12, +0x5F, 0xD2, 0xEC, 0x54, 0x7F, 0xFC, 0x90, 0x82, +0x96, 0x12, 0x20, 0xCE, 0x90, 0x82, 0x96, 0x12, +0x44, 0xEE, 0x12, 0x58, 0x97, 0x7F, 0x7C, 0xF1, +0xB0, 0x12, 0x20, 0xDA, 0xCC, 0xC0, 0x00, 0xC0, +0x7F, 0x8C, 0xF1, 0xB0, 0x12, 0x20, 0xDA, 0x00, +0xC0, 0x00, 0x14, 0x12, 0x5F, 0xD9, 0x90, 0x82, +0x7F, 0x12, 0x20, 0xDA, 0x00, 0x03, 0x3E, 0x60, +0xE4, 0xFD, 0xFF, 0x12, 0x5D, 0xB7, 0xD0, 0xD0, +0x92, 0xAF, 0x22, 0x90, 0x81, 0xAF, 0xE0, 0x30, +0xE0, 0x13, 0x90, 0x01, 0x57, 0xE4, 0xF0, 0xB1, +0x15, 0x12, 0x67, 0xC9, 0x30, 0xE0, 0x02, 0x31, +0xCA, 0x12, 0x67, 0xC2, 0xF0, 0x22, 0xEF, 0x60, +0x35, 0x12, 0x47, 0x84, 0x70, 0x30, 0x90, 0x81, +0x47, 0xE0, 0x54, 0xFE, 0xF0, 0x7B, 0x2B, 0x7D, +0x0F, 0x7F, 0xFF, 0xB1, 0x1C, 0x90, 0x06, 0x04, +0xE0, 0x54, 0xBF, 0xF0, 0xD1, 0xC3, 0xBF, 0x01, +0x0F, 0x90, 0x81, 0x46, 0xE0, 0x44, 0x40, 0xF0, +0x7D, 0x06, 0xD1, 0x2F, 0x74, 0x06, 0xF0, 0x22, +0x12, 0x62, 0xC5, 0x74, 0x08, 0xF0, 0x22, 0x7F, +0x01, 0x31, 0xCE, 0x90, 0x81, 0x45, 0x22, 0x7B, +0x2F, 0xF1, 0x9C, 0x12, 0x57, 0xE3, 0x7D, 0x08, +0xD1, 0x2F, 0x74, 0x08, 0xF0, 0x22, 0xEF, 0x70, +0x3E, 0x7D, 0x78, 0x7F, 0x02, 0x12, 0x56, 0x83, +0x7D, 0x02, 0x7F, 0x03, 0x12, 0x56, 0x83, 0x7D, +0xC8, 0x7F, 0x02, 0x12, 0x56, 0xFD, 0x12, 0x47, +0xD3, 0xF0, 0xE4, 0xFF, 0x12, 0x47, 0x8C, 0xEF, +0x70, 0x0C, 0xB1, 0x77, 0xB1, 0x61, 0x12, 0x7B, +0x6C, 0x54, 0x7F, 0xF0, 0x80, 0x06, 0x7D, 0x01, +0x7F, 0x0C, 0x71, 0x21, 0x12, 0x74, 0x12, 0x90, +0x06, 0x0A, 0xE0, 0x54, 0xF8, 0xF0, 0x22, 0x90, +0x01, 0x36, 0x74, 0x78, 0xF0, 0xA3, 0x74, 0x02, +0xF0, 0x7D, 0x78, 0xFF, 0xF1, 0xC3, 0x7D, 0x02, +0x7F, 0x03, 0xF1, 0xC3, 0x90, 0x06, 0x0A, 0xE0, +0x44, 0x07, 0x12, 0x6E, 0x14, 0xE4, 0xFF, 0x12, +0x47, 0x8C, 0xBF, 0x01, 0x11, 0x12, 0x64, 0x4B, +0xF0, 0x90, 0x81, 0x4E, 0xE0, 0x20, 0xE2, 0x0A, +0x7D, 0x01, 0x7F, 0x04, 0x61, 0x21, 0x12, 0x65, +0xC1, 0xF0, 0x22, 0x7D, 0x08, 0xE4, 0xFF, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x82, +0x89, 0xEF, 0xF0, 0xA3, 0xED, 0xF0, 0x90, 0x80, +0x3E, 0xE0, 0x04, 0xF0, 0x90, 0x04, 0x1D, 0xE0, +0x60, 0x2C, 0x90, 0x05, 0x22, 0xE0, 0x90, 0x82, +0x8D, 0xF0, 0x7B, 0x26, 0x12, 0x5F, 0x97, 0x12, +0x5D, 0xF1, 0xEF, 0x64, 0x01, 0x70, 0x03, 0x12, +0x7A, 0x58, 0x90, 0x82, 0x8D, 0xE0, 0xFD, 0x7B, +0x27, 0xE4, 0xFF, 0xB1, 0x1C, 0x90, 0x82, 0x89, +0xE0, 0xFF, 0xF1, 0x22, 0x80, 0x0A, 0x90, 0x82, +0x89, 0xE0, 0xFF, 0xF1, 0x22, 0x12, 0x7A, 0x58, +0x12, 0x5F, 0xCB, 0x7F, 0x01, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x90, 0x82, 0xB1, 0xEF, 0xF0, 0xC3, 0x94, +0x02, 0x50, 0x48, 0x90, 0x80, 0x46, 0xE0, 0xFF, +0x90, 0x04, 0x1C, 0xE0, 0x6F, 0x70, 0x3C, 0x90, +0x81, 0x4E, 0xE0, 0x64, 0x0E, 0x70, 0x14, 0x90, +0x82, 0xB1, 0xE0, 0x70, 0x2E, 0x90, 0x81, 0x46, +0xE0, 0x54, 0x7F, 0xF0, 0x90, 0x06, 0x04, 0x31, +0xC6, 0x80, 0x1E, 0x90, 0x81, 0x4E, 0xE0, 0x64, +0x06, 0x70, 0x18, 0x90, 0x82, 0xB1, 0xE0, 0x60, +0x12, 0x12, 0x7B, 0x6C, 0x12, 0x7B, 0x64, 0xE0, +0x44, 0x80, 0xF0, 0x90, 0x81, 0x4E, 0x74, 0x04, +0xF0, 0xB1, 0x17, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x12, 0x62, 0xCF, 0x90, 0x81, 0x4E, 0xE0, 0x64, +0x0C, 0x60, 0x07, 0xE4, 0x71, 0x1E, 0xB1, 0x17, +0xD1, 0xC3, 0x22, 0xB1, 0x15, 0x90, 0x81, 0x44, +0x74, 0x01, 0xF0, 0x22, 0x7D, 0xFF, 0x7F, 0xFF, +0xA1, 0x1C, 0xF0, 0x7D, 0x04, 0x7F, 0x01, 0x21, +0xCE, 0xB1, 0x17, 0x12, 0x57, 0x96, 0x80, 0xE5, +0x7E, 0x08, 0x12, 0x2E, 0xA2, 0x90, 0x85, 0xBB, +0x22, 0x7D, 0x01, 0x7F, 0x02, 0xF1, 0xC3, 0x7D, +0x02, 0x7F, 0x02, 0x74, 0x3D, 0x2F, 0xF8, 0xE6, +0x4D, 0xFE, 0xF6, 0x74, 0x30, 0x02, 0x56, 0xA7, +0x7B, 0x2D, 0xF1, 0x9C, 0x12, 0x5D, 0xF1, 0x90, +0x01, 0x37, 0x74, 0x02, 0xF0, 0xFD, 0x7F, 0x03, +0xF1, 0xC3, 0x12, 0x57, 0xE3, 0xE4, 0xFD, 0x7F, +0x01, 0x31, 0xCE, 0xE4, 0x90, 0x81, 0x45, 0xF0, +0x22, 0x22, 0x80, 0xA1, 0xB1, 0x17, 0x80, 0x9D, +0x90, 0x01, 0xC8, 0xE4, 0xF0, 0xA3, 0xF0, 0xA3, +0xF0, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0xC8, 0x7F, +0xFF, 0xFE, 0x12, 0x2B, 0x27, 0xBF, 0x01, 0x09, +0x90, 0x81, 0xC8, 0xE0, 0x64, 0x03, 0x60, 0x03, +0x22, 0x01, 0xBA, 0xE4, 0x90, 0x81, 0xCD, 0xF0, +0x90, 0x81, 0xCD, 0xE0, 0xFF, 0xC3, 0x94, 0x02, +0x40, 0x02, 0x01, 0xF5, 0xC3, 0x74, 0xFE, 0x9F, +0xFF, 0xE4, 0x94, 0x00, 0xFE, 0x7B, 0x01, 0x7A, +0x81, 0x79, 0xC9, 0x12, 0x2B, 0x27, 0xEF, 0x64, +0x01, 0x70, 0x77, 0x90, 0x81, 0xC9, 0xE0, 0xFF, +0x54, 0xC0, 0xFE, 0x60, 0x05, 0xEF, 0x54, 0x0C, +0x70, 0x16, 0x90, 0x81, 0xC9, 0xE0, 0xFF, 0x54, +0x30, 0x60, 0x67, 0xEF, 0x54, 0x03, 0x60, 0x62, +0x90, 0x81, 0xCA, 0x74, 0x01, 0xF0, 0x80, 0x05, +0xE4, 0x90, 0x81, 0xCA, 0xF0, 0x90, 0x81, 0xCA, +0xE0, 0x90, 0x81, 0xC9, 0x70, 0x16, 0xE0, 0xFF, +0xEE, 0x13, 0x13, 0x54, 0x3F, 0x90, 0x81, 0xCB, +0xF0, 0xEF, 0x54, 0x0C, 0x13, 0x13, 0x54, 0x3F, +0xA3, 0xF0, 0x80, 0x0D, 0xE0, 0xFE, 0x54, 0x30, +0x90, 0x81, 0xCB, 0xF0, 0xEE, 0x54, 0x03, 0xA3, +0xF0, 0x90, 0x81, 0xCB, 0xE0, 0x64, 0x30, 0x70, +0x54, 0xA3, 0xE0, 0x64, 0x02, 0x70, 0x4E, 0x90, +0x00, 0xF5, 0xE0, 0x54, 0x40, 0x90, 0x81, 0xCE, +0xF0, 0xE0, 0x70, 0x41, 0xA3, 0x74, 0x02, 0xF0, +0x80, 0x10, 0x90, 0x81, 0xCF, 0x74, 0x01, 0xF0, +0x80, 0x08, 0x90, 0x81, 0xCD, 0xE0, 0x04, 0xF0, +0x01, 0x20, 0x90, 0x01, 0xC4, 0x74, 0xF8, 0xF0, +0x74, 0x4F, 0xA3, 0xF0, 0x90, 0x81, 0xCF, 0xE0, +0x90, 0x01, 0xC8, 0xF0, 0x90, 0x81, 0xC9, 0xE0, +0x90, 0x01, 0xC9, 0xF0, 0x90, 0x81, 0xCA, 0xE0, +0x90, 0x01, 0xCA, 0xF0, 0xE4, 0xFD, 0x7F, 0x1F, +0x12, 0x32, 0x1E, 0x80, 0xD5, 0x22, 0x90, 0x00, +0x80, 0xE0, 0x44, 0x80, 0xFD, 0x7F, 0x80, 0x12, +0x32, 0x1E, 0x90, 0xFD, 0x00, 0xE0, 0x54, 0xBF, +0xF0, 0x12, 0x4F, 0xF8, 0x12, 0x74, 0x48, 0x12, +0x32, 0x77, 0x12, 0x74, 0x55, 0x31, 0x53, 0x7F, +0x01, 0x12, 0x42, 0x15, 0x90, 0x81, 0xBB, 0x74, +0x02, 0xF0, 0xFF, 0x12, 0x42, 0x15, 0x90, 0x81, +0xBB, 0xE0, 0x04, 0xF0, 0x12, 0x5F, 0xFA, 0x31, +0x64, 0x90, 0x01, 0xCC, 0x74, 0x0F, 0xF0, 0x90, +0x00, 0x80, 0xE0, 0x44, 0x40, 0xFD, 0x7F, 0x80, +0x12, 0x32, 0x1E, 0x75, 0x20, 0xFF, 0xF1, 0xCF, +0x12, 0x74, 0x85, 0x12, 0x75, 0x07, 0xE4, 0xFF, +0x02, 0x42, 0x9E, 0xE4, 0x90, 0x80, 0x3C, 0x31, +0x5C, 0xA3, 0xF0, 0x22, 0xF0, 0xA3, 0xF0, 0xA3, +0xF0, 0xA3, 0xF0, 0x22, 0x31, 0x77, 0x12, 0x74, +0x3A, 0x51, 0x17, 0x12, 0x4A, 0x36, 0x12, 0x79, +0xC8, 0x12, 0x7B, 0x13, 0x02, 0x45, 0x6F, 0xE4, +0xFD, 0xFF, 0x12, 0x7B, 0x2D, 0xED, 0x70, 0x12, +0x31, 0xB6, 0xC0, 0x83, 0xC0, 0x82, 0x31, 0xAE, +0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xF4, 0x5E, +0x80, 0x0F, 0x31, 0xB6, 0xC0, 0x83, 0xC0, 0x82, +0x31, 0xAE, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, +0x4E, 0xD0, 0x82, 0xD0, 0x83, 0xF0, 0x31, 0xC1, +0x90, 0x81, 0x40, 0xEF, 0xF0, 0x22, 0xE0, 0xFE, +0x74, 0x01, 0xA8, 0x07, 0x08, 0x22, 0x74, 0x38, +0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, +0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x7D, 0x08, 0xED, 0x14, 0xF9, 0x24, 0x38, 0x31, +0xB9, 0xE0, 0x60, 0x3A, 0x7C, 0x08, 0xEC, 0x14, +0x90, 0x82, 0xAA, 0xF0, 0x74, 0x38, 0x29, 0x31, +0xB9, 0xE0, 0xFB, 0x7A, 0x00, 0x90, 0x82, 0xAA, +0x12, 0x6B, 0x2E, 0x80, 0x05, 0xC3, 0x33, 0xCE, +0x33, 0xCE, 0xD8, 0xF9, 0xFF, 0xEE, 0x5A, 0xFE, +0xEF, 0x5B, 0x4E, 0x60, 0x0F, 0xE9, 0x75, 0xF0, +0x08, 0xA4, 0xFF, 0x90, 0x82, 0xAA, 0xE0, 0x2F, +0x04, 0xFF, 0x80, 0x06, 0xDC, 0xC8, 0xDD, 0xBA, +0x7F, 0x00, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x7E, +0x00, 0x7F, 0x01, 0x7D, 0x00, 0x7B, 0x01, 0x7A, +0x81, 0x79, 0x41, 0x12, 0x45, 0x6F, 0x90, 0x81, +0x41, 0xE0, 0x54, 0xFD, 0xF0, 0xE4, 0x31, 0x5D, +0xA3, 0x74, 0x0C, 0xF0, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x8B, 0x54, 0x8A, 0x55, +0x89, 0x56, 0x90, 0x05, 0x27, 0xE0, 0xF5, 0x57, +0x8B, 0x13, 0x8A, 0x14, 0x89, 0x15, 0x75, 0x16, +0x01, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0x41, 0x12, +0x2B, 0xED, 0x12, 0x74, 0x1A, 0xFF, 0xC3, 0x13, +0x20, 0xE0, 0x02, 0x41, 0xF3, 0x90, 0x81, 0x41, +0xE0, 0x30, 0xE0, 0x73, 0xD1, 0x99, 0x75, 0x57, +0x21, 0x90, 0x81, 0x41, 0xE0, 0x13, 0x13, 0x54, +0x3F, 0x30, 0xE0, 0x07, 0xD1, 0x8D, 0x43, 0x57, +0x08, 0x80, 0x0C, 0xE4, 0x90, 0x81, 0x42, 0xF0, +0xA3, 0xF0, 0x7D, 0x40, 0xFF, 0xD1, 0x83, 0x91, +0x88, 0x13, 0x54, 0x1F, 0x30, 0xE0, 0x03, 0x43, +0x57, 0x12, 0xEF, 0xC4, 0x54, 0x0F, 0x30, 0xE0, +0x03, 0x43, 0x57, 0x14, 0x90, 0x81, 0x41, 0xE0, +0xC4, 0x13, 0x54, 0x07, 0x30, 0xE0, 0x03, 0x43, +0x57, 0x80, 0x12, 0x7B, 0x39, 0x20, 0xE0, 0x03, +0x43, 0x57, 0x40, 0x71, 0x9E, 0x90, 0x81, 0x44, +0xE0, 0x70, 0x04, 0x7F, 0x01, 0x71, 0xA5, 0x91, +0x90, 0x30, 0xE0, 0x04, 0x7F, 0x04, 0x80, 0x0B, +0x91, 0x9B, 0xEF, 0x60, 0x04, 0x7F, 0x01, 0x80, +0x02, 0x7F, 0x02, 0x71, 0xA5, 0x61, 0x66, 0x75, +0x57, 0x01, 0x71, 0x9E, 0x90, 0x81, 0x44, 0xE0, +0x64, 0x04, 0x60, 0x02, 0x61, 0x99, 0xFF, 0x71, +0xA5, 0x61, 0x99, 0x90, 0x81, 0x41, 0xE0, 0x30, +0xE0, 0x74, 0xD1, 0x99, 0x43, 0x57, 0x31, 0x90, +0x81, 0x41, 0xE0, 0x13, 0x13, 0x54, 0x3F, 0x30, +0xE0, 0x07, 0xD1, 0x8D, 0x43, 0x57, 0x08, 0x80, +0x06, 0x7D, 0x40, 0xE4, 0xFF, 0xD1, 0x83, 0x91, +0x88, 0x13, 0x54, 0x1F, 0x30, 0xE0, 0x03, 0x43, +0x57, 0x02, 0xEF, 0xC4, 0x54, 0x0F, 0x30, 0xE0, +0x03, 0x43, 0x57, 0x04, 0x71, 0x9E, 0x91, 0x90, +0x30, 0xE0, 0x0A, 0xF1, 0x70, 0x60, 0x2F, 0xE4, +0xFD, 0x7F, 0x02, 0x80, 0x1C, 0xF1, 0x96, 0x90, +0x81, 0x45, 0xE0, 0xB4, 0x02, 0x18, 0xF1, 0xAF, +0x91, 0x9B, 0xBF, 0x01, 0x09, 0x90, 0x81, 0x4D, +0xE0, 0xFF, 0x7D, 0x01, 0x80, 0x03, 0xE4, 0xFD, +0xFF, 0x12, 0x4B, 0x21, 0x80, 0x08, 0x90, 0x81, +0x4E, 0xE0, 0x90, 0x81, 0x45, 0xF0, 0x90, 0x05, +0x40, 0x74, 0x22, 0xF0, 0x80, 0x2B, 0x75, 0x57, +0x01, 0x71, 0x9E, 0x90, 0x81, 0x45, 0xE0, 0xB4, +0x02, 0x06, 0x7D, 0x01, 0x7F, 0x04, 0x80, 0x0B, +0x90, 0x81, 0x45, 0xE0, 0xB4, 0x08, 0x07, 0x7D, +0x01, 0x7F, 0x0C, 0x12, 0x4B, 0x21, 0x12, 0x63, +0x26, 0x90, 0x81, 0x4D, 0x12, 0x61, 0x76, 0x51, +0x17, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x05, +0x27, 0xE5, 0x57, 0xF0, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x81, 0x44, 0xE0, +0xF5, 0x5A, 0xE5, 0x5A, 0x6F, 0x70, 0x02, 0x81, +0x83, 0xEF, 0x14, 0x60, 0x38, 0x14, 0x60, 0x5C, +0x14, 0x60, 0x7C, 0x14, 0x70, 0x02, 0x81, 0x62, +0x24, 0x04, 0x60, 0x02, 0x81, 0x83, 0xE5, 0x5A, +0xB4, 0x04, 0x04, 0xF1, 0x55, 0x81, 0x83, 0xE5, +0x5A, 0xB4, 0x02, 0x04, 0xF1, 0x61, 0x81, 0x83, +0xE5, 0x5A, 0xB4, 0x03, 0x04, 0xF1, 0x6B, 0x81, +0x83, 0xE5, 0x5A, 0x64, 0x01, 0x60, 0x02, 0x81, +0x83, 0xF1, 0x58, 0x81, 0x83, 0xE5, 0x5A, 0xB4, +0x04, 0x05, 0x12, 0x4F, 0xA9, 0x81, 0x83, 0xE5, +0x5A, 0xB4, 0x02, 0x05, 0x12, 0x4F, 0x93, 0x80, +0x7A, 0xE5, 0x5A, 0xB4, 0x03, 0x05, 0x12, 0x4F, +0xF4, 0x80, 0x70, 0xE5, 0x5A, 0x70, 0x6C, 0x12, +0x4F, 0xF2, 0x80, 0x67, 0xE5, 0x5A, 0xB4, 0x04, +0x04, 0xF1, 0x3B, 0x80, 0x5E, 0xE5, 0x5A, 0xB4, +0x01, 0x04, 0xF1, 0x2A, 0x80, 0x55, 0xE5, 0x5A, +0xB4, 0x03, 0x04, 0xF1, 0x1A, 0x80, 0x4C, 0xE5, +0x5A, 0x70, 0x48, 0xF1, 0x27, 0x80, 0x44, 0xE5, +0x5A, 0xB4, 0x04, 0x04, 0xF1, 0x9E, 0x80, 0x3B, +0xE5, 0x5A, 0xB4, 0x01, 0x04, 0xF1, 0x49, 0x80, +0x32, 0xE5, 0x5A, 0xB4, 0x02, 0x04, 0xF1, 0x66, +0x80, 0x29, 0xE5, 0x5A, 0x70, 0x25, 0xF1, 0x46, +0x80, 0x21, 0xE5, 0x5A, 0xB4, 0x03, 0x04, 0xF1, +0x1E, 0x80, 0x18, 0xE5, 0x5A, 0xB4, 0x01, 0x04, +0xF1, 0x03, 0x80, 0x0F, 0xE5, 0x5A, 0xB4, 0x02, +0x04, 0xF1, 0x8F, 0x80, 0x06, 0xE5, 0x5A, 0x70, +0x02, 0xF1, 0x22, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x90, 0x81, 0x41, 0xE0, 0xFF, 0x13, 0x13, 0x22, +0x90, 0x81, 0x41, 0xE0, 0xFF, 0xC4, 0x13, 0x13, +0x54, 0x03, 0x22, 0x90, 0x05, 0x43, 0xE0, 0x7F, +0x00, 0x30, 0xE7, 0x02, 0x7F, 0x01, 0x22, 0xE4, +0xF5, 0x4E, 0x90, 0x81, 0x4B, 0xE0, 0x60, 0x75, +0x12, 0x47, 0x84, 0x70, 0x70, 0xB1, 0x27, 0x12, +0x44, 0xD0, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, +0xC0, 0x07, 0x90, 0x05, 0x62, 0xB1, 0x40, 0x78, +0x10, 0x12, 0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, +0xD0, 0x01, 0xD0, 0x00, 0x12, 0x44, 0xD0, 0xC0, +0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0xA3, +0xB1, 0x40, 0x78, 0x18, 0x12, 0x20, 0xBB, 0xD0, +0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0xF1, +0xBE, 0x90, 0x81, 0x49, 0xE0, 0xFF, 0xC4, 0x54, +0x0F, 0x60, 0x08, 0x90, 0x81, 0x47, 0x91, 0x93, +0x20, 0xE0, 0x03, 0x75, 0x4E, 0x01, 0x90, 0x81, +0x41, 0xE0, 0x30, 0xE0, 0x11, 0x90, 0x81, 0x45, +0xE0, 0xB4, 0x02, 0x03, 0xE4, 0xF5, 0x4E, 0x91, +0x9B, 0xEF, 0x70, 0x02, 0xF5, 0x4E, 0xE5, 0x4E, +0x60, 0x03, 0x12, 0x49, 0x71, 0x22, 0xF0, 0x90, +0x05, 0x61, 0xE0, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, +0x78, 0x08, 0x12, 0x20, 0xBB, 0xA8, 0x04, 0xA9, +0x05, 0xAA, 0x06, 0xAB, 0x07, 0x90, 0x05, 0x60, +0xE0, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x22, 0xE4, +0x90, 0x81, 0xC4, 0xF0, 0x90, 0x81, 0x4B, 0xE0, +0x60, 0x74, 0x12, 0x47, 0x84, 0x70, 0x6F, 0x12, +0x7B, 0x74, 0xB1, 0x26, 0x12, 0x44, 0xD0, 0xC0, +0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0x90, +0x05, 0x62, 0xB1, 0x40, 0x78, 0x10, 0x12, 0x20, +0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, +0x00, 0x12, 0x44, 0xD0, 0xC0, 0x04, 0xC0, 0x05, +0xC0, 0x06, 0xC0, 0x07, 0xA3, 0xB1, 0x40, 0x78, +0x18, 0x12, 0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, +0xD0, 0x01, 0xD0, 0x00, 0xF1, 0xBE, 0x90, 0x81, +0xC4, 0x74, 0x01, 0xF0, 0xE4, 0x90, 0x81, 0x52, +0xF0, 0x90, 0x81, 0x41, 0xE0, 0x30, 0xE0, 0x15, +0x90, 0x81, 0x45, 0xE0, 0xB4, 0x02, 0x05, 0xE4, +0x90, 0x81, 0xC4, 0xF0, 0x91, 0x9B, 0xEF, 0x70, +0x04, 0x90, 0x81, 0xC4, 0xF0, 0x90, 0x81, 0xC4, +0xE0, 0x60, 0x03, 0x12, 0x49, 0x71, 0x22, 0x90, +0x81, 0x41, 0xE0, 0x30, 0xE0, 0x06, 0x90, 0x81, +0x43, 0x74, 0x01, 0xF0, 0x90, 0x81, 0x4B, 0xE0, +0x70, 0x02, 0xC1, 0x65, 0x90, 0x81, 0x62, 0xE0, +0x04, 0xB1, 0x26, 0x12, 0x44, 0xD0, 0xC0, 0x04, +0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x05, +0x62, 0xB1, 0x40, 0x78, 0x10, 0x12, 0x20, 0xBB, +0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, +0x12, 0x44, 0xD0, 0xC0, 0x04, 0xC0, 0x05, 0xC0, +0x06, 0xC0, 0x07, 0xA3, 0xB1, 0x40, 0x78, 0x18, +0x12, 0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0, +0x01, 0xD0, 0x00, 0x12, 0x44, 0xD0, 0x90, 0x81, +0x96, 0x12, 0x20, 0xCE, 0x90, 0x81, 0x47, 0xE0, +0x54, 0x7F, 0xF0, 0xA3, 0xE0, 0x30, 0xE0, 0x0C, +0x12, 0x67, 0xB0, 0x74, 0x05, 0xF0, 0x12, 0x6C, +0xF1, 0x12, 0x6E, 0x0C, 0x12, 0x65, 0xB9, 0x13, +0x54, 0x1F, 0x30, 0xE0, 0x09, 0x90, 0x01, 0x3B, +0xE0, 0x30, 0xE4, 0x02, 0xD1, 0x79, 0x90, 0x82, +0xAB, 0xE0, 0x04, 0xF0, 0xE0, 0xC3, 0x94, 0x80, +0x40, 0x0B, 0x90, 0x01, 0x98, 0xE0, 0x54, 0xFE, +0xF0, 0xE0, 0x44, 0x01, 0xF0, 0x12, 0x79, 0xD9, +0x90, 0x81, 0xB7, 0xE0, 0x30, 0xE0, 0x09, 0x90, +0x01, 0x3B, 0xE0, 0x30, 0xE4, 0x02, 0xD1, 0x79, +0x22, 0x7D, 0x02, 0x7F, 0x02, 0xD1, 0x83, 0x7D, +0x01, 0x7F, 0x02, 0x74, 0x3D, 0xF1, 0xA7, 0xFE, +0xF6, 0x74, 0x30, 0x80, 0x1A, 0x90, 0x01, 0x34, +0x74, 0x40, 0xF0, 0xFD, 0xE4, 0xFF, 0x02, 0x4F, +0xC3, 0x7D, 0x03, 0x7F, 0x02, 0x74, 0x45, 0x2F, +0xF8, 0xE6, 0x4D, 0xFE, 0xF6, 0x74, 0x38, 0x2F, +0xF5, 0x82, 0xE4, 0x34, 0x01, 0xF5, 0x83, 0xEE, +0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0xF1, 0xD6, 0xEF, 0x64, 0x01, 0x70, 0x1B, +0x90, 0x81, 0xB9, 0xE0, 0x7D, 0x10, 0x7F, 0x03, +0x60, 0x08, 0xD1, 0x9D, 0x12, 0x6B, 0xC9, 0xF0, +0x80, 0x04, 0xD1, 0xFD, 0xD1, 0x79, 0x12, 0x4E, +0x37, 0x80, 0x1D, 0x90, 0x81, 0xB9, 0xE0, 0x7D, +0x10, 0x7F, 0x03, 0x60, 0x04, 0xD1, 0x9D, 0x80, +0x02, 0xD1, 0xFD, 0x12, 0x4F, 0xBF, 0x7D, 0x01, +0x7F, 0x02, 0x12, 0x4F, 0xC3, 0x12, 0x4D, 0x6C, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x74, 0x45, 0xF1, +0xA7, 0x80, 0xA0, 0x7B, 0x1F, 0x7D, 0x6F, 0x7F, +0xFF, 0x12, 0x4D, 0x1C, 0x90, 0x05, 0x27, 0xE0, +0x54, 0xBF, 0xF0, 0x90, 0x81, 0x44, 0x74, 0x04, +0xF0, 0x22, 0xF1, 0x33, 0xF0, 0x22, 0x7B, 0x25, +0x80, 0xE3, 0x12, 0x4F, 0xF2, 0x80, 0xDC, 0x12, +0x4F, 0xF2, 0x7B, 0x20, 0x12, 0x4F, 0x9C, 0xF1, +0x33, 0xF0, 0x22, 0xF1, 0xE3, 0x90, 0x81, 0x44, +0x74, 0x02, 0x22, 0xF1, 0x96, 0x7B, 0x23, 0x12, +0x4F, 0x9C, 0xF1, 0x33, 0xF0, 0x22, 0x12, 0x4F, +0xF2, 0x7B, 0x21, 0x12, 0x4F, 0x9C, 0x90, 0x81, +0x44, 0x74, 0x03, 0xF0, 0x22, 0x12, 0x4F, 0xA9, +0x12, 0x7B, 0x5C, 0xE4, 0x90, 0x81, 0x44, 0xF0, +0x22, 0x12, 0x4F, 0x93, 0x80, 0xF2, 0x12, 0x4D, +0x77, 0x80, 0xE3, 0x12, 0x4F, 0xF4, 0x80, 0xE8, +0x90, 0x81, 0x45, 0xE0, 0x64, 0x02, 0x22, 0x91, +0x90, 0x30, 0xE0, 0x0B, 0xF1, 0x70, 0x60, 0x07, +0x7D, 0x01, 0x7F, 0x02, 0x12, 0x4B, 0x21, 0xF1, +0x70, 0x60, 0x03, 0x12, 0x75, 0xDA, 0x22, 0x12, +0x4D, 0x77, 0x7B, 0x24, 0xE1, 0x05, 0x90, 0x05, +0x27, 0xE0, 0x44, 0x40, 0xF0, 0x22, 0x7B, 0x22, +0x12, 0x4F, 0x9C, 0xF1, 0x96, 0x80, 0xA7, 0x2F, +0xF8, 0xE6, 0xFE, 0xED, 0xF4, 0x5E, 0x22, 0x12, +0x4D, 0x17, 0x12, 0x4F, 0xA3, 0xF1, 0x96, 0x90, +0x81, 0x45, 0x74, 0x04, 0xF0, 0x22, 0x12, 0x44, +0xD0, 0x90, 0x81, 0x9E, 0x12, 0x20, 0xCE, 0x90, +0x81, 0x47, 0xE0, 0x44, 0x80, 0xF0, 0x22, 0x75, +0xE8, 0x03, 0x75, 0xA8, 0x84, 0x22, 0x90, 0x01, +0x3F, 0x74, 0x10, 0xF0, 0x22, 0x7D, 0x02, 0x7F, +0x02, 0xC1, 0x83, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0xE4, 0x90, 0x82, 0x83, 0xF0, 0xA3, +0xF0, 0x12, 0x5D, 0xF1, 0x90, 0x85, 0xBB, 0x12, +0x20, 0xDA, 0xCC, 0xF0, 0x00, 0xC0, 0x7F, 0x8C, +0x12, 0x4F, 0xB0, 0x12, 0x20, 0xDA, 0x00, 0x00, +0x00, 0x14, 0xF1, 0xD9, 0x90, 0x82, 0x7F, 0x12, +0x20, 0xDA, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xFD, +0xFF, 0xB1, 0xB7, 0x7F, 0xE8, 0x7E, 0x08, 0x12, +0x2D, 0x5C, 0xEF, 0x54, 0x0E, 0xFF, 0xE4, 0xFE, +0xED, 0x54, 0xF4, 0xFD, 0xEC, 0x54, 0x03, 0xFC, +0xE4, 0xFB, 0xFA, 0xF9, 0xF8, 0xC3, 0x12, 0x44, +0xDD, 0x60, 0x17, 0xD3, 0x11, 0x89, 0x40, 0x09, +0x90, 0x01, 0xC3, 0xE0, 0x44, 0x02, 0xF0, 0x80, +0x09, 0xD1, 0x5A, 0x90, 0x82, 0x83, 0xD1, 0x53, +0x80, 0xC9, 0xC3, 0x11, 0x89, 0x50, 0x1B, 0xF1, +0xD2, 0xEC, 0x44, 0x80, 0xFC, 0x90, 0x82, 0x85, +0x12, 0x20, 0xCE, 0x90, 0x82, 0x85, 0x12, 0x44, +0xEE, 0x11, 0x97, 0x7F, 0x7C, 0x7E, 0x08, 0x12, +0x2E, 0xA2, 0x90, 0x01, 0x00, 0x74, 0x3F, 0xF0, +0xA3, 0xE0, 0x54, 0xFD, 0xF0, 0x90, 0x05, 0x53, +0xE0, 0x44, 0x20, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x90, 0x82, 0x84, 0xE0, 0x94, 0xE8, 0x90, +0x82, 0x83, 0xE0, 0x94, 0x03, 0x22, 0xFC, 0x90, +0x85, 0xBB, 0x02, 0x20, 0xCE, 0x90, 0x82, 0x55, +0xEF, 0xF0, 0xA3, 0xED, 0xF0, 0xA3, 0x12, 0x20, +0xDA, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x90, 0x82, +0x63, 0xF0, 0x7F, 0x24, 0x7E, 0x08, 0x12, 0x2D, +0x5C, 0x90, 0x82, 0x5B, 0x12, 0x20, 0xCE, 0x90, +0x82, 0x55, 0xE0, 0xFB, 0x70, 0x04, 0x31, 0x81, +0x80, 0x06, 0xEB, 0x31, 0x87, 0x12, 0x2D, 0x5C, +0x90, 0x82, 0x5F, 0x12, 0x20, 0xCE, 0x90, 0x82, +0x56, 0x12, 0x55, 0x40, 0x78, 0x17, 0xB1, 0xD9, +0xAB, 0x07, 0x90, 0x82, 0x5F, 0x12, 0x44, 0xEE, +0xED, 0x54, 0x7F, 0xFD, 0xEC, 0x54, 0x80, 0xFC, +0x12, 0x44, 0xD0, 0xEC, 0x44, 0x80, 0xFC, 0x90, +0x82, 0x5F, 0x12, 0x20, 0xCE, 0x31, 0x81, 0xEC, +0x54, 0x7F, 0x11, 0x96, 0x31, 0x9A, 0x31, 0x87, +0xC0, 0x06, 0xC0, 0x07, 0x90, 0x82, 0x5F, 0x12, +0x44, 0xEE, 0x11, 0x97, 0xD0, 0x07, 0xD0, 0x06, +0x12, 0x2E, 0xA2, 0x31, 0x81, 0xEC, 0x44, 0x80, +0x11, 0x96, 0x31, 0x9A, 0x70, 0x04, 0x7F, 0x20, +0x80, 0x09, 0x90, 0x82, 0x55, 0xE0, 0xB4, 0x01, +0x16, 0x7F, 0x28, 0x7E, 0x08, 0x12, 0x2D, 0x5C, +0x78, 0x08, 0x12, 0x20, 0xA8, 0xEF, 0x54, 0x01, +0xFF, 0xE4, 0x90, 0x82, 0x63, 0xEF, 0xF0, 0x90, +0x82, 0x63, 0xE0, 0x90, 0x82, 0x55, 0x60, 0x0E, +0xE0, 0x75, 0xF0, 0x08, 0xA4, 0x24, 0x66, 0xF5, +0x82, 0xE4, 0x34, 0x87, 0x80, 0x0C, 0xE0, 0x75, +0xF0, 0x08, 0xA4, 0x24, 0x64, 0xF5, 0x82, 0xE4, +0x34, 0x87, 0x31, 0x92, 0x12, 0x2D, 0x5C, 0xED, +0x54, 0x0F, 0xFD, 0xE4, 0xFC, 0x90, 0x82, 0x57, +0x12, 0x20, 0xCE, 0x90, 0x82, 0x57, 0x02, 0x44, +0xEE, 0x90, 0x82, 0x5B, 0x02, 0x44, 0xEE, 0x75, +0xF0, 0x08, 0xA4, 0x24, 0x62, 0xF5, 0x82, 0xE4, +0x34, 0x87, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, +0xFF, 0x22, 0x7F, 0x24, 0x7E, 0x08, 0x12, 0x2E, +0xA2, 0x90, 0x82, 0x55, 0xE0, 0x22, 0x90, 0x82, +0x73, 0xEF, 0xF0, 0xAB, 0x05, 0x90, 0x82, 0x79, +0x12, 0x20, 0xDA, 0x00, 0x00, 0x00, 0x00, 0xAF, +0x03, 0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x14, 0xB1, +0xD9, 0xAB, 0x07, 0x90, 0x82, 0x75, 0x12, 0x44, +0xEE, 0xED, 0x54, 0x0F, 0xFD, 0xE4, 0xFC, 0x12, +0x44, 0xD0, 0xEC, 0x54, 0x0F, 0xFC, 0x90, 0x82, +0x79, 0x12, 0x20, 0xCE, 0x90, 0x82, 0x73, 0xE0, +0x75, 0xF0, 0x08, 0xA4, 0x24, 0x60, 0xF5, 0x82, +0xE4, 0x34, 0x87, 0x31, 0x92, 0xC0, 0x06, 0xC0, +0x07, 0x90, 0x82, 0x79, 0x12, 0x44, 0xEE, 0x11, +0x97, 0xD0, 0x07, 0xD0, 0x06, 0x02, 0x2E, 0xA2, +0xAC, 0x07, 0xED, 0xAD, 0x04, 0x78, 0x24, 0xF2, +0xED, 0x08, 0xF2, 0xEB, 0xB4, 0x04, 0x07, 0x78, +0x27, 0x74, 0x01, 0xF2, 0x80, 0x0E, 0xEB, 0x78, +0x27, 0xB4, 0x05, 0x05, 0x74, 0x02, 0xF2, 0x80, +0x03, 0x74, 0x04, 0xF2, 0xB1, 0x73, 0xE2, 0x94, +0x00, 0x50, 0x45, 0xE4, 0x78, 0x26, 0xF2, 0x71, +0x1B, 0x9F, 0x40, 0x02, 0x61, 0x1A, 0x71, 0x24, +0x60, 0x1F, 0x74, 0x37, 0x2E, 0xF8, 0xE2, 0x78, +0x32, 0xF2, 0xEE, 0xFF, 0x78, 0x25, 0xE2, 0x2F, +0xFF, 0x18, 0xE2, 0x34, 0x00, 0x8F, 0x82, 0xF5, +0x83, 0xE0, 0x78, 0x29, 0xF2, 0x78, 0x32, 0xB1, +0x93, 0x78, 0x24, 0x08, 0xE2, 0xFF, 0x08, 0xE2, +0x2F, 0xFF, 0x78, 0x28, 0xE2, 0xFD, 0x12, 0x32, +0x1E, 0x78, 0x26, 0xE2, 0x04, 0xF2, 0x80, 0xBF, +0xB1, 0x73, 0xE2, 0x94, 0x07, 0x50, 0x30, 0xE4, +0x78, 0x26, 0xF2, 0x71, 0x1B, 0x9F, 0x40, 0x02, +0x61, 0x1A, 0x71, 0x24, 0x60, 0x14, 0x78, 0x26, +0xE2, 0xFF, 0xB1, 0x85, 0xE0, 0x78, 0x29, 0xF2, +0x74, 0x37, 0x2F, 0xF8, 0xE2, 0x78, 0x32, 0xF2, +0xB1, 0x93, 0xB1, 0x6B, 0xB1, 0x85, 0xEF, 0xF0, +0x78, 0x26, 0xE2, 0x04, 0xF2, 0x80, 0xD4, 0x90, +0x82, 0x35, 0xE0, 0x60, 0x0A, 0xB1, 0x63, 0x12, +0x2D, 0x5C, 0x78, 0x2E, 0x12, 0x45, 0x1F, 0xE4, +0x78, 0x26, 0xF2, 0x71, 0x1B, 0x9F, 0x50, 0x4E, +0x71, 0x24, 0x60, 0x2B, 0x78, 0x2E, 0x12, 0x44, +0xFA, 0x78, 0x26, 0xE2, 0xFB, 0x75, 0xF0, 0x08, +0xA4, 0xF9, 0xF8, 0x12, 0x20, 0xA8, 0x78, 0x29, +0xEF, 0xF2, 0x74, 0x37, 0x2B, 0xF8, 0xE2, 0x78, +0x32, 0xF2, 0xE2, 0xFE, 0xF4, 0x5F, 0xFF, 0x78, +0x28, 0xE2, 0xFD, 0xEE, 0x5D, 0x4F, 0xF2, 0xB1, +0x6B, 0xFD, 0xC3, 0x74, 0x03, 0x9D, 0xFD, 0xE4, +0x94, 0x00, 0xFC, 0x7B, 0xFE, 0x74, 0x2A, 0x2D, +0xF9, 0x74, 0x80, 0x3C, 0xFA, 0xEF, 0x12, 0x1F, +0xEA, 0xE2, 0x04, 0xF2, 0x80, 0xAD, 0x78, 0x2A, +0x12, 0x44, 0xFA, 0x11, 0x97, 0xB1, 0x63, 0x12, +0x2E, 0xA2, 0x22, 0x78, 0x27, 0xE2, 0xFF, 0x18, +0xE2, 0xFE, 0xC3, 0x22, 0x74, 0x33, 0x2E, 0xF8, +0xE2, 0x78, 0x28, 0xF2, 0x90, 0x82, 0x35, 0xE0, +0x22, 0x78, 0x10, 0x74, 0x01, 0xF2, 0x90, 0x02, +0x09, 0xE0, 0x78, 0x00, 0xF2, 0x08, 0x74, 0x20, +0xF2, 0x18, 0xE2, 0xFF, 0x30, 0xE0, 0x05, 0x08, +0xE2, 0x24, 0x80, 0xF2, 0xEF, 0xC3, 0x13, 0x90, +0xFD, 0x10, 0xF0, 0x78, 0x01, 0xE2, 0xB1, 0x7B, +0xE0, 0x78, 0x03, 0xF2, 0x64, 0x04, 0x60, 0x0D, +0xE2, 0xFF, 0x64, 0x08, 0x60, 0x07, 0xEF, 0x64, +0x0C, 0x60, 0x02, 0xA1, 0x59, 0xE4, 0x78, 0x02, +0xF2, 0x78, 0x03, 0xE2, 0xFF, 0x18, 0xE2, 0xC3, +0x9F, 0x50, 0x26, 0xE2, 0xFD, 0x18, 0xE2, 0x2D, +0x90, 0x81, 0xD3, 0xF0, 0xE0, 0xFF, 0xB1, 0x7B, +0xE0, 0xFE, 0x74, 0x04, 0x2D, 0xF8, 0xEE, 0xF2, +0xEF, 0xB4, 0xFF, 0x06, 0x90, 0xFD, 0x10, 0xE0, +0x04, 0xF0, 0x78, 0x02, 0xE2, 0x04, 0xF2, 0x80, +0xD0, 0x78, 0x04, 0xE2, 0x78, 0x12, 0xF2, 0xFF, +0x78, 0x05, 0xE2, 0x78, 0x11, 0xF2, 0x78, 0x06, +0xE2, 0x78, 0x13, 0xF2, 0x78, 0x07, 0xE2, 0x78, +0x14, 0xF2, 0x78, 0x08, 0xE2, 0x78, 0x33, 0xF2, +0x78, 0x09, 0xE2, 0x78, 0x34, 0xF2, 0x78, 0x0A, +0xE2, 0x78, 0x35, 0xF2, 0x78, 0x0B, 0xE2, 0x78, +0x36, 0xF2, 0x78, 0x0C, 0xE2, 0x78, 0x37, 0xF2, +0x78, 0x0D, 0xE2, 0x78, 0x38, 0xF2, 0x78, 0x0E, +0xE2, 0x78, 0x39, 0xF2, 0x78, 0x0F, 0xE2, 0x78, +0x3A, 0xF2, 0xE4, 0x78, 0x15, 0xF2, 0xEF, 0x24, +0xF8, 0x60, 0x56, 0x24, 0xFC, 0x60, 0x4D, 0x24, +0x08, 0x60, 0x02, 0xA1, 0x3B, 0x78, 0x11, 0xE2, +0xB4, 0x01, 0x05, 0x12, 0x29, 0xC5, 0xA1, 0x40, +0x78, 0x11, 0xE2, 0xB4, 0x02, 0x05, 0x12, 0x11, +0xBD, 0xA1, 0x40, 0x78, 0x11, 0xE2, 0xB4, 0x03, +0x05, 0x12, 0x6F, 0x9D, 0xA1, 0x40, 0x78, 0x11, +0xE2, 0xB4, 0x10, 0x07, 0xB1, 0xA4, 0x12, 0x32, +0xAA, 0xA1, 0x40, 0x78, 0x11, 0xE2, 0xB4, 0x11, +0x07, 0xB1, 0xA4, 0x12, 0x32, 0x06, 0xA1, 0x40, +0x78, 0x11, 0xE2, 0xF4, 0x60, 0x02, 0xA1, 0x40, +0x18, 0xF2, 0xA1, 0x40, 0x78, 0x15, 0x74, 0x01, +0xF2, 0x78, 0x11, 0xE2, 0x64, 0x07, 0x60, 0x02, +0xA1, 0x25, 0x78, 0x34, 0xB1, 0x5C, 0x78, 0x08, +0x12, 0x20, 0xBB, 0xC0, 0x04, 0xA9, 0x05, 0xAA, +0x06, 0xAB, 0x07, 0x78, 0x33, 0xB1, 0x5C, 0xD0, +0x00, 0x12, 0x44, 0xD0, 0xC0, 0x04, 0xC0, 0x05, +0xC0, 0x06, 0xC0, 0x07, 0x78, 0x35, 0xB1, 0x5C, +0x78, 0x10, 0x12, 0x20, 0xBB, 0xD0, 0x03, 0xD0, +0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, 0x44, 0xD0, +0x78, 0x18, 0x12, 0x45, 0x1F, 0x78, 0x15, 0xE2, +0x60, 0x7D, 0x18, 0xE2, 0xFF, 0x18, 0xE2, 0xFD, +0xB1, 0xE3, 0x78, 0x1C, 0x12, 0x45, 0x1F, 0x78, +0x38, 0xB1, 0x5C, 0x78, 0x08, 0x12, 0x20, 0xBB, +0xC0, 0x04, 0xA9, 0x05, 0xAA, 0x06, 0xAB, 0x07, +0x78, 0x37, 0xB1, 0x5C, 0xD0, 0x00, 0x12, 0x44, +0xD0, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, +0x07, 0x78, 0x39, 0xB1, 0x5C, 0x78, 0x10, 0x12, +0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, +0xD0, 0x00, 0x12, 0x44, 0xD0, 0x78, 0x20, 0x12, +0x45, 0x1F, 0x78, 0x20, 0x12, 0x44, 0xFA, 0x12, +0x20, 0x9B, 0x78, 0x1C, 0x12, 0x45, 0x12, 0x12, +0x44, 0xC3, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, +0xC0, 0x07, 0x78, 0x18, 0x12, 0x44, 0xFA, 0x78, +0x20, 0x12, 0x45, 0x12, 0x12, 0x44, 0xC3, 0xD0, +0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, +0x44, 0xD0, 0x78, 0x18, 0x12, 0x45, 0x1F, 0x78, +0x18, 0x12, 0x44, 0xFA, 0x90, 0x82, 0x7F, 0x12, +0x20, 0xCE, 0x78, 0x13, 0xE2, 0xFD, 0x08, 0xE2, +0xFF, 0xB1, 0xB7, 0x80, 0x1B, 0x78, 0x13, 0xE2, +0xFF, 0x08, 0xE2, 0xFD, 0x78, 0x11, 0xE2, 0xFB, +0x78, 0x15, 0xE2, 0x90, 0x82, 0x35, 0xF0, 0x51, +0x00, 0x80, 0x05, 0x78, 0x10, 0x74, 0x02, 0xF2, +0x78, 0x10, 0xE2, 0xFF, 0xC3, 0x94, 0x02, 0x50, +0x10, 0xEF, 0x60, 0x0A, 0x78, 0x02, 0xE2, 0xFF, +0x18, 0xE2, 0x2F, 0xF2, 0x61, 0x53, 0x7F, 0x01, +0x22, 0x7F, 0x00, 0x22, 0xE2, 0xFF, 0xE4, 0xFC, +0xFD, 0xFE, 0x22, 0x78, 0x24, 0xE2, 0xFE, 0x08, +0xE2, 0xFF, 0x22, 0x78, 0x28, 0xE2, 0xFF, 0x78, +0x26, 0xE2, 0x22, 0xD3, 0x78, 0x25, 0xE2, 0x94, +0xFF, 0x18, 0x22, 0x24, 0x00, 0xF5, 0x82, 0xE4, +0x34, 0xFC, 0xF5, 0x83, 0x22, 0xFD, 0x18, 0xE2, +0x2D, 0xFD, 0x18, 0xE2, 0x34, 0x00, 0x8D, 0x82, +0xF5, 0x83, 0x22, 0xE2, 0xFF, 0xF4, 0xFE, 0x78, +0x29, 0xE2, 0x5E, 0xFE, 0x18, 0xE2, 0xFD, 0xEF, +0x5D, 0x4E, 0xF2, 0x22, 0x78, 0x14, 0xE2, 0xFE, +0x18, 0xE2, 0xFD, 0xED, 0xFF, 0x78, 0x16, 0xEE, +0xF2, 0xFE, 0x08, 0xEF, 0xF2, 0xFF, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xC0, 0x07, +0xC0, 0x05, 0x90, 0x82, 0x7F, 0x12, 0x44, 0xEE, +0x90, 0x82, 0x75, 0x12, 0x20, 0xCE, 0xD0, 0x05, +0xD0, 0x07, 0x31, 0xA6, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x12, 0x20, 0xBB, 0xA8, 0x04, 0xA9, 0x05, +0xAA, 0x06, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x11, 0x9D, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0xE4, 0x90, 0x82, 0xA2, 0xF0, 0xA3, 0xF0, +0x90, 0x05, 0x22, 0xE0, 0x90, 0x82, 0xA4, 0xF0, +0x7B, 0x47, 0xF1, 0x97, 0x90, 0x05, 0xF8, 0xE0, +0x70, 0x1B, 0xA3, 0xE0, 0x70, 0x17, 0xA3, 0xE0, +0x70, 0x13, 0xA3, 0xE0, 0x70, 0x0F, 0x90, 0x82, +0xA4, 0xE0, 0xFD, 0x7B, 0x48, 0xE4, 0xFF, 0x12, +0x4D, 0x1C, 0x7F, 0x01, 0x22, 0xD3, 0x90, 0x82, +0xA3, 0xE0, 0x94, 0xE8, 0x90, 0x82, 0xA2, 0xE0, +0x94, 0x03, 0x40, 0x16, 0x90, 0x01, 0xC0, 0xE0, +0x44, 0x20, 0xF0, 0x90, 0x82, 0xA4, 0xE0, 0xFD, +0x7B, 0x5B, 0xE4, 0xFF, 0x12, 0x4D, 0x1C, 0x7F, +0x00, 0x22, 0xD1, 0x5A, 0x90, 0x82, 0xA2, 0xD1, +0x53, 0x80, 0xB1, 0xE4, 0x75, 0xF0, 0x01, 0x02, +0x44, 0x9F, 0x7F, 0x32, 0x7E, 0x00, 0x02, 0x32, +0xAA, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x90, 0x82, 0x9E, 0xEF, 0xF0, 0x90, 0x04, 0x1D, +0xE0, 0x60, 0x21, 0x90, 0x05, 0x22, 0xE0, 0x90, +0x82, 0xA1, 0xF0, 0x7B, 0x29, 0xF1, 0x97, 0xB1, +0xF1, 0xBF, 0x01, 0x02, 0xD1, 0x9D, 0x90, 0x82, +0xA1, 0xE0, 0xFD, 0x7B, 0x2A, 0xE4, 0xFF, 0x12, +0x4D, 0x1C, 0x80, 0x02, 0xD1, 0x9D, 0xF1, 0xCB, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x80, 0x47, +0xE0, 0xFF, 0x90, 0x82, 0x95, 0x74, 0x0B, 0xF0, +0x7B, 0x08, 0x7D, 0x01, 0xD1, 0xE7, 0x90, 0x82, +0x9F, 0xEE, 0xF0, 0xFC, 0xA3, 0xEF, 0xF0, 0xFD, +0x90, 0x82, 0x9E, 0xE0, 0xFF, 0xF1, 0x8B, 0x54, +0x3F, 0xF0, 0xBF, 0x01, 0x02, 0x80, 0x16, 0xEF, +0x70, 0x02, 0x80, 0x07, 0x90, 0x81, 0x4E, 0xE0, +0x30, 0xE3, 0x0A, 0xF1, 0x7E, 0x54, 0xEF, 0xF1, +0x8A, 0x44, 0x40, 0xF0, 0x22, 0xF1, 0x7E, 0x44, +0x10, 0xF1, 0x8A, 0x44, 0x80, 0xF0, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x82, +0x93, 0xED, 0xF0, 0xA3, 0xEB, 0xF0, 0x90, 0x82, +0x92, 0xEF, 0xF0, 0xE4, 0xFD, 0xFC, 0x12, 0x7A, +0xFF, 0x7C, 0x00, 0xAD, 0x07, 0x90, 0x82, 0x92, +0xE0, 0x90, 0x04, 0x25, 0xF0, 0x90, 0x82, 0x93, +0xE0, 0x60, 0x0E, 0x74, 0x0F, 0x2F, 0xF5, 0x82, +0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x80, +0xF0, 0xAF, 0x05, 0x74, 0x08, 0x2F, 0xF5, 0x82, +0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE4, 0xF0, 0x74, +0x09, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, +0x83, 0xE0, 0x54, 0xF0, 0xF0, 0xAF, 0x05, 0xF1, +0x9E, 0xE0, 0x20, 0xE1, 0x15, 0x54, 0x01, 0xFE, +0x90, 0x82, 0x94, 0xE0, 0x25, 0xE0, 0x25, 0xE0, +0xFB, 0xEE, 0x44, 0x02, 0x4B, 0xFE, 0xF1, 0x9E, +0xEE, 0xF0, 0x90, 0x82, 0x95, 0xE0, 0xFF, 0xAE, +0x05, 0x74, 0x1E, 0x2E, 0xF5, 0x82, 0xE4, 0x34, +0xFC, 0xF5, 0x83, 0xEF, 0xF0, 0x74, 0x21, 0x2E, +0xF1, 0x81, 0x54, 0xF7, 0xF0, 0xAE, 0x04, 0xAF, +0x05, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x74, 0x21, +0x2D, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, +0xE0, 0x22, 0xF0, 0x74, 0x1F, 0x2D, 0xF5, 0x82, +0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x22, 0x7D, +0xFF, 0xE4, 0xFF, 0x02, 0x4D, 0x1C, 0x74, 0x16, +0x2F, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, +0x22, 0x90, 0x04, 0x1D, 0xE0, 0x70, 0x1B, 0x90, +0x80, 0x45, 0xE0, 0xFF, 0x90, 0x82, 0x95, 0x74, +0x09, 0xF0, 0x7B, 0x18, 0xE4, 0xFD, 0xD1, 0xE7, +0x90, 0x81, 0xC2, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, +0xF1, 0xCB, 0x22, 0x90, 0x04, 0x1F, 0x74, 0x20, +0xF0, 0x22, 0x7F, 0x7C, 0x7E, 0x08, 0x02, 0x2D, +0x5C, 0x7F, 0x70, 0x7E, 0x0E, 0x02, 0x2E, 0xA2, +0x90, 0x00, 0xF7, 0xE0, 0x20, 0xE7, 0x09, 0xE0, +0x7F, 0x01, 0x20, 0xE6, 0x0C, 0x7F, 0x02, 0x22, +0x90, 0x00, 0xF7, 0xE0, 0x30, 0xE6, 0x02, 0x7F, +0x03, 0x22, 0xF1, 0xE0, 0x90, 0x80, 0x42, 0xEF, +0xF0, 0x11, 0x1A, 0x90, 0x01, 0x64, 0x74, 0x01, +0xF0, 0x90, 0x00, 0x12, 0xE0, 0x54, 0xC7, 0x44, +0x20, 0xFD, 0x7F, 0x12, 0x12, 0x32, 0x1E, 0x02, +0x2D, 0xA7, 0x90, 0x00, 0x08, 0xE0, 0x54, 0xEF, +0xF0, 0x11, 0x92, 0x11, 0xBA, 0x11, 0x51, 0x11, +0x70, 0xE4, 0xF5, 0x35, 0xF5, 0x37, 0xF5, 0x36, +0xF5, 0x37, 0x75, 0x38, 0x80, 0xAD, 0x35, 0x7F, +0x50, 0x12, 0x32, 0x1E, 0xAD, 0x36, 0x7F, 0x51, +0x12, 0x32, 0x1E, 0xAD, 0x37, 0x7F, 0x52, 0x12, +0x32, 0x1E, 0xAD, 0x38, 0x7F, 0x53, 0x02, 0x32, +0x1E, 0x75, 0x3D, 0x10, 0xE4, 0xF5, 0x3E, 0x75, +0x3F, 0x07, 0x75, 0x40, 0x02, 0x90, 0x01, 0x30, +0xE5, 0x3D, 0xF0, 0xA3, 0xE5, 0x3E, 0xF0, 0xA3, +0xE5, 0x3F, 0xF0, 0xA3, 0xE5, 0x40, 0xF0, 0x22, +0x75, 0x45, 0x07, 0x75, 0x46, 0x01, 0x43, 0x46, +0x10, 0x75, 0x47, 0x03, 0x75, 0x48, 0x62, 0x90, +0x01, 0x38, 0xE5, 0x45, 0xF0, 0xA3, 0xE5, 0x46, +0xF0, 0xA3, 0xE5, 0x47, 0xF0, 0xA3, 0xE5, 0x48, +0xF0, 0x22, 0x90, 0x01, 0x30, 0xE4, 0x12, 0x51, +0x5C, 0x90, 0x01, 0x38, 0x12, 0x51, 0x5C, 0xFD, +0x7F, 0x50, 0x12, 0x32, 0x1E, 0xE4, 0xFD, 0x7F, +0x51, 0x12, 0x32, 0x1E, 0xE4, 0xFD, 0x7F, 0x52, +0x12, 0x32, 0x1E, 0xE4, 0xFD, 0x7F, 0x53, 0x02, +0x32, 0x1E, 0x90, 0x01, 0x34, 0x74, 0xFF, 0x12, +0x51, 0x5C, 0x90, 0x01, 0x3C, 0x12, 0x51, 0x5C, +0xFD, 0x7F, 0x54, 0x12, 0x32, 0x1E, 0x7D, 0xFF, +0x7F, 0x55, 0x12, 0x32, 0x1E, 0x7D, 0xFF, 0x7F, +0x56, 0x12, 0x32, 0x1E, 0x7D, 0xFF, 0x7F, 0x57, +0x02, 0x32, 0x1E, 0x90, 0x01, 0xCF, 0xE0, 0x90, +0x82, 0xAC, 0xF0, 0xE0, 0xFF, 0x30, 0xE0, 0x07, +0x90, 0x01, 0xCF, 0xE0, 0x54, 0xFE, 0xF0, 0xEF, +0x30, 0xE5, 0x22, 0x90, 0x01, 0xCF, 0xE0, 0x54, +0xDF, 0xF0, 0x90, 0x01, 0x34, 0x74, 0x20, 0xF0, +0xE4, 0xF5, 0xA8, 0xF5, 0xE8, 0x11, 0x92, 0x90, +0x00, 0x03, 0xE0, 0x54, 0xFB, 0xFD, 0x7F, 0x03, +0x12, 0x32, 0x1E, 0x80, 0xFE, 0x22, 0xE4, 0x90, +0x81, 0xD0, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0x90, +0x81, 0xD0, 0xE0, 0x64, 0x01, 0xF0, 0x24, 0x1E, +0x90, 0x01, 0xC4, 0xF0, 0x74, 0x61, 0xA3, 0xF0, +0x90, 0x81, 0x4B, 0xE0, 0x60, 0x0E, 0x90, 0x81, +0x4E, 0xE0, 0xFF, 0x90, 0x81, 0x4D, 0xE0, 0x6F, +0x60, 0x02, 0x31, 0x68, 0xC2, 0xAF, 0x12, 0x74, +0xE0, 0xBF, 0x01, 0x02, 0x31, 0xAD, 0xD2, 0xAF, +0xF1, 0xC1, 0x12, 0x32, 0x9E, 0xBF, 0x01, 0x03, +0x12, 0x72, 0xCA, 0x12, 0x41, 0x4D, 0x80, 0xBF, +0x90, 0x81, 0x41, 0xE0, 0x90, 0x81, 0x4D, 0x30, +0xE0, 0x04, 0xE0, 0xFF, 0x80, 0x1C, 0xE0, 0xFF, +0x7D, 0x01, 0x02, 0x4B, 0x21, 0x90, 0x81, 0x4B, +0xE0, 0x60, 0x0E, 0x90, 0x06, 0x92, 0xE0, 0x30, +0xE1, 0x02, 0x41, 0xCF, 0x12, 0x74, 0x12, 0x31, +0x68, 0x22, 0xAE, 0x07, 0x12, 0x54, 0x9B, 0xBF, +0x01, 0x10, 0x12, 0x7B, 0x39, 0x20, 0xE0, 0x0A, +0xAF, 0x06, 0x7D, 0x01, 0x12, 0x4B, 0x21, 0x7F, +0x01, 0x22, 0x7F, 0x00, 0x22, 0x90, 0x81, 0x46, +0xE0, 0x30, 0xE0, 0x19, 0x90, 0x81, 0x41, 0xE0, +0xFF, 0x30, 0xE0, 0x0F, 0xC3, 0x13, 0x30, 0xE0, +0x08, 0x12, 0x7A, 0x4B, 0xBF, 0x01, 0x06, 0x80, +0x02, 0x80, 0x00, 0x31, 0xCE, 0x22, 0x90, 0x81, +0x4E, 0xE0, 0xFF, 0x60, 0x03, 0xB4, 0x08, 0x0E, +0x12, 0x76, 0x98, 0xBF, 0x01, 0x08, 0x31, 0xE7, +0x90, 0x01, 0xE5, 0xE0, 0x04, 0xF0, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x77, +0x1A, 0x31, 0xF8, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x12, 0x76, 0xFD, 0x90, 0x81, 0x56, 0xE0, 0x20, +0xE0, 0x0C, 0x90, 0x00, 0x26, 0xE0, 0x54, 0x7F, +0xFD, 0x7F, 0x26, 0x12, 0x32, 0x1E, 0x90, 0x00, +0x08, 0xE0, 0x54, 0xEF, 0xFD, 0x7F, 0x08, 0x12, +0x32, 0x1E, 0xE4, 0xFF, 0x90, 0x81, 0xD3, 0xEF, +0xF0, 0xE4, 0xA3, 0xF0, 0xA3, 0xF0, 0x90, 0x01, +0x09, 0xE0, 0x7F, 0x00, 0x30, 0xE7, 0x02, 0x7F, +0x01, 0x90, 0x81, 0xD3, 0xE0, 0x6F, 0x60, 0x35, +0xC3, 0x90, 0x81, 0xD5, 0xE0, 0x94, 0x88, 0x90, +0x81, 0xD4, 0xE0, 0x94, 0x13, 0x40, 0x08, 0x90, +0x01, 0xC0, 0xE0, 0x44, 0x10, 0xF0, 0x22, 0x90, +0x81, 0xD4, 0x12, 0x5E, 0x53, 0xF1, 0xD0, 0xD3, +0x90, 0x81, 0xD5, 0xE0, 0x94, 0x32, 0x90, 0x81, +0xD4, 0xE0, 0x94, 0x00, 0x40, 0xC0, 0x90, 0x01, +0xC6, 0xE0, 0x30, 0xE0, 0xB9, 0x22, 0x90, 0x81, +0x46, 0x12, 0x54, 0x93, 0x30, 0xE0, 0x1E, 0xEF, +0x54, 0xBF, 0xF0, 0x90, 0x04, 0xE0, 0xE0, 0x90, +0x81, 0x47, 0x30, 0xE0, 0x06, 0xE0, 0x44, 0x01, +0xF0, 0x80, 0x08, 0xE0, 0x54, 0xFE, 0x51, 0xC4, +0x74, 0x04, 0xF0, 0x31, 0x68, 0x22, 0x90, 0x81, +0x46, 0xE0, 0xFF, 0xF1, 0x7E, 0x30, 0xE0, 0x23, +0xEF, 0x54, 0x7F, 0xF0, 0x90, 0x04, 0xE0, 0xE0, +0x90, 0x81, 0x47, 0x30, 0xE1, 0x06, 0xE0, 0x44, +0x02, 0xF0, 0x80, 0x07, 0xE0, 0x54, 0xFD, 0x51, +0xC4, 0x04, 0xF0, 0x90, 0x81, 0x4B, 0xE0, 0x60, +0x02, 0x31, 0x68, 0x22, 0xF0, 0x90, 0x01, 0xB9, +0x74, 0x01, 0xF0, 0x90, 0x01, 0xB8, 0x22, 0x12, +0x7B, 0x43, 0x30, 0xE0, 0x05, 0x90, 0x01, 0x5B, +0xE4, 0xF0, 0x90, 0x06, 0x92, 0x74, 0x02, 0xF0, +0x90, 0x01, 0x3C, 0x74, 0x04, 0xF0, 0xE4, 0xF5, +0x1D, 0x90, 0x81, 0xAA, 0xE0, 0xC3, 0x13, 0x54, +0x7F, 0xF5, 0x1E, 0xE4, 0xFB, 0xFD, 0x7F, 0x58, +0x7E, 0x01, 0x12, 0x49, 0x0C, 0x90, 0x81, 0x46, +0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x81, 0x4B, +0xE0, 0x64, 0x01, 0x70, 0x18, 0x71, 0x36, 0x60, +0x0C, 0xE4, 0xFD, 0x7F, 0x0C, 0x12, 0x4B, 0x21, +0x12, 0x4D, 0x17, 0x80, 0xB2, 0x90, 0x81, 0x4E, +0xE0, 0x70, 0x02, 0xF1, 0xD7, 0x22, 0x12, 0x75, +0xF0, 0xEF, 0x70, 0x02, 0x71, 0x05, 0x22, 0x90, +0x81, 0x4F, 0xE0, 0x44, 0x01, 0xF0, 0x90, 0x81, +0x49, 0xE0, 0x54, 0x0F, 0x22, 0x90, 0x06, 0xA9, +0xE0, 0xF5, 0x4E, 0x54, 0xC0, 0x70, 0x07, 0x71, +0x7F, 0x54, 0xFD, 0xF0, 0x21, 0x68, 0xE5, 0x4E, +0x30, 0xE6, 0x18, 0x90, 0x81, 0x4B, 0xE0, 0x64, +0x01, 0x70, 0x12, 0x71, 0x2F, 0x64, 0x02, 0x60, +0x05, 0x12, 0x5F, 0xA9, 0x80, 0x07, 0x12, 0x4F, +0x80, 0x80, 0x02, 0x71, 0x7F, 0xE5, 0x4E, 0x90, +0x81, 0x4F, 0x30, 0xE7, 0x05, 0x12, 0x48, 0xF8, +0xE1, 0x85, 0xE0, 0x54, 0xFD, 0xF0, 0x22, 0x90, +0x81, 0x4F, 0xE0, 0x54, 0xFE, 0xF0, 0x22, 0x90, +0x06, 0xA9, 0xE0, 0x90, 0x81, 0xC1, 0xF0, 0xE0, +0xFD, 0x54, 0xC0, 0x70, 0x04, 0x71, 0x7F, 0x80, +0x55, 0xED, 0x30, 0xE6, 0x3F, 0x90, 0x81, 0x4B, +0xE0, 0x64, 0x02, 0x70, 0x27, 0x90, 0x81, 0x46, +0xE0, 0xFF, 0xC3, 0x13, 0x20, 0xE0, 0x09, 0x90, +0x81, 0x4F, 0xE0, 0x44, 0x01, 0xF0, 0x80, 0x1A, +0x71, 0x36, 0x64, 0x01, 0x70, 0x20, 0x90, 0x81, +0x4F, 0xE0, 0x44, 0x04, 0xF0, 0x7F, 0x01, 0x12, +0x5E, 0x61, 0x80, 0x12, 0x71, 0x2F, 0x64, 0x02, +0x60, 0x05, 0x12, 0x5F, 0xA9, 0x80, 0x07, 0x12, +0x4F, 0x80, 0x80, 0x02, 0x71, 0x7F, 0x90, 0x81, +0xC1, 0xE0, 0x90, 0x81, 0x4F, 0x30, 0xE7, 0x05, +0x12, 0x48, 0xF8, 0xE1, 0x85, 0xE0, 0x54, 0xFD, +0xF0, 0x22, 0xB1, 0xB9, 0x13, 0x54, 0x1F, 0x30, +0xE0, 0x0C, 0xEF, 0xC4, 0x13, 0x13, 0x54, 0x03, +0x30, 0xE0, 0x03, 0x12, 0x57, 0xDD, 0x12, 0x6C, +0x98, 0x30, 0xE0, 0x08, 0xF1, 0x96, 0x54, 0x07, +0x70, 0x38, 0x80, 0x34, 0x12, 0x6C, 0xA2, 0x40, +0x2F, 0x12, 0x47, 0x84, 0x70, 0x2C, 0x12, 0x6C, +0xBB, 0x71, 0x36, 0x70, 0x04, 0x91, 0x4B, 0xF0, +0x22, 0x90, 0x81, 0x55, 0xE0, 0x04, 0xF0, 0xE0, +0xD3, 0x94, 0x02, 0x40, 0x0A, 0x91, 0x4B, 0xF0, +0xE4, 0x90, 0x81, 0x55, 0xF0, 0x80, 0x03, 0x12, +0x4F, 0x80, 0xE4, 0x90, 0x81, 0x54, 0xF0, 0x22, +0x31, 0x68, 0x22, 0x90, 0x81, 0x47, 0xE0, 0x54, +0xFB, 0x22, 0xF1, 0x8D, 0xFF, 0x54, 0x7F, 0x90, +0x81, 0x4B, 0xF0, 0xEF, 0xF1, 0x7E, 0xA3, 0xB1, +0xD0, 0xFD, 0x54, 0xF0, 0xC4, 0x54, 0x0F, 0xFF, +0x90, 0x81, 0x49, 0xE0, 0x54, 0xF0, 0x4F, 0x12, +0x73, 0xA6, 0xFC, 0x54, 0x01, 0x25, 0xE0, 0xFF, +0x90, 0x81, 0x46, 0xE0, 0x54, 0xFD, 0x4F, 0xF0, +0xEC, 0x54, 0x04, 0xC3, 0x13, 0xFF, 0x90, 0x81, +0x48, 0xE0, 0x54, 0xFD, 0x4F, 0xF0, 0xED, 0x54, +0x0F, 0xC4, 0x54, 0xF0, 0xFF, 0xA3, 0xE0, 0x54, +0x0F, 0x4F, 0xF0, 0x90, 0x00, 0x02, 0x12, 0x1F, +0xBD, 0x90, 0x81, 0x4A, 0x12, 0x73, 0x9F, 0xFD, +0x7F, 0x02, 0x12, 0x49, 0xCE, 0x90, 0x82, 0x3B, +0x12, 0x45, 0x37, 0xD1, 0xB2, 0x51, 0xC5, 0xF0, +0x90, 0x81, 0x4B, 0x12, 0x7B, 0x20, 0x71, 0x35, +0x90, 0x01, 0xBE, 0xF0, 0x22, 0x90, 0x05, 0x62, +0xE0, 0xFE, 0x90, 0x05, 0x61, 0xE0, 0xFD, 0xED, +0x78, 0x02, 0xCE, 0xC3, 0x13, 0xCE, 0x13, 0xD8, +0xF9, 0xFF, 0x90, 0x81, 0xBF, 0xEE, 0xF0, 0xA3, +0xEF, 0xF0, 0x12, 0x47, 0x84, 0x60, 0x02, 0xA1, +0xAC, 0x90, 0x81, 0x4B, 0xE0, 0x70, 0x02, 0xA1, +0xAC, 0x90, 0x81, 0x49, 0xE0, 0xFF, 0xC4, 0x54, +0x0F, 0x64, 0x01, 0x70, 0x22, 0x90, 0x06, 0xAB, +0xE0, 0x90, 0x81, 0x52, 0xF0, 0x90, 0x06, 0xAA, +0xE0, 0x90, 0x81, 0x51, 0xF0, 0xA3, 0xE0, 0xFF, +0x70, 0x08, 0x90, 0x81, 0x51, 0xE0, 0xFE, 0xFF, +0x80, 0x00, 0x90, 0x81, 0x52, 0xEF, 0xF0, 0x12, +0x77, 0xF5, 0xE4, 0x90, 0x81, 0x54, 0xF0, 0xA3, +0x12, 0x6E, 0x14, 0x12, 0x47, 0xD3, 0xF1, 0x99, +0x54, 0xEF, 0xF0, 0x90, 0x81, 0x41, 0xE0, 0x30, +0xE0, 0x04, 0x71, 0x87, 0x80, 0x02, 0x71, 0x3D, +0xB1, 0xB9, 0x13, 0x54, 0x1F, 0x30, 0xE0, 0x61, +0xEF, 0xC4, 0x13, 0x13, 0x54, 0x03, 0x20, 0xE0, +0x27, 0xB1, 0xC8, 0x6F, 0x70, 0x53, 0x90, 0x81, +0x47, 0xE0, 0x44, 0x40, 0xF0, 0x12, 0x7B, 0x74, +0xF0, 0x12, 0x57, 0xD6, 0xFD, 0x7F, 0x03, 0x12, +0x56, 0x9D, 0x12, 0x56, 0x7F, 0x12, 0x57, 0xDD, +0x90, 0x81, 0x52, 0xE0, 0x14, 0xF0, 0x80, 0x31, +0x90, 0x81, 0x49, 0xE0, 0xC4, 0x54, 0x0F, 0x64, +0x01, 0x70, 0x26, 0xB1, 0xC8, 0xFE, 0x6F, 0x60, +0x20, 0x90, 0x05, 0x73, 0xE0, 0xFF, 0xEE, 0x6F, +0x60, 0x17, 0xB1, 0xB9, 0x54, 0x3F, 0x30, 0xE0, +0x10, 0xEF, 0x54, 0xBF, 0xF0, 0x12, 0x57, 0xD6, +0xFD, 0x7F, 0x03, 0x12, 0x56, 0xFD, 0x12, 0x4F, +0xB9, 0xB1, 0xC1, 0xF0, 0x90, 0x81, 0x41, 0xE0, +0xC3, 0x13, 0x20, 0xE0, 0x03, 0xB1, 0xC1, 0xF0, +0x22, 0x90, 0x81, 0x47, 0xE0, 0xFF, 0x13, 0x13, +0x22, 0x90, 0x81, 0x47, 0xE0, 0x44, 0x04, 0x22, +0x90, 0x81, 0x51, 0xE0, 0xFF, 0xA3, 0xE0, 0x22, +0xF0, 0x90, 0x00, 0x01, 0x02, 0x1F, 0xBD, 0xF1, +0x8D, 0xFF, 0x54, 0x01, 0xFE, 0x90, 0x81, 0xAF, +0x12, 0x6C, 0x04, 0xFF, 0xF0, 0x12, 0x1F, 0xA4, +0xFE, 0x54, 0x04, 0xFD, 0xEF, 0x54, 0xFB, 0x4D, +0xFF, 0x90, 0x81, 0xAF, 0xF0, 0xEE, 0x54, 0x08, +0xFE, 0xEF, 0x54, 0xF7, 0x4E, 0xFF, 0xF0, 0x12, +0x1F, 0xA4, 0x54, 0x10, 0x25, 0xE0, 0x25, 0xE0, +0xFE, 0xEF, 0x54, 0xBF, 0x4E, 0x90, 0x81, 0xAF, +0xF0, 0x90, 0x05, 0x52, 0xE0, 0x54, 0x07, 0xFF, +0x90, 0x82, 0x3B, 0x60, 0x15, 0x12, 0x45, 0x37, +0xB1, 0xD1, 0xFD, 0x90, 0x05, 0x56, 0xE0, 0xC3, +0x9D, 0x90, 0x81, 0xB1, 0xF0, 0xA3, 0xED, 0xF0, +0x80, 0x25, 0x12, 0x45, 0x37, 0xB1, 0xD1, 0xFB, +0xFF, 0x90, 0x05, 0x54, 0xE0, 0xC3, 0x9F, 0xFF, +0xE4, 0x94, 0x00, 0xFE, 0x7C, 0x00, 0x7D, 0x05, +0x12, 0x20, 0x30, 0x90, 0x81, 0xB1, 0xEF, 0xF0, +0xEB, 0x75, 0xF0, 0x05, 0x84, 0xA3, 0xF0, 0x90, +0x82, 0x3B, 0x12, 0x45, 0x37, 0x12, 0x1F, 0xA4, +0x20, 0xE0, 0x0A, 0x12, 0x4D, 0x15, 0x90, 0x01, +0x57, 0xE4, 0xF0, 0x80, 0x06, 0x12, 0x49, 0xCA, +0xF1, 0xC2, 0xF0, 0x12, 0x7A, 0x07, 0x13, 0x54, +0x1F, 0x20, 0xE0, 0x04, 0xEF, 0x44, 0x20, 0xF0, +0xF1, 0xC9, 0x30, 0xE0, 0x15, 0x90, 0x81, 0x4B, +0x74, 0x01, 0xF0, 0xE4, 0x90, 0x81, 0x4D, 0xF0, +0xB1, 0xC1, 0xF1, 0xAF, 0x74, 0x06, 0xF0, 0x02, +0x6C, 0xF1, 0xE4, 0x90, 0x81, 0x4B, 0xF0, 0x90, +0x81, 0x4D, 0x74, 0x0C, 0xF0, 0x90, 0x81, 0x46, +0xE0, 0x54, 0xFE, 0xF0, 0xA3, 0xE0, 0x54, 0xFB, +0xF0, 0x22, 0x90, 0x82, 0x3E, 0x12, 0x45, 0x40, +0x12, 0x77, 0x73, 0x90, 0x81, 0x4B, 0xE0, 0xFF, +0x12, 0x4E, 0x46, 0x90, 0x81, 0x4B, 0xE0, 0x60, +0x1D, 0x90, 0x82, 0x3E, 0x12, 0x45, 0x37, 0xB1, +0xD1, 0x54, 0x0F, 0xFF, 0x90, 0x00, 0x02, 0x12, +0x1F, 0xBD, 0xFD, 0x12, 0x77, 0x99, 0xF1, 0xB0, +0x74, 0x01, 0xF0, 0x12, 0x6C, 0xF1, 0x22, 0x90, +0x82, 0x38, 0x12, 0x45, 0x40, 0x90, 0x82, 0x37, +0xEF, 0xF0, 0x12, 0x45, 0x49, 0x67, 0x17, 0x00, +0x67, 0x20, 0x01, 0x67, 0x29, 0x12, 0x67, 0x32, +0x14, 0x67, 0x3B, 0x20, 0x67, 0x43, 0x24, 0x67, +0x4C, 0x25, 0x67, 0x55, 0x26, 0x67, 0x5D, 0x27, +0x67, 0x66, 0xC0, 0x00, 0x00, 0x67, 0x6E, 0x90, +0x82, 0x38, 0x12, 0x45, 0x37, 0x02, 0x73, 0x55, +0x90, 0x82, 0x38, 0x12, 0x45, 0x37, 0x02, 0x73, +0xAD, 0x90, 0x82, 0x38, 0x12, 0x45, 0x37, 0x02, +0x6F, 0x8A, 0x90, 0x82, 0x38, 0x12, 0x45, 0x37, +0x02, 0x74, 0x23, 0x90, 0x82, 0x38, 0x12, 0x45, +0x37, 0x81, 0x52, 0x90, 0x82, 0x38, 0x12, 0x45, +0x37, 0x02, 0x52, 0x35, 0x90, 0x82, 0x38, 0x12, +0x45, 0x37, 0x02, 0x74, 0x32, 0x90, 0x82, 0x38, +0x12, 0x45, 0x37, 0xA1, 0xD7, 0x90, 0x82, 0x38, +0x12, 0x45, 0x37, 0x02, 0x6B, 0xDB, 0x90, 0x82, +0x38, 0x12, 0x45, 0x37, 0x80, 0x34, 0x90, 0x01, +0xC0, 0xE0, 0x44, 0x01, 0xF0, 0x90, 0x82, 0x37, +0xE0, 0x90, 0x01, 0xC2, 0xF0, 0x22, 0xC4, 0x13, +0x13, 0x13, 0x54, 0x01, 0x22, 0x90, 0x81, 0x46, +0xE0, 0x44, 0x04, 0xF0, 0x22, 0x90, 0x82, 0x3B, +0x12, 0x45, 0x40, 0x02, 0x1F, 0xA4, 0xEF, 0x54, +0xFB, 0xF0, 0x90, 0x81, 0x4F, 0xE0, 0x54, 0xFD, +0xF0, 0x22, 0x12, 0x1F, 0xA4, 0x90, 0x81, 0xBC, +0xB1, 0xD0, 0x90, 0x81, 0xBD, 0xF0, 0x22, 0xF0, +0x90, 0x81, 0x5D, 0xE0, 0xFF, 0xA3, 0xE0, 0xFD, +0x90, 0x81, 0x64, 0xE0, 0xFB, 0x90, 0x82, 0x9D, +0x22, 0x22, 0x90, 0x81, 0xAF, 0xE0, 0x44, 0x10, +0x22, 0x90, 0x81, 0xAF, 0xE0, 0xC3, 0x13, 0x22, +0x7F, 0x14, 0x7E, 0x00, 0x02, 0x32, 0xAA, 0x7D, +0x01, 0x7F, 0x04, 0x02, 0x4B, 0x21, 0xE4, 0xFB, +0xFA, 0xFD, 0x7F, 0x01, 0x12, 0x43, 0x4E, 0x90, +0x82, 0x36, 0xEF, 0xF0, 0x60, 0xF0, 0x90, 0x80, +0x3C, 0xE0, 0xFF, 0x70, 0x04, 0xA3, 0xE0, 0x60, +0xE5, 0xC2, 0xAF, 0xEF, 0x30, 0xE1, 0x09, 0x90, +0x80, 0x3C, 0xE0, 0x54, 0xFD, 0xF0, 0x11, 0x1D, +0xD2, 0xAF, 0xC2, 0xAF, 0x90, 0x80, 0x3C, 0xE0, +0xFF, 0x30, 0xE2, 0x05, 0x54, 0xFB, 0xF0, 0x31, +0xAF, 0xD2, 0xAF, 0x80, 0xD1, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x80, 0x9C, 0xE0, +0xFF, 0x90, 0x80, 0x9B, 0xE0, 0xB5, 0x07, 0x04, +0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x70, +0x3F, 0x90, 0x80, 0x9B, 0xE0, 0xFE, 0x75, 0xF0, +0x08, 0x90, 0x80, 0x4B, 0x12, 0x45, 0x2B, 0xE0, +0xFD, 0xEE, 0x75, 0xF0, 0x08, 0xA4, 0x24, 0x4C, +0xF9, 0x74, 0x80, 0x35, 0xF0, 0xFA, 0x7B, 0x01, +0xAF, 0x05, 0x12, 0x66, 0xE7, 0x90, 0x80, 0x9B, +0x31, 0xA8, 0xB4, 0x0A, 0x02, 0x7F, 0x01, 0xEF, +0x60, 0x05, 0xE4, 0x90, 0x80, 0x9B, 0xF0, 0x11, +0x7D, 0x90, 0x80, 0x3C, 0xE0, 0x44, 0x02, 0xF0, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x01, 0xCC, +0xE0, 0x54, 0x0F, 0x90, 0x82, 0xA7, 0xF0, 0x90, +0x82, 0xA7, 0xE0, 0xFD, 0x70, 0x02, 0x21, 0x80, +0x90, 0x80, 0x9B, 0xE0, 0xFF, 0x70, 0x06, 0xA3, +0xE0, 0x64, 0x09, 0x60, 0x0A, 0xEF, 0x14, 0xFF, +0x90, 0x80, 0x9C, 0xE0, 0xB5, 0x07, 0x04, 0x7F, +0x01, 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x60, 0x08, +0x90, 0x01, 0xC1, 0xE0, 0x44, 0x01, 0xF0, 0x22, +0x90, 0x82, 0xA5, 0x71, 0x2E, 0x80, 0x05, 0xC3, +0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, 0xEF, +0x5D, 0x70, 0x02, 0x21, 0x63, 0xE4, 0x90, 0x82, +0xA8, 0xF0, 0x90, 0x82, 0xA8, 0xE0, 0xF9, 0xC3, +0x94, 0x04, 0x50, 0x38, 0x31, 0x82, 0xA4, 0xFF, +0xE9, 0xFD, 0x7C, 0x00, 0x2F, 0xFF, 0xEC, 0x35, +0xF0, 0xFE, 0x74, 0xD0, 0x31, 0x99, 0x75, 0xF0, +0x08, 0x90, 0x80, 0x4B, 0x31, 0x8A, 0x31, 0x81, +0xA4, 0x2D, 0xFF, 0xEC, 0x35, 0xF0, 0xFE, 0x74, +0xF0, 0x31, 0x99, 0x75, 0xF0, 0x08, 0x90, 0x80, +0x4F, 0x31, 0x8A, 0xF0, 0x90, 0x82, 0xA8, 0xE0, +0x04, 0xF0, 0x80, 0xBE, 0x90, 0x82, 0xA7, 0xE0, +0xFF, 0x90, 0x82, 0xA5, 0xE0, 0xFE, 0x74, 0x01, +0xA8, 0x06, 0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8, +0xFC, 0xF4, 0x5F, 0x90, 0x82, 0xA7, 0xF0, 0x90, +0x82, 0xA5, 0xE0, 0xFF, 0x74, 0x01, 0xA8, 0x07, +0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0x90, +0x01, 0xCC, 0xF0, 0x90, 0x82, 0xA5, 0xE0, 0x04, +0xF0, 0xE0, 0x54, 0x03, 0xF0, 0x90, 0x80, 0x9C, +0x31, 0xA8, 0xB4, 0x0A, 0x02, 0x7F, 0x01, 0xEF, +0x70, 0x02, 0x01, 0x87, 0xE4, 0x90, 0x80, 0x9C, +0xF0, 0x01, 0x87, 0x90, 0x01, 0xC0, 0xE0, 0x44, +0x02, 0xF0, 0x90, 0x82, 0xA5, 0xE0, 0x44, 0x80, +0x90, 0x00, 0x8A, 0x31, 0x81, 0x90, 0x01, 0xD0, +0x12, 0x45, 0x2B, 0xE0, 0x90, 0x01, 0xC3, 0xF0, +0x22, 0xF0, 0x90, 0x82, 0xA5, 0xE0, 0x75, 0xF0, +0x04, 0x22, 0x12, 0x45, 0x2B, 0xE5, 0x82, 0x29, +0xF5, 0x82, 0xE4, 0x35, 0x83, 0xF5, 0x83, 0xEF, +0x22, 0x2F, 0xF5, 0x82, 0x74, 0x01, 0x3E, 0xF5, +0x83, 0xE0, 0xFF, 0x90, 0x80, 0x9C, 0xE0, 0x22, +0xE0, 0x04, 0xF0, 0xE0, 0x7F, 0x00, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xE4, 0xFF, +0x90, 0x81, 0x34, 0xE0, 0xFE, 0x90, 0x81, 0x33, +0xE0, 0xFD, 0xB5, 0x06, 0x04, 0x7E, 0x01, 0x80, +0x02, 0x7E, 0x00, 0xEE, 0x64, 0x01, 0x60, 0x41, +0x90, 0x01, 0xAF, 0xE0, 0x70, 0x0A, 0xED, 0x51, +0x73, 0xFA, 0x7B, 0x01, 0x51, 0xCB, 0x7F, 0x01, +0xEF, 0x60, 0x2E, 0x90, 0x81, 0x33, 0x31, 0xA8, +0xB4, 0x0A, 0x02, 0x7F, 0x01, 0xEF, 0x60, 0x05, +0xE4, 0x90, 0x81, 0x33, 0xF0, 0x90, 0x81, 0x34, +0xE0, 0xFF, 0x90, 0x81, 0x33, 0xE0, 0xB5, 0x07, +0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xEF, +0x70, 0x07, 0x90, 0x80, 0x3C, 0xE0, 0x44, 0x04, +0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x81, 0x33, +0xE0, 0xFF, 0x70, 0x06, 0xA3, 0xE0, 0x64, 0x09, +0x60, 0x0A, 0xEF, 0x14, 0xFF, 0x90, 0x81, 0x34, +0xE0, 0xB5, 0x07, 0x04, 0x7F, 0x01, 0x80, 0x02, +0x7F, 0x00, 0xEF, 0x60, 0x09, 0x90, 0x01, 0xC1, +0xE0, 0x44, 0x02, 0xF0, 0x80, 0x28, 0xC0, 0x01, +0x90, 0x81, 0x34, 0xE0, 0x51, 0x73, 0xA8, 0x01, +0xFC, 0x7D, 0x01, 0xD0, 0x01, 0x7E, 0x00, 0x7F, +0x0F, 0x12, 0x44, 0x79, 0x90, 0x81, 0x34, 0x31, +0xA8, 0xB4, 0x0A, 0x02, 0x7F, 0x01, 0xEF, 0x60, +0x05, 0xE4, 0x90, 0x81, 0x34, 0xF0, 0xD0, 0xD0, +0x92, 0xAF, 0x22, 0x75, 0xF0, 0x0F, 0xA4, 0x24, +0x9D, 0xF9, 0x74, 0x80, 0x35, 0xF0, 0x22, 0x90, +0x82, 0x46, 0x74, 0x12, 0xF0, 0x90, 0x82, 0x54, +0x74, 0x05, 0xF0, 0x90, 0x82, 0x48, 0xEF, 0xF0, +0xA3, 0xED, 0xF0, 0xA3, 0xEB, 0xF0, 0x90, 0x82, +0x44, 0xE0, 0x90, 0x82, 0x4B, 0xF0, 0x90, 0x82, +0x45, 0xE0, 0x90, 0x82, 0x4C, 0xF0, 0x7B, 0x01, +0x7A, 0x82, 0x79, 0x46, 0x51, 0x16, 0x7F, 0x04, +0x90, 0x82, 0xA9, 0xEF, 0xF0, 0x7F, 0x02, 0x12, +0x43, 0x27, 0x90, 0x80, 0x3C, 0xE0, 0xFF, 0x90, +0x82, 0xA9, 0xE0, 0xFE, 0xEF, 0x4E, 0x90, 0x80, +0x3C, 0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x82, 0x37, 0x12, 0x45, 0x40, +0x90, 0x82, 0xA6, 0xE0, 0xFF, 0x04, 0xF0, 0x90, +0x00, 0x01, 0xEF, 0x12, 0x1F, 0xFC, 0x7F, 0xAF, +0x7E, 0x01, 0xD1, 0xA7, 0xEF, 0x60, 0x3A, 0x90, +0x82, 0x37, 0x12, 0x45, 0x37, 0x8B, 0x13, 0x8A, +0x14, 0x89, 0x15, 0x90, 0x00, 0x0E, 0x12, 0x1F, +0xBD, 0x24, 0x02, 0xF5, 0x16, 0x7B, 0x01, 0x7A, +0x01, 0x79, 0xA0, 0x12, 0x2B, 0xED, 0x90, 0x82, +0x37, 0x12, 0x45, 0x37, 0x90, 0x00, 0x0E, 0x12, +0x1F, 0xBD, 0x90, 0x01, 0xAE, 0xF0, 0xA3, 0x74, +0xFF, 0xF0, 0x90, 0x01, 0xCB, 0xE0, 0x64, 0x80, +0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xE0, 0xFF, +0x74, 0x01, 0x7E, 0x00, 0xA8, 0x07, 0x08, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, +0x81, 0x48, 0xE0, 0xFE, 0xC3, 0x13, 0x30, 0xE0, +0x1E, 0x90, 0x82, 0x64, 0x74, 0x1E, 0xF0, 0x90, +0x82, 0x72, 0x74, 0x01, 0xF0, 0x90, 0x82, 0x66, +0xEF, 0xF0, 0x7B, 0x01, 0x7A, 0x82, 0x79, 0x64, +0x51, 0x16, 0x7F, 0x04, 0x12, 0x47, 0x5F, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x12, 0x55, 0x47, 0x12, +0x4F, 0xBF, 0x7F, 0x01, 0x71, 0x38, 0x90, 0x81, +0xB7, 0xE0, 0x30, 0xE0, 0x15, 0x71, 0xC9, 0xF0, +0x90, 0x81, 0xBA, 0xE0, 0x60, 0x05, 0x14, 0xF0, +0x02, 0x4E, 0x37, 0x71, 0xD1, 0xE4, 0xFF, 0x12, +0x56, 0xB2, 0x22, 0x90, 0x81, 0xBD, 0xE0, 0x60, +0x0F, 0xE4, 0xF0, 0x90, 0x05, 0x53, 0xE0, 0x44, +0x02, 0xF0, 0x90, 0x05, 0xFC, 0xE0, 0x04, 0xF0, +0x90, 0x81, 0x41, 0xE0, 0x30, 0xE0, 0x10, 0xA3, +0x74, 0x01, 0xF0, 0x90, 0x81, 0x41, 0xE0, 0xFF, +0xC3, 0x13, 0x30, 0xE0, 0x02, 0x91, 0x13, 0x12, +0x54, 0xA7, 0xE4, 0xFF, 0x71, 0x38, 0x02, 0x4D, +0xDB, 0x90, 0x81, 0xB9, 0xE0, 0x90, 0x05, 0x73, +0x22, 0x90, 0x81, 0xB8, 0xE0, 0x14, 0x90, 0x81, +0xBA, 0xF0, 0x22, 0x12, 0x1F, 0xA4, 0xFF, 0x54, +0x01, 0xFE, 0x90, 0x81, 0xB7, 0x91, 0x04, 0x12, +0x65, 0xD0, 0x90, 0x81, 0xB8, 0xF0, 0x90, 0x00, +0x02, 0x12, 0x1F, 0xBD, 0x90, 0x81, 0xB9, 0xF0, +0x71, 0xD1, 0x90, 0x81, 0xB7, 0xE0, 0x54, 0x01, +0xFF, 0x02, 0x56, 0xB2, 0xE0, 0x54, 0xFE, 0x4E, +0xFE, 0xF0, 0xEF, 0x54, 0x02, 0xFF, 0xEE, 0x54, +0xFD, 0x4F, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x12, 0x54, 0x9B, 0xBF, 0x01, 0x04, +0x7F, 0x01, 0x80, 0x02, 0x7F, 0x02, 0x12, 0x53, +0xA5, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x81, +0x41, 0xE0, 0xFF, 0x30, 0xE0, 0x3E, 0x90, 0x81, +0x45, 0xE0, 0x7E, 0x00, 0xB4, 0x02, 0x02, 0x7E, +0x01, 0x90, 0x81, 0x44, 0xE0, 0x7D, 0x00, 0xB4, +0x04, 0x02, 0x7D, 0x01, 0xED, 0x4E, 0x70, 0x24, +0xEF, 0xC3, 0x13, 0x30, 0xE0, 0x02, 0x80, 0xBB, +0x91, 0x75, 0x90, 0x81, 0x45, 0xE0, 0xB4, 0x0C, +0x06, 0xE4, 0xFD, 0x7F, 0x08, 0x80, 0x0A, 0x90, +0x81, 0x45, 0xE0, 0xB4, 0x04, 0x06, 0xE4, 0xFD, +0xFF, 0x12, 0x4B, 0x21, 0x22, 0x90, 0x01, 0x57, +0xE0, 0x60, 0x1C, 0x12, 0x47, 0xD6, 0xF0, 0x91, +0x98, 0x30, 0xE0, 0x03, 0x02, 0x67, 0x96, 0x91, +0xA2, 0x40, 0x0C, 0xE4, 0xFF, 0x12, 0x47, 0x8C, +0xBF, 0x01, 0x04, 0x12, 0x64, 0x4B, 0xF0, 0x22, +0x90, 0x81, 0x46, 0xE0, 0xFF, 0x13, 0x13, 0x54, +0x3F, 0x22, 0x90, 0x81, 0x54, 0xE0, 0x04, 0xF0, +0x90, 0x81, 0x4F, 0xE0, 0x54, 0xEF, 0xF0, 0x90, +0x81, 0xA8, 0xE0, 0xFF, 0x90, 0x81, 0x54, 0xE0, +0xD3, 0x9F, 0x22, 0x91, 0xAF, 0x40, 0x31, 0x90, +0x81, 0x65, 0xE0, 0x04, 0xF0, 0x90, 0x81, 0xA7, +0xE0, 0xFF, 0x90, 0x81, 0x65, 0xE0, 0xD3, 0x9F, +0x50, 0x1E, 0x90, 0x81, 0x5D, 0xE0, 0x04, 0xF0, +0x12, 0x49, 0xB5, 0x90, 0x81, 0x64, 0xF0, 0xFB, +0x90, 0x81, 0x5D, 0xE0, 0xFF, 0xA3, 0xE0, 0xFD, +0x90, 0x82, 0x9D, 0x74, 0x04, 0xF0, 0x91, 0xF1, +0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0xAC, 0x07, 0x90, 0x81, 0x47, 0xE0, 0x12, 0x67, +0x7E, 0x30, 0xE0, 0x02, 0xA1, 0xAD, 0x90, 0x81, +0x46, 0xE0, 0x30, 0xE0, 0x16, 0x90, 0x81, 0x68, +0xE0, 0x24, 0x04, 0x90, 0x81, 0x60, 0xF0, 0x90, +0x81, 0x68, 0xE0, 0x24, 0x03, 0x90, 0x81, 0x5F, +0xF0, 0x80, 0x0D, 0x90, 0x81, 0x60, 0x74, 0x02, +0xF0, 0x90, 0x81, 0x5F, 0x14, 0xF0, 0x0B, 0x0B, +0x90, 0x81, 0x5F, 0xE0, 0xFA, 0x90, 0x81, 0x5E, +0xE0, 0xD3, 0x9A, 0x50, 0x0E, 0x90, 0x81, 0x53, +0xEB, 0xF0, 0x90, 0x81, 0x60, 0xE0, 0xC3, 0x9D, +0x2C, 0x80, 0x11, 0xC3, 0xED, 0x9A, 0x2B, 0x90, +0x81, 0x53, 0xF0, 0x90, 0x81, 0x5F, 0xE0, 0xFF, +0xA3, 0xE0, 0xC3, 0x9F, 0x90, 0x81, 0x63, 0xF0, +0x90, 0x81, 0x60, 0xE0, 0xFF, 0x24, 0x0A, 0xFD, +0xE4, 0x33, 0xFC, 0x90, 0x81, 0x63, 0xB1, 0xB9, +0x98, 0x40, 0x04, 0xEF, 0x24, 0x0A, 0xF0, 0x90, +0x81, 0x63, 0xE0, 0xFF, 0x24, 0x23, 0xFD, 0xE4, +0x33, 0xFC, 0x90, 0x81, 0x53, 0xB1, 0xB9, 0x98, +0x40, 0x04, 0xEF, 0x24, 0x23, 0xF0, 0x90, 0x81, +0x63, 0xE0, 0xFF, 0x7E, 0x00, 0x90, 0x81, 0x57, +0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x05, 0x58, +0xE0, 0x6F, 0x70, 0x01, 0xE4, 0x60, 0x02, 0xD1, +0x15, 0xD1, 0x0C, 0x80, 0x07, 0x90, 0x81, 0x48, +0xE0, 0x44, 0x01, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0xE0, 0xD3, 0x9D, 0xEC, 0x64, 0x80, 0xF8, +0x74, 0x80, 0x22, 0xD1, 0x1F, 0x90, 0x81, 0xC4, +0xEF, 0xF0, 0x30, 0xE0, 0x05, 0x7D, 0x01, 0xE4, +0x80, 0x02, 0xE4, 0xFD, 0xFF, 0x12, 0x49, 0xCE, +0x90, 0x81, 0xC4, 0xE0, 0x30, 0xE6, 0x11, 0x90, +0x01, 0x2F, 0xE0, 0x30, 0xE7, 0x04, 0xE4, 0xF0, +0x80, 0x06, 0x90, 0x01, 0x2F, 0x74, 0x80, 0xF0, +0x90, 0x81, 0x46, 0xE0, 0x90, 0x04, 0xEC, 0x30, +0xE0, 0x06, 0xE0, 0x54, 0xDD, 0xF0, 0x80, 0x04, +0xE0, 0x44, 0x22, 0xF0, 0x12, 0x67, 0xB0, 0x74, +0x02, 0xF0, 0x81, 0xF1, 0x90, 0x81, 0x48, 0xE0, +0x54, 0xFE, 0xF0, 0x22, 0xF0, 0x90, 0x81, 0x57, +0xA3, 0xE0, 0x90, 0x05, 0x58, 0xF0, 0x22, 0xE4, +0x90, 0x81, 0xC6, 0xF0, 0xA3, 0xF0, 0x90, 0x00, +0x83, 0xE0, 0x90, 0x81, 0xC5, 0xF0, 0x90, 0x00, +0x83, 0xE0, 0xFE, 0x90, 0x81, 0xC5, 0xE0, 0xFF, +0xB5, 0x06, 0x01, 0x22, 0xC3, 0x90, 0x81, 0xC7, +0xE0, 0x94, 0x64, 0x90, 0x81, 0xC6, 0xE0, 0x94, +0x00, 0x40, 0x0D, 0x90, 0x01, 0xC0, 0xE0, 0x44, +0x40, 0xF0, 0x90, 0x81, 0xC5, 0xE0, 0xFF, 0x22, +0x90, 0x81, 0xC6, 0x12, 0x5E, 0x53, 0x80, 0xC6, +0x90, 0x81, 0x41, 0xE0, 0xFF, 0x30, 0xE0, 0x3E, +0x90, 0x81, 0x45, 0xE0, 0x7E, 0x00, 0xB4, 0x02, +0x02, 0x7E, 0x01, 0x90, 0x81, 0x44, 0xE0, 0x7D, +0x00, 0xB4, 0x04, 0x02, 0x7D, 0x01, 0xED, 0x4E, +0x70, 0x24, 0xEF, 0xC3, 0x13, 0x30, 0xE0, 0x02, +0x81, 0x13, 0x12, 0x57, 0x77, 0x90, 0x81, 0x45, +0xE0, 0xB4, 0x08, 0x06, 0xE4, 0xFD, 0x7F, 0x0C, +0x80, 0x09, 0x90, 0x81, 0x45, 0xE0, 0x70, 0x06, +0xFD, 0x7F, 0x04, 0x12, 0x4B, 0x21, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x82, +0x8E, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xE4, 0xA3, +0xF0, 0xA3, 0xF0, 0x90, 0x82, 0x8E, 0xE0, 0xFE, +0xA3, 0xE0, 0xF5, 0x82, 0x8E, 0x83, 0xE0, 0x60, +0x29, 0xC3, 0x90, 0x82, 0x91, 0xE0, 0x94, 0xE8, +0x90, 0x82, 0x90, 0xE0, 0x94, 0x03, 0x40, 0x0B, +0x90, 0x01, 0xC0, 0xE0, 0x44, 0x80, 0xF0, 0x7F, +0x00, 0x80, 0x11, 0x90, 0x82, 0x90, 0x12, 0x5E, +0x53, 0x7F, 0x0A, 0x7E, 0x00, 0x12, 0x32, 0xAA, +0x80, 0xC9, 0x7F, 0x01, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x7B, 0x01, 0x7A, 0x82, 0x79, 0x3B, 0x7F, +0xF5, 0x7E, 0x00, 0x12, 0x2B, 0x27, 0xBF, 0x01, +0x06, 0x90, 0x82, 0x3B, 0xE0, 0xA3, 0xF0, 0x7B, +0x01, 0x7A, 0x82, 0x79, 0x3B, 0x7F, 0xF6, 0x7E, +0x00, 0x12, 0x2B, 0x27, 0xBF, 0x01, 0x08, 0x90, +0x82, 0x3B, 0xE0, 0x90, 0x82, 0x3D, 0xF0, 0x7B, +0x01, 0x7A, 0x82, 0x79, 0x3B, 0x7F, 0xF4, 0x7E, +0x00, 0x12, 0x2B, 0x27, 0xBF, 0x01, 0x08, 0x90, +0x82, 0x3B, 0xE0, 0x90, 0x82, 0x3E, 0xF0, 0x7B, +0x01, 0x7A, 0x82, 0x79, 0x3B, 0x7F, 0xF3, 0x7E, +0x00, 0x12, 0x2B, 0x27, 0xBF, 0x01, 0x08, 0x90, +0x82, 0x3B, 0xE0, 0x90, 0x82, 0x3F, 0xF0, 0x7B, +0x01, 0x7A, 0x82, 0x79, 0x3B, 0x7F, 0xF2, 0x7E, +0x00, 0x12, 0x2B, 0x27, 0xBF, 0x01, 0x08, 0x90, +0x82, 0x3B, 0xE0, 0x90, 0x82, 0x40, 0xF0, 0x90, +0x82, 0x3C, 0xE0, 0xFF, 0xA3, 0xE0, 0xFD, 0xA3, +0xE0, 0xFB, 0xA3, 0xE0, 0x90, 0x82, 0x44, 0xF0, +0x90, 0x82, 0x40, 0xE0, 0x90, 0x82, 0x45, 0xF0, +0x41, 0x7F, 0x12, 0x1F, 0xA4, 0xFF, 0x90, 0x81, +0x37, 0xF0, 0xBF, 0x01, 0x07, 0xD1, 0xF9, 0xE4, +0x90, 0x81, 0x37, 0xF0, 0x22, 0xE4, 0x90, 0x81, +0xE3, 0xF0, 0x90, 0x87, 0x5F, 0xE0, 0x90, 0x81, +0xE2, 0xF0, 0xE4, 0x90, 0x81, 0xEF, 0xF0, 0x90, +0x81, 0xDF, 0xF0, 0x90, 0x81, 0xDF, 0xE0, 0xFF, +0xC3, 0x94, 0x40, 0x50, 0x11, 0x74, 0xF2, 0x2F, +0x12, 0x72, 0xC2, 0x74, 0xFF, 0xF0, 0x90, 0x81, +0xDF, 0xE0, 0x04, 0xF0, 0x80, 0xE5, 0xE4, 0x90, +0x81, 0xDF, 0xF0, 0x90, 0x81, 0xE2, 0xE0, 0xFF, +0x90, 0x81, 0xDF, 0xE0, 0xFE, 0xC3, 0x9F, 0x40, +0x03, 0x02, 0x70, 0xA1, 0x74, 0xDF, 0x2E, 0xF9, +0xE4, 0x34, 0x86, 0x12, 0x72, 0x99, 0x75, 0x16, +0x0A, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0xD4, 0x12, +0x2B, 0xED, 0x90, 0x81, 0xD5, 0xE0, 0xFF, 0x12, +0x2F, 0x27, 0xEF, 0x04, 0x90, 0x81, 0xEF, 0xF0, +0x90, 0x81, 0xD4, 0xE0, 0xFF, 0xA3, 0xE0, 0xFD, +0x12, 0x31, 0xEA, 0xEF, 0x24, 0xC8, 0x90, 0x81, +0xF1, 0xF0, 0x75, 0xF0, 0x08, 0xA4, 0xF0, 0x90, +0x81, 0xD5, 0xE0, 0x54, 0x0F, 0x90, 0x81, 0xF0, +0xF0, 0xE4, 0x90, 0x81, 0xDE, 0xF0, 0x90, 0x81, +0xE0, 0xF0, 0x90, 0x81, 0xE0, 0xE0, 0xFF, 0xC3, +0x94, 0x04, 0x50, 0x57, 0x90, 0x81, 0xF0, 0xE0, +0xFE, 0xA8, 0x07, 0x08, 0x80, 0x02, 0xC3, 0x13, +0xD8, 0xFC, 0x20, 0xE0, 0x3E, 0x90, 0x81, 0xE0, +0xE0, 0x25, 0xE0, 0xFF, 0x90, 0x81, 0xF1, 0xE0, +0x2F, 0x24, 0xF2, 0xF9, 0xE4, 0x34, 0x81, 0xFA, +0x7B, 0x01, 0xC0, 0x03, 0xC0, 0x01, 0x90, 0x81, +0xDE, 0xE0, 0x75, 0xF0, 0x02, 0xA4, 0x24, 0xD6, +0xF9, 0x74, 0x81, 0x35, 0xF0, 0x8B, 0x13, 0xF5, +0x14, 0x89, 0x15, 0x75, 0x16, 0x02, 0xD0, 0x01, +0xD0, 0x03, 0x12, 0x2B, 0xED, 0x90, 0x81, 0xDE, +0xE0, 0x04, 0xF0, 0x90, 0x81, 0xE0, 0xE0, 0x04, +0xF0, 0x80, 0x9F, 0x90, 0x81, 0xEF, 0xE0, 0xFF, +0x90, 0x81, 0xDF, 0xE0, 0x2F, 0xF0, 0x02, 0x6F, +0xD3, 0xE4, 0x90, 0x81, 0xE3, 0xF0, 0x90, 0x81, +0xE3, 0xE0, 0xC3, 0x94, 0x40, 0x40, 0x02, 0x41, +0x64, 0xE0, 0xFF, 0x24, 0xF2, 0x51, 0xC2, 0xE0, +0x90, 0x81, 0xE5, 0xF0, 0xE0, 0xFE, 0x54, 0xF0, +0xC4, 0x54, 0x0F, 0xFD, 0x90, 0x81, 0xE4, 0xF0, +0xEE, 0x54, 0x0F, 0xFE, 0xA3, 0xF0, 0x74, 0xF3, +0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, +0xE0, 0x90, 0x81, 0xE6, 0xF0, 0xFC, 0xEE, 0xFE, +0xEC, 0xFB, 0xEB, 0xFF, 0x90, 0x81, 0xEB, 0xEE, +0xF0, 0xA3, 0xEF, 0xF0, 0xED, 0x12, 0x45, 0x49, +0x71, 0x15, 0x00, 0x71, 0x40, 0x01, 0x71, 0xBB, +0x02, 0x72, 0x55, 0x03, 0x71, 0xCB, 0x04, 0x71, +0xE1, 0x05, 0x71, 0xE1, 0x06, 0x71, 0xE1, 0x07, +0x71, 0xE1, 0x08, 0x72, 0x32, 0x09, 0x72, 0x43, +0x0A, 0x00, 0x00, 0x72, 0x64, 0x90, 0x81, 0xE3, +0xE0, 0xFD, 0x51, 0x84, 0xE0, 0xFE, 0x74, 0xF4, +0x2D, 0x51, 0x78, 0xE0, 0xFD, 0xED, 0xFF, 0x90, +0x81, 0xED, 0xEE, 0xF0, 0xFC, 0xA3, 0xEF, 0xF0, +0x90, 0x81, 0xE6, 0xE0, 0xFF, 0x12, 0x2F, 0x96, +0x90, 0x81, 0xE1, 0x74, 0x02, 0xF0, 0x41, 0x55, +0x51, 0x80, 0x12, 0x55, 0x40, 0x51, 0x65, 0x12, +0x55, 0x40, 0x12, 0x44, 0xD0, 0xC0, 0x04, 0xC0, +0x05, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x81, 0xE3, +0xE0, 0x24, 0xF6, 0xF5, 0x82, 0xE4, 0x34, 0x81, +0xF5, 0x83, 0x12, 0x55, 0x40, 0x78, 0x10, 0x12, +0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, +0xD0, 0x00, 0x12, 0x44, 0xD0, 0xC0, 0x04, 0xC0, +0x05, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x81, 0xE3, +0xE0, 0x24, 0xF7, 0xF5, 0x82, 0xE4, 0x34, 0x81, +0xF5, 0x83, 0x12, 0x55, 0x40, 0x78, 0x18, 0x12, +0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, +0xD0, 0x00, 0x51, 0xA1, 0x90, 0x81, 0xE7, 0x12, +0x44, 0xEE, 0x90, 0x85, 0x96, 0x12, 0x20, 0xCE, +0x90, 0x81, 0xEB, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, +0x12, 0x2E, 0xE4, 0x90, 0x81, 0xE1, 0x74, 0x04, +0xF0, 0x41, 0x55, 0x90, 0x81, 0xE6, 0xE0, 0xFD, +0x51, 0x72, 0xE0, 0xFB, 0xE4, 0xFF, 0x12, 0x30, +0xC7, 0x80, 0x0E, 0x90, 0x81, 0xE6, 0xE0, 0xFD, +0x51, 0x72, 0xE0, 0xFB, 0xE4, 0xFF, 0x12, 0x30, +0x6A, 0x90, 0x81, 0xE1, 0x74, 0x01, 0xF0, 0x80, +0x74, 0x90, 0x81, 0xE1, 0x74, 0x02, 0xF0, 0x51, +0x80, 0x12, 0x55, 0x40, 0x51, 0x65, 0x12, 0x55, +0x40, 0x12, 0x44, 0xD0, 0xC0, 0x04, 0xC0, 0x05, +0xC0, 0x06, 0xC0, 0x07, 0x90, 0x81, 0xE5, 0x12, +0x55, 0x40, 0x78, 0x10, 0x12, 0x20, 0xBB, 0xD0, +0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x51, +0xA1, 0x90, 0x81, 0xE4, 0xE0, 0x24, 0xFB, 0xFF, +0xC0, 0x07, 0x90, 0x81, 0xE7, 0x12, 0x44, 0xEE, +0x90, 0x82, 0x7F, 0x12, 0x20, 0xCE, 0x90, 0x81, +0xE6, 0xE0, 0xFD, 0xD0, 0x07, 0x12, 0x5D, 0xB7, +0x80, 0x23, 0x90, 0x81, 0xE1, 0x74, 0x01, 0x51, +0x8E, 0x75, 0x16, 0x01, 0x51, 0xAA, 0xF0, 0x7B, +0x04, 0x80, 0x0F, 0x90, 0x81, 0xE1, 0x74, 0x04, +0x51, 0x8E, 0x75, 0x16, 0x04, 0x51, 0xAA, 0xF0, +0x7B, 0x06, 0x12, 0x5A, 0x00, 0x90, 0x81, 0xE1, +0xE0, 0x24, 0x02, 0xFF, 0x90, 0x81, 0xE3, 0xE0, +0x2F, 0xF0, 0x01, 0xA6, 0x22, 0x78, 0x08, 0x12, +0x20, 0xBB, 0xA8, 0x04, 0xA9, 0x05, 0xAA, 0x06, +0xAB, 0x07, 0x90, 0x81, 0xE3, 0xE0, 0x24, 0xF4, +0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, 0x22, +0x90, 0x81, 0xE3, 0xE0, 0x24, 0xF5, 0xF5, 0x82, +0xE4, 0x34, 0x81, 0xF5, 0x83, 0x22, 0xF0, 0x90, +0x81, 0xE3, 0xE0, 0x24, 0xF4, 0xF9, 0xE4, 0x34, +0x81, 0x75, 0x13, 0x01, 0xF5, 0x14, 0x89, 0x15, +0x22, 0x12, 0x44, 0xD0, 0x90, 0x81, 0xE7, 0x02, +0x20, 0xCE, 0x7B, 0xFE, 0x7A, 0x80, 0x79, 0x33, +0x12, 0x2B, 0xED, 0x90, 0x81, 0xE6, 0xE0, 0xFF, +0x90, 0x81, 0xE5, 0xE0, 0xFD, 0xE4, 0x90, 0x82, +0x35, 0x22, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, +0x83, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x12, 0x2D, 0xA7, 0xE4, 0xF5, 0x53, 0x12, +0x32, 0x9E, 0xEF, 0x60, 0x73, 0x63, 0x53, 0x01, +0xE5, 0x53, 0x24, 0xCA, 0x90, 0x01, 0xC4, 0xF0, +0x74, 0x72, 0xA3, 0xF0, 0x90, 0x00, 0x88, 0xE0, +0xF5, 0x51, 0xF5, 0x52, 0x54, 0x0F, 0x60, 0xDF, +0xE5, 0x51, 0x30, 0xE0, 0x0B, 0x20, 0xE4, 0x03, +0x12, 0x29, 0xC5, 0x53, 0x52, 0xEE, 0x80, 0x3F, +0xE5, 0x51, 0x30, 0xE1, 0x16, 0x20, 0xE5, 0x0E, +0x12, 0x11, 0xBD, 0xEF, 0x70, 0x03, 0x43, 0x52, +0x20, 0x90, 0x01, 0x06, 0xE4, 0xF0, 0x53, 0x52, +0xFD, 0x80, 0x24, 0xE5, 0x51, 0x30, 0xE2, 0x0B, +0x20, 0xE6, 0x03, 0x12, 0x6F, 0x9D, 0x53, 0x52, +0xFB, 0x80, 0x14, 0xE5, 0x51, 0x30, 0xE3, 0x0F, +0x20, 0xE7, 0x09, 0x12, 0x5B, 0x31, 0xEF, 0x70, +0x03, 0x43, 0x52, 0x80, 0x53, 0x52, 0xF7, 0xAD, +0x52, 0x7F, 0x88, 0x12, 0x32, 0x1E, 0x80, 0x87, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x02, 0x09, +0xE0, 0xF5, 0x54, 0x12, 0x1F, 0xA4, 0x25, 0x54, +0x90, 0x80, 0x44, 0x12, 0x65, 0xD0, 0x25, 0x54, +0x90, 0x80, 0x45, 0xF0, 0x90, 0x00, 0x02, 0x12, +0x1F, 0xBD, 0x25, 0x54, 0x90, 0x80, 0x46, 0x71, +0xA6, 0x25, 0x54, 0x90, 0x80, 0x47, 0x71, 0x9F, +0x25, 0x54, 0x90, 0x80, 0x48, 0xF0, 0x90, 0x00, +0x05, 0x12, 0x1F, 0xBD, 0x25, 0x54, 0x90, 0x80, +0x49, 0xF0, 0x90, 0x00, 0x06, 0x12, 0x1F, 0xBD, +0x25, 0x54, 0x90, 0x80, 0x4A, 0xF0, 0x22, 0xF0, +0x90, 0x00, 0x04, 0x02, 0x1F, 0xBD, 0xF0, 0x90, +0x00, 0x03, 0x02, 0x1F, 0xBD, 0x8B, 0x54, 0x8A, +0x55, 0x89, 0x56, 0x12, 0x65, 0xD1, 0xFF, 0xF5, +0x58, 0x12, 0x1F, 0xA4, 0xFE, 0xC3, 0x13, 0x30, +0xE0, 0x0A, 0x90, 0x00, 0x02, 0x12, 0x1F, 0xBD, +0xF5, 0x59, 0x80, 0x02, 0x8F, 0x59, 0x85, 0x58, +0x57, 0xE5, 0x57, 0xD3, 0x95, 0x59, 0x50, 0x1E, +0x91, 0x1A, 0x54, 0x01, 0xFD, 0xAF, 0x57, 0x12, +0x51, 0x7A, 0xAF, 0x57, 0x12, 0x47, 0x8C, 0xEF, +0xAF, 0x57, 0x70, 0x04, 0x91, 0x11, 0x80, 0x02, +0x91, 0x10, 0x05, 0x57, 0x80, 0xDB, 0xE5, 0x58, +0x70, 0x15, 0xFF, 0x12, 0x47, 0x8C, 0xEF, 0x70, +0x0E, 0x12, 0x4D, 0x77, 0x12, 0x4D, 0x61, 0x91, +0x12, 0x54, 0xBF, 0xF0, 0x54, 0x7F, 0xF0, 0x22, +0x22, 0x22, 0x90, 0x81, 0x46, 0xE0, 0x54, 0xF7, +0xF0, 0x22, 0xAB, 0x54, 0xAA, 0x55, 0xA9, 0x56, +0x02, 0x1F, 0xA4, 0x12, 0x1F, 0xA4, 0x54, 0x01, +0xFF, 0x90, 0x81, 0xBE, 0xE0, 0x54, 0xFE, 0x4F, +0xF0, 0x22, 0x12, 0x1F, 0xA4, 0x90, 0x81, 0xAE, +0xF0, 0x22, 0xE4, 0x90, 0x81, 0x33, 0xF0, 0xA3, +0xF0, 0x90, 0x80, 0x9B, 0xF0, 0xA3, 0xF0, 0x22, +0x90, 0x01, 0x94, 0xE0, 0x44, 0x01, 0xF0, 0x90, +0x01, 0xC7, 0xE4, 0xF0, 0x22, 0x90, 0x01, 0x01, +0xE0, 0x44, 0x04, 0xF0, 0x90, 0x01, 0x9C, 0x74, +0x7E, 0xF0, 0xA3, 0x74, 0x92, 0xF0, 0xA3, 0x74, +0xA0, 0xF0, 0xA3, 0x74, 0x24, 0xF0, 0x90, 0x01, +0x9B, 0x74, 0x49, 0xF0, 0x90, 0x01, 0x9A, 0x74, +0xE0, 0xF0, 0x90, 0x01, 0x99, 0xE4, 0xF0, 0x90, +0x01, 0x98, 0x04, 0xF0, 0x22, 0xE4, 0x90, 0x81, +0xC8, 0xF0, 0xA3, 0xF0, 0x90, 0x01, 0x98, 0xE0, +0x7F, 0x00, 0x30, 0xE4, 0x02, 0x7F, 0x01, 0xEF, +0x64, 0x01, 0x60, 0x3D, 0xC3, 0x90, 0x81, 0xC9, +0xE0, 0x94, 0x88, 0x90, 0x81, 0xC8, 0xE0, 0x94, +0x13, 0x40, 0x0F, 0x90, 0x01, 0xC1, 0xE0, 0x44, +0x10, 0xF0, 0x90, 0x01, 0xC7, 0x74, 0xFD, 0xF0, +0x80, 0x1F, 0x90, 0x81, 0xC8, 0x12, 0x5E, 0x53, +0x12, 0x67, 0xD0, 0xD3, 0x90, 0x81, 0xC9, 0xE0, +0x94, 0x32, 0x90, 0x81, 0xC8, 0xE0, 0x94, 0x00, +0x40, 0xBA, 0x90, 0x01, 0xC6, 0xE0, 0x30, 0xE3, +0xB3, 0x90, 0x01, 0xC7, 0x74, 0xFE, 0xF0, 0x22, +0x7F, 0x02, 0x90, 0x81, 0xBB, 0xE0, 0xFE, 0xEF, +0xC3, 0x9E, 0x50, 0x18, 0xEF, 0x25, 0xE0, 0x24, +0x81, 0xF8, 0xE6, 0x30, 0xE4, 0x0B, 0x90, 0x01, +0xB8, 0x74, 0x08, 0xF0, 0xA3, 0xF0, 0x7F, 0x00, +0x22, 0x0F, 0x80, 0xDE, 0x7F, 0x01, 0x22, 0x90, +0x01, 0xE4, 0x74, 0x1C, 0xF0, 0xA3, 0xE4, 0xF0, +0x22, 0x90, 0x01, 0x34, 0xE0, 0x55, 0x3D, 0xF5, +0x41, 0xA3, 0xE0, 0x55, 0x3E, 0xF5, 0x42, 0xA3, +0xE0, 0x55, 0x3F, 0xF5, 0x43, 0xA3, 0xE0, 0x55, +0x40, 0xF5, 0x44, 0x90, 0x01, 0x34, 0xE5, 0x41, +0xF0, 0xA3, 0xE5, 0x42, 0xF0, 0xA3, 0xE5, 0x43, +0xF0, 0xA3, 0xE5, 0x44, 0xF0, 0x22, 0x90, 0x01, +0x3C, 0xE0, 0x55, 0x45, 0xF5, 0x49, 0xA3, 0xE0, +0x55, 0x46, 0xF5, 0x4A, 0xA3, 0xE0, 0x55, 0x47, +0xF5, 0x4B, 0xA3, 0xE0, 0x55, 0x48, 0xF5, 0x4C, +0x90, 0x01, 0x3C, 0xE5, 0x49, 0xF0, 0xA3, 0xE5, +0x4A, 0xF0, 0xA3, 0xE5, 0x4B, 0xF0, 0xA3, 0xE5, +0x4C, 0xF0, 0x53, 0x91, 0xDF, 0x22, 0x90, 0x81, +0x41, 0xE0, 0x30, 0xE0, 0x05, 0xE4, 0xA3, 0xF0, +0xA3, 0xF0, 0x22, 0x90, 0x81, 0x41, 0xE0, 0xFF, +0x30, 0xE0, 0x05, 0x12, 0x57, 0x70, 0x60, 0x15, +0x90, 0x81, 0x4B, 0xE0, 0x70, 0x04, 0xEF, 0x30, +0xE0, 0x0B, 0x90, 0x81, 0x4E, 0xE0, 0x64, 0x02, +0x60, 0x03, 0x12, 0x64, 0xC5, 0x22, 0xE4, 0xFF, +0x12, 0x47, 0x8C, 0xBF, 0x01, 0x13, 0x90, 0x81, +0x4B, 0xE0, 0x60, 0x0D, 0x12, 0x63, 0x36, 0x64, +0x02, 0x60, 0x03, 0x02, 0x5F, 0xA9, 0x12, 0x4F, +0x80, 0x22, 0x90, 0x81, 0x4B, 0xE0, 0x70, 0x07, +0x90, 0x81, 0x41, 0xE0, 0x30, 0xE0, 0x12, 0x90, +0x81, 0x41, 0xE0, 0x30, 0xE0, 0x08, 0x12, 0x54, +0x9B, 0xBF, 0x01, 0x05, 0x80, 0x04, 0x12, 0x63, +0x05, 0x22, 0x90, 0x81, 0x4B, 0xE0, 0x64, 0x02, +0x60, 0x0D, 0x12, 0x63, 0x36, 0x60, 0x08, 0xB1, +0xF0, 0xEF, 0x70, 0x03, 0x12, 0x4B, 0x1E, 0x22, +0x90, 0x04, 0x1A, 0xE0, 0xF4, 0x60, 0x03, 0x7F, +0x00, 0x22, 0x90, 0x04, 0x1B, 0xE0, 0x54, 0x07, +0x64, 0x07, 0x7F, 0x01, 0x60, 0x02, 0x7F, 0x00, +0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0xB1, 0xF0, 0xEF, 0x64, 0x01, 0x60, 0x05, 0x75, +0x0D, 0x01, 0x80, 0x43, 0x90, 0x81, 0x4F, 0xE0, +0xFF, 0x54, 0x03, 0x60, 0x05, 0x75, 0x0D, 0x02, +0x80, 0x35, 0xEF, 0x30, 0xE2, 0x05, 0x75, 0x0D, +0x08, 0x80, 0x2C, 0x90, 0x81, 0x4F, 0xE0, 0x30, +0xE4, 0x05, 0x75, 0x0D, 0x10, 0x80, 0x20, 0x12, +0x65, 0xB9, 0x54, 0x3F, 0x20, 0xE0, 0x05, 0x75, +0x0D, 0x20, 0x80, 0x13, 0xD1, 0x7A, 0x8F, 0x0E, +0xE5, 0x0E, 0x64, 0x01, 0x60, 0x05, 0x85, 0x0E, +0x0D, 0x80, 0x04, 0xD1, 0x72, 0x80, 0x0E, 0x90, +0x01, 0xB9, 0x74, 0x04, 0xF0, 0x90, 0x01, 0xB8, +0xE5, 0x0D, 0xF0, 0x7F, 0x00, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0x90, 0x01, 0xB8, 0xE4, 0xF0, 0x7F, +0x01, 0x22, 0x90, 0x81, 0x4D, 0xE0, 0xD3, 0x94, +0x00, 0x40, 0x06, 0x75, 0x58, 0x04, 0x7F, 0xFF, +0x22, 0x90, 0x81, 0xAE, 0xE0, 0x60, 0x06, 0x75, +0x58, 0x80, 0x7F, 0xFF, 0x22, 0x7F, 0x01, 0x22, +0x90, 0x81, 0xB7, 0xE0, 0xC3, 0x13, 0x20, 0xE0, +0x35, 0x90, 0x02, 0x87, 0xE0, 0x60, 0x02, 0x80, +0x08, 0x90, 0x01, 0x00, 0xE0, 0x64, 0x3F, 0x60, +0x05, 0x75, 0x51, 0x01, 0x80, 0x22, 0x90, 0x02, +0x96, 0xE0, 0x60, 0x05, 0x75, 0x51, 0x10, 0x80, +0x17, 0x90, 0x02, 0x86, 0xE0, 0x20, 0xE1, 0x02, +0x80, 0x07, 0x90, 0x02, 0x86, 0xE0, 0x30, 0xE3, +0x05, 0x75, 0x51, 0x04, 0x80, 0x02, 0x80, 0x9A, +0x90, 0x01, 0xB9, 0x74, 0x08, 0xF0, 0x90, 0x01, +0xB8, 0xE5, 0x51, 0xF0, 0x7F, 0x00, 0x22, 0x90, +0x81, 0xBC, 0xE0, 0x60, 0x0F, 0xE4, 0xF0, 0x90, +0x05, 0x53, 0xE0, 0x44, 0x01, 0xF0, 0x90, 0x05, +0xFD, 0xE0, 0x04, 0xF0, 0x22, 0x90, 0x01, 0xC4, +0x74, 0xFD, 0xF0, 0x74, 0x76, 0xA3, 0xF0, 0x90, +0x00, 0x90, 0xE0, 0x20, 0xE0, 0xF9, 0x74, 0xFD, +0x04, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x76, 0xA3, +0xF0, 0x22, 0x90, 0x81, 0x56, 0xE0, 0xFD, 0x7F, +0x93, 0x12, 0x32, 0x1E, 0x90, 0x81, 0x4C, 0xE0, +0x60, 0x12, 0x90, 0x01, 0x2F, 0xE0, 0x30, 0xE7, +0x05, 0x74, 0x10, 0xF0, 0x80, 0x06, 0x90, 0x01, +0x2F, 0x74, 0x90, 0xF0, 0x90, 0x00, 0x08, 0xE0, +0x44, 0x10, 0xFD, 0x7F, 0x08, 0x12, 0x32, 0x1E, +0x7F, 0x01, 0x12, 0x62, 0x1C, 0x90, 0x81, 0x56, +0xE0, 0x20, 0xE0, 0x0C, 0x90, 0x00, 0x26, 0xE0, +0x44, 0x80, 0xFD, 0x7F, 0x26, 0x12, 0x32, 0x1E, +0x90, 0x00, 0x90, 0xE0, 0x44, 0x01, 0xFD, 0x7F, +0x90, 0x12, 0x32, 0x1E, 0x7F, 0x14, 0x7E, 0x00, +0x02, 0x32, 0xAA, 0x90, 0x81, 0x46, 0xE0, 0x54, +0xFB, 0xF0, 0xE4, 0x90, 0x81, 0x54, 0xF0, 0xA3, +0xF0, 0x90, 0x81, 0x4F, 0xF0, 0x90, 0x81, 0x47, +0xE0, 0x54, 0xF7, 0xF0, 0x54, 0xBF, 0xF0, 0x12, +0x4F, 0xB9, 0x7D, 0x10, 0x7F, 0x03, 0x02, 0x56, +0xFD, 0xEF, 0x24, 0xFE, 0x60, 0x0B, 0x04, 0x70, +0x24, 0x90, 0x81, 0x51, 0x74, 0x02, 0xF0, 0x80, +0x13, 0xED, 0x70, 0x06, 0x90, 0x81, 0xAB, 0xE0, +0x80, 0x02, 0xED, 0x14, 0x90, 0x81, 0x51, 0xF0, +0x90, 0x81, 0x51, 0xE0, 0xA3, 0xF0, 0x90, 0x81, +0x47, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x7B, 0x2E, +0x12, 0x7B, 0x55, 0x7D, 0x02, 0x7F, 0x01, 0x12, +0x49, 0xCE, 0x12, 0x7B, 0x5C, 0x90, 0x81, 0x45, +0x74, 0x02, 0xF0, 0x22, 0x90, 0x81, 0xA2, 0x74, +0x04, 0xF0, 0xA3, 0x14, 0xF0, 0xA3, 0xE4, 0xF0, +0xA3, 0x74, 0x64, 0xF0, 0xA3, 0x74, 0x01, 0xF0, +0xA3, 0x74, 0x05, 0xF0, 0x22, 0x12, 0x55, 0x27, +0x12, 0x44, 0xD0, 0xC0, 0x04, 0xC0, 0x05, 0xC0, +0x06, 0xC0, 0x07, 0x90, 0x05, 0x62, 0x12, 0x55, +0x40, 0x78, 0x10, 0x12, 0x20, 0xBB, 0xD0, 0x03, +0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, 0x44, +0xD0, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, +0x07, 0xA3, 0x12, 0x55, 0x40, 0x78, 0x18, 0x12, +0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, +0xD0, 0x00, 0x12, 0x44, 0xD0, 0x90, 0x81, 0x9A, +0x12, 0x20, 0xCE, 0x90, 0x81, 0x9E, 0x12, 0x44, +0xEE, 0x90, 0x81, 0x9A, 0x12, 0x45, 0x06, 0xC3, +0x12, 0x44, 0xDD, 0x40, 0x44, 0x90, 0x81, 0x46, +0xE0, 0x90, 0x81, 0x9E, 0x30, 0xE0, 0x0F, 0x31, +0x6E, 0x90, 0x81, 0x68, 0xE0, 0x24, 0x04, 0x2F, +0xFF, 0x90, 0x81, 0xA2, 0x80, 0x05, 0x31, 0x6E, +0x90, 0x81, 0xA3, 0xE0, 0xFE, 0xC3, 0xEF, 0x9E, +0x90, 0x81, 0xC1, 0xF0, 0x90, 0x81, 0xC1, 0xE0, +0xFF, 0xC3, 0x94, 0x2D, 0x50, 0x13, 0x74, 0x69, +0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, +0xE0, 0x04, 0xF0, 0x90, 0x81, 0x61, 0xE0, 0x04, +0xF0, 0x90, 0x81, 0x61, 0xE0, 0xFF, 0xD3, 0x90, +0x81, 0xA5, 0xE0, 0x9F, 0x90, 0x81, 0xA4, 0xE0, +0x94, 0x00, 0x40, 0x02, 0x21, 0x52, 0xE4, 0xFF, +0xFE, 0x31, 0x5B, 0xEF, 0xD3, 0x9D, 0x40, 0x07, +0x90, 0x81, 0xC2, 0xEE, 0xF0, 0x80, 0x05, 0x0E, +0xEE, 0xB4, 0x2D, 0xED, 0xE4, 0xFF, 0xFE, 0x31, +0x5B, 0xC3, 0x90, 0x81, 0xA5, 0xE0, 0x9D, 0xFD, +0x90, 0x81, 0xA4, 0xE0, 0x94, 0x00, 0xFC, 0xEF, +0xD3, 0x9D, 0xE4, 0x9C, 0x40, 0x07, 0x90, 0x81, +0xC3, 0xEE, 0xF0, 0x80, 0x05, 0x0E, 0xEE, 0xB4, +0x2D, 0xDD, 0x90, 0x81, 0xC2, 0xE0, 0x90, 0x81, +0x66, 0xF0, 0x90, 0x81, 0xC3, 0xE0, 0x90, 0x81, +0x67, 0x31, 0x53, 0x94, 0x0A, 0x40, 0x0A, 0xEF, +0x24, 0xF6, 0x90, 0x81, 0x5E, 0xF0, 0xE4, 0x80, +0x09, 0xE4, 0x90, 0x81, 0x5E, 0x31, 0x53, 0x74, +0x0A, 0x9F, 0x90, 0x81, 0x5D, 0xF0, 0x90, 0x81, +0x66, 0xE0, 0xFF, 0xA3, 0xE0, 0xC3, 0x9F, 0x90, +0x81, 0x64, 0xF0, 0x90, 0x81, 0x46, 0xE0, 0x30, +0xE0, 0x05, 0x90, 0x81, 0xA2, 0x80, 0x03, 0x90, +0x81, 0xA3, 0xE0, 0x04, 0xFF, 0x90, 0x81, 0x64, +0xE0, 0x2F, 0xF0, 0x90, 0x81, 0x64, 0xE0, 0xC3, +0x94, 0x10, 0x50, 0x03, 0x74, 0x10, 0xF0, 0x90, +0x81, 0x64, 0xE0, 0x24, 0x02, 0x12, 0x67, 0xAF, +0x74, 0x03, 0xF0, 0x12, 0x6C, 0xF1, 0xE4, 0xFF, +0x31, 0x8B, 0x22, 0xF0, 0x90, 0x81, 0x66, 0xE0, +0xFF, 0xC3, 0x22, 0x74, 0x69, 0x2E, 0xF5, 0x82, +0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0, 0x2F, 0xFF, +0x90, 0x81, 0xA6, 0xE0, 0xFD, 0x22, 0x12, 0x45, +0x06, 0x90, 0x81, 0x9A, 0x12, 0x44, 0xEE, 0x12, +0x44, 0xB5, 0x78, 0x0A, 0x12, 0x20, 0xA8, 0x90, +0x81, 0x63, 0xE0, 0xFE, 0xC3, 0x74, 0x0A, 0x9E, +0x2F, 0xFF, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x82, 0xAF, 0xEF, 0xF0, 0x7E, +0x00, 0x7F, 0x2D, 0x7D, 0x00, 0x7B, 0x01, 0x7A, +0x81, 0x79, 0x69, 0x12, 0x45, 0x6F, 0xE4, 0x90, +0x81, 0x62, 0xF0, 0x90, 0x81, 0x61, 0xF0, 0x90, +0x81, 0x65, 0xF0, 0x90, 0x82, 0xAF, 0xE0, 0xB4, +0x01, 0x09, 0x90, 0x81, 0x66, 0x74, 0x2D, 0xF0, +0xE4, 0xA3, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x90, 0x81, 0xAF, 0xE0, 0x54, 0xFE, 0xF0, 0x54, +0xFD, 0xF0, 0x54, 0xEF, 0xF0, 0x44, 0x08, 0xF0, +0x22, 0x90, 0x81, 0xAF, 0xE0, 0x30, 0xE0, 0x0D, +0xE4, 0xF5, 0x1D, 0x90, 0x81, 0xB1, 0x12, 0x49, +0x02, 0x12, 0x67, 0xC2, 0xF0, 0x90, 0x80, 0x42, +0xE0, 0xB4, 0x01, 0x12, 0x51, 0x07, 0x13, 0x54, +0x1F, 0x20, 0xE0, 0x0A, 0xEF, 0xC4, 0x13, 0x54, +0x07, 0x30, 0xE0, 0x02, 0x51, 0x0F, 0x22, 0x90, +0x81, 0xAF, 0xE0, 0xFF, 0x13, 0x13, 0x22, 0x90, +0x81, 0xAF, 0xE0, 0x30, 0xE0, 0x34, 0xC4, 0x13, +0x54, 0x07, 0x30, 0xE0, 0x2D, 0x90, 0x82, 0xB0, +0xE0, 0x04, 0xF0, 0xE0, 0xD3, 0x94, 0xC8, 0x40, +0x21, 0x90, 0x81, 0xAF, 0xE0, 0x54, 0xDF, 0xF0, +0xE4, 0x90, 0x82, 0xB0, 0xF0, 0x90, 0x81, 0xAF, +0xE0, 0x13, 0x30, 0xE0, 0x0D, 0x90, 0x81, 0x46, +0xE0, 0x44, 0x01, 0xF0, 0x90, 0x81, 0x56, 0x74, +0xD0, 0xF0, 0x22, 0x90, 0x81, 0x44, 0xE0, 0x64, +0x02, 0x7F, 0x01, 0x60, 0x02, 0x7F, 0x00, 0x22, +0x90, 0x80, 0x46, 0xE0, 0xFF, 0x90, 0x82, 0x8A, +0xE0, 0xFB, 0x90, 0x82, 0x95, 0x74, 0x0A, 0xF0, +0x7D, 0x01, 0x12, 0x5E, 0xE7, 0x90, 0x82, 0x8B, +0xEE, 0xF0, 0xFC, 0xA3, 0xEF, 0xF0, 0xFD, 0x90, +0x82, 0x89, 0xE0, 0xFF, 0x12, 0x5E, 0xBD, 0x90, +0x82, 0x8B, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90, +0x04, 0x80, 0xE0, 0x54, 0x0F, 0xFD, 0xAC, 0x07, +0x51, 0xF3, 0x44, 0x01, 0xF0, 0x51, 0xF3, 0x54, +0xFB, 0xF0, 0xAC, 0x07, 0x74, 0x16, 0x2C, 0x12, +0x5F, 0xA1, 0xE0, 0x44, 0xFA, 0xF0, 0x74, 0x15, +0x2C, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, +0xE0, 0x44, 0x1F, 0xF0, 0xAC, 0x07, 0x74, 0x06, +0x2C, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, +0xE0, 0x44, 0x0F, 0xF0, 0x90, 0x04, 0x53, 0xE4, +0xF0, 0x90, 0x04, 0x52, 0xF0, 0x90, 0x04, 0x51, +0x74, 0xFF, 0xF0, 0x90, 0x04, 0x50, 0x74, 0xFD, +0xF0, 0x74, 0x14, 0x2C, 0x51, 0xEB, 0xE0, 0x54, +0xC0, 0x4D, 0xFD, 0x74, 0x14, 0x2F, 0x51, 0xEB, +0xED, 0xF0, 0x22, 0xF5, 0x82, 0xE4, 0x34, 0xFC, +0xF5, 0x83, 0x22, 0x74, 0x11, 0x2C, 0xF5, 0x82, +0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x22, 0xE4, +0xFE, 0xEF, 0xC3, 0x13, 0xFD, 0xEF, 0x30, 0xE0, +0x02, 0x7E, 0x80, 0x90, 0xFD, 0x10, 0xED, 0xF0, +0xAF, 0x06, 0x22, 0x7E, 0x00, 0x7F, 0x04, 0x7D, +0x00, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0xB7, 0x22, +0xE0, 0x90, 0x01, 0xBA, 0xF0, 0x90, 0x81, 0x4D, +0xE0, 0x90, 0x01, 0xBB, 0x22, 0xEF, 0x13, 0x13, +0x13, 0x54, 0x1F, 0xFE, 0xEF, 0x54, 0x07, 0xFF, +0x22, 0x90, 0x81, 0x41, 0xE0, 0xC4, 0x13, 0x13, +0x54, 0x03, 0x22, 0x90, 0x81, 0x46, 0xE0, 0x13, +0x13, 0x13, 0x54, 0x1F, 0x22, 0x90, 0x06, 0x04, +0xE0, 0x54, 0x7F, 0xF0, 0x22, 0x7D, 0x6F, 0x7F, +0xFF, 0x02, 0x4D, 0x1C, 0x90, 0x05, 0x27, 0xE0, +0x54, 0xBF, 0xF0, 0x22, 0x90, 0x06, 0x04, 0xE0, +0x44, 0x40, 0xF0, 0x22, 0x90, 0x81, 0x46, 0xE0, +0x54, 0xBF, 0xF0, 0x22, 0x90, 0x81, 0x51, 0xE0, +0x90, 0x05, 0x73, 0x22, 0x69, 0xCF +}; + +u32 array_length_mp_8188e_t_fw_nic = 15262; + +u8 array_mp_8188e_t_fw_nic_89em[] = { +0xE1, 0x88, 0x40, 0x00, 0x1C, 0x00, 0x00, 0x00, +0x05, 0x05, 0x14, 0x28, 0xFC, 0x37, 0x00, 0x00, +0xA5, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x02, 0x45, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xC1, 0xA4, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xC1, 0x1B, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xE1, 0xFA, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xC2, 0xAF, 0x80, 0xFE, 0x32, 0x12, 0x41, 0x04, +0x85, 0xD0, 0x0B, 0x75, 0xD0, 0x08, 0xAA, 0xE0, +0xC2, 0x8C, 0xE5, 0x8A, 0x24, 0x67, 0xF5, 0x8A, +0xE5, 0x8C, 0x34, 0x79, 0xF5, 0x8C, 0xD2, 0x8C, +0xEC, 0x24, 0x87, 0xF8, 0xE6, 0xBC, 0x02, 0x02, +0x74, 0xFF, 0xC3, 0x95, 0x81, 0xB4, 0x40, 0x00, +0x40, 0xCE, 0x79, 0x03, 0x78, 0x80, 0x16, 0xE6, +0x08, 0x70, 0x0B, 0xC2, 0xAF, 0xE6, 0x30, 0xE1, +0x03, 0x44, 0x18, 0xF6, 0xD2, 0xAF, 0x08, 0xD9, +0xED, 0xEA, 0x8B, 0xD0, 0x22, 0xE5, 0x0C, 0xFF, +0x23, 0x24, 0x81, 0xF8, 0x0F, 0x08, 0x08, 0xBF, +0x03, 0x04, 0x7F, 0x00, 0x78, 0x81, 0xE6, 0x30, +0xE4, 0xF2, 0x00, 0xE5, 0x0C, 0xC3, 0x9F, 0x50, +0x20, 0x05, 0x0C, 0x74, 0x86, 0x25, 0x0C, 0xF8, +0xE6, 0xFD, 0xA6, 0x81, 0x08, 0xE6, 0xAE, 0x0C, +0xBE, 0x02, 0x02, 0x74, 0xFF, 0xCD, 0xF8, 0xE8, +0x6D, 0x60, 0xE0, 0x08, 0xE6, 0xC0, 0xE0, 0x80, +0xF6, 0xE5, 0x0C, 0xD3, 0x9F, 0x40, 0x27, 0xE5, +0x0C, 0x24, 0x87, 0xF8, 0xE6, 0xAE, 0x0C, 0xBE, +0x02, 0x02, 0x74, 0xFF, 0xFD, 0x18, 0xE6, 0xCD, +0xF8, 0xE5, 0x81, 0x6D, 0x60, 0x06, 0xD0, 0xE0, +0xF6, 0x18, 0x80, 0xF5, 0xE5, 0x0C, 0x24, 0x86, +0xC8, 0xF6, 0x15, 0x0C, 0x80, 0xD3, 0xE5, 0x0C, +0x23, 0x24, 0x81, 0xF8, 0x7F, 0x04, 0xC2, 0xAF, +0xE6, 0x30, 0xE0, 0x03, 0x10, 0xE2, 0x0C, 0x7F, +0x00, 0x30, 0xE1, 0x07, 0x30, 0xE3, 0x04, 0x7F, +0x08, 0x54, 0xF4, 0x54, 0x7C, 0xC6, 0xD2, 0xAF, +0x54, 0x80, 0x42, 0x07, 0x22, 0x78, 0x86, 0xA6, +0x81, 0x74, 0x02, 0x60, 0x06, 0xFF, 0x08, 0x76, +0xFF, 0xDF, 0xFB, 0x7F, 0x03, 0xE4, 0x78, 0x80, +0xF6, 0x08, 0xF6, 0x08, 0xDF, 0xFA, 0x78, 0x81, +0x76, 0x30, 0x90, 0x46, 0x15, 0x74, 0x01, 0x93, +0xC0, 0xE0, 0xE4, 0x93, 0xC0, 0xE0, 0x43, 0x89, +0x01, 0x75, 0x8A, 0x60, 0x75, 0x8C, 0x79, 0xD2, +0x8C, 0xD2, 0xAF, 0x22, 0x02, 0xEF, 0xD3, 0x94, +0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, 0x74, 0x81, +0x2F, 0x2F, 0xF8, 0xE6, 0x20, 0xE5, 0xF4, 0xC2, +0xAF, 0xE6, 0x44, 0x30, 0xF6, 0xD2, 0xAF, 0xAE, +0x0C, 0xEE, 0xC3, 0x9F, 0x50, 0x21, 0x0E, 0x74, +0x86, 0x2E, 0xF8, 0xE6, 0xF9, 0x08, 0xE6, 0x18, +0xBE, 0x02, 0x02, 0x74, 0xFF, 0xFD, 0xED, 0x69, +0x60, 0x09, 0x09, 0xE7, 0x19, 0x19, 0xF7, 0x09, +0x09, 0x80, 0xF3, 0x16, 0x16, 0x80, 0xDA, 0xEE, +0xD3, 0x9F, 0x40, 0x04, 0x05, 0x81, 0x05, 0x81, +0xEE, 0xD3, 0x9F, 0x40, 0x22, 0x74, 0x86, 0x2E, +0xF8, 0x08, 0xE6, 0xF9, 0xEE, 0xB5, 0x0C, 0x02, +0xA9, 0x81, 0x18, 0x06, 0x06, 0xE6, 0xFD, 0xED, +0x69, 0x60, 0x09, 0x19, 0x19, 0xE7, 0x09, 0x09, +0xF7, 0x19, 0x80, 0xF3, 0x1E, 0x80, 0xD9, 0xEF, +0x24, 0x86, 0xF8, 0xE6, 0x04, 0xF8, 0xEF, 0x2F, +0x04, 0x90, 0x46, 0x15, 0x93, 0xF6, 0x08, 0xEF, +0x2F, 0x93, 0xF6, 0x7F, 0x00, 0x22, 0xEF, 0xD3, +0x94, 0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, 0xEF, +0x23, 0x24, 0x81, 0xF8, 0xE6, 0x30, 0xE5, 0xF4, +0xC2, 0xAF, 0xE6, 0x54, 0x8C, 0xF6, 0xD2, 0xAF, +0xE5, 0x0C, 0xB5, 0x07, 0x0A, 0x74, 0x86, 0x2F, +0xF8, 0xE6, 0xF5, 0x81, 0x02, 0x41, 0x4D, 0x50, +0x2E, 0x74, 0x87, 0x2F, 0xF8, 0xE6, 0xBF, 0x02, +0x02, 0x74, 0xFF, 0xFD, 0x18, 0xE6, 0xF9, 0x74, +0x86, 0x2F, 0xF8, 0xFB, 0xE6, 0xFC, 0xE9, 0x6C, +0x60, 0x08, 0xA8, 0x05, 0xE7, 0xF6, 0x1D, 0x19, +0x80, 0xF4, 0xA8, 0x03, 0xA6, 0x05, 0x1F, 0xE5, +0x0C, 0xB5, 0x07, 0xE3, 0x7F, 0x00, 0x22, 0x74, +0x87, 0x2F, 0xF8, 0xE6, 0xFD, 0x18, 0x86, 0x01, +0x0F, 0x74, 0x86, 0x2F, 0xF8, 0xA6, 0x01, 0x08, +0x86, 0x04, 0xE5, 0x0C, 0xB5, 0x07, 0x02, 0xAC, +0x81, 0xED, 0x6C, 0x60, 0x08, 0x0D, 0x09, 0xA8, +0x05, 0xE6, 0xF7, 0x80, 0xF4, 0xE5, 0x0C, 0xB5, +0x07, 0xDE, 0x89, 0x81, 0x7F, 0x00, 0x22, 0xEF, +0xD3, 0x94, 0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, +0xEF, 0x23, 0x24, 0x81, 0xF8, 0xC2, 0xAF, 0xE6, +0x30, 0xE5, 0x05, 0x30, 0xE0, 0x02, 0xD2, 0xE4, +0xD2, 0xE2, 0xC6, 0xD2, 0xAF, 0x7F, 0x00, 0x30, +0xE2, 0x01, 0x0F, 0x02, 0x41, 0x4C, 0x8F, 0xF0, +0xE4, 0xFF, 0xFE, 0xE5, 0x0C, 0x23, 0x24, 0x80, +0xF8, 0xC2, 0xA9, 0x30, 0xF7, 0x0D, 0x7F, 0x08, +0xE6, 0x60, 0x0B, 0x2D, 0xF6, 0x60, 0x30, 0x50, +0x2E, 0x80, 0x07, 0x30, 0xF1, 0x06, 0xED, 0xF6, +0x60, 0x25, 0x7E, 0x02, 0x08, 0x30, 0xF0, 0x10, +0xC2, 0xAF, 0xE6, 0x10, 0xE7, 0x23, 0x0E, 0x30, +0xE2, 0x0C, 0xD2, 0xAF, 0x7F, 0x04, 0x80, 0x12, +0xC2, 0xAF, 0xE6, 0x10, 0xE7, 0x13, 0x54, 0xEC, +0x4E, 0xF6, 0xD2, 0xAF, 0x02, 0x41, 0x4D, 0x7F, +0x08, 0x08, 0xEF, 0x44, 0x83, 0xF4, 0xC2, 0xAF, +0x56, 0xC6, 0xD2, 0xAF, 0x54, 0x80, 0x4F, 0xFF, +0x22, 0xE7, 0x09, 0xF6, 0x08, 0xDF, 0xFA, 0x80, +0x46, 0xE7, 0x09, 0xF2, 0x08, 0xDF, 0xFA, 0x80, +0x3E, 0x88, 0x82, 0x8C, 0x83, 0xE7, 0x09, 0xF0, +0xA3, 0xDF, 0xFA, 0x80, 0x32, 0xE3, 0x09, 0xF6, +0x08, 0xDF, 0xFA, 0x80, 0x78, 0xE3, 0x09, 0xF2, +0x08, 0xDF, 0xFA, 0x80, 0x70, 0x88, 0x82, 0x8C, +0x83, 0xE3, 0x09, 0xF0, 0xA3, 0xDF, 0xFA, 0x80, +0x64, 0x89, 0x82, 0x8A, 0x83, 0xE0, 0xA3, 0xF6, +0x08, 0xDF, 0xFA, 0x80, 0x58, 0x89, 0x82, 0x8A, +0x83, 0xE0, 0xA3, 0xF2, 0x08, 0xDF, 0xFA, 0x80, +0x4C, 0x80, 0xD2, 0x80, 0xFA, 0x80, 0xC6, 0x80, +0xD4, 0x80, 0x69, 0x80, 0xF2, 0x80, 0x33, 0x80, +0x10, 0x80, 0xA6, 0x80, 0xEA, 0x80, 0x9A, 0x80, +0xA8, 0x80, 0xDA, 0x80, 0xE2, 0x80, 0xCA, 0x80, +0x33, 0x89, 0x82, 0x8A, 0x83, 0xEC, 0xFA, 0xE4, +0x93, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, 0xC5, +0x83, 0xCC, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, +0xCC, 0xC5, 0x83, 0xCC, 0xDF, 0xE9, 0xDE, 0xE7, +0x80, 0x0D, 0x89, 0x82, 0x8A, 0x83, 0xE4, 0x93, +0xA3, 0xF6, 0x08, 0xDF, 0xF9, 0xEC, 0xFA, 0xA9, +0xF0, 0xED, 0xFB, 0x22, 0x89, 0x82, 0x8A, 0x83, +0xEC, 0xFA, 0xE0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, +0xCC, 0xC5, 0x83, 0xCC, 0xF0, 0xA3, 0xC8, 0xC5, +0x82, 0xC8, 0xCC, 0xC5, 0x83, 0xCC, 0xDF, 0xEA, +0xDE, 0xE8, 0x80, 0xDB, 0x89, 0x82, 0x8A, 0x83, +0xE4, 0x93, 0xA3, 0xF2, 0x08, 0xDF, 0xF9, 0x80, +0xCC, 0x88, 0xF0, 0xEF, 0x60, 0x01, 0x0E, 0x4E, +0x60, 0xC3, 0x88, 0xF0, 0xED, 0x24, 0x02, 0xB4, +0x04, 0x00, 0x50, 0xB9, 0xF5, 0x82, 0xEB, 0x24, +0x02, 0xB4, 0x04, 0x00, 0x50, 0xAF, 0x23, 0x23, +0x45, 0x82, 0x23, 0x90, 0x43, 0xF9, 0x73, 0xC5, +0xF0, 0xF8, 0xA3, 0xE0, 0x28, 0xF0, 0xC5, 0xF0, +0xF8, 0xE5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, +0x83, 0xE0, 0x38, 0xF0, 0x22, 0xEF, 0x5B, 0xFF, +0xEE, 0x5A, 0xFE, 0xED, 0x59, 0xFD, 0xEC, 0x58, +0xFC, 0x22, 0xEF, 0x4B, 0xFF, 0xEE, 0x4A, 0xFE, +0xED, 0x49, 0xFD, 0xEC, 0x48, 0xFC, 0x22, 0xEB, +0x9F, 0xF5, 0xF0, 0xEA, 0x9E, 0x42, 0xF0, 0xE9, +0x9D, 0x42, 0xF0, 0xE8, 0x9C, 0x45, 0xF0, 0x22, +0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, +0xA3, 0xE0, 0xFF, 0x22, 0xE2, 0xFC, 0x08, 0xE2, +0xFD, 0x08, 0xE2, 0xFE, 0x08, 0xE2, 0xFF, 0x22, +0xE2, 0xFB, 0x08, 0xE2, 0xF9, 0x08, 0xE2, 0xFA, +0x08, 0xE2, 0xCB, 0xF8, 0x22, 0xEC, 0xF2, 0x08, +0xED, 0xF2, 0x08, 0xEE, 0xF2, 0x08, 0xEF, 0xF2, +0x22, 0xA4, 0x25, 0x82, 0xF5, 0x82, 0xE5, 0xF0, +0x35, 0x83, 0xF5, 0x83, 0x22, 0xE0, 0xFB, 0xA3, +0xE0, 0xFA, 0xA3, 0xE0, 0xF9, 0x22, 0xEB, 0xF0, +0xA3, 0xEA, 0xF0, 0xA3, 0xE9, 0xF0, 0x22, 0xD0, +0x83, 0xD0, 0x82, 0xF8, 0xE4, 0x93, 0x70, 0x12, +0x74, 0x01, 0x93, 0x70, 0x0D, 0xA3, 0xA3, 0x93, +0xF8, 0x74, 0x01, 0x93, 0xF5, 0x82, 0x88, 0x83, +0xE4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xEF, +0xA3, 0xA3, 0xA3, 0x80, 0xDF, 0xEF, 0x4E, 0x60, +0x12, 0xEF, 0x60, 0x01, 0x0E, 0xED, 0xBB, 0x01, +0x0B, 0x89, 0x82, 0x8A, 0x83, 0xF0, 0xA3, 0xDF, +0xFC, 0xDE, 0xFA, 0x22, 0x89, 0xF0, 0x50, 0x07, +0xF7, 0x09, 0xDF, 0xFC, 0xA9, 0xF0, 0x22, 0xBB, +0xFE, 0xFC, 0xF3, 0x09, 0xDF, 0xFC, 0xA9, 0xF0, +0x22, 0x02, 0x45, 0xBF, 0x02, 0x41, 0xDD, 0xE4, +0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0x40, 0x03, +0xF6, 0x80, 0x01, 0xF2, 0x08, 0xDF, 0xF4, 0x80, +0x29, 0xE4, 0x93, 0xA3, 0xF8, 0x54, 0x07, 0x24, +0x0C, 0xC8, 0xC3, 0x33, 0xC4, 0x54, 0x0F, 0x44, +0x20, 0xC8, 0x83, 0x40, 0x04, 0xF4, 0x56, 0x80, +0x01, 0x46, 0xF6, 0xDF, 0xE4, 0x80, 0x0B, 0x01, +0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, +0x46, 0x04, 0xE4, 0x7E, 0x01, 0x93, 0x60, 0xBC, +0xA3, 0xFF, 0x54, 0x3F, 0x30, 0xE5, 0x09, 0x54, +0x1F, 0xFE, 0xE4, 0x93, 0xA3, 0x60, 0x01, 0x0E, +0xCF, 0x54, 0xC0, 0x25, 0xE0, 0x60, 0xA8, 0x40, +0xB8, 0xE4, 0x93, 0xA3, 0xFA, 0xE4, 0x93, 0xA3, +0xF8, 0xE4, 0x93, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, +0xCA, 0xC5, 0x83, 0xCA, 0xF0, 0xA3, 0xC8, 0xC5, +0x82, 0xC8, 0xCA, 0xC5, 0x83, 0xCA, 0xDF, 0xE9, +0xDE, 0xE7, 0x80, 0xBE, 0x41, 0x82, 0xA5, 0x00, +0x41, 0x82, 0xA6, 0x00, 0x41, 0x82, 0xAF, 0x00, +0x41, 0x82, 0xB1, 0x00, 0x00, 0x50, 0xF5, 0x59, +0x36, 0x5F, 0xD5, 0xC0, 0xE0, 0xC0, 0xF0, 0xC0, +0x83, 0xC0, 0x82, 0xC0, 0xD0, 0x75, 0xD0, 0x00, +0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x02, 0xC0, 0x03, +0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, +0x90, 0x01, 0xC4, 0x74, 0x1B, 0xF0, 0x74, 0x46, +0xA3, 0xF0, 0xD1, 0x6A, 0x74, 0x1B, 0x04, 0x90, +0x01, 0xC4, 0xF0, 0x74, 0x46, 0xA3, 0xF0, 0xD0, +0x07, 0xD0, 0x06, 0xD0, 0x05, 0xD0, 0x04, 0xD0, +0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0xD0, +0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0, +0xE0, 0x32, 0x90, 0x00, 0x54, 0xE0, 0x55, 0x35, +0xF5, 0x39, 0xA3, 0xE0, 0x55, 0x36, 0xF5, 0x3A, +0xA3, 0xE0, 0x55, 0x37, 0xF5, 0x3B, 0xA3, 0xE0, +0x55, 0x38, 0xF5, 0x3C, 0xAD, 0x39, 0x7F, 0x54, +0x12, 0x32, 0x1E, 0xAD, 0x3A, 0x7F, 0x55, 0x12, +0x32, 0x1E, 0xAD, 0x3B, 0x7F, 0x56, 0x12, 0x32, +0x1E, 0xAD, 0x3C, 0x7F, 0x57, 0x12, 0x32, 0x1E, +0x53, 0x91, 0xEF, 0x22, 0xC0, 0xE0, 0xC0, 0xF0, +0xC0, 0x83, 0xC0, 0x82, 0xC0, 0xD0, 0x75, 0xD0, +0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x02, 0xC0, +0x03, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, +0x07, 0x90, 0x01, 0xC4, 0x74, 0xA4, 0xF0, 0x74, +0x46, 0xA3, 0xF0, 0x12, 0x6E, 0x5D, 0xE5, 0x41, +0x30, 0xE4, 0x02, 0xF1, 0x40, 0xE5, 0x41, 0x30, +0xE6, 0x03, 0x12, 0x6E, 0xBA, 0xE5, 0x43, 0x30, +0xE0, 0x03, 0x12, 0x6E, 0xC7, 0xE5, 0x43, 0x30, +0xE1, 0x03, 0x12, 0x55, 0xCB, 0xE5, 0x43, 0x30, +0xE2, 0x03, 0x12, 0x70, 0x12, 0xE5, 0x43, 0x30, +0xE3, 0x02, 0xF1, 0x53, 0xE5, 0x43, 0x30, 0xE4, +0x02, 0xF1, 0x95, 0xE5, 0x43, 0x30, 0xE5, 0x03, +0x12, 0x67, 0x75, 0xE5, 0x43, 0x30, 0xE6, 0x02, +0xF1, 0xCD, 0xE5, 0x44, 0x30, 0xE1, 0x03, 0x12, +0x67, 0xB2, 0x74, 0xA4, 0x04, 0x90, 0x01, 0xC4, +0xF0, 0x74, 0x46, 0xA3, 0xF0, 0xD0, 0x07, 0xD0, +0x06, 0xD0, 0x05, 0xD0, 0x04, 0xD0, 0x03, 0xD0, +0x02, 0xD0, 0x01, 0xD0, 0x00, 0xD0, 0xD0, 0xD0, +0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0, 0xE0, 0x32, +0x12, 0x60, 0x74, 0x7F, 0x02, 0x8F, 0x0F, 0x7F, +0x02, 0x71, 0x27, 0x90, 0x80, 0x3C, 0xE0, 0x45, +0x0F, 0xF0, 0x22, 0xF1, 0x6A, 0x70, 0x12, 0x90, +0x81, 0x4B, 0xE0, 0x60, 0x0C, 0x90, 0x81, 0x4F, +0xE0, 0x20, 0xE4, 0x05, 0xF1, 0xB7, 0x12, 0x49, +0x00, 0x22, 0xE4, 0xFF, 0xF1, 0x72, 0xEF, 0x64, +0x01, 0x22, 0x12, 0x77, 0xB6, 0xF1, 0xC2, 0xE0, +0xFD, 0x7C, 0x00, 0x12, 0x6D, 0x55, 0x80, 0x05, +0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, +0xEE, 0x5C, 0xFE, 0xEF, 0x5D, 0x4E, 0x7F, 0x00, +0x60, 0x02, 0x7F, 0x01, 0x22, 0xF1, 0x6A, 0x70, +0x1D, 0x90, 0x81, 0x4B, 0xE0, 0x60, 0x17, 0x90, +0x81, 0x4F, 0xE0, 0x20, 0xE4, 0x10, 0xF1, 0xB7, +0xF0, 0x90, 0x81, 0x46, 0xE0, 0x12, 0x6F, 0x97, +0x54, 0x07, 0x70, 0x02, 0xF1, 0xE4, 0x22, 0x90, +0x01, 0x57, 0xE4, 0xF0, 0x90, 0x01, 0x3C, 0x74, +0x02, 0x22, 0x74, 0x38, 0x2E, 0xF5, 0x82, 0xE4, +0x34, 0x81, 0xF5, 0x83, 0x22, 0xE4, 0xFF, 0xF1, +0x72, 0xBF, 0x01, 0x0F, 0x90, 0x81, 0x4B, 0xE0, +0x60, 0x09, 0x12, 0x65, 0xA2, 0x54, 0x07, 0x70, +0x02, 0xF1, 0xE4, 0x22, 0x90, 0x81, 0x41, 0xE0, +0x90, 0x81, 0x4D, 0x30, 0xE0, 0x05, 0xE0, 0xFF, +0x02, 0x76, 0xBD, 0xE0, 0xFF, 0x7D, 0x01, 0x02, +0x4B, 0x1C, 0xC0, 0xE0, 0xC0, 0xF0, 0xC0, 0x83, +0xC0, 0x82, 0xC0, 0xD0, 0x75, 0xD0, 0x00, 0xC0, +0x00, 0xC0, 0x01, 0xC0, 0x02, 0xC0, 0x03, 0xC0, +0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0x90, +0x01, 0xC4, 0x74, 0xFA, 0xF0, 0x74, 0x47, 0xA3, +0xF0, 0x12, 0x6E, 0x8A, 0xE5, 0x49, 0x30, 0xE1, +0x02, 0x11, 0xA3, 0xE5, 0x49, 0x30, 0xE2, 0x03, +0x12, 0x70, 0x35, 0xE5, 0x4A, 0x30, 0xE0, 0x03, +0x12, 0x70, 0x91, 0xE5, 0x4A, 0x30, 0xE4, 0x03, +0x12, 0x72, 0x0B, 0xE5, 0x4B, 0x30, 0xE1, 0x03, +0x12, 0x6F, 0x19, 0xE5, 0x4B, 0x30, 0xE0, 0x03, +0x12, 0x72, 0x21, 0xE5, 0x4B, 0x30, 0xE4, 0x03, +0x12, 0x72, 0x69, 0xE5, 0x4C, 0x30, 0xE1, 0x05, +0x7F, 0x04, 0x12, 0x47, 0x45, 0xE5, 0x4C, 0x30, +0xE4, 0x03, 0x12, 0x72, 0x6A, 0xE5, 0x4C, 0x30, +0xE5, 0x03, 0x12, 0x73, 0x24, 0xE5, 0x4C, 0x30, +0xE6, 0x03, 0x12, 0x73, 0x58, 0x74, 0xFA, 0x04, +0x90, 0x01, 0xC4, 0xF0, 0x74, 0x47, 0xA3, 0xF0, +0xD0, 0x07, 0xD0, 0x06, 0xD0, 0x05, 0xD0, 0x04, +0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, +0xD0, 0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, +0xD0, 0xE0, 0x32, 0x90, 0x81, 0x4B, 0xE0, 0x60, +0x03, 0x12, 0x6F, 0xBA, 0x90, 0x81, 0xAF, 0xE0, +0x30, 0xE0, 0x49, 0xC4, 0x54, 0x0F, 0x20, 0xE0, +0x17, 0xE4, 0xF5, 0x1D, 0x90, 0x81, 0xB1, 0x31, +0x07, 0xB1, 0x0E, 0x12, 0x77, 0xC2, 0x30, 0xE0, +0x02, 0x31, 0xCD, 0x12, 0x57, 0x7A, 0xF0, 0x22, +0x90, 0x81, 0xAF, 0xE0, 0xC4, 0x54, 0x0F, 0x30, +0xE0, 0x22, 0xE4, 0xF5, 0x1D, 0x90, 0x81, 0xB2, +0x31, 0x07, 0x90, 0x81, 0xAF, 0xE0, 0x54, 0xEF, +0xF0, 0xE0, 0xC3, 0x13, 0x30, 0xE0, 0x06, 0x7D, +0x04, 0x7F, 0x01, 0x21, 0xD1, 0x7B, 0x31, 0xF1, +0x95, 0x12, 0x73, 0x88, 0x22, 0xE0, 0x44, 0x02, +0xF0, 0xE4, 0xF5, 0x1D, 0x90, 0x81, 0xA9, 0xE0, +0xF5, 0x1E, 0xE4, 0xFB, 0xFD, 0x7F, 0x54, 0x7E, +0x01, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x8E, 0x19, 0x8F, 0x1A, 0xE5, 0x1E, 0x31, 0x66, +0x85, 0x19, 0x83, 0x85, 0x1A, 0x82, 0xF0, 0xE5, +0x1D, 0x31, 0x66, 0xFF, 0xE5, 0x1E, 0x13, 0x13, +0x13, 0x54, 0x1F, 0x4F, 0xA3, 0xF0, 0xEB, 0x31, +0x66, 0xFF, 0xE5, 0x1D, 0x13, 0x13, 0x13, 0x54, +0x1F, 0x4F, 0x31, 0x6D, 0xF0, 0xBD, 0x01, 0x0D, +0x85, 0x1A, 0x82, 0x8E, 0x83, 0xA3, 0xA3, 0xA3, +0x74, 0x03, 0xF0, 0x80, 0x06, 0x31, 0x6D, 0xA3, +0x74, 0x01, 0xF0, 0x31, 0x6D, 0xA3, 0x74, 0x05, +0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x54, 0x07, +0xC4, 0x33, 0x54, 0xE0, 0x22, 0x85, 0x1A, 0x82, +0x85, 0x19, 0x83, 0xA3, 0xA3, 0x22, 0x90, 0x81, +0x4F, 0xE0, 0x44, 0x10, 0xF0, 0x90, 0x81, 0x54, +0xE0, 0x60, 0x04, 0x64, 0x01, 0x70, 0x11, 0xE4, +0xF5, 0x1D, 0x90, 0x81, 0x54, 0xE0, 0x31, 0xBA, +0x31, 0x08, 0x90, 0x81, 0x54, 0xE0, 0x80, 0x11, +0xE4, 0xF5, 0x1D, 0x31, 0xC1, 0xA4, 0x24, 0xFE, +0x31, 0xBA, 0x31, 0x08, 0x31, 0xC1, 0xA4, 0x24, +0xFE, 0x31, 0xBA, 0x90, 0x81, 0x64, 0xF0, 0x90, +0x81, 0x4E, 0xE0, 0x20, 0xE2, 0x03, 0x12, 0x77, +0xF3, 0x22, 0xFF, 0x90, 0x81, 0x53, 0xE0, 0x2F, +0x22, 0x90, 0x81, 0x54, 0xE0, 0x75, 0xF0, 0x03, +0x22, 0xE0, 0x54, 0x7F, 0xF0, 0x7D, 0x0C, 0x7F, +0x01, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0xAC, 0x07, 0xEF, 0x14, 0x60, 0x15, 0x14, 0x60, +0x19, 0x24, 0x02, 0x70, 0x1A, 0xED, 0x54, 0x01, +0xFE, 0x90, 0x81, 0x46, 0xE0, 0x54, 0xFE, 0x4E, +0xF0, 0x80, 0x0C, 0x90, 0x81, 0x4E, 0xED, 0xF0, +0x80, 0x05, 0x90, 0x81, 0x4D, 0xED, 0xF0, 0x90, +0x00, 0x8F, 0xE0, 0x30, 0xE4, 0x2E, 0xEC, 0x14, +0x60, 0x07, 0x14, 0x60, 0x1D, 0x24, 0x02, 0x70, +0x23, 0x90, 0x81, 0x46, 0xE0, 0x54, 0x01, 0xC4, +0x33, 0x33, 0x33, 0x54, 0x80, 0xFF, 0x90, 0x81, +0x4E, 0xE0, 0x54, 0x7F, 0x4F, 0xFD, 0x7F, 0x88, +0x80, 0x07, 0x90, 0x81, 0x4D, 0xE0, 0xFD, 0x7F, +0x89, 0x12, 0x32, 0x1E, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x7E, 0x00, 0x7F, 0x62, 0x7D, 0x00, 0x7B, +0x01, 0x7A, 0x81, 0x79, 0x46, 0x12, 0x45, 0x55, +0x12, 0x77, 0x9C, 0x12, 0x45, 0x55, 0x90, 0x81, +0x4A, 0x74, 0x02, 0xF0, 0x90, 0x81, 0x51, 0x14, +0xF0, 0xA3, 0xF0, 0xA3, 0x74, 0x10, 0xF0, 0x90, +0x81, 0x57, 0xE4, 0xF0, 0xA3, 0x74, 0x02, 0x51, +0xF3, 0xF0, 0xE4, 0xFD, 0xFF, 0x31, 0xD1, 0x7D, +0x0C, 0x7F, 0x02, 0x31, 0xD1, 0x31, 0xCD, 0x90, +0x80, 0x42, 0xE0, 0xFF, 0xB4, 0x01, 0x08, 0x90, +0x81, 0x56, 0x74, 0x99, 0xF0, 0x80, 0x29, 0xEF, +0xB4, 0x03, 0x08, 0x90, 0x81, 0x56, 0x74, 0x90, +0xF0, 0x80, 0x1D, 0x90, 0x81, 0x56, 0x74, 0x40, +0xF0, 0x90, 0x00, 0x2C, 0xE0, 0x54, 0x0F, 0xFF, +0xBF, 0x05, 0x08, 0x90, 0x81, 0x68, 0x74, 0x02, +0xF0, 0x80, 0x05, 0xE4, 0x90, 0x81, 0x68, 0xF0, +0x90, 0x81, 0xA8, 0x74, 0x02, 0xF0, 0xA3, 0x74, +0x0F, 0xF0, 0xA3, 0xE0, 0x54, 0x01, 0x44, 0x28, +0xF0, 0xA3, 0x74, 0x07, 0x51, 0xF3, 0xF0, 0x90, +0x05, 0x58, 0x74, 0x02, 0xF0, 0x7E, 0x00, 0xFF, +0x7D, 0x00, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0xAC, +0x12, 0x45, 0x55, 0x12, 0x77, 0xDB, 0x90, 0x06, +0x0A, 0xE0, 0x54, 0xF8, 0xF0, 0x7B, 0x56, 0xE4, +0xFD, 0x7F, 0xFF, 0xB1, 0x15, 0xE4, 0x90, 0x81, +0xAE, 0xF0, 0x22, 0xF0, 0x90, 0x81, 0x68, 0xE0, +0x24, 0x04, 0x90, 0x81, 0x63, 0xF0, 0xA3, 0x74, +0x10, 0x22, 0x90, 0x82, 0xAD, 0xEF, 0xF0, 0xB1, +0x70, 0x90, 0x82, 0xAD, 0xE0, 0x60, 0x02, 0xB1, +0x10, 0x7D, 0x04, 0xD1, 0x28, 0x74, 0x04, 0xF0, +0x22, 0xFD, 0x7F, 0x0C, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x90, 0x82, 0xAE, 0xED, 0xF0, +0x90, 0x81, 0x46, 0xE0, 0xFE, 0xC4, 0x13, 0x13, +0x54, 0x03, 0x30, 0xE0, 0x02, 0x81, 0x62, 0xEE, +0x12, 0x67, 0xD3, 0x30, 0xE0, 0x02, 0x81, 0x62, +0x90, 0x81, 0x4E, 0xE0, 0xFE, 0x6F, 0x70, 0x02, +0x81, 0x62, 0xEF, 0x70, 0x02, 0x61, 0xD8, 0x24, +0xFE, 0x70, 0x02, 0x81, 0x11, 0x24, 0xFE, 0x60, +0x47, 0x24, 0xFC, 0x70, 0x02, 0x81, 0x4C, 0x24, +0xFC, 0x60, 0x02, 0x81, 0x5B, 0xEE, 0xB4, 0x0E, +0x02, 0x91, 0xE5, 0x90, 0x81, 0x4E, 0xE0, 0x70, +0x04, 0x7F, 0x01, 0x71, 0x02, 0x90, 0x81, 0x4E, +0xE0, 0xB4, 0x06, 0x02, 0x91, 0xBE, 0x90, 0x81, +0x4E, 0xE0, 0xB4, 0x04, 0x0D, 0x90, 0x82, 0xAE, +0xE0, 0xFF, 0x60, 0x04, 0xB1, 0xEF, 0x80, 0x02, +0xB1, 0x5A, 0x90, 0x81, 0x4E, 0xE0, 0x64, 0x08, +0x60, 0x02, 0x81, 0x5B, 0xB1, 0x65, 0x81, 0x5B, +0x90, 0x81, 0x4E, 0xE0, 0x70, 0x04, 0x7F, 0x01, +0x71, 0x02, 0x90, 0x81, 0x4E, 0xE0, 0xB4, 0x06, +0x02, 0x91, 0xBE, 0x90, 0x81, 0x4E, 0xE0, 0xB4, +0x0E, 0x07, 0x91, 0x67, 0xBF, 0x01, 0x02, 0x91, +0xE5, 0x90, 0x81, 0x4E, 0xE0, 0x64, 0x0C, 0x60, +0x02, 0x81, 0x5B, 0x91, 0x67, 0xEF, 0x64, 0x01, +0x60, 0x02, 0x81, 0x5B, 0xB1, 0x2B, 0x81, 0x5B, +0x90, 0x81, 0x4E, 0xE0, 0xB4, 0x0E, 0x07, 0x91, +0x67, 0xBF, 0x01, 0x02, 0x91, 0xE5, 0x90, 0x81, +0x4E, 0xE0, 0xB4, 0x06, 0x02, 0x91, 0xBE, 0x90, +0x81, 0x4E, 0xE0, 0xB4, 0x0C, 0x07, 0x91, 0x67, +0xBF, 0x01, 0x02, 0xB1, 0x2B, 0x90, 0x81, 0x4E, +0xE0, 0x64, 0x04, 0x70, 0x56, 0x12, 0x75, 0x3F, +0xEF, 0x64, 0x01, 0x70, 0x4E, 0xF1, 0xC9, 0x80, +0x4A, 0x90, 0x81, 0x4E, 0xE0, 0xB4, 0x0E, 0x07, +0x91, 0x67, 0xBF, 0x01, 0x02, 0x91, 0xE5, 0x90, +0x81, 0x4E, 0xE0, 0xB4, 0x06, 0x02, 0x91, 0xBE, +0x90, 0x81, 0x4E, 0xE0, 0xB4, 0x0C, 0x07, 0x91, +0x67, 0xBF, 0x01, 0x02, 0xB1, 0x2B, 0x90, 0x81, +0x4E, 0xE0, 0x70, 0x04, 0x7F, 0x01, 0x71, 0x02, +0x90, 0x81, 0x4E, 0xE0, 0xB4, 0x04, 0x14, 0x12, +0x75, 0xFB, 0x80, 0x0F, 0x90, 0x81, 0x4E, 0xE0, +0xB4, 0x0C, 0x08, 0x12, 0x6F, 0x8C, 0x30, 0xE0, +0x02, 0xD1, 0x30, 0x90, 0x81, 0x4E, 0x12, 0x77, +0xA9, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x75, +0x26, 0xEF, 0x64, 0x01, 0x60, 0x05, 0x75, 0x1F, +0x01, 0x80, 0x30, 0x12, 0x70, 0x87, 0x30, 0xE0, +0x05, 0x75, 0x1F, 0x02, 0x80, 0x25, 0x90, 0x81, +0x4D, 0xE0, 0xD3, 0x94, 0x04, 0x40, 0x05, 0x75, +0x1F, 0x08, 0x80, 0x17, 0x90, 0x81, 0xAF, 0xE0, +0x30, 0xE0, 0x0B, 0xC4, 0x54, 0x0F, 0x30, 0xE0, +0x05, 0x75, 0x1F, 0x11, 0x80, 0x05, 0x12, 0x5F, +0xC0, 0x80, 0x0E, 0x90, 0x01, 0xB9, 0x74, 0x02, +0xF0, 0x90, 0x01, 0xB8, 0xE5, 0x1F, 0xF0, 0x7F, +0x00, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x81, +0x47, 0xE0, 0x90, 0x06, 0x04, 0x20, 0xE0, 0x07, +0xE0, 0x44, 0x40, 0xF1, 0x9B, 0x80, 0x0F, 0x31, +0xC9, 0x90, 0x05, 0x27, 0xE0, 0x54, 0x7F, 0xF0, +0x90, 0x81, 0x45, 0x74, 0x0C, 0xF0, 0xE4, 0xFB, +0xFD, 0x7F, 0xFF, 0x80, 0x30, 0x90, 0x81, 0x47, +0xE0, 0xC3, 0x13, 0x20, 0xE0, 0x04, 0x31, 0xCD, +0x80, 0x15, 0x12, 0x77, 0xE3, 0xE0, 0x44, 0x80, +0xF1, 0x9B, 0x90, 0x05, 0x27, 0xE0, 0x44, 0x80, +0xF0, 0x90, 0x81, 0x45, 0x74, 0x04, 0xF0, 0xE4, +0xFB, 0xFD, 0x7F, 0xFF, 0x80, 0x07, 0xB1, 0x70, +0xE4, 0xFB, 0xFD, 0x7F, 0xFF, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x05, 0x22, 0xED, +0xF0, 0x90, 0x80, 0x40, 0xEB, 0xF0, 0xD0, 0xD0, +0x92, 0xAF, 0x22, 0x12, 0x47, 0x6A, 0x70, 0x29, +0x90, 0x81, 0x47, 0xE0, 0x54, 0xFD, 0xF0, 0x7B, +0x2C, 0x12, 0x76, 0x0F, 0x7D, 0x08, 0x7F, 0x01, +0xD1, 0xC0, 0xBF, 0x01, 0x0F, 0x90, 0x81, 0x46, +0xE0, 0x44, 0x80, 0xF0, 0x7D, 0x0E, 0xD1, 0x28, +0x74, 0x0E, 0xF0, 0x22, 0x12, 0x73, 0x4E, 0x04, +0xF0, 0x22, 0x12, 0x77, 0xDB, 0xB1, 0x10, 0x7D, +0x0C, 0x7F, 0x01, 0x21, 0xD1, 0xB1, 0x0E, 0x31, +0xCD, 0x90, 0x81, 0x45, 0x74, 0x0C, 0xF0, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, +0x01, 0x01, 0xE0, 0x44, 0x02, 0xF0, 0x90, 0x01, +0x00, 0x74, 0xFF, 0xF0, 0x90, 0x06, 0xB7, 0x74, +0x09, 0xF0, 0x90, 0x06, 0xB4, 0x74, 0x86, 0xF0, +0x12, 0x74, 0xB4, 0xEC, 0x54, 0x7F, 0xFC, 0x90, +0x82, 0x96, 0x12, 0x20, 0xCE, 0x90, 0x82, 0x96, +0x12, 0x44, 0xE0, 0x12, 0x5E, 0xAB, 0x7F, 0x7C, +0xF1, 0xA9, 0x12, 0x20, 0xDA, 0xCC, 0xC0, 0x00, +0xC0, 0x7F, 0x8C, 0xF1, 0xA9, 0x12, 0x20, 0xDA, +0x00, 0xC0, 0x00, 0x14, 0x12, 0x74, 0xBB, 0x90, +0x82, 0x7F, 0x12, 0x20, 0xDA, 0x00, 0x03, 0x3E, +0x60, 0xE4, 0xFD, 0xFF, 0x12, 0x5F, 0x36, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x90, 0x81, 0xAF, 0xE0, +0x30, 0xE0, 0x13, 0x90, 0x01, 0x57, 0xE4, 0xF0, +0xB1, 0x0E, 0x12, 0x77, 0xC2, 0x30, 0xE0, 0x02, +0x31, 0xCD, 0x12, 0x57, 0x7A, 0xF0, 0x22, 0xEF, +0x60, 0x35, 0x12, 0x47, 0x6A, 0x70, 0x30, 0x90, +0x81, 0x47, 0xE0, 0x54, 0xFE, 0xF0, 0x7B, 0x2B, +0x7D, 0x0F, 0x7F, 0xFF, 0xB1, 0x15, 0x90, 0x06, +0x04, 0xE0, 0x54, 0xBF, 0xF0, 0xD1, 0xBC, 0xBF, +0x01, 0x0F, 0x90, 0x81, 0x46, 0xE0, 0x44, 0x40, +0xF0, 0x7D, 0x06, 0xD1, 0x28, 0x74, 0x06, 0xF0, +0x22, 0x12, 0x73, 0x4E, 0x74, 0x08, 0xF0, 0x22, +0x7F, 0x01, 0x31, 0xD1, 0x90, 0x81, 0x45, 0x22, +0x7B, 0x2F, 0xF1, 0x95, 0x12, 0x73, 0x88, 0x7D, +0x08, 0xD1, 0x28, 0x74, 0x08, 0xF0, 0x22, 0xEF, +0x70, 0x3E, 0x7D, 0x78, 0x7F, 0x02, 0x12, 0x54, +0x7F, 0x7D, 0x02, 0x7F, 0x03, 0x12, 0x54, 0x7F, +0x7D, 0xC8, 0x7F, 0x02, 0x12, 0x54, 0xD4, 0x12, +0x47, 0xB7, 0xF0, 0xE4, 0xFF, 0x12, 0x47, 0x72, +0xEF, 0x70, 0x0C, 0xB1, 0x70, 0xB1, 0x5A, 0x12, +0x77, 0xEB, 0x54, 0x7F, 0xF0, 0x80, 0x06, 0x7D, +0x01, 0x7F, 0x0C, 0x71, 0x1C, 0x12, 0x70, 0x7F, +0x90, 0x06, 0x0A, 0xE0, 0x54, 0xF8, 0xF0, 0x22, +0x90, 0x01, 0x36, 0x74, 0x78, 0xF0, 0xA3, 0x74, +0x02, 0xF0, 0x7D, 0x78, 0xFF, 0xF1, 0xBC, 0x7D, +0x02, 0x7F, 0x03, 0xF1, 0xBC, 0x90, 0x06, 0x0A, +0xE0, 0x44, 0x07, 0x12, 0x71, 0xAE, 0xE4, 0xFF, +0x12, 0x47, 0x72, 0xBF, 0x01, 0x11, 0x12, 0x6F, +0x85, 0xF0, 0x90, 0x81, 0x4E, 0xE0, 0x20, 0xE2, +0x0A, 0x7D, 0x01, 0x7F, 0x04, 0x61, 0x1C, 0x12, +0x56, 0x16, 0xF0, 0x22, 0x7D, 0x08, 0xE4, 0xFF, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, +0x82, 0x89, 0xEF, 0xF0, 0xA3, 0xED, 0xF0, 0x90, +0x80, 0x3E, 0xE0, 0x04, 0xF0, 0x90, 0x04, 0x1D, +0xE0, 0x60, 0x2C, 0x90, 0x05, 0x22, 0xE0, 0x90, +0x82, 0x8D, 0xF0, 0x7B, 0x26, 0x12, 0x67, 0xDA, +0x12, 0x74, 0x49, 0xEF, 0x64, 0x01, 0x70, 0x03, +0x12, 0x76, 0xE1, 0x90, 0x82, 0x8D, 0xE0, 0xFD, +0x7B, 0x27, 0xE4, 0xFF, 0xB1, 0x15, 0x90, 0x82, +0x89, 0xE0, 0xFF, 0xF1, 0x1B, 0x80, 0x0A, 0x90, +0x82, 0x89, 0xE0, 0xFF, 0xF1, 0x1B, 0x12, 0x76, +0xE1, 0x12, 0x67, 0x50, 0x7F, 0x01, 0xD0, 0xD0, +0x92, 0xAF, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x82, 0xB0, 0xEF, 0xF0, 0xC3, +0x94, 0x02, 0x50, 0x48, 0x90, 0x80, 0x46, 0xE0, +0xFF, 0x90, 0x04, 0x1C, 0xE0, 0x6F, 0x70, 0x3C, +0x90, 0x81, 0x4E, 0xE0, 0x64, 0x0E, 0x70, 0x14, +0x90, 0x82, 0xB0, 0xE0, 0x70, 0x2E, 0x90, 0x81, +0x46, 0xE0, 0x54, 0x7F, 0xF0, 0x90, 0x06, 0x04, +0x31, 0xC9, 0x80, 0x1E, 0x90, 0x81, 0x4E, 0xE0, +0x64, 0x06, 0x70, 0x18, 0x90, 0x82, 0xB0, 0xE0, +0x60, 0x12, 0x12, 0x77, 0xEB, 0x12, 0x77, 0xE3, +0xE0, 0x44, 0x80, 0xF0, 0x90, 0x81, 0x4E, 0x74, +0x04, 0xF0, 0xB1, 0x10, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x12, 0x70, 0x4A, 0x90, 0x81, 0x4E, 0xE0, +0x64, 0x0C, 0x60, 0x07, 0xE4, 0x71, 0x19, 0xB1, +0x10, 0xD1, 0xBC, 0x22, 0xB1, 0x0E, 0x90, 0x81, +0x44, 0x74, 0x01, 0xF0, 0x22, 0x7D, 0xFF, 0x7F, +0xFF, 0xA1, 0x15, 0xF0, 0x7D, 0x04, 0x7F, 0x01, +0x21, 0xD1, 0xB1, 0x10, 0x12, 0x74, 0xC2, 0x80, +0xE5, 0x7E, 0x08, 0x12, 0x2E, 0xA2, 0x90, 0x85, +0xBB, 0x22, 0x7D, 0x01, 0x7F, 0x02, 0xF1, 0xBC, +0x7D, 0x02, 0x7F, 0x02, 0x74, 0x3D, 0x2F, 0xF8, +0xE6, 0x4D, 0xFE, 0xF6, 0x74, 0x30, 0x02, 0x54, +0x6A, 0x7B, 0x2D, 0xF1, 0x95, 0x12, 0x74, 0x49, +0x90, 0x01, 0x37, 0x74, 0x02, 0xF0, 0xFD, 0x7F, +0x03, 0xF1, 0xBC, 0x12, 0x73, 0x88, 0xE4, 0xFD, +0x7F, 0x01, 0x31, 0xD1, 0xE4, 0x90, 0x81, 0x45, +0xF0, 0x22, 0x7B, 0x1F, 0x7D, 0x6F, 0x7F, 0xFF, +0xB1, 0x15, 0x90, 0x05, 0x27, 0xE0, 0x54, 0xBF, +0xF0, 0x90, 0x81, 0x44, 0x74, 0x04, 0xF0, 0x22, +0x90, 0x01, 0xC8, 0xE4, 0xF0, 0xA3, 0xF0, 0xA3, +0xF0, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0xC8, 0x7F, +0xFF, 0xFE, 0x12, 0x2B, 0x27, 0xBF, 0x01, 0x0A, +0x90, 0x81, 0xC8, 0xE0, 0x64, 0x03, 0x60, 0x04, +0x01, 0xB1, 0x01, 0xB9, 0xE4, 0x90, 0x81, 0xCD, +0xF0, 0x90, 0x81, 0xCD, 0xE0, 0xFF, 0xC3, 0x94, +0x02, 0x40, 0x02, 0x01, 0xF4, 0xC3, 0x74, 0xFE, +0x9F, 0xFF, 0xE4, 0x94, 0x00, 0xFE, 0x7B, 0x01, +0x7A, 0x81, 0x79, 0xC9, 0x12, 0x2B, 0x27, 0xEF, +0x64, 0x01, 0x70, 0x6D, 0x90, 0x81, 0xC9, 0xE0, +0xFF, 0x54, 0xC0, 0xFE, 0x60, 0x05, 0xEF, 0x54, +0x0C, 0x70, 0x16, 0x90, 0x81, 0xC9, 0xE0, 0xFF, +0x54, 0x30, 0x60, 0x5D, 0xEF, 0x54, 0x03, 0x60, +0x58, 0x90, 0x81, 0xCA, 0x74, 0x01, 0xF0, 0x80, +0x05, 0xE4, 0x90, 0x81, 0xCA, 0xF0, 0x90, 0x81, +0xCA, 0xE0, 0x90, 0x81, 0xC9, 0x70, 0x16, 0xE0, +0xFF, 0xEE, 0x13, 0x13, 0x54, 0x3F, 0x90, 0x81, +0xCB, 0xF0, 0xEF, 0x54, 0x0C, 0x13, 0x13, 0x54, +0x3F, 0xA3, 0xF0, 0x80, 0x0D, 0xE0, 0xFE, 0x54, +0x30, 0x90, 0x81, 0xCB, 0xF0, 0xEE, 0x54, 0x03, +0xA3, 0xF0, 0x90, 0x81, 0xCC, 0xE0, 0xB4, 0x01, +0x08, 0x90, 0x81, 0xCB, 0xE0, 0x64, 0x30, 0x60, +0x43, 0x90, 0x81, 0xCF, 0x74, 0x02, 0xF0, 0x80, +0x10, 0x90, 0x81, 0xCF, 0x74, 0x01, 0xF0, 0x80, +0x08, 0x90, 0x81, 0xCD, 0xE0, 0x04, 0xF0, 0x01, +0x29, 0x90, 0x01, 0xC4, 0x74, 0x00, 0xF0, 0x74, +0x50, 0xA3, 0xF0, 0x90, 0x81, 0xCF, 0xE0, 0x90, +0x01, 0xC8, 0xF0, 0x90, 0x81, 0xC9, 0xE0, 0x90, +0x01, 0xC9, 0xF0, 0x90, 0x81, 0xCA, 0xE0, 0x90, +0x01, 0xCA, 0xF0, 0xE4, 0xFD, 0x7F, 0x1F, 0x12, +0x32, 0x1E, 0x80, 0xD5, 0x22, 0x90, 0x00, 0x80, +0xE0, 0x44, 0x80, 0xFD, 0x7F, 0x80, 0x12, 0x32, +0x1E, 0x90, 0xFD, 0x00, 0xE0, 0x54, 0xBF, 0xF0, +0x11, 0x00, 0x12, 0x6D, 0xEF, 0x12, 0x32, 0x77, +0x12, 0x6D, 0xFC, 0x31, 0x52, 0x7F, 0x01, 0x12, +0x42, 0x15, 0x90, 0x81, 0xBB, 0x74, 0x02, 0xF0, +0xFF, 0x12, 0x42, 0x15, 0x90, 0x81, 0xBB, 0xE0, +0x04, 0xF0, 0x12, 0x58, 0x0A, 0x31, 0x63, 0x90, +0x01, 0xCC, 0x74, 0x0F, 0xF0, 0x90, 0x00, 0x80, +0xE0, 0x44, 0x40, 0xFD, 0x7F, 0x80, 0x12, 0x32, +0x1E, 0x75, 0x20, 0xFF, 0x12, 0x59, 0x2F, 0x12, +0x5F, 0x67, 0x12, 0x6E, 0x53, 0xE4, 0xFF, 0x02, +0x42, 0x9E, 0xE4, 0x90, 0x80, 0x3C, 0x31, 0x5B, +0xA3, 0xF0, 0x22, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, +0xA3, 0xF0, 0x22, 0x31, 0x76, 0x12, 0x6C, 0x9C, +0x31, 0xB8, 0x12, 0x4A, 0x39, 0x12, 0x76, 0x63, +0x12, 0x77, 0x9C, 0x02, 0x45, 0x55, 0xE4, 0xFD, +0xFF, 0x12, 0x77, 0xB6, 0xED, 0x70, 0x13, 0x12, +0x47, 0xC2, 0xC0, 0x83, 0xC0, 0x82, 0x31, 0xB0, +0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xF4, 0x5E, +0x80, 0x10, 0x12, 0x47, 0xC2, 0xC0, 0x83, 0xC0, +0x82, 0x31, 0xB0, 0x80, 0x02, 0xC3, 0x33, 0xD8, +0xFC, 0x4E, 0xD0, 0x82, 0xD0, 0x83, 0xF0, 0x12, +0x6C, 0xFC, 0x90, 0x81, 0x40, 0xEF, 0xF0, 0x22, +0xE0, 0xFE, 0x74, 0x01, 0xA8, 0x07, 0x08, 0x22, +0x7E, 0x00, 0x7F, 0x01, 0x7D, 0x00, 0x7B, 0x01, +0x7A, 0x81, 0x79, 0x41, 0x12, 0x45, 0x55, 0x90, +0x81, 0x41, 0xE0, 0x54, 0xFD, 0xF0, 0xE4, 0x31, +0x5C, 0xA3, 0x74, 0x0C, 0xF0, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x8B, 0x54, 0x8A, +0x55, 0x89, 0x56, 0x90, 0x05, 0x27, 0xE0, 0xF5, +0x57, 0x8B, 0x13, 0x8A, 0x14, 0x89, 0x15, 0x75, +0x16, 0x01, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0x41, +0x12, 0x2B, 0xED, 0x12, 0x77, 0xD2, 0xFF, 0xC3, +0x13, 0x20, 0xE0, 0x02, 0x41, 0x94, 0x90, 0x81, +0x41, 0xE0, 0x30, 0xE0, 0x73, 0x91, 0x5C, 0x75, +0x57, 0x21, 0x90, 0x81, 0x41, 0xE0, 0x13, 0x13, +0x54, 0x3F, 0x30, 0xE0, 0x07, 0x91, 0x50, 0x43, +0x57, 0x08, 0x80, 0x0C, 0xE4, 0x90, 0x81, 0x42, +0xF0, 0xA3, 0xF0, 0x7D, 0x40, 0xFF, 0x91, 0x7F, +0x90, 0x81, 0x41, 0x91, 0x31, 0x30, 0xE0, 0x03, +0x43, 0x57, 0x12, 0xEF, 0xC4, 0x54, 0x0F, 0x30, +0xE0, 0x03, 0x43, 0x57, 0x14, 0x90, 0x81, 0x41, +0xE0, 0xC4, 0x13, 0x54, 0x07, 0x30, 0xE0, 0x03, +0x43, 0x57, 0x80, 0x12, 0x76, 0xD7, 0x20, 0xE0, +0x03, 0x43, 0x57, 0x40, 0x71, 0x41, 0x90, 0x81, +0x44, 0xE0, 0x70, 0x04, 0x7F, 0x01, 0x71, 0x48, +0x91, 0x39, 0x30, 0xE0, 0x04, 0x7F, 0x04, 0x80, +0x0B, 0x91, 0x44, 0xEF, 0x60, 0x04, 0x7F, 0x01, +0x80, 0x02, 0x7F, 0x02, 0x71, 0x48, 0x61, 0x09, +0x75, 0x57, 0x01, 0x71, 0x41, 0x90, 0x81, 0x44, +0xE0, 0x64, 0x04, 0x60, 0x02, 0x61, 0x3C, 0xFF, +0x71, 0x48, 0x61, 0x3C, 0x90, 0x81, 0x41, 0xE0, +0x30, 0xE0, 0x76, 0x91, 0x5C, 0x43, 0x57, 0x31, +0x90, 0x81, 0x41, 0xE0, 0x13, 0x13, 0x54, 0x3F, +0x30, 0xE0, 0x07, 0x91, 0x50, 0x43, 0x57, 0x08, +0x80, 0x06, 0x7D, 0x40, 0xE4, 0xFF, 0x91, 0x7F, +0x90, 0x81, 0x41, 0x91, 0x31, 0x30, 0xE0, 0x03, +0x43, 0x57, 0x02, 0xEF, 0xC4, 0x54, 0x0F, 0x30, +0xE0, 0x03, 0x43, 0x57, 0x04, 0x71, 0x41, 0x91, +0x39, 0x30, 0xE0, 0x0A, 0xF1, 0x5B, 0x60, 0x31, +0xE4, 0xFD, 0x7F, 0x02, 0x80, 0x1E, 0x12, 0x74, +0xC2, 0x90, 0x81, 0x45, 0xE0, 0xB4, 0x02, 0x19, +0x12, 0x74, 0xD4, 0x91, 0x44, 0xBF, 0x01, 0x09, +0x90, 0x81, 0x4D, 0xE0, 0xFF, 0x7D, 0x01, 0x80, +0x03, 0xE4, 0xFD, 0xFF, 0x12, 0x4B, 0x1C, 0x80, +0x08, 0x90, 0x81, 0x4E, 0xE0, 0x90, 0x81, 0x45, +0xF0, 0x90, 0x05, 0x40, 0x74, 0x22, 0xF0, 0x80, +0x2B, 0x75, 0x57, 0x01, 0x71, 0x41, 0x90, 0x81, +0x45, 0xE0, 0xB4, 0x02, 0x06, 0x7D, 0x01, 0x7F, +0x04, 0x80, 0x0B, 0x90, 0x81, 0x45, 0xE0, 0xB4, +0x08, 0x07, 0x7D, 0x01, 0x7F, 0x0C, 0x12, 0x4B, +0x1C, 0x12, 0x75, 0xA7, 0x90, 0x81, 0x4D, 0x12, +0x47, 0xF3, 0x31, 0xB8, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x90, 0x05, 0x27, 0xE5, 0x57, 0xF0, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, +0x81, 0x44, 0xE0, 0xF5, 0x5A, 0xE5, 0x5A, 0x6F, +0x70, 0x02, 0x81, 0x29, 0xEF, 0x14, 0x60, 0x38, +0x14, 0x60, 0x5A, 0x14, 0x60, 0x7B, 0x14, 0x70, +0x02, 0x81, 0x05, 0x24, 0x04, 0x60, 0x02, 0x81, +0x29, 0xE5, 0x5A, 0xB4, 0x04, 0x04, 0xF1, 0xC0, +0x81, 0x29, 0xE5, 0x5A, 0xB4, 0x02, 0x04, 0xF1, +0xC5, 0x81, 0x29, 0xE5, 0x5A, 0xB4, 0x03, 0x04, +0xF1, 0xCA, 0x81, 0x29, 0xE5, 0x5A, 0x64, 0x01, +0x60, 0x02, 0x81, 0x29, 0xF1, 0xB7, 0x81, 0x29, +0xE5, 0x5A, 0xB4, 0x04, 0x05, 0x12, 0x4F, 0xA2, +0x81, 0x29, 0xE5, 0x5A, 0xB4, 0x02, 0x05, 0x12, +0x4F, 0x8C, 0x80, 0x7D, 0xE5, 0x5A, 0xB4, 0x03, +0x04, 0xF1, 0xCE, 0x80, 0x74, 0xE5, 0x5A, 0x70, +0x70, 0xF1, 0x97, 0x80, 0x6C, 0xE5, 0x5A, 0xB4, +0x04, 0x05, 0x12, 0x74, 0x3D, 0x80, 0x62, 0xE5, +0x5A, 0xB4, 0x01, 0x04, 0xF1, 0xA1, 0x80, 0x59, +0xE5, 0x5A, 0xB4, 0x03, 0x04, 0xF1, 0xDD, 0x80, +0x50, 0xE5, 0x5A, 0x70, 0x4C, 0xF1, 0x9F, 0x80, +0x48, 0xE5, 0x5A, 0xB4, 0x04, 0x05, 0x12, 0x74, +0xCA, 0x80, 0x3E, 0xE5, 0x5A, 0xB4, 0x01, 0x04, +0xF1, 0x87, 0x80, 0x35, 0xE5, 0x5A, 0xB4, 0x02, +0x04, 0xF1, 0xAA, 0x80, 0x2C, 0xE5, 0x5A, 0x70, +0x28, 0xF1, 0x93, 0x80, 0x24, 0xE5, 0x5A, 0xB4, +0x03, 0x05, 0x12, 0x76, 0xB8, 0x80, 0x1A, 0xE5, +0x5A, 0xB4, 0x01, 0x05, 0x12, 0x4F, 0xEA, 0x80, +0x10, 0xE5, 0x5A, 0xB4, 0x02, 0x05, 0x12, 0x76, +0xB0, 0x80, 0x06, 0xE5, 0x5A, 0x70, 0x02, 0xF1, +0x9A, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x81, +0x47, 0xE0, 0xFF, 0x13, 0x13, 0x13, 0x54, 0x1F, +0x22, 0x90, 0x81, 0x41, 0xE0, 0xFF, 0xC4, 0x13, +0x13, 0x54, 0x03, 0x22, 0x90, 0x05, 0x43, 0xE0, +0x7F, 0x00, 0x30, 0xE7, 0x02, 0x7F, 0x01, 0x22, +0x90, 0x01, 0x34, 0x74, 0x40, 0xF0, 0xFD, 0xE4, +0xFF, 0x02, 0x4F, 0xBC, 0x7D, 0x03, 0x7F, 0x02, +0x74, 0x45, 0x2F, 0xF8, 0xE6, 0x4D, 0xFE, 0xF6, +0x74, 0x38, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x01, +0xF5, 0x83, 0xEE, 0xF0, 0x22, 0x7D, 0x02, 0x7F, +0x02, 0x91, 0x7F, 0x7D, 0x01, 0x7F, 0x02, 0x74, +0x3D, 0xF1, 0xAF, 0xFE, 0xF6, 0x74, 0x30, 0x80, +0xE1, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0xB1, 0xC4, 0xEF, 0x64, 0x01, 0x70, 0x1B, 0x90, +0x81, 0xB9, 0xE0, 0x7D, 0x10, 0x7F, 0x03, 0x60, +0x08, 0x91, 0x60, 0x12, 0x72, 0xD5, 0xF0, 0x80, +0x04, 0x91, 0xD4, 0x91, 0x75, 0x12, 0x4E, 0x30, +0x80, 0x1D, 0x90, 0x81, 0xB9, 0xE0, 0x7D, 0x10, +0x7F, 0x03, 0x60, 0x04, 0x91, 0x60, 0x80, 0x02, +0x91, 0xD4, 0x12, 0x4F, 0xB8, 0x7D, 0x01, 0x7F, +0x02, 0x12, 0x4F, 0xBC, 0x12, 0x4D, 0x65, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x74, 0x45, 0xF1, 0xAF, +0x80, 0x8C, 0x90, 0x05, 0x62, 0xE0, 0xFE, 0x90, +0x05, 0x61, 0xE0, 0xFD, 0xED, 0x78, 0x02, 0xCE, +0xC3, 0x13, 0xCE, 0x13, 0xD8, 0xF9, 0xFF, 0x90, +0x81, 0xBF, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x12, +0x47, 0x6A, 0x60, 0x02, 0xA1, 0xB7, 0x90, 0x81, +0x4B, 0xE0, 0x70, 0x02, 0xA1, 0xB7, 0x90, 0x81, +0x49, 0xE0, 0xFF, 0xC4, 0x54, 0x0F, 0x64, 0x01, +0x70, 0x22, 0x90, 0x06, 0xAB, 0xE0, 0x90, 0x81, +0x52, 0xF0, 0x90, 0x06, 0xAA, 0xE0, 0x90, 0x81, +0x51, 0xF0, 0xA3, 0xE0, 0xFF, 0x70, 0x08, 0x90, +0x81, 0x51, 0xE0, 0xFE, 0xFF, 0x80, 0x00, 0x90, +0x81, 0x52, 0xEF, 0xF0, 0xE4, 0x90, 0x81, 0x54, +0xF0, 0xA3, 0x12, 0x71, 0xAE, 0x12, 0x47, 0xB7, +0x12, 0x6F, 0x99, 0x54, 0xEF, 0xF0, 0x90, 0x81, +0x41, 0xE0, 0x30, 0xE0, 0x05, 0x12, 0x65, 0x39, +0x80, 0x03, 0x12, 0x65, 0xAA, 0x91, 0x2E, 0x30, +0xE0, 0x5A, 0xEF, 0xC4, 0x13, 0x13, 0x54, 0x03, +0x20, 0xE0, 0x23, 0xD1, 0x1D, 0x6F, 0x70, 0x4C, +0x90, 0x81, 0x47, 0xE0, 0x44, 0x40, 0xF0, 0x12, +0x72, 0xDD, 0xF0, 0xB1, 0xC4, 0xFD, 0x7F, 0x03, +0x91, 0x60, 0x91, 0x7B, 0xF1, 0x81, 0x90, 0x81, +0x52, 0xE0, 0x14, 0xF0, 0x80, 0x2E, 0x90, 0x81, +0x49, 0xE0, 0xC4, 0x54, 0x0F, 0x64, 0x01, 0x70, +0x23, 0xD1, 0x1D, 0xFE, 0x6F, 0x60, 0x1D, 0x90, +0x05, 0x73, 0xE0, 0xFF, 0xEE, 0x6F, 0x60, 0x14, +0x12, 0x6F, 0x8C, 0x30, 0xE0, 0x0E, 0xEF, 0x54, +0xBF, 0xF0, 0xB1, 0xC4, 0xFD, 0x7F, 0x03, 0x91, +0xD4, 0x12, 0x4F, 0xB2, 0xD1, 0x16, 0xF0, 0x90, +0x81, 0x41, 0xE0, 0xC3, 0x13, 0x20, 0xE0, 0x03, +0xD1, 0x16, 0xF0, 0x22, 0x90, 0x01, 0x3F, 0x74, +0x10, 0xF0, 0x22, 0x90, 0x81, 0x41, 0xE0, 0x30, +0xE0, 0x06, 0x90, 0x81, 0x43, 0x74, 0x01, 0xF0, +0x90, 0x81, 0x4B, 0xE0, 0x60, 0x25, 0x91, 0x2E, +0x30, 0xE0, 0x09, 0x90, 0x01, 0x3B, 0xE0, 0x30, +0xE4, 0x02, 0x91, 0x75, 0x90, 0x82, 0xAB, 0xE0, +0x04, 0xF0, 0xE0, 0xC3, 0x94, 0x80, 0x40, 0x0B, +0x90, 0x01, 0x98, 0xE0, 0x54, 0xFE, 0xF0, 0xE0, +0x44, 0x01, 0xF0, 0xD1, 0x25, 0x90, 0x81, 0xB7, +0xE0, 0x30, 0xE0, 0x09, 0x90, 0x01, 0x3B, 0xE0, +0x30, 0xE4, 0x02, 0x91, 0x75, 0x22, 0x90, 0x81, +0x47, 0xE0, 0x44, 0x04, 0x22, 0x90, 0x81, 0x51, +0xE0, 0xFF, 0xA3, 0xE0, 0x22, 0x90, 0x81, 0xAF, +0xE0, 0x30, 0xE0, 0x0C, 0xE4, 0xF5, 0x1D, 0x90, +0x81, 0xB1, 0x12, 0x49, 0x07, 0xF1, 0x7A, 0xF0, +0x90, 0x80, 0x42, 0xE0, 0xB4, 0x01, 0x13, 0x90, +0x81, 0xAF, 0x91, 0x31, 0x20, 0xE0, 0x0B, 0xEF, +0xC4, 0x13, 0x54, 0x07, 0x30, 0xE0, 0x03, 0x12, +0x76, 0x74, 0x22, 0x12, 0x77, 0xC9, 0xFF, 0x54, +0x01, 0xFE, 0x90, 0x81, 0xAF, 0xF1, 0xE1, 0xFF, +0xF0, 0x12, 0x1F, 0xA4, 0xFE, 0x54, 0x04, 0xFD, +0xEF, 0x54, 0xFB, 0x4D, 0xFF, 0x90, 0x81, 0xAF, +0xF0, 0xEE, 0x54, 0x08, 0xFE, 0xEF, 0x54, 0xF7, +0x4E, 0xFF, 0xF0, 0x12, 0x1F, 0xA4, 0x54, 0x10, +0x25, 0xE0, 0x25, 0xE0, 0xFE, 0xEF, 0x54, 0xBF, +0x4E, 0x90, 0x81, 0xAF, 0xF0, 0x90, 0x05, 0x52, +0xE0, 0x54, 0x07, 0xFF, 0x90, 0x82, 0x3B, 0x60, +0x15, 0x12, 0x45, 0x1D, 0xF1, 0x31, 0xFD, 0x90, +0x05, 0x56, 0xE0, 0xC3, 0x9D, 0x90, 0x81, 0xB1, +0xF0, 0xA3, 0xED, 0xF0, 0x80, 0x25, 0x12, 0x45, +0x1D, 0xF1, 0x31, 0xFB, 0xFF, 0x90, 0x05, 0x54, +0xE0, 0xC3, 0x9F, 0xFF, 0xE4, 0x94, 0x00, 0xFE, +0x7C, 0x00, 0x7D, 0x05, 0x12, 0x20, 0x30, 0x90, +0x81, 0xB1, 0xEF, 0xF0, 0xEB, 0x75, 0xF0, 0x05, +0x84, 0xA3, 0xF0, 0x90, 0x82, 0x3B, 0x12, 0x45, +0x1D, 0x12, 0x1F, 0xA4, 0x20, 0xE0, 0x0A, 0x12, +0x4D, 0x0E, 0x90, 0x01, 0x57, 0xE4, 0xF0, 0x80, +0x06, 0x12, 0x49, 0xCD, 0xF1, 0x7A, 0xF0, 0x90, +0x81, 0xAF, 0x91, 0x31, 0x20, 0xE0, 0x04, 0xEF, +0x44, 0x20, 0xF0, 0x12, 0x77, 0xC2, 0x30, 0xE0, +0x17, 0x90, 0x81, 0x4B, 0x74, 0x01, 0xF0, 0xE4, +0x90, 0x81, 0x4D, 0xF0, 0xD1, 0x16, 0xF0, 0x12, +0x71, 0xB9, 0x74, 0x06, 0xF0, 0x02, 0x70, 0xD7, +0xE4, 0x90, 0x81, 0x4B, 0xF0, 0x90, 0x81, 0x4D, +0x74, 0x0C, 0xF0, 0x90, 0x81, 0x46, 0xE0, 0x54, +0xFE, 0xF0, 0xA3, 0xE0, 0x54, 0xFB, 0xF0, 0x22, +0xF0, 0x90, 0x00, 0x01, 0x02, 0x1F, 0xBD, 0x12, +0x1F, 0xA4, 0xFF, 0x54, 0x01, 0xFE, 0x90, 0x81, +0xB7, 0xF1, 0xE1, 0xF1, 0x30, 0x90, 0x81, 0xB8, +0x12, 0x64, 0x74, 0x90, 0x81, 0xB9, 0xF0, 0x12, +0x72, 0xE5, 0x90, 0x81, 0xB7, 0xE0, 0x54, 0x01, +0xFF, 0x81, 0x89, 0x90, 0x81, 0x45, 0xE0, 0x64, +0x02, 0x22, 0x91, 0x39, 0x30, 0xE0, 0x0B, 0xF1, +0x5B, 0x60, 0x07, 0x7D, 0x01, 0x7F, 0x02, 0x12, +0x4B, 0x1C, 0xF1, 0x5B, 0x60, 0x03, 0x12, 0x67, +0x5F, 0x22, 0x90, 0x81, 0xAF, 0xE0, 0x44, 0x10, +0x22, 0x7D, 0x02, 0x7F, 0x02, 0x81, 0x7F, 0x7B, +0x21, 0x12, 0x4F, 0x95, 0x90, 0x81, 0x44, 0x74, +0x03, 0xF0, 0x22, 0xF1, 0x97, 0x80, 0xF0, 0x02, +0x4F, 0x8E, 0xF1, 0x97, 0x02, 0x4F, 0xEA, 0xF1, +0x97, 0x7B, 0x20, 0x12, 0x4F, 0x95, 0xF1, 0xD4, +0xF0, 0x22, 0x12, 0x4D, 0x70, 0x80, 0xDD, 0x2F, +0xF8, 0xE6, 0xFE, 0xED, 0xF4, 0x5E, 0x22, 0x12, +0x76, 0x16, 0xE4, 0x90, 0x81, 0x44, 0xF0, 0x22, +0x12, 0x4F, 0xA2, 0x80, 0xF2, 0x12, 0x4F, 0x8C, +0x80, 0xED, 0xF1, 0xCE, 0x80, 0xE9, 0x12, 0x4D, +0x10, 0x02, 0x4F, 0x8E, 0x12, 0x73, 0x88, 0x90, +0x81, 0x44, 0x74, 0x02, 0x22, 0xF1, 0xD4, 0xF0, +0x22, 0xE0, 0x54, 0xFE, 0x4E, 0xFE, 0xF0, 0xEF, +0x54, 0x02, 0xFF, 0xEE, 0x54, 0xFD, 0x4F, 0x22, +0x90, 0x00, 0xF7, 0xE0, 0x20, 0xE7, 0x09, 0xE0, +0x7F, 0x01, 0x20, 0xE6, 0x0C, 0x7F, 0x02, 0x22, +0x90, 0x00, 0xF7, 0xE0, 0x30, 0xE6, 0x02, 0x7F, +0x03, 0x22, 0x12, 0x57, 0xF0, 0x90, 0x80, 0x42, +0xEF, 0xF0, 0x11, 0x2B, 0x90, 0x01, 0x64, 0x74, +0x01, 0xF0, 0x90, 0x00, 0x12, 0xE0, 0x54, 0xC7, +0x44, 0x20, 0xFD, 0x7F, 0x12, 0x12, 0x32, 0x1E, +0x02, 0x2D, 0xA7, 0x90, 0x00, 0x08, 0xE0, 0x54, +0xEF, 0xF0, 0x11, 0xA3, 0x11, 0xCB, 0x11, 0x62, +0x11, 0x81, 0xE4, 0xF5, 0x35, 0xF5, 0x37, 0xF5, +0x36, 0xF5, 0x37, 0x75, 0x38, 0x80, 0xAD, 0x35, +0x7F, 0x50, 0x12, 0x32, 0x1E, 0xAD, 0x36, 0x7F, +0x51, 0x12, 0x32, 0x1E, 0xAD, 0x37, 0x7F, 0x52, +0x12, 0x32, 0x1E, 0xAD, 0x38, 0x7F, 0x53, 0x02, +0x32, 0x1E, 0x75, 0x3D, 0x10, 0xE4, 0xF5, 0x3E, +0x75, 0x3F, 0x07, 0x75, 0x40, 0x02, 0x90, 0x01, +0x30, 0xE5, 0x3D, 0xF0, 0xA3, 0xE5, 0x3E, 0xF0, +0xA3, 0xE5, 0x3F, 0xF0, 0xA3, 0xE5, 0x40, 0xF0, +0x22, 0x75, 0x45, 0x07, 0x75, 0x46, 0x01, 0x43, +0x46, 0x10, 0x75, 0x47, 0x03, 0x75, 0x48, 0x62, +0x90, 0x01, 0x38, 0xE5, 0x45, 0xF0, 0xA3, 0xE5, +0x46, 0xF0, 0xA3, 0xE5, 0x47, 0xF0, 0xA3, 0xE5, +0x48, 0xF0, 0x22, 0x90, 0x01, 0x30, 0xE4, 0x12, +0x51, 0x5B, 0x90, 0x01, 0x38, 0x12, 0x51, 0x5B, +0xFD, 0x7F, 0x50, 0x12, 0x32, 0x1E, 0xE4, 0xFD, +0x7F, 0x51, 0x12, 0x32, 0x1E, 0xE4, 0xFD, 0x7F, +0x52, 0x12, 0x32, 0x1E, 0xE4, 0xFD, 0x7F, 0x53, +0x02, 0x32, 0x1E, 0x90, 0x01, 0x34, 0x74, 0xFF, +0x12, 0x51, 0x5B, 0x90, 0x01, 0x3C, 0x12, 0x51, +0x5B, 0xFD, 0x7F, 0x54, 0x12, 0x32, 0x1E, 0x7D, +0xFF, 0x7F, 0x55, 0x12, 0x32, 0x1E, 0x7D, 0xFF, +0x7F, 0x56, 0x12, 0x32, 0x1E, 0x7D, 0xFF, 0x7F, +0x57, 0x02, 0x32, 0x1E, 0x90, 0x01, 0xCF, 0xE0, +0x90, 0x82, 0xAC, 0xF0, 0xE0, 0xFF, 0x30, 0xE0, +0x07, 0x90, 0x01, 0xCF, 0xE0, 0x54, 0xFE, 0xF0, +0xEF, 0x30, 0xE5, 0x22, 0x90, 0x01, 0xCF, 0xE0, +0x54, 0xDF, 0xF0, 0x90, 0x01, 0x34, 0x74, 0x20, +0xF0, 0xE4, 0xF5, 0xA8, 0xF5, 0xE8, 0x11, 0xA3, +0x90, 0x00, 0x03, 0xE0, 0x54, 0xFB, 0xFD, 0x7F, +0x03, 0x12, 0x32, 0x1E, 0x80, 0xFE, 0x22, 0x75, +0xE8, 0x03, 0x75, 0xA8, 0x84, 0x22, 0xE4, 0x90, +0x81, 0xD0, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0x90, +0x81, 0xD0, 0xE0, 0x64, 0x01, 0xF0, 0x24, 0x36, +0x90, 0x01, 0xC4, 0xF0, 0x74, 0x59, 0xA3, 0xF0, +0x90, 0x81, 0x4B, 0xE0, 0x60, 0x0F, 0x90, 0x81, +0x4E, 0xE0, 0xFF, 0x90, 0x81, 0x4D, 0xE0, 0x6F, +0x60, 0x03, 0x12, 0x47, 0xE4, 0xC2, 0xAF, 0x12, +0x6E, 0x2C, 0xBF, 0x01, 0x02, 0x31, 0x80, 0xD2, +0xAF, 0xF1, 0x58, 0x12, 0x32, 0x9E, 0xBF, 0x01, +0x02, 0x51, 0xE4, 0x12, 0x41, 0x4D, 0x80, 0xBF, +0x90, 0x81, 0x46, 0xE0, 0x30, 0xE0, 0x18, 0x90, +0x81, 0x41, 0xE0, 0xFF, 0x30, 0xE0, 0x0E, 0xC3, +0x13, 0x30, 0xE0, 0x07, 0xF1, 0xC8, 0xBF, 0x01, +0x06, 0x80, 0x02, 0x80, 0x00, 0x31, 0xA0, 0x22, +0x90, 0x81, 0x4E, 0xE0, 0xFF, 0x60, 0x03, 0xB4, +0x08, 0x0D, 0x51, 0x3D, 0xBF, 0x01, 0x08, 0x31, +0xB8, 0x90, 0x01, 0xE5, 0xE0, 0x04, 0xF0, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x51, +0x8C, 0x31, 0xC8, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x12, 0x74, 0xE3, 0x90, 0x81, 0x56, 0xE0, 0x20, +0xE0, 0x0C, 0x90, 0x00, 0x26, 0xE0, 0x54, 0x7F, +0xFD, 0x7F, 0x26, 0x12, 0x32, 0x1E, 0x90, 0x00, +0x08, 0xE0, 0x54, 0xEF, 0xFD, 0x7F, 0x08, 0x12, +0x32, 0x1E, 0xE4, 0xFF, 0x90, 0x81, 0xD3, 0xEF, +0xF0, 0xE4, 0xA3, 0xF0, 0xA3, 0xF0, 0x90, 0x01, +0x09, 0xE0, 0x7F, 0x00, 0x30, 0xE7, 0x02, 0x7F, +0x01, 0x90, 0x81, 0xD3, 0xE0, 0x6F, 0x60, 0x34, +0xC3, 0x90, 0x81, 0xD5, 0xE0, 0x94, 0x88, 0x90, +0x81, 0xD4, 0xE0, 0x94, 0x13, 0x40, 0x08, 0x90, +0x01, 0xC0, 0xE0, 0x44, 0x10, 0xF0, 0x22, 0x90, +0x81, 0xD4, 0xF1, 0x59, 0xF1, 0x60, 0xD3, 0x90, +0x81, 0xD5, 0xE0, 0x94, 0x32, 0x90, 0x81, 0xD4, +0xE0, 0x94, 0x00, 0x40, 0xC1, 0x90, 0x01, 0xC6, +0xE0, 0x30, 0xE0, 0xBA, 0x22, 0x90, 0x81, 0xB7, +0xE0, 0xC3, 0x13, 0x20, 0xE0, 0x35, 0x90, 0x02, +0x87, 0xE0, 0x60, 0x02, 0x80, 0x08, 0x90, 0x01, +0x00, 0xE0, 0x64, 0x3F, 0x60, 0x05, 0x75, 0x51, +0x01, 0x80, 0x22, 0x90, 0x02, 0x96, 0xE0, 0x60, +0x05, 0x75, 0x51, 0x10, 0x80, 0x17, 0x90, 0x02, +0x86, 0xE0, 0x20, 0xE1, 0x02, 0x80, 0x07, 0x90, +0x02, 0x86, 0xE0, 0x30, 0xE3, 0x05, 0x75, 0x51, +0x04, 0x80, 0x02, 0xE1, 0xC0, 0x90, 0x01, 0xB9, +0x74, 0x08, 0xF0, 0x90, 0x01, 0xB8, 0xE5, 0x51, +0xF0, 0x7F, 0x00, 0x22, 0x90, 0x81, 0x56, 0xE0, +0xFD, 0x7F, 0x93, 0x12, 0x32, 0x1E, 0x90, 0x81, +0x4C, 0xE0, 0x60, 0x12, 0x90, 0x01, 0x2F, 0xE0, +0x30, 0xE7, 0x05, 0x74, 0x10, 0xF0, 0x80, 0x06, +0x90, 0x01, 0x2F, 0x74, 0x90, 0xF0, 0x90, 0x00, +0x08, 0xE0, 0x44, 0x10, 0xFD, 0x7F, 0x08, 0x12, +0x32, 0x1E, 0x7F, 0x01, 0x31, 0xEC, 0x90, 0x81, +0x56, 0xE0, 0x20, 0xE0, 0x0C, 0x90, 0x00, 0x26, +0xE0, 0x44, 0x80, 0xFD, 0x7F, 0x26, 0x12, 0x32, +0x1E, 0x90, 0x00, 0x90, 0xE0, 0x44, 0x01, 0xFD, +0x7F, 0x90, 0x12, 0x32, 0x1E, 0x7F, 0x14, 0x7E, +0x00, 0x02, 0x32, 0xAA, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x12, 0x2D, 0xA7, 0xE4, 0xF5, +0x53, 0x12, 0x32, 0x9E, 0xEF, 0x60, 0x72, 0x63, +0x53, 0x01, 0xE5, 0x53, 0x24, 0xE4, 0x90, 0x01, +0xC4, 0xF0, 0x74, 0x5A, 0xA3, 0xF0, 0x90, 0x00, +0x88, 0xE0, 0xF5, 0x51, 0xF5, 0x52, 0x54, 0x0F, +0x60, 0xDF, 0xE5, 0x51, 0x30, 0xE0, 0x0B, 0x20, +0xE4, 0x03, 0x12, 0x29, 0xC5, 0x53, 0x52, 0xEE, +0x80, 0x3E, 0xE5, 0x51, 0x30, 0xE1, 0x16, 0x20, +0xE5, 0x0E, 0x12, 0x11, 0xBD, 0xEF, 0x70, 0x03, +0x43, 0x52, 0x20, 0x90, 0x01, 0x06, 0xE4, 0xF0, +0x53, 0x52, 0xFD, 0x80, 0x23, 0xE5, 0x51, 0x30, +0xE2, 0x0B, 0x20, 0xE6, 0x03, 0x12, 0x69, 0x4A, +0x53, 0x52, 0xFB, 0x80, 0x13, 0xE5, 0x51, 0x30, +0xE3, 0x0E, 0x20, 0xE7, 0x08, 0x71, 0x6E, 0xEF, +0x70, 0x03, 0x43, 0x52, 0x80, 0x53, 0x52, 0xF7, +0xAD, 0x52, 0x7F, 0x88, 0x12, 0x32, 0x1E, 0x80, +0x88, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x78, 0x10, +0x74, 0x01, 0xF2, 0x90, 0x02, 0x09, 0xE0, 0x78, +0x00, 0xF2, 0x08, 0x74, 0x20, 0xF2, 0x18, 0xE2, +0xFF, 0x30, 0xE0, 0x05, 0x08, 0xE2, 0x24, 0x80, +0xF2, 0xEF, 0xC3, 0x13, 0x90, 0xFD, 0x10, 0xF0, +0x78, 0x01, 0xE2, 0xB1, 0x99, 0xE0, 0x78, 0x03, +0xF2, 0x64, 0x04, 0x60, 0x0D, 0xE2, 0xFF, 0x64, +0x08, 0x60, 0x07, 0xEF, 0x64, 0x0C, 0x60, 0x02, +0xA1, 0x8F, 0xE4, 0x78, 0x02, 0xF2, 0x78, 0x03, +0xE2, 0xFF, 0x18, 0xE2, 0xC3, 0x9F, 0x50, 0x26, +0xE2, 0xFD, 0x18, 0xE2, 0x2D, 0x90, 0x81, 0xD3, +0xF0, 0xE0, 0xFF, 0xB1, 0x99, 0xE0, 0xFE, 0x74, +0x04, 0x2D, 0xF8, 0xEE, 0xF2, 0xEF, 0xB4, 0xFF, +0x06, 0x90, 0xFD, 0x10, 0xE0, 0x04, 0xF0, 0x78, +0x02, 0xE2, 0x04, 0xF2, 0x80, 0xD0, 0x78, 0x04, +0xE2, 0x78, 0x12, 0xF2, 0xFF, 0x78, 0x05, 0xE2, +0x78, 0x11, 0xF2, 0x78, 0x06, 0xE2, 0x78, 0x13, +0xF2, 0x78, 0x07, 0xE2, 0x78, 0x14, 0xF2, 0x78, +0x08, 0xE2, 0x78, 0x33, 0xF2, 0x78, 0x09, 0xE2, +0x78, 0x34, 0xF2, 0x78, 0x0A, 0xE2, 0x78, 0x35, +0xF2, 0x78, 0x0B, 0xE2, 0x78, 0x36, 0xF2, 0x78, +0x0C, 0xE2, 0x78, 0x37, 0xF2, 0x78, 0x0D, 0xE2, +0x78, 0x38, 0xF2, 0x78, 0x0E, 0xE2, 0x78, 0x39, +0xF2, 0x78, 0x0F, 0xE2, 0x78, 0x3A, 0xF2, 0xE4, +0x78, 0x15, 0xF2, 0xEF, 0x24, 0xF8, 0x60, 0x56, +0x24, 0xFC, 0x60, 0x4D, 0x24, 0x08, 0x60, 0x02, +0xA1, 0x71, 0x78, 0x11, 0xE2, 0xB4, 0x01, 0x05, +0x12, 0x29, 0xC5, 0xA1, 0x76, 0x78, 0x11, 0xE2, +0xB4, 0x02, 0x05, 0x12, 0x11, 0xBD, 0xA1, 0x76, +0x78, 0x11, 0xE2, 0xB4, 0x03, 0x05, 0x12, 0x69, +0x4A, 0xA1, 0x76, 0x78, 0x11, 0xE2, 0xB4, 0x10, +0x07, 0xB1, 0xAF, 0x12, 0x32, 0xAA, 0xA1, 0x76, +0x78, 0x11, 0xE2, 0xB4, 0x11, 0x07, 0xB1, 0xAF, +0x12, 0x32, 0x06, 0xA1, 0x76, 0x78, 0x11, 0xE2, +0xF4, 0x60, 0x02, 0xA1, 0x76, 0x18, 0xF2, 0xA1, +0x76, 0x78, 0x15, 0x74, 0x01, 0xF2, 0x78, 0x11, +0xE2, 0x64, 0x07, 0x60, 0x02, 0xA1, 0x5A, 0x78, +0x34, 0xB1, 0x92, 0x78, 0x08, 0x12, 0x20, 0xBB, +0xC0, 0x04, 0xB1, 0xA8, 0x78, 0x33, 0xB1, 0x92, +0xD0, 0x00, 0x12, 0x44, 0xC2, 0xC0, 0x04, 0xC0, +0x05, 0xC0, 0x06, 0xC0, 0x07, 0x78, 0x35, 0xB1, +0x92, 0x78, 0x10, 0x12, 0x20, 0xBB, 0xD0, 0x03, +0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, 0x44, +0xC2, 0x78, 0x18, 0x12, 0x45, 0x05, 0x78, 0x15, +0xE2, 0x60, 0x79, 0x18, 0xE2, 0xFF, 0x18, 0xE2, +0xFD, 0xF1, 0x28, 0x78, 0x1C, 0x12, 0x45, 0x05, +0x78, 0x38, 0xB1, 0x92, 0x78, 0x08, 0x12, 0x20, +0xBB, 0xC0, 0x04, 0xB1, 0xA8, 0x78, 0x37, 0xB1, +0x92, 0xD0, 0x00, 0x12, 0x44, 0xC2, 0xC0, 0x04, +0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0x78, 0x39, +0xB1, 0x92, 0x78, 0x10, 0x12, 0x20, 0xBB, 0xD0, +0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, +0x44, 0xC2, 0x78, 0x20, 0x12, 0x45, 0x05, 0x78, +0x20, 0x12, 0x44, 0xEC, 0x12, 0x20, 0x9B, 0x78, +0x1C, 0x12, 0x44, 0xF8, 0x12, 0x44, 0xB5, 0xC0, +0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0x78, +0x18, 0x12, 0x44, 0xEC, 0x78, 0x20, 0x12, 0x44, +0xF8, 0x12, 0x44, 0xB5, 0xD0, 0x03, 0xD0, 0x02, +0xD0, 0x01, 0xD0, 0x00, 0x12, 0x44, 0xC2, 0x78, +0x18, 0x12, 0x45, 0x05, 0x78, 0x18, 0x12, 0x44, +0xEC, 0x90, 0x82, 0x7F, 0x12, 0x20, 0xCE, 0x78, +0x13, 0xE2, 0xFD, 0x08, 0xE2, 0xFF, 0xF1, 0x36, +0x80, 0x1C, 0x78, 0x13, 0xE2, 0xFF, 0x08, 0xE2, +0xFD, 0x78, 0x11, 0xE2, 0xFB, 0x78, 0x15, 0xE2, +0x90, 0x82, 0x35, 0xF0, 0x12, 0x67, 0xE1, 0x80, +0x05, 0x78, 0x10, 0x74, 0x02, 0xF2, 0x78, 0x10, +0xE2, 0xFF, 0xC3, 0x94, 0x02, 0x50, 0x10, 0xEF, +0x60, 0x0A, 0x78, 0x02, 0xE2, 0xFF, 0x18, 0xE2, +0x2F, 0xF2, 0x61, 0x90, 0x7F, 0x01, 0x22, 0x7F, +0x00, 0x22, 0xE2, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, +0x22, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0xFC, +0xF5, 0x83, 0x22, 0x12, 0x20, 0xBB, 0xA8, 0x04, +0xA9, 0x05, 0xAA, 0x06, 0xAB, 0x07, 0x22, 0x78, +0x14, 0xE2, 0xFE, 0x18, 0xE2, 0xFD, 0xED, 0xFF, +0x78, 0x16, 0xEE, 0xF2, 0xFE, 0x08, 0xEF, 0xF2, +0xFF, 0x22, 0x90, 0x82, 0x55, 0xEF, 0xF0, 0xA3, +0xED, 0xF0, 0xA3, 0x12, 0x20, 0xDA, 0x00, 0x00, +0x00, 0x00, 0xE4, 0x90, 0x82, 0x63, 0xF0, 0x7F, +0x24, 0x7E, 0x08, 0x12, 0x2D, 0x5C, 0x90, 0x82, +0x5B, 0x12, 0x20, 0xCE, 0x90, 0x82, 0x55, 0xE0, +0xFB, 0x70, 0x04, 0xD1, 0xA4, 0x80, 0x06, 0xEB, +0xD1, 0xB1, 0x12, 0x2D, 0x5C, 0x90, 0x82, 0x5F, +0x12, 0x20, 0xCE, 0x90, 0x82, 0x56, 0x12, 0x6C, +0x21, 0x78, 0x17, 0xB1, 0xA3, 0x90, 0x82, 0x5F, +0x12, 0x44, 0xE0, 0xED, 0x54, 0x7F, 0xFD, 0xEC, +0x54, 0x80, 0xFC, 0x12, 0x44, 0xC2, 0xEC, 0x44, +0x80, 0xFC, 0x90, 0x82, 0x5F, 0x12, 0x20, 0xCE, +0xD1, 0xA4, 0xEC, 0x54, 0x7F, 0xD1, 0xAA, 0xD1, +0xC4, 0xD1, 0xB1, 0xC0, 0x06, 0xC0, 0x07, 0x90, +0x82, 0x5F, 0x12, 0x44, 0xE0, 0xD1, 0xAB, 0xD0, +0x07, 0xD0, 0x06, 0x12, 0x2E, 0xA2, 0xD1, 0xA4, +0xEC, 0x44, 0x80, 0xD1, 0xAA, 0xD1, 0xC4, 0x70, +0x04, 0x7F, 0x20, 0x80, 0x09, 0x90, 0x82, 0x55, +0xE0, 0xB4, 0x01, 0x16, 0x7F, 0x28, 0x7E, 0x08, +0x12, 0x2D, 0x5C, 0x78, 0x08, 0x12, 0x20, 0xA8, +0xEF, 0x54, 0x01, 0xFF, 0xE4, 0x90, 0x82, 0x63, +0xEF, 0xF0, 0x90, 0x82, 0x63, 0xE0, 0x90, 0x82, +0x55, 0x60, 0x0E, 0xE0, 0x75, 0xF0, 0x08, 0xA4, +0x24, 0x66, 0xF5, 0x82, 0xE4, 0x34, 0x87, 0x80, +0x0C, 0xE0, 0x75, 0xF0, 0x08, 0xA4, 0x24, 0x64, +0xF5, 0x82, 0xE4, 0x34, 0x87, 0xD1, 0xBC, 0x12, +0x2D, 0x5C, 0xED, 0x54, 0x0F, 0xFD, 0xE4, 0xFC, +0x90, 0x82, 0x57, 0x12, 0x20, 0xCE, 0x90, 0x82, +0x57, 0x02, 0x44, 0xE0, 0x90, 0x82, 0x5B, 0x02, +0x44, 0xE0, 0xFC, 0x90, 0x85, 0xBB, 0x02, 0x20, +0xCE, 0x75, 0xF0, 0x08, 0xA4, 0x24, 0x62, 0xF5, +0x82, 0xE4, 0x34, 0x87, 0xF5, 0x83, 0xE0, 0xFE, +0xA3, 0xE0, 0xFF, 0x22, 0x7F, 0x24, 0x7E, 0x08, +0x12, 0x2E, 0xA2, 0x90, 0x82, 0x55, 0xE0, 0x22, +0x90, 0x82, 0x73, 0xEF, 0xF0, 0xAB, 0x05, 0x90, +0x82, 0x79, 0x12, 0x20, 0xDA, 0x00, 0x00, 0x00, +0x00, 0xAF, 0x03, 0xE4, 0xFC, 0xFD, 0xFE, 0x78, +0x14, 0xB1, 0xA3, 0x90, 0x82, 0x75, 0x12, 0x44, +0xE0, 0xED, 0x54, 0x0F, 0xFD, 0xE4, 0xFC, 0x12, +0x44, 0xC2, 0xEC, 0x54, 0x0F, 0xFC, 0x90, 0x82, +0x79, 0x12, 0x20, 0xCE, 0x90, 0x82, 0x73, 0xE0, +0x75, 0xF0, 0x08, 0xA4, 0x24, 0x60, 0xF5, 0x82, +0xE4, 0x34, 0x87, 0xD1, 0xBC, 0xC0, 0x06, 0xC0, +0x07, 0x90, 0x82, 0x79, 0x12, 0x44, 0xE0, 0xD1, +0xAB, 0xD0, 0x07, 0xD0, 0x06, 0x02, 0x2E, 0xA2, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xB1, +0xC2, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xC0, 0x07, 0xC0, +0x05, 0x90, 0x82, 0x7F, 0x12, 0x44, 0xE0, 0x90, +0x82, 0x75, 0x12, 0x20, 0xCE, 0xD0, 0x05, 0xD0, +0x07, 0xD1, 0xD0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x22, 0xE4, 0x75, 0xF0, 0x01, 0x02, 0x44, 0x9F, +0x7F, 0x14, 0x7E, 0x00, 0x02, 0x32, 0xAA, 0xE4, +0x90, 0x81, 0xC8, 0xF0, 0xA3, 0xF0, 0x90, 0x01, +0x98, 0xE0, 0x7F, 0x00, 0x30, 0xE4, 0x02, 0x7F, +0x01, 0xEF, 0x64, 0x01, 0x60, 0x3B, 0xC3, 0x90, +0x81, 0xC9, 0xE0, 0x94, 0x88, 0x90, 0x81, 0xC8, +0xE0, 0x94, 0x13, 0x40, 0x0F, 0x90, 0x01, 0xC1, +0xE0, 0x44, 0x10, 0xF0, 0x90, 0x01, 0xC7, 0x74, +0xFD, 0xF0, 0x80, 0x1D, 0x90, 0x81, 0xC8, 0xF1, +0x59, 0xF1, 0x60, 0xD3, 0x90, 0x81, 0xC9, 0xE0, +0x94, 0x32, 0x90, 0x81, 0xC8, 0xE0, 0x94, 0x00, +0x40, 0xBC, 0x90, 0x01, 0xC6, 0xE0, 0x30, 0xE3, +0xB5, 0x90, 0x01, 0xC7, 0x74, 0xFE, 0xF0, 0x22, +0x90, 0x01, 0xB8, 0xE4, 0xF0, 0x7F, 0x01, 0x22, +0x90, 0x81, 0x44, 0xE0, 0x64, 0x02, 0x7F, 0x01, +0x60, 0x02, 0x7F, 0x00, 0x22, 0xE4, 0xFB, 0xFA, +0xFD, 0x7F, 0x01, 0x12, 0x43, 0x4E, 0x90, 0x82, +0x36, 0xEF, 0xF0, 0x60, 0xF0, 0x90, 0x80, 0x3C, +0xE0, 0xFF, 0x70, 0x04, 0xA3, 0xE0, 0x60, 0xE5, +0xC2, 0xAF, 0xEF, 0x30, 0xE1, 0x0A, 0x90, 0x80, +0x3C, 0xE0, 0x54, 0xFD, 0xF0, 0x12, 0x60, 0x15, +0xD2, 0xAF, 0xC2, 0xAF, 0x90, 0x80, 0x3C, 0xE0, +0xFF, 0x30, 0xE2, 0x05, 0x54, 0xFB, 0xF0, 0x31, +0xA4, 0xD2, 0xAF, 0x80, 0xD0, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x80, 0x9C, 0xE0, +0xFF, 0x90, 0x80, 0x9B, 0xE0, 0xB5, 0x07, 0x04, +0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x70, +0x3E, 0x90, 0x80, 0x9B, 0xE0, 0xFE, 0x75, 0xF0, +0x08, 0x90, 0x80, 0x4B, 0x12, 0x45, 0x11, 0xE0, +0xFD, 0xEE, 0x75, 0xF0, 0x08, 0xA4, 0x24, 0x4C, +0xF9, 0x74, 0x80, 0x35, 0xF0, 0xFA, 0x7B, 0x01, +0xAF, 0x05, 0x71, 0x24, 0x90, 0x80, 0x9B, 0x31, +0x9D, 0xB4, 0x0A, 0x02, 0x7F, 0x01, 0xEF, 0x60, +0x05, 0xE4, 0x90, 0x80, 0x9B, 0xF0, 0x11, 0x74, +0x90, 0x80, 0x3C, 0xE0, 0x44, 0x02, 0xF0, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x90, 0x01, 0xCC, 0xE0, +0x54, 0x0F, 0x90, 0x82, 0xA7, 0xF0, 0x90, 0x82, +0xA7, 0xE0, 0xFD, 0x70, 0x02, 0x21, 0x72, 0x90, +0x80, 0x9B, 0xE0, 0xFF, 0x70, 0x06, 0xA3, 0xE0, +0x64, 0x09, 0x60, 0x0A, 0xEF, 0x14, 0xFF, 0x90, +0x80, 0x9C, 0xE0, 0xB5, 0x07, 0x04, 0x7F, 0x01, +0x80, 0x02, 0x7F, 0x00, 0xEF, 0x60, 0x08, 0x90, +0x01, 0xC1, 0xE0, 0x44, 0x01, 0xF0, 0x22, 0x90, +0x82, 0xA5, 0x12, 0x6D, 0x53, 0x80, 0x05, 0xC3, +0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, 0xEF, +0x5D, 0x70, 0x02, 0x21, 0x55, 0xE4, 0x90, 0x82, +0xA8, 0xF0, 0x90, 0x82, 0xA8, 0xE0, 0xF9, 0xC3, +0x94, 0x04, 0x50, 0x32, 0x31, 0x74, 0xA4, 0xFF, +0xE9, 0xFD, 0x7C, 0x00, 0x2F, 0xFF, 0xEC, 0x35, +0xF0, 0xFE, 0x74, 0xD0, 0x31, 0x8B, 0x90, 0x80, +0x4B, 0x31, 0x7C, 0x31, 0x73, 0xA4, 0x2D, 0xFF, +0xEC, 0x35, 0xF0, 0xFE, 0x74, 0xF0, 0x31, 0x8B, +0x90, 0x80, 0x4F, 0x31, 0x7C, 0xF0, 0x90, 0x82, +0xA8, 0xE0, 0x04, 0xF0, 0x80, 0xC4, 0x90, 0x82, +0xA7, 0xE0, 0xFF, 0x90, 0x82, 0xA5, 0xE0, 0xFE, +0x74, 0x01, 0xA8, 0x06, 0x08, 0x80, 0x02, 0xC3, +0x33, 0xD8, 0xFC, 0xF4, 0x5F, 0x90, 0x82, 0xA7, +0xF0, 0x90, 0x82, 0xA5, 0xE0, 0xFF, 0x74, 0x01, +0xA8, 0x07, 0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8, +0xFC, 0x90, 0x01, 0xCC, 0xF0, 0x90, 0x82, 0xA5, +0xE0, 0x04, 0xF0, 0xE0, 0x54, 0x03, 0xF0, 0x90, +0x80, 0x9C, 0x31, 0x9D, 0xB4, 0x0A, 0x02, 0x7F, +0x01, 0xEF, 0x70, 0x02, 0x01, 0x7E, 0xE4, 0x90, +0x80, 0x9C, 0xF0, 0x01, 0x7E, 0x90, 0x01, 0xC0, +0xE0, 0x44, 0x02, 0xF0, 0x90, 0x82, 0xA5, 0xE0, +0x44, 0x80, 0x90, 0x00, 0x8A, 0x31, 0x73, 0x90, +0x01, 0xD0, 0x12, 0x45, 0x11, 0xE0, 0x90, 0x01, +0xC3, 0xF0, 0x22, 0xF0, 0x90, 0x82, 0xA5, 0xE0, +0x75, 0xF0, 0x04, 0x22, 0x12, 0x45, 0x11, 0xE5, +0x82, 0x29, 0xF5, 0x82, 0xE4, 0x35, 0x83, 0xF5, +0x83, 0xEF, 0x22, 0x2F, 0xF5, 0x82, 0x74, 0x01, +0x3E, 0xF5, 0x83, 0xE0, 0xFF, 0x90, 0x80, 0x9C, +0xE0, 0x75, 0xF0, 0x08, 0x22, 0xE0, 0x04, 0xF0, +0xE0, 0x7F, 0x00, 0x22, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0xE4, 0xFF, 0x90, 0x81, 0x34, +0xE0, 0xFE, 0x90, 0x81, 0x33, 0xE0, 0xFD, 0xB5, +0x06, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, +0xEE, 0x64, 0x01, 0x60, 0x41, 0x90, 0x01, 0xAF, +0xE0, 0x70, 0x0A, 0xED, 0x51, 0x68, 0xFA, 0x7B, +0x01, 0x51, 0xC0, 0x7F, 0x01, 0xEF, 0x60, 0x2E, +0x90, 0x81, 0x33, 0x31, 0x9D, 0xB4, 0x0A, 0x02, +0x7F, 0x01, 0xEF, 0x60, 0x05, 0xE4, 0x90, 0x81, +0x33, 0xF0, 0x90, 0x81, 0x34, 0xE0, 0xFF, 0x90, +0x81, 0x33, 0xE0, 0xB5, 0x07, 0x04, 0x7F, 0x01, +0x80, 0x02, 0x7F, 0x00, 0xEF, 0x70, 0x07, 0x90, +0x80, 0x3C, 0xE0, 0x44, 0x04, 0xF0, 0xD0, 0xD0, +0x92, 0xAF, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x81, 0x33, 0xE0, 0xFF, 0x70, +0x06, 0xA3, 0xE0, 0x64, 0x09, 0x60, 0x0A, 0xEF, +0x14, 0xFF, 0x90, 0x81, 0x34, 0xE0, 0xB5, 0x07, +0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xEF, +0x60, 0x09, 0x90, 0x01, 0xC1, 0xE0, 0x44, 0x02, +0xF0, 0x80, 0x28, 0xC0, 0x01, 0x90, 0x81, 0x34, +0xE0, 0x51, 0x68, 0xA8, 0x01, 0xFC, 0x7D, 0x01, +0xD0, 0x01, 0x7E, 0x00, 0x7F, 0x0F, 0x12, 0x44, +0x79, 0x90, 0x81, 0x34, 0x31, 0x9D, 0xB4, 0x0A, +0x02, 0x7F, 0x01, 0xEF, 0x60, 0x05, 0xE4, 0x90, +0x81, 0x34, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x75, 0xF0, 0x0F, 0xA4, 0x24, 0x9D, 0xF9, 0x74, +0x80, 0x35, 0xF0, 0x22, 0x90, 0x82, 0x46, 0x74, +0x12, 0xF0, 0x90, 0x82, 0x54, 0x74, 0x05, 0xF0, +0x90, 0x82, 0x48, 0xEF, 0xF0, 0xA3, 0xED, 0xF0, +0xA3, 0xEB, 0xF0, 0x90, 0x82, 0x44, 0xE0, 0x90, +0x82, 0x4B, 0xF0, 0x90, 0x82, 0x45, 0xE0, 0x90, +0x82, 0x4C, 0xF0, 0x7B, 0x01, 0x7A, 0x82, 0x79, +0x46, 0x51, 0x0B, 0x7F, 0x04, 0x90, 0x82, 0xA9, +0xEF, 0xF0, 0x7F, 0x02, 0x12, 0x43, 0x27, 0x90, +0x80, 0x3C, 0xE0, 0xFF, 0x90, 0x82, 0xA9, 0xE0, +0xFE, 0xEF, 0x4E, 0x90, 0x80, 0x3C, 0xF0, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, +0x82, 0x37, 0x12, 0x45, 0x26, 0x90, 0x82, 0xA6, +0xE0, 0xFF, 0x04, 0xF0, 0x90, 0x00, 0x01, 0xEF, +0x12, 0x1F, 0xFC, 0x7F, 0xAF, 0x7E, 0x01, 0x12, +0x6C, 0xAA, 0xEF, 0x60, 0x3A, 0x90, 0x82, 0x37, +0x12, 0x45, 0x1D, 0x8B, 0x13, 0x8A, 0x14, 0x89, +0x15, 0x90, 0x00, 0x0E, 0x12, 0x1F, 0xBD, 0x24, +0x02, 0xF5, 0x16, 0x7B, 0x01, 0x7A, 0x01, 0x79, +0xA0, 0x12, 0x2B, 0xED, 0x90, 0x82, 0x37, 0x12, +0x45, 0x1D, 0x90, 0x00, 0x0E, 0x12, 0x1F, 0xBD, +0x90, 0x01, 0xAE, 0xF0, 0xA3, 0x74, 0xFF, 0xF0, +0x90, 0x01, 0xCB, 0xE0, 0x64, 0x80, 0xF0, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x90, 0x82, 0x38, 0x12, +0x45, 0x26, 0x90, 0x82, 0x37, 0xEF, 0xF0, 0x12, +0x45, 0x2F, 0x63, 0x54, 0x00, 0x63, 0x5C, 0x01, +0x63, 0x64, 0x12, 0x63, 0x6C, 0x14, 0x63, 0x75, +0x20, 0x63, 0x7D, 0x24, 0x63, 0x86, 0x25, 0x63, +0x8F, 0x26, 0x63, 0x98, 0x27, 0x63, 0xA1, 0xC0, +0x00, 0x00, 0x63, 0xAA, 0x90, 0x82, 0x38, 0x12, +0x45, 0x1D, 0x80, 0x72, 0x90, 0x82, 0x38, 0x12, +0x45, 0x1D, 0x81, 0x13, 0x90, 0x82, 0x38, 0x12, +0x45, 0x1D, 0x80, 0x4E, 0x90, 0x82, 0x38, 0x12, +0x45, 0x1D, 0x02, 0x6C, 0x77, 0x90, 0x82, 0x38, +0x12, 0x45, 0x1D, 0x81, 0x7B, 0x90, 0x82, 0x38, +0x12, 0x45, 0x1D, 0x02, 0x51, 0xD6, 0x90, 0x82, +0x38, 0x12, 0x45, 0x1D, 0x02, 0x6C, 0x86, 0x90, +0x82, 0x38, 0x12, 0x45, 0x1D, 0x02, 0x56, 0x53, +0x90, 0x82, 0x38, 0x12, 0x45, 0x1D, 0x02, 0x57, +0x37, 0x90, 0x82, 0x38, 0x12, 0x45, 0x1D, 0x02, +0x6C, 0x8E, 0x90, 0x01, 0xC0, 0xE0, 0x44, 0x01, +0xF0, 0x90, 0x82, 0x37, 0xE0, 0x90, 0x01, 0xC2, +0xF0, 0x22, 0x12, 0x1F, 0xA4, 0xFF, 0x90, 0x81, +0x37, 0xF0, 0xBF, 0x01, 0x08, 0x12, 0x6D, 0x5D, +0xE4, 0x90, 0x81, 0x37, 0xF0, 0x22, 0x90, 0x02, +0x09, 0xE0, 0xF5, 0x54, 0x12, 0x1F, 0xA4, 0x25, +0x54, 0x90, 0x80, 0x44, 0x12, 0x57, 0x30, 0x25, +0x54, 0x90, 0x80, 0x45, 0x91, 0x74, 0x25, 0x54, +0x90, 0x80, 0x46, 0xB1, 0x24, 0x25, 0x54, 0x90, +0x80, 0x47, 0xB1, 0x1D, 0x25, 0x54, 0x90, 0x80, +0x48, 0xF0, 0x90, 0x00, 0x05, 0x12, 0x1F, 0xBD, +0x25, 0x54, 0x90, 0x80, 0x49, 0xF0, 0x90, 0x00, +0x06, 0x12, 0x1F, 0xBD, 0x25, 0x54, 0x90, 0x80, +0x4A, 0xF0, 0x22, 0x8B, 0x54, 0x8A, 0x55, 0x89, +0x56, 0x12, 0x57, 0x31, 0xFF, 0xF5, 0x58, 0x12, +0x1F, 0xA4, 0xFE, 0xC3, 0x13, 0x30, 0xE0, 0x06, +0x91, 0x75, 0xF5, 0x59, 0x80, 0x02, 0x8F, 0x59, +0x85, 0x58, 0x57, 0xE5, 0x57, 0xD3, 0x95, 0x59, +0x50, 0x1F, 0x12, 0x77, 0xD2, 0x54, 0x01, 0xFD, +0xAF, 0x57, 0x12, 0x51, 0x79, 0xAF, 0x57, 0x12, +0x47, 0x72, 0xEF, 0xAF, 0x57, 0x70, 0x04, 0xF1, +0xD2, 0x80, 0x02, 0xF1, 0xD1, 0x05, 0x57, 0x80, +0xDA, 0xE5, 0x58, 0x70, 0x16, 0xFF, 0x12, 0x47, +0x72, 0xEF, 0x70, 0x0F, 0x12, 0x4D, 0x70, 0x12, +0x4D, 0x5A, 0x12, 0x70, 0x7F, 0x54, 0xBF, 0xF0, +0x54, 0x7F, 0xF0, 0x22, 0xF0, 0x90, 0x00, 0x02, +0x02, 0x1F, 0xBD, 0x12, 0x77, 0xC9, 0xFF, 0x54, +0x7F, 0x90, 0x81, 0x4B, 0xF0, 0xEF, 0xF1, 0xD3, +0xA3, 0x12, 0x57, 0x30, 0xFD, 0x54, 0xF0, 0xC4, +0x54, 0x0F, 0xFF, 0x90, 0x81, 0x49, 0xE0, 0x54, +0xF0, 0x4F, 0xB1, 0x24, 0xFC, 0x54, 0x01, 0x25, +0xE0, 0xFF, 0x90, 0x81, 0x46, 0xE0, 0x54, 0xFD, +0x4F, 0xF0, 0xEC, 0x54, 0x04, 0xC3, 0x13, 0xFF, +0x90, 0x81, 0x48, 0xE0, 0x54, 0xFD, 0x4F, 0xF0, +0xED, 0x54, 0x0F, 0xC4, 0x54, 0xF0, 0xFF, 0xA3, +0xE0, 0x54, 0x0F, 0x4F, 0x91, 0x74, 0x90, 0x81, +0x4A, 0xB1, 0x1D, 0xFD, 0x7F, 0x02, 0x12, 0x49, +0xD1, 0x90, 0x82, 0x3B, 0x12, 0x45, 0x1D, 0x91, +0xEA, 0x12, 0x73, 0x4E, 0xF0, 0x90, 0x81, 0x4B, +0x12, 0x77, 0xA9, 0xB1, 0x31, 0x90, 0x01, 0xBE, +0xF0, 0x22, 0x90, 0x82, 0x3E, 0x12, 0x45, 0x26, +0x12, 0x75, 0x00, 0x90, 0x81, 0x4B, 0xE0, 0xFF, +0x12, 0x4E, 0x3F, 0x90, 0x81, 0x4B, 0xE0, 0x60, +0x1B, 0x90, 0x82, 0x3E, 0x12, 0x45, 0x1D, 0x12, +0x57, 0x31, 0x54, 0x0F, 0xFF, 0x91, 0x75, 0xFD, +0x12, 0x75, 0xCE, 0x12, 0x71, 0xB9, 0x74, 0x01, +0xF0, 0x12, 0x70, 0xD7, 0x22, 0xF0, 0x90, 0x00, +0x04, 0x02, 0x1F, 0xBD, 0xF0, 0x90, 0x00, 0x03, +0x02, 0x1F, 0xBD, 0x90, 0x81, 0x4F, 0xE0, 0x44, +0x01, 0xF0, 0x90, 0x81, 0x49, 0xE0, 0x54, 0x0F, +0x22, 0x90, 0x06, 0xA9, 0xE0, 0x90, 0x81, 0xC1, +0xF0, 0xE0, 0xFD, 0x54, 0xC0, 0x70, 0x04, 0xB1, +0xA2, 0x80, 0x53, 0xED, 0x30, 0xE6, 0x3D, 0x90, +0x81, 0x4B, 0xE0, 0x64, 0x02, 0x70, 0x26, 0x90, +0x81, 0x46, 0xE0, 0xFF, 0xC3, 0x13, 0x20, 0xE0, +0x09, 0x90, 0x81, 0x4F, 0xE0, 0x44, 0x01, 0xF0, +0x80, 0x19, 0xB1, 0x32, 0x64, 0x01, 0x70, 0x1E, +0x90, 0x81, 0x4F, 0xE0, 0x44, 0x04, 0xF0, 0x7F, +0x01, 0xD1, 0xA5, 0x80, 0x11, 0xB1, 0x2B, 0x64, +0x02, 0x60, 0x04, 0xB1, 0xEC, 0x80, 0x07, 0x12, +0x4F, 0x79, 0x80, 0x02, 0xB1, 0xA2, 0x90, 0x81, +0xC1, 0xE0, 0x90, 0x81, 0x4F, 0x30, 0xE7, 0x05, +0x12, 0x48, 0xFD, 0xE1, 0x57, 0xE0, 0x54, 0xFD, +0xF0, 0x22, 0x90, 0x81, 0x4F, 0xE0, 0x54, 0xFE, +0xF0, 0x22, 0x90, 0x06, 0xA9, 0xE0, 0xF5, 0x4E, +0x54, 0xC0, 0x70, 0x08, 0xB1, 0xA2, 0x54, 0xFD, +0xF0, 0x02, 0x47, 0xE4, 0xE5, 0x4E, 0x30, 0xE6, +0x17, 0x90, 0x81, 0x4B, 0xE0, 0x64, 0x01, 0x70, +0x11, 0xB1, 0x2B, 0x64, 0x02, 0x60, 0x04, 0xB1, +0xEC, 0x80, 0x07, 0x12, 0x4F, 0x79, 0x80, 0x02, +0xB1, 0xA2, 0xE5, 0x4E, 0x90, 0x81, 0x4F, 0x30, +0xE7, 0x05, 0x12, 0x48, 0xFD, 0xE1, 0x57, 0xE0, +0x54, 0xFD, 0xF0, 0x22, 0x90, 0x04, 0x1D, 0xE0, +0x70, 0x1B, 0x90, 0x80, 0x45, 0xE0, 0xFF, 0x90, +0x82, 0x95, 0x74, 0x09, 0xF0, 0x7B, 0x18, 0xE4, +0xFD, 0xD1, 0x0E, 0x90, 0x81, 0xC2, 0xEE, 0xF0, +0xA3, 0xEF, 0xF0, 0xF1, 0x50, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x82, 0x93, +0xED, 0xF0, 0xA3, 0xEB, 0xF0, 0x90, 0x82, 0x92, +0xEF, 0xF0, 0xE4, 0xFD, 0xFC, 0x12, 0x77, 0x88, +0x7C, 0x00, 0xAD, 0x07, 0x90, 0x82, 0x92, 0xE0, +0x90, 0x04, 0x25, 0xF0, 0x90, 0x82, 0x93, 0xE0, +0x60, 0x0E, 0x74, 0x0F, 0x2F, 0xF5, 0x82, 0xE4, +0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x80, 0xF0, +0xAF, 0x05, 0x74, 0x08, 0x2F, 0xF5, 0x82, 0xE4, +0x34, 0xFC, 0xF5, 0x83, 0xE4, 0xF0, 0x74, 0x09, +0x2F, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, +0xE0, 0x54, 0xF0, 0xF0, 0xAF, 0x05, 0xF1, 0x45, +0xE0, 0x20, 0xE1, 0x15, 0x54, 0x01, 0xFE, 0x90, +0x82, 0x94, 0xE0, 0x25, 0xE0, 0x25, 0xE0, 0xFB, +0xEE, 0x44, 0x02, 0x4B, 0xFE, 0xF1, 0x45, 0xEE, +0xF0, 0x90, 0x82, 0x95, 0xE0, 0xFF, 0xAE, 0x05, +0x74, 0x1E, 0x2E, 0xF5, 0x82, 0xE4, 0x34, 0xFC, +0xF5, 0x83, 0xEF, 0xF0, 0x74, 0x21, 0x2E, 0xF1, +0x2F, 0x54, 0xF7, 0xF0, 0xAE, 0x04, 0xAF, 0x05, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x82, 0x9E, 0xEF, +0xF0, 0x90, 0x04, 0x1D, 0xE0, 0x60, 0x22, 0x90, +0x05, 0x22, 0xE0, 0x90, 0x82, 0xA1, 0xF0, 0x7B, +0x29, 0xF1, 0xDA, 0x12, 0x74, 0x49, 0xBF, 0x01, +0x02, 0xD1, 0xE2, 0x90, 0x82, 0xA1, 0xE0, 0xFD, +0x7B, 0x2A, 0xE4, 0xFF, 0x12, 0x4D, 0x15, 0x80, +0x02, 0xD1, 0xE2, 0xF1, 0x50, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0x90, 0x80, 0x47, 0xE0, 0xFF, 0x90, +0x82, 0x95, 0x74, 0x0B, 0xF0, 0x7B, 0x08, 0x7D, +0x01, 0xD1, 0x0E, 0x90, 0x82, 0x9F, 0xEE, 0xF0, +0xFC, 0xA3, 0xEF, 0xF0, 0xFD, 0x90, 0x82, 0x9E, +0xE0, 0xFF, 0xF1, 0x39, 0x54, 0x3F, 0xF0, 0xBF, +0x01, 0x02, 0x80, 0x16, 0xEF, 0x70, 0x02, 0x80, +0x07, 0x90, 0x81, 0x4E, 0xE0, 0x30, 0xE3, 0x0A, +0xF1, 0x2C, 0x54, 0xEF, 0xF1, 0x38, 0x44, 0x40, +0xF0, 0x22, 0xF1, 0x2C, 0x44, 0x10, 0xF1, 0x38, +0x44, 0x80, 0xF0, 0x22, 0x74, 0x21, 0x2D, 0xF5, +0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x22, +0xF0, 0x74, 0x1F, 0x2D, 0xF5, 0x82, 0xE4, 0x34, +0xFC, 0xF5, 0x83, 0xE0, 0x22, 0x74, 0x16, 0x2F, +0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0x22, +0x90, 0x04, 0x1F, 0x74, 0x20, 0xF0, 0x22, 0x90, +0x81, 0x46, 0xE0, 0x44, 0x04, 0xF0, 0x22, 0x90, +0x81, 0x4B, 0xE0, 0x64, 0x02, 0x60, 0x0D, 0xB1, +0x32, 0x60, 0x09, 0x12, 0x75, 0x26, 0xEF, 0x70, +0x03, 0x12, 0x4B, 0x19, 0x22, 0xE4, 0xFF, 0x12, +0x47, 0x72, 0xBF, 0x01, 0x11, 0x90, 0x81, 0x4B, +0xE0, 0x60, 0x0B, 0xB1, 0x32, 0x64, 0x02, 0x60, +0x02, 0xA1, 0xEC, 0x12, 0x4F, 0x79, 0x22, 0x90, +0x81, 0x4B, 0xE0, 0x64, 0x01, 0x70, 0x1A, 0xB1, +0x32, 0x60, 0x0D, 0xE4, 0xFD, 0x7F, 0x0C, 0x12, +0x4B, 0x1C, 0x12, 0x4D, 0x10, 0x02, 0x70, 0x4A, +0x90, 0x81, 0x4E, 0xE0, 0x70, 0x03, 0x12, 0x77, +0xF3, 0x22, 0x90, 0x81, 0x4B, 0xE0, 0x70, 0x07, +0x90, 0x81, 0x41, 0xE0, 0x30, 0xE0, 0x11, 0x90, +0x81, 0x41, 0xE0, 0x30, 0xE0, 0x08, 0x12, 0x54, +0x44, 0xBF, 0x01, 0x04, 0x80, 0x91, 0xF1, 0x8F, +0x22, 0x22, 0x22, 0xC4, 0x13, 0x13, 0x13, 0x54, +0x01, 0x22, 0x7D, 0xFF, 0xE4, 0xFF, 0x02, 0x4D, +0x15, 0xAC, 0x07, 0xED, 0xAD, 0x04, 0x78, 0x24, +0xF2, 0xED, 0x08, 0xF2, 0xEB, 0xB4, 0x04, 0x07, +0x78, 0x27, 0x74, 0x01, 0xF2, 0x80, 0x0E, 0xEB, +0x78, 0x27, 0xB4, 0x05, 0x05, 0x74, 0x02, 0xF2, +0x80, 0x03, 0x74, 0x04, 0xF2, 0x31, 0x23, 0xE2, +0x94, 0x00, 0x50, 0x45, 0xE4, 0x78, 0x26, 0xF2, +0x11, 0xFD, 0x9F, 0x40, 0x02, 0x01, 0xFC, 0x31, +0x06, 0x60, 0x1F, 0x74, 0x37, 0x2E, 0xF8, 0xE2, +0x78, 0x32, 0xF2, 0xEE, 0xFF, 0x78, 0x25, 0xE2, +0x2F, 0xFF, 0x18, 0xE2, 0x34, 0x00, 0x8F, 0x82, +0xF5, 0x83, 0xE0, 0x78, 0x29, 0xF2, 0x78, 0x32, +0x31, 0x39, 0x78, 0x24, 0x08, 0xE2, 0xFF, 0x08, +0xE2, 0x2F, 0xFF, 0x78, 0x28, 0xE2, 0xFD, 0x12, +0x32, 0x1E, 0x78, 0x26, 0xE2, 0x04, 0xF2, 0x80, +0xBF, 0x31, 0x23, 0xE2, 0x94, 0x07, 0x50, 0x30, +0xE4, 0x78, 0x26, 0xF2, 0x11, 0xFD, 0x9F, 0x40, +0x02, 0x01, 0xFC, 0x31, 0x06, 0x60, 0x14, 0x78, +0x26, 0xE2, 0xFF, 0x31, 0x2B, 0xE0, 0x78, 0x29, +0xF2, 0x74, 0x37, 0x2F, 0xF8, 0xE2, 0x78, 0x32, +0xF2, 0x31, 0x39, 0x31, 0x1B, 0x31, 0x2B, 0xEF, +0xF0, 0x78, 0x26, 0xE2, 0x04, 0xF2, 0x80, 0xD4, +0x90, 0x82, 0x35, 0xE0, 0x60, 0x0A, 0x31, 0x13, +0x12, 0x2D, 0x5C, 0x78, 0x2E, 0x12, 0x45, 0x05, +0xE4, 0x78, 0x26, 0xF2, 0x11, 0xFD, 0x9F, 0x50, +0x4E, 0x31, 0x06, 0x60, 0x2B, 0x78, 0x2E, 0x12, +0x44, 0xEC, 0x78, 0x26, 0xE2, 0xFB, 0x75, 0xF0, +0x08, 0xA4, 0xF9, 0xF8, 0x12, 0x20, 0xA8, 0x78, +0x29, 0xEF, 0xF2, 0x74, 0x37, 0x2B, 0xF8, 0xE2, +0x78, 0x32, 0xF2, 0xE2, 0xFE, 0xF4, 0x5F, 0xFF, +0x78, 0x28, 0xE2, 0xFD, 0xEE, 0x5D, 0x4F, 0xF2, +0x31, 0x1B, 0xFD, 0xC3, 0x74, 0x03, 0x9D, 0xFD, +0xE4, 0x94, 0x00, 0xFC, 0x7B, 0xFE, 0x74, 0x2A, +0x2D, 0xF9, 0x74, 0x80, 0x3C, 0xFA, 0xEF, 0x12, +0x1F, 0xEA, 0xE2, 0x04, 0xF2, 0x80, 0xAD, 0x78, +0x2A, 0x12, 0x44, 0xEC, 0x12, 0x5E, 0xAB, 0x31, +0x13, 0x12, 0x2E, 0xA2, 0x22, 0x78, 0x27, 0xE2, +0xFF, 0x18, 0xE2, 0xFE, 0xC3, 0x22, 0x74, 0x33, +0x2E, 0xF8, 0xE2, 0x78, 0x28, 0xF2, 0x90, 0x82, +0x35, 0xE0, 0x22, 0x78, 0x24, 0xE2, 0xFE, 0x08, +0xE2, 0xFF, 0x22, 0x78, 0x28, 0xE2, 0xFF, 0x78, +0x26, 0xE2, 0x22, 0xD3, 0x78, 0x25, 0xE2, 0x94, +0xFF, 0x18, 0x22, 0xFD, 0x18, 0xE2, 0x2D, 0xFD, +0x18, 0xE2, 0x34, 0x00, 0x8D, 0x82, 0xF5, 0x83, +0x22, 0xE2, 0xFF, 0xF4, 0xFE, 0x78, 0x29, 0xE2, +0x5E, 0xFE, 0x18, 0xE2, 0xFD, 0xEF, 0x5D, 0x4E, +0xF2, 0x22, 0xE4, 0x90, 0x81, 0xE3, 0xF0, 0x90, +0x87, 0x5F, 0xE0, 0x90, 0x81, 0xE2, 0xF0, 0xE4, +0x90, 0x81, 0xEF, 0xF0, 0x90, 0x81, 0xDF, 0xF0, +0x90, 0x81, 0xDF, 0xE0, 0xFF, 0xC3, 0x94, 0x40, +0x50, 0x10, 0x74, 0xF2, 0x2F, 0x91, 0x4E, 0x74, +0xFF, 0xF0, 0x90, 0x81, 0xDF, 0xE0, 0x04, 0xF0, +0x80, 0xE6, 0xE4, 0x90, 0x81, 0xDF, 0xF0, 0x90, +0x81, 0xE2, 0xE0, 0xFF, 0x90, 0x81, 0xDF, 0xE0, +0xFE, 0xC3, 0x9F, 0x40, 0x02, 0x41, 0x4A, 0x74, +0xDF, 0x2E, 0xF9, 0xE4, 0x34, 0x86, 0x91, 0x46, +0x75, 0x16, 0x0A, 0x7B, 0x01, 0x7A, 0x81, 0x79, +0xD4, 0x12, 0x2B, 0xED, 0x90, 0x81, 0xD5, 0xE0, +0xFF, 0x12, 0x2F, 0x27, 0xEF, 0x04, 0x90, 0x81, +0xEF, 0xF0, 0x90, 0x81, 0xD4, 0xE0, 0xFF, 0xA3, +0xE0, 0xFD, 0x12, 0x31, 0xEA, 0xEF, 0x24, 0xC8, +0x90, 0x81, 0xF1, 0xF0, 0x75, 0xF0, 0x08, 0xA4, +0xF0, 0x90, 0x81, 0xD5, 0xE0, 0x54, 0x0F, 0x90, +0x81, 0xF0, 0xF0, 0xE4, 0x90, 0x81, 0xDE, 0xF0, +0x90, 0x81, 0xE0, 0xF0, 0x90, 0x81, 0xE0, 0xE0, +0xFF, 0xC3, 0x94, 0x04, 0x50, 0x57, 0x90, 0x81, +0xF0, 0xE0, 0xFE, 0xA8, 0x07, 0x08, 0x80, 0x02, +0xC3, 0x13, 0xD8, 0xFC, 0x20, 0xE0, 0x3E, 0x90, +0x81, 0xE0, 0xE0, 0x25, 0xE0, 0xFF, 0x90, 0x81, +0xF1, 0xE0, 0x2F, 0x24, 0xF2, 0xF9, 0xE4, 0x34, +0x81, 0xFA, 0x7B, 0x01, 0xC0, 0x03, 0xC0, 0x01, +0x90, 0x81, 0xDE, 0xE0, 0x75, 0xF0, 0x02, 0xA4, +0x24, 0xD6, 0xF9, 0x74, 0x81, 0x35, 0xF0, 0x8B, +0x13, 0xF5, 0x14, 0x89, 0x15, 0x75, 0x16, 0x02, +0xD0, 0x01, 0xD0, 0x03, 0x12, 0x2B, 0xED, 0x90, +0x81, 0xDE, 0xE0, 0x04, 0xF0, 0x90, 0x81, 0xE0, +0xE0, 0x04, 0xF0, 0x80, 0x9F, 0x90, 0x81, 0xEF, +0xE0, 0xFF, 0x90, 0x81, 0xDF, 0xE0, 0x2F, 0xF0, +0x21, 0x7F, 0xE4, 0x90, 0x81, 0xE3, 0xF0, 0x90, +0x81, 0xE3, 0xE0, 0xC3, 0x94, 0x40, 0x40, 0x02, +0x61, 0xF3, 0xE0, 0xFF, 0x24, 0xF2, 0x91, 0x4E, +0xE0, 0x90, 0x81, 0xE5, 0xF0, 0xE0, 0xFE, 0x54, +0xF0, 0xC4, 0x54, 0x0F, 0xFD, 0x90, 0x81, 0xE4, +0xF0, 0xEE, 0x54, 0x0F, 0xFE, 0xA3, 0xF0, 0x74, +0xF3, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, +0x83, 0xE0, 0x90, 0x81, 0xE6, 0xF0, 0xFC, 0xEE, +0xFE, 0xEC, 0xFB, 0xEB, 0xFF, 0x90, 0x81, 0xEB, +0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xED, 0x12, 0x45, +0x2F, 0x6A, 0xBE, 0x00, 0x6A, 0xF0, 0x01, 0x6B, +0x5D, 0x02, 0x6B, 0xE4, 0x03, 0x6B, 0x68, 0x04, +0x6B, 0x79, 0x05, 0x6B, 0x79, 0x06, 0x6B, 0x79, +0x07, 0x6B, 0x79, 0x08, 0x6B, 0xC1, 0x09, 0x6B, +0xD2, 0x0A, 0x00, 0x00, 0x6B, 0xF3, 0x90, 0x81, +0xE3, 0xE0, 0xFD, 0x24, 0xF5, 0xF5, 0x82, 0xE4, +0x34, 0x81, 0xF5, 0x83, 0xE0, 0xFE, 0x74, 0xF4, +0x2D, 0x91, 0x33, 0xE0, 0xFD, 0xED, 0xFF, 0x90, +0x81, 0xED, 0xEE, 0xF0, 0xFC, 0xA3, 0xEF, 0xF0, +0x90, 0x81, 0xE6, 0xE0, 0xFF, 0x12, 0x2F, 0x96, +0x90, 0x81, 0xE1, 0x74, 0x02, 0xF0, 0x61, 0xE4, +0x71, 0xF4, 0x12, 0x44, 0xC2, 0xC0, 0x04, 0xC0, +0x05, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x81, 0xE3, +0xE0, 0x24, 0xF6, 0xF5, 0x82, 0xE4, 0x34, 0x81, +0x91, 0x1F, 0x78, 0x10, 0x12, 0x20, 0xBB, 0xD0, +0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, +0x44, 0xC2, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, +0xC0, 0x07, 0x90, 0x81, 0xE3, 0xE0, 0x24, 0xF7, +0xF5, 0x82, 0xE4, 0x34, 0x81, 0x91, 0x1F, 0x78, +0x18, 0x12, 0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, +0xD0, 0x01, 0xD0, 0x00, 0x91, 0x56, 0x90, 0x81, +0xE7, 0x12, 0x44, 0xE0, 0x90, 0x85, 0x96, 0x12, +0x20, 0xCE, 0x90, 0x81, 0xEB, 0xE0, 0xFE, 0xA3, +0xE0, 0xFF, 0x12, 0x2E, 0xE4, 0x90, 0x81, 0xE1, +0x74, 0x04, 0xF0, 0x61, 0xE4, 0x91, 0x28, 0xE0, +0xFB, 0xE4, 0xFF, 0x12, 0x30, 0xC7, 0x80, 0x09, +0x91, 0x28, 0xE0, 0xFB, 0xE4, 0xFF, 0x12, 0x30, +0x6A, 0x90, 0x81, 0xE1, 0x74, 0x01, 0xF0, 0x80, +0x6B, 0x90, 0x81, 0xE1, 0x74, 0x02, 0xF0, 0x71, +0xF4, 0x12, 0x44, 0xC2, 0xC0, 0x04, 0xC0, 0x05, +0xC0, 0x06, 0xC0, 0x07, 0x90, 0x81, 0xE5, 0x91, +0x21, 0x78, 0x10, 0x12, 0x20, 0xBB, 0xD0, 0x03, +0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x91, 0x56, +0x90, 0x81, 0xE4, 0xE0, 0x24, 0xFB, 0xFF, 0xC0, +0x07, 0x90, 0x81, 0xE7, 0x12, 0x44, 0xE0, 0x90, +0x82, 0x7F, 0x12, 0x20, 0xCE, 0x90, 0x81, 0xE6, +0xE0, 0xFD, 0xD0, 0x07, 0x12, 0x5F, 0x36, 0x80, +0x23, 0x90, 0x81, 0xE1, 0x74, 0x01, 0x91, 0x3B, +0x75, 0x16, 0x01, 0x91, 0x5F, 0xF0, 0x7B, 0x04, +0x80, 0x0F, 0x90, 0x81, 0xE1, 0x74, 0x04, 0x91, +0x3B, 0x75, 0x16, 0x04, 0x91, 0x5F, 0xF0, 0x7B, +0x06, 0x12, 0x67, 0xE1, 0x90, 0x81, 0xE1, 0xE0, +0x24, 0x02, 0xFF, 0x90, 0x81, 0xE3, 0xE0, 0x2F, +0xF0, 0x41, 0x4F, 0x22, 0x90, 0x81, 0xE3, 0xE0, +0x24, 0xF5, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, +0x83, 0xE0, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x78, +0x08, 0x12, 0x20, 0xBB, 0xA8, 0x04, 0xA9, 0x05, +0xAA, 0x06, 0xAB, 0x07, 0x90, 0x81, 0xE3, 0xE0, +0x24, 0xF4, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, +0x83, 0xE0, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x22, +0x90, 0x81, 0xE6, 0xE0, 0xFD, 0x90, 0x81, 0xE3, +0xE0, 0x24, 0xF4, 0xF5, 0x82, 0xE4, 0x34, 0x81, +0xF5, 0x83, 0x22, 0xF0, 0x90, 0x81, 0xE3, 0xE0, +0x24, 0xF4, 0xF9, 0xE4, 0x34, 0x81, 0x75, 0x13, +0x01, 0xF5, 0x14, 0x89, 0x15, 0x22, 0xF5, 0x82, +0xE4, 0x34, 0x81, 0xF5, 0x83, 0x22, 0x12, 0x44, +0xC2, 0x90, 0x81, 0xE7, 0x02, 0x20, 0xCE, 0x7B, +0xFE, 0x7A, 0x80, 0x79, 0x33, 0x12, 0x2B, 0xED, +0x90, 0x81, 0xE6, 0xE0, 0xFF, 0x90, 0x81, 0xE5, +0xE0, 0xFD, 0xE4, 0x90, 0x82, 0x35, 0x22, 0x12, +0x1F, 0xA4, 0x54, 0x01, 0xFF, 0x90, 0x81, 0xBE, +0xE0, 0x54, 0xFE, 0x4F, 0xF0, 0x22, 0x12, 0x1F, +0xA4, 0x90, 0x81, 0xAE, 0xF0, 0x22, 0x12, 0x1F, +0xA4, 0x90, 0x81, 0xBC, 0x12, 0x57, 0x30, 0x90, +0x81, 0xBD, 0xF0, 0x22, 0xE4, 0x90, 0x81, 0x33, +0xF0, 0xA3, 0xF0, 0x90, 0x80, 0x9B, 0xF0, 0xA3, +0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x90, 0x82, 0x8E, 0xEE, 0xF0, 0xA3, 0xEF, +0xF0, 0xE4, 0xA3, 0xF0, 0xA3, 0xF0, 0x90, 0x82, +0x8E, 0xE0, 0xFE, 0xA3, 0xE0, 0xF5, 0x82, 0x8E, +0x83, 0xE0, 0x60, 0x29, 0xC3, 0x90, 0x82, 0x91, +0xE0, 0x94, 0xE8, 0x90, 0x82, 0x90, 0xE0, 0x94, +0x03, 0x40, 0x0B, 0x90, 0x01, 0xC0, 0xE0, 0x44, +0x80, 0xF0, 0x7F, 0x00, 0x80, 0x11, 0x90, 0x82, +0x90, 0x12, 0x5F, 0x59, 0x7F, 0x0A, 0x7E, 0x00, +0x12, 0x32, 0xAA, 0x80, 0xC9, 0x7F, 0x01, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x7D, 0x08, 0xED, 0x14, 0xF9, +0x24, 0x38, 0x12, 0x47, 0xC5, 0xE0, 0x60, 0x3A, +0x7C, 0x08, 0xEC, 0x14, 0x90, 0x82, 0xAA, 0xF0, +0x74, 0x38, 0x29, 0x12, 0x47, 0xC5, 0xE0, 0xFB, +0x7A, 0x00, 0x90, 0x82, 0xAA, 0xB1, 0x53, 0x80, +0x05, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, +0xFF, 0xEE, 0x5A, 0xFE, 0xEF, 0x5B, 0x4E, 0x60, +0x0F, 0xE9, 0x75, 0xF0, 0x08, 0xA4, 0xFF, 0x90, +0x82, 0xAA, 0xE0, 0x2F, 0x04, 0xFF, 0x80, 0x06, +0xDC, 0xC8, 0xDD, 0xB9, 0x7F, 0x00, 0xD0, 0xD0, +0x92, 0xAF, 0x22, 0xE0, 0xFF, 0x74, 0x01, 0x7E, +0x00, 0xA8, 0x07, 0x08, 0x22, 0x7B, 0x01, 0x7A, +0x82, 0x79, 0x3B, 0x7F, 0xF5, 0x7E, 0x00, 0x12, +0x2B, 0x27, 0xBF, 0x01, 0x06, 0x90, 0x82, 0x3B, +0xE0, 0xA3, 0xF0, 0x7B, 0x01, 0x7A, 0x82, 0x79, +0x3B, 0x7F, 0xF6, 0x7E, 0x00, 0x12, 0x2B, 0x27, +0xBF, 0x01, 0x08, 0x90, 0x82, 0x3B, 0xE0, 0x90, +0x82, 0x3D, 0xF0, 0x7B, 0x01, 0x7A, 0x82, 0x79, +0x3B, 0x7F, 0xF4, 0x7E, 0x00, 0x12, 0x2B, 0x27, +0xBF, 0x01, 0x08, 0x90, 0x82, 0x3B, 0xE0, 0x90, +0x82, 0x3E, 0xF0, 0x7B, 0x01, 0x7A, 0x82, 0x79, +0x3B, 0x7F, 0xF3, 0x7E, 0x00, 0x12, 0x2B, 0x27, +0xBF, 0x01, 0x08, 0x90, 0x82, 0x3B, 0xE0, 0x90, +0x82, 0x3F, 0xF0, 0x7B, 0x01, 0x7A, 0x82, 0x79, +0x3B, 0x7F, 0xF2, 0x7E, 0x00, 0x12, 0x2B, 0x27, +0xBF, 0x01, 0x08, 0x90, 0x82, 0x3B, 0xE0, 0x90, +0x82, 0x40, 0xF0, 0x90, 0x82, 0x3C, 0xE0, 0xFF, +0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFB, 0xA3, 0xE0, +0x90, 0x82, 0x44, 0xF0, 0x90, 0x82, 0x40, 0xE0, +0x90, 0x82, 0x45, 0xF0, 0x02, 0x62, 0x74, 0x90, +0x01, 0x94, 0xE0, 0x44, 0x01, 0xF0, 0x90, 0x01, +0xC7, 0xE4, 0xF0, 0x22, 0x90, 0x01, 0x01, 0xE0, +0x44, 0x04, 0xF0, 0x90, 0x01, 0x9C, 0x74, 0x7E, +0xF0, 0xA3, 0x74, 0x92, 0xF0, 0xA3, 0x74, 0xA0, +0xF0, 0xA3, 0x74, 0x24, 0xF0, 0x90, 0x01, 0x9B, +0x74, 0x49, 0xF0, 0x90, 0x01, 0x9A, 0x74, 0xE0, +0xF0, 0x90, 0x01, 0x99, 0xE4, 0xF0, 0x90, 0x01, +0x98, 0x04, 0xF0, 0x22, 0x7F, 0x02, 0x90, 0x81, +0xBB, 0xE0, 0xFE, 0xEF, 0xC3, 0x9E, 0x50, 0x18, +0xEF, 0x25, 0xE0, 0x24, 0x81, 0xF8, 0xE6, 0x30, +0xE4, 0x0B, 0x90, 0x01, 0xB8, 0x74, 0x08, 0xF0, +0xA3, 0xF0, 0x7F, 0x00, 0x22, 0x0F, 0x80, 0xDE, +0x7F, 0x01, 0x22, 0x90, 0x01, 0xE4, 0x74, 0x1C, +0xF0, 0xA3, 0xE4, 0xF0, 0x22, 0x90, 0x01, 0x34, +0xE0, 0x55, 0x3D, 0xF5, 0x41, 0xA3, 0xE0, 0x55, +0x3E, 0xF5, 0x42, 0xA3, 0xE0, 0x55, 0x3F, 0xF5, +0x43, 0xA3, 0xE0, 0x55, 0x40, 0xF5, 0x44, 0x90, +0x01, 0x34, 0xE5, 0x41, 0xF0, 0xA3, 0xE5, 0x42, +0xF0, 0xA3, 0xE5, 0x43, 0xF0, 0xA3, 0xE5, 0x44, +0xF0, 0x22, 0x90, 0x01, 0x3C, 0xE0, 0x55, 0x45, +0xF5, 0x49, 0xA3, 0xE0, 0x55, 0x46, 0xF5, 0x4A, +0xA3, 0xE0, 0x55, 0x47, 0xF5, 0x4B, 0xA3, 0xE0, +0x55, 0x48, 0xF5, 0x4C, 0x90, 0x01, 0x3C, 0xE5, +0x49, 0xF0, 0xA3, 0xE5, 0x4A, 0xF0, 0xA3, 0xE5, +0x4B, 0xF0, 0xA3, 0xE5, 0x4C, 0xF0, 0x53, 0x91, +0xDF, 0x22, 0x90, 0x81, 0x41, 0xE0, 0x30, 0xE0, +0x05, 0xE4, 0xA3, 0xF0, 0xA3, 0xF0, 0x22, 0x90, +0x81, 0xBD, 0xE0, 0x60, 0x0F, 0xE4, 0xF0, 0x90, +0x05, 0x53, 0xE0, 0x44, 0x02, 0xF0, 0x90, 0x05, +0xFC, 0xE0, 0x04, 0xF0, 0x90, 0x81, 0x41, 0xE0, +0x30, 0xE0, 0x10, 0xA3, 0x74, 0x01, 0xF0, 0x90, +0x81, 0x41, 0xE0, 0xFF, 0xC3, 0x13, 0x30, 0xE0, +0x02, 0xD1, 0xFE, 0x12, 0x76, 0x1E, 0xE4, 0xFF, +0x12, 0x72, 0xEF, 0x02, 0x4D, 0xD4, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x54, 0x44, +0xBF, 0x01, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, +0x02, 0x12, 0x53, 0x48, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x90, 0x81, 0x41, 0xE0, 0xFF, 0x30, 0xE0, +0x3E, 0x90, 0x81, 0x45, 0xE0, 0x7E, 0x00, 0xB4, +0x02, 0x02, 0x7E, 0x01, 0x90, 0x81, 0x44, 0xE0, +0x7D, 0x00, 0xB4, 0x04, 0x02, 0x7D, 0x01, 0xED, +0x4E, 0x70, 0x24, 0xEF, 0xC3, 0x13, 0x30, 0xE0, +0x02, 0x80, 0xBB, 0xF1, 0x60, 0x90, 0x81, 0x45, +0xE0, 0xB4, 0x0C, 0x06, 0xE4, 0xFD, 0x7F, 0x08, +0x80, 0x0A, 0x90, 0x81, 0x45, 0xE0, 0xB4, 0x04, +0x06, 0xE4, 0xFD, 0xFF, 0x12, 0x4B, 0x1C, 0x22, +0x90, 0x01, 0x57, 0xE0, 0x60, 0x1E, 0x12, 0x47, +0xBA, 0xF0, 0x90, 0x81, 0x46, 0xF1, 0x8F, 0x30, +0xE0, 0x02, 0x80, 0x22, 0xF1, 0xA2, 0x9F, 0x40, +0x0B, 0xE4, 0xFF, 0x12, 0x47, 0x72, 0xBF, 0x01, +0x03, 0xF1, 0x85, 0xF0, 0x22, 0x90, 0x81, 0x47, +0xE0, 0x54, 0xFB, 0x22, 0x90, 0x81, 0x47, 0xE0, +0xFF, 0x13, 0x13, 0x54, 0x3F, 0x22, 0xEF, 0x54, +0xFB, 0xF0, 0x90, 0x81, 0x4F, 0xE0, 0x54, 0xFD, +0xF0, 0x22, 0x90, 0x81, 0x54, 0xE0, 0x04, 0xF0, +0x90, 0x81, 0x4F, 0xE0, 0x54, 0xEF, 0xF0, 0x90, +0x81, 0xA8, 0xE0, 0xFF, 0x90, 0x81, 0x54, 0xE0, +0xD3, 0x22, 0x12, 0x54, 0x2E, 0x30, 0xE0, 0x0C, +0xEF, 0xC4, 0x13, 0x13, 0x54, 0x03, 0x30, 0xE0, +0x03, 0x12, 0x57, 0x81, 0x90, 0x81, 0x46, 0xF1, +0x8F, 0x30, 0xE0, 0x08, 0xF1, 0x96, 0x54, 0x07, +0x70, 0x37, 0x80, 0x32, 0xF1, 0xA2, 0x9F, 0x40, +0x2D, 0x12, 0x47, 0x6A, 0x70, 0x2B, 0x12, 0x65, +0x32, 0x70, 0x04, 0xF1, 0x85, 0xF0, 0x22, 0x90, +0x81, 0x55, 0xE0, 0x04, 0xF0, 0xE0, 0xD3, 0x94, +0x02, 0x40, 0x0A, 0xF1, 0x85, 0xF0, 0xE4, 0x90, +0x81, 0x55, 0xF0, 0x80, 0x03, 0x12, 0x4F, 0x79, +0xE4, 0x90, 0x81, 0x54, 0xF0, 0x22, 0x12, 0x47, +0xE4, 0x22, 0x90, 0x81, 0x41, 0xE0, 0xFF, 0x30, +0xE0, 0x05, 0x12, 0x57, 0x5B, 0x60, 0x15, 0x90, +0x81, 0x4B, 0xE0, 0x70, 0x04, 0xEF, 0x30, 0xE0, +0x0B, 0x90, 0x81, 0x4E, 0xE0, 0x64, 0x02, 0x60, +0x03, 0x12, 0x54, 0xDA, 0x22, 0x90, 0x81, 0x4B, +0xE0, 0x60, 0x0E, 0x90, 0x06, 0x92, 0xE0, 0x30, +0xE1, 0x02, 0x80, 0x06, 0x11, 0x7F, 0x12, 0x47, +0xE4, 0x22, 0x11, 0x87, 0x30, 0xE0, 0x05, 0x90, +0x01, 0x5B, 0xE4, 0xF0, 0x90, 0x06, 0x92, 0x74, +0x02, 0xF0, 0x90, 0x01, 0x3C, 0x74, 0x04, 0xF0, +0xE4, 0xF5, 0x1D, 0x90, 0x81, 0xAA, 0xE0, 0xC3, +0x13, 0x54, 0x7F, 0xF5, 0x1E, 0xE4, 0xFB, 0xFD, +0x7F, 0x58, 0x7E, 0x01, 0x12, 0x49, 0x11, 0x90, +0x81, 0x46, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, +0x81, 0x46, 0xE0, 0x54, 0xF7, 0xF0, 0x22, 0x90, +0x81, 0x46, 0xE0, 0x13, 0x13, 0x13, 0x54, 0x1F, +0x22, 0x31, 0xCA, 0x90, 0x81, 0xC4, 0xEF, 0xF0, +0x30, 0xE0, 0x05, 0x7D, 0x01, 0xE4, 0x80, 0x02, +0xE4, 0xFD, 0xFF, 0x12, 0x49, 0xD1, 0x90, 0x81, +0xC4, 0xE0, 0x30, 0xE6, 0x11, 0x90, 0x01, 0x2F, +0xE0, 0x30, 0xE7, 0x04, 0xE4, 0xF0, 0x80, 0x06, +0x90, 0x01, 0x2F, 0x74, 0x80, 0xF0, 0x90, 0x81, +0x46, 0xE0, 0x90, 0x04, 0xEC, 0x30, 0xE0, 0x06, +0xE0, 0x54, 0xDD, 0xF0, 0x80, 0x04, 0xE0, 0x44, +0x22, 0xF0, 0x31, 0xB9, 0x74, 0x02, 0xF0, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xAC, 0x07, +0x90, 0x81, 0x47, 0xE0, 0x12, 0x67, 0xD3, 0x30, +0xE0, 0x02, 0x21, 0x98, 0x90, 0x81, 0x46, 0xE0, +0x30, 0xE0, 0x16, 0x90, 0x81, 0x68, 0xE0, 0x24, +0x04, 0x90, 0x81, 0x60, 0xF0, 0x90, 0x81, 0x68, +0xE0, 0x24, 0x03, 0x90, 0x81, 0x5F, 0xF0, 0x80, +0x0D, 0x90, 0x81, 0x60, 0x74, 0x02, 0xF0, 0x90, +0x81, 0x5F, 0x14, 0xF0, 0x0B, 0x0B, 0x90, 0x81, +0x5F, 0xE0, 0xFA, 0x90, 0x81, 0x5E, 0xE0, 0xD3, +0x9A, 0x50, 0x0E, 0x90, 0x81, 0x53, 0xEB, 0xF0, +0x90, 0x81, 0x60, 0xE0, 0xC3, 0x9D, 0x2C, 0x80, +0x11, 0xC3, 0xED, 0x9A, 0x2B, 0x90, 0x81, 0x53, +0xF0, 0x90, 0x81, 0x5F, 0xE0, 0xFF, 0xA3, 0xE0, +0xC3, 0x9F, 0x90, 0x81, 0x63, 0xF0, 0x90, 0x81, +0x60, 0xE0, 0xFF, 0x24, 0x0A, 0xFD, 0xE4, 0x33, +0xFC, 0x90, 0x81, 0x63, 0x31, 0xA4, 0x98, 0x40, +0x04, 0xEF, 0x24, 0x0A, 0xF0, 0x90, 0x81, 0x63, +0xE0, 0xFF, 0x24, 0x23, 0xFD, 0xE4, 0x33, 0xFC, +0x90, 0x81, 0x53, 0x31, 0xA4, 0x98, 0x40, 0x04, +0xEF, 0x24, 0x23, 0xF0, 0x90, 0x81, 0x63, 0xE0, +0xFF, 0x7E, 0x00, 0x90, 0x81, 0x57, 0xEE, 0xF0, +0xA3, 0xEF, 0xF0, 0x90, 0x05, 0x58, 0xE0, 0x6F, +0x70, 0x01, 0xE4, 0x60, 0x02, 0x31, 0xAF, 0x90, +0x81, 0x48, 0xE0, 0x54, 0xFE, 0xF0, 0x80, 0x07, +0x90, 0x81, 0x48, 0xE0, 0x44, 0x01, 0xF0, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0xE0, 0xD3, 0x9D, 0xEC, +0x64, 0x80, 0xF8, 0x74, 0x80, 0x22, 0xF0, 0x90, +0x81, 0x57, 0xA3, 0xE0, 0x90, 0x05, 0x58, 0xF0, +0x22, 0x90, 0x81, 0x5D, 0xE0, 0xFF, 0xA3, 0xE0, +0xFD, 0x90, 0x81, 0x64, 0xE0, 0xFB, 0x90, 0x82, +0x9D, 0x22, 0xE4, 0x90, 0x81, 0xC6, 0xF0, 0xA3, +0xF0, 0x90, 0x00, 0x83, 0xE0, 0x90, 0x81, 0xC5, +0xF0, 0x90, 0x00, 0x83, 0xE0, 0xFE, 0x90, 0x81, +0xC5, 0xE0, 0xFF, 0xB5, 0x06, 0x01, 0x22, 0xC3, +0x90, 0x81, 0xC7, 0xE0, 0x94, 0x64, 0x90, 0x81, +0xC6, 0xE0, 0x94, 0x00, 0x40, 0x0D, 0x90, 0x01, +0xC0, 0xE0, 0x44, 0x40, 0xF0, 0x90, 0x81, 0xC5, +0xE0, 0xFF, 0x22, 0x90, 0x81, 0xC6, 0x12, 0x5F, +0x59, 0x80, 0xC6, 0x90, 0x81, 0xBC, 0xE0, 0x60, +0x0F, 0xE4, 0xF0, 0x90, 0x05, 0x53, 0xE0, 0x44, +0x01, 0xF0, 0x90, 0x05, 0xFD, 0xE0, 0x04, 0xF0, +0x22, 0x90, 0x81, 0x41, 0xE0, 0xFF, 0x30, 0xE0, +0x3F, 0x90, 0x81, 0x45, 0xE0, 0x7E, 0x00, 0xB4, +0x02, 0x02, 0x7E, 0x01, 0x90, 0x81, 0x44, 0xE0, +0x7D, 0x00, 0xB4, 0x04, 0x02, 0x7D, 0x01, 0xED, +0x4E, 0x70, 0x25, 0xEF, 0xC3, 0x13, 0x30, 0xE0, +0x03, 0x02, 0x6E, 0xFE, 0x12, 0x57, 0x62, 0x90, +0x81, 0x45, 0xE0, 0xB4, 0x08, 0x06, 0xE4, 0xFD, +0x7F, 0x0C, 0x80, 0x09, 0x90, 0x81, 0x45, 0xE0, +0x70, 0x06, 0xFD, 0x7F, 0x04, 0x12, 0x4B, 0x1C, +0x22, 0x22, 0x51, 0x90, 0x12, 0x4F, 0xB8, 0x7F, +0x01, 0x51, 0xEF, 0x90, 0x81, 0xB7, 0xE0, 0x30, +0xE0, 0x15, 0x51, 0xD5, 0xF0, 0x90, 0x81, 0xBA, +0xE0, 0x60, 0x05, 0x14, 0xF0, 0x02, 0x4E, 0x30, +0x51, 0xE5, 0xE4, 0xFF, 0x12, 0x54, 0x89, 0x22, +0xE4, 0x90, 0x81, 0xC4, 0xF0, 0x90, 0x81, 0x4B, +0xE0, 0x60, 0x39, 0x12, 0x47, 0x6A, 0x70, 0x34, +0x51, 0xDD, 0xF0, 0x90, 0x81, 0xC4, 0x74, 0x01, +0xF0, 0xE4, 0x90, 0x81, 0x52, 0xF0, 0x90, 0x81, +0x41, 0xE0, 0x30, 0xE0, 0x16, 0x90, 0x81, 0x45, +0xE0, 0xB4, 0x02, 0x05, 0xE4, 0x90, 0x81, 0xC4, +0xF0, 0x12, 0x54, 0x44, 0xEF, 0x70, 0x04, 0x90, +0x81, 0xC4, 0xF0, 0x90, 0x81, 0xC4, 0xE0, 0x60, +0x03, 0x12, 0x49, 0x76, 0x22, 0x90, 0x81, 0xB9, +0xE0, 0x90, 0x05, 0x73, 0x22, 0x90, 0x81, 0x51, +0xE0, 0x90, 0x05, 0x73, 0x22, 0x90, 0x81, 0xB8, +0xE0, 0x14, 0x90, 0x81, 0xBA, 0xF0, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x81, +0x48, 0xE0, 0xFE, 0xC3, 0x13, 0x30, 0xE0, 0x1F, +0x90, 0x82, 0x64, 0x74, 0x1E, 0xF0, 0x90, 0x82, +0x72, 0x74, 0x01, 0xF0, 0x90, 0x82, 0x66, 0xEF, +0xF0, 0x7B, 0x01, 0x7A, 0x82, 0x79, 0x64, 0x12, +0x62, 0x0B, 0x7F, 0x04, 0x12, 0x47, 0x45, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x90, 0x81, 0x46, 0x12, +0x54, 0x3C, 0x30, 0xE0, 0x1F, 0xEF, 0x54, 0xBF, +0xF0, 0x90, 0x04, 0xE0, 0xE0, 0x90, 0x81, 0x47, +0x30, 0xE0, 0x06, 0xE0, 0x44, 0x01, 0xF0, 0x80, +0x08, 0xE0, 0x54, 0xFE, 0x71, 0x4D, 0x74, 0x04, +0xF0, 0x12, 0x47, 0xE4, 0x22, 0xF0, 0x90, 0x01, +0xB9, 0x74, 0x01, 0xF0, 0x90, 0x01, 0xB8, 0x22, +0x90, 0x81, 0x46, 0xE0, 0xFF, 0x12, 0x67, 0xD3, +0x30, 0xE0, 0x24, 0xEF, 0x54, 0x7F, 0xF0, 0x90, +0x04, 0xE0, 0xE0, 0x90, 0x81, 0x47, 0x30, 0xE1, +0x06, 0xE0, 0x44, 0x02, 0xF0, 0x80, 0x07, 0xE0, +0x54, 0xFD, 0x71, 0x4D, 0x04, 0xF0, 0x90, 0x81, +0x4B, 0xE0, 0x60, 0x03, 0x12, 0x47, 0xE4, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xE4, +0x90, 0x82, 0x83, 0xF0, 0xA3, 0xF0, 0x91, 0x49, +0x90, 0x85, 0xBB, 0x12, 0x20, 0xDA, 0xCC, 0xF0, +0x00, 0xC0, 0x7F, 0x8C, 0x12, 0x4F, 0xA9, 0x12, +0x20, 0xDA, 0x00, 0x00, 0x00, 0x14, 0x91, 0xBB, +0x90, 0x82, 0x7F, 0x12, 0x20, 0xDA, 0x00, 0x00, +0x00, 0x00, 0xE4, 0xFD, 0xFF, 0x12, 0x5F, 0x36, +0x7F, 0xE8, 0x7E, 0x08, 0x12, 0x2D, 0x5C, 0xEF, +0x54, 0x0E, 0xFF, 0xE4, 0xFE, 0xED, 0x54, 0xF4, +0xFD, 0xEC, 0x54, 0x03, 0xFC, 0xE4, 0xFB, 0xFA, +0xF9, 0xF8, 0xC3, 0x12, 0x44, 0xCF, 0x60, 0x18, +0xD3, 0x91, 0x30, 0x40, 0x09, 0x90, 0x01, 0xC3, +0xE0, 0x44, 0x02, 0xF0, 0x80, 0x0A, 0x91, 0xAD, +0x90, 0x82, 0x83, 0x12, 0x5F, 0x59, 0x80, 0xC8, +0xC3, 0x91, 0x30, 0x50, 0x1C, 0x91, 0xB4, 0xEC, +0x44, 0x80, 0xFC, 0x90, 0x82, 0x85, 0x12, 0x20, +0xCE, 0x90, 0x82, 0x85, 0x12, 0x44, 0xE0, 0x12, +0x5E, 0xAB, 0x7F, 0x7C, 0x7E, 0x08, 0x12, 0x2E, +0xA2, 0x90, 0x01, 0x00, 0x74, 0x3F, 0xF0, 0xA3, +0xE0, 0x54, 0xFD, 0xF0, 0x90, 0x05, 0x53, 0xE0, +0x44, 0x20, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x90, 0x82, 0x84, 0xE0, 0x94, 0xE8, 0x90, 0x82, +0x83, 0xE0, 0x94, 0x03, 0x22, 0x91, 0xC2, 0x7B, +0x23, 0x12, 0x4F, 0x95, 0x12, 0x57, 0xD4, 0xF0, +0x22, 0xE4, 0x90, 0x82, 0xA2, 0xF0, 0xA3, 0xF0, +0x90, 0x05, 0x22, 0xE0, 0x90, 0x82, 0xA4, 0xF0, +0x7B, 0x47, 0x12, 0x67, 0xDA, 0x90, 0x05, 0xF8, +0xE0, 0x70, 0x1B, 0xA3, 0xE0, 0x70, 0x17, 0xA3, +0xE0, 0x70, 0x13, 0xA3, 0xE0, 0x70, 0x0F, 0x90, +0x82, 0xA4, 0xE0, 0xFD, 0x7B, 0x48, 0xE4, 0xFF, +0x12, 0x4D, 0x15, 0x7F, 0x01, 0x22, 0xD3, 0x90, +0x82, 0xA3, 0xE0, 0x94, 0xE8, 0x90, 0x82, 0xA2, +0xE0, 0x94, 0x03, 0x40, 0x16, 0x90, 0x01, 0xC0, +0xE0, 0x44, 0x20, 0xF0, 0x90, 0x82, 0xA4, 0xE0, +0xFD, 0x7B, 0x5B, 0xE4, 0xFF, 0x12, 0x4D, 0x15, +0x7F, 0x00, 0x22, 0x91, 0xAD, 0x90, 0x82, 0xA2, +0x12, 0x5F, 0x59, 0x80, 0xB0, 0x7F, 0x32, 0x7E, +0x00, 0x02, 0x32, 0xAA, 0x7F, 0x7C, 0x7E, 0x08, +0x02, 0x2D, 0x5C, 0x7F, 0x70, 0x7E, 0x0E, 0x02, +0x2E, 0xA2, 0x90, 0x05, 0x27, 0xE0, 0x44, 0x40, +0xF0, 0x22, 0x7B, 0x22, 0x12, 0x4F, 0x95, 0x91, +0xC2, 0x02, 0x57, 0x8C, 0x12, 0x4D, 0x10, 0x12, +0x4F, 0x9C, 0x91, 0xC2, 0x90, 0x81, 0x45, 0x74, +0x04, 0xF0, 0x22, 0x90, 0x01, 0xC4, 0x74, 0xE3, +0xF0, 0x74, 0x74, 0xA3, 0xF0, 0x90, 0x00, 0x90, +0xE0, 0x20, 0xE0, 0xF9, 0x74, 0xE3, 0x04, 0x90, +0x01, 0xC4, 0xF0, 0x74, 0x74, 0xA3, 0xF0, 0x22, +0x90, 0x81, 0x46, 0xE0, 0x54, 0xFB, 0xF0, 0xE4, +0x90, 0x81, 0x54, 0xF0, 0xA3, 0xF0, 0x90, 0x81, +0x4F, 0xF0, 0x90, 0x81, 0x47, 0xE0, 0x54, 0xF7, +0xF0, 0x54, 0xBF, 0xF0, 0x12, 0x4F, 0xB2, 0x7D, +0x10, 0x7F, 0x03, 0x02, 0x54, 0xD4, 0x90, 0x04, +0x1A, 0xE0, 0xF4, 0x60, 0x03, 0x7F, 0x00, 0x22, +0x90, 0x04, 0x1B, 0xE0, 0x54, 0x07, 0x64, 0x07, +0x7F, 0x01, 0x60, 0x02, 0x7F, 0x00, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xB1, 0x26, +0xEF, 0x64, 0x01, 0x60, 0x05, 0x75, 0x0D, 0x01, +0x80, 0x42, 0x90, 0x81, 0x4F, 0xE0, 0xFF, 0x54, +0x03, 0x60, 0x05, 0x75, 0x0D, 0x02, 0x80, 0x34, +0xEF, 0x30, 0xE2, 0x05, 0x75, 0x0D, 0x08, 0x80, +0x2B, 0x90, 0x81, 0x4F, 0xE0, 0x30, 0xE4, 0x05, +0x75, 0x0D, 0x10, 0x80, 0x1F, 0x12, 0x6F, 0x8C, +0x20, 0xE0, 0x05, 0x75, 0x0D, 0x20, 0x80, 0x14, +0xB1, 0xB0, 0x8F, 0x0E, 0xE5, 0x0E, 0x64, 0x01, +0x60, 0x05, 0x85, 0x0E, 0x0D, 0x80, 0x05, 0x12, +0x5F, 0xC0, 0x80, 0x0E, 0x90, 0x01, 0xB9, 0x74, +0x04, 0xF0, 0x90, 0x01, 0xB8, 0xE5, 0x0D, 0xF0, +0x7F, 0x00, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xB1, +0x26, 0xEF, 0x70, 0x03, 0x12, 0x67, 0x8F, 0x22, +0x90, 0x81, 0x4D, 0xE0, 0xD3, 0x94, 0x00, 0x40, +0x06, 0x75, 0x58, 0x04, 0x7F, 0xFF, 0x22, 0x90, +0x81, 0xAE, 0xE0, 0x60, 0x06, 0x75, 0x58, 0x80, +0x7F, 0xFF, 0x22, 0x7F, 0x01, 0x22, 0xEF, 0x24, +0xFE, 0x60, 0x0B, 0x04, 0x70, 0x24, 0x90, 0x81, +0x51, 0x74, 0x02, 0xF0, 0x80, 0x13, 0xED, 0x70, +0x06, 0x90, 0x81, 0xAB, 0xE0, 0x80, 0x02, 0xED, +0x14, 0x90, 0x81, 0x51, 0xF0, 0x90, 0x81, 0x51, +0xE0, 0xA3, 0xF0, 0x90, 0x81, 0x47, 0xE0, 0x44, +0x08, 0xF0, 0x22, 0x7B, 0x2E, 0xD1, 0x0F, 0x7D, +0x02, 0x7F, 0x01, 0x12, 0x49, 0xD1, 0xD1, 0x16, +0x90, 0x81, 0x45, 0x74, 0x02, 0xF0, 0x22, 0x7D, +0x6F, 0x7F, 0xFF, 0x02, 0x4D, 0x15, 0x90, 0x05, +0x27, 0xE0, 0x54, 0xBF, 0xF0, 0x22, 0xE4, 0xF5, +0x4E, 0x90, 0x81, 0x4B, 0xE0, 0x60, 0x3B, 0x12, +0x47, 0x6A, 0x70, 0x36, 0x90, 0x81, 0x49, 0xE0, +0xFF, 0xC4, 0x54, 0x0F, 0x60, 0x09, 0x90, 0x81, +0x47, 0x12, 0x54, 0x3C, 0x20, 0xE0, 0x03, 0x75, +0x4E, 0x01, 0x90, 0x81, 0x41, 0xE0, 0x30, 0xE0, +0x12, 0x90, 0x81, 0x45, 0xE0, 0xB4, 0x02, 0x03, +0xE4, 0xF5, 0x4E, 0x12, 0x54, 0x44, 0xEF, 0x70, +0x02, 0xF5, 0x4E, 0xE5, 0x4E, 0x60, 0x03, 0x12, +0x49, 0x76, 0x22, 0x90, 0x81, 0xAF, 0xE0, 0x54, +0xFE, 0xF0, 0x54, 0xFD, 0xF0, 0x54, 0xEF, 0xF0, +0x44, 0x08, 0xF0, 0x22, 0x90, 0x81, 0xAF, 0xE0, +0x30, 0xE0, 0x34, 0xC4, 0x13, 0x54, 0x07, 0x30, +0xE0, 0x2D, 0x90, 0x82, 0xAF, 0xE0, 0x04, 0xF0, +0xE0, 0xD3, 0x94, 0xC8, 0x40, 0x21, 0x90, 0x81, +0xAF, 0xE0, 0x54, 0xDF, 0xF0, 0xE4, 0x90, 0x82, +0xAF, 0xF0, 0x90, 0x81, 0xAF, 0xE0, 0x13, 0x30, +0xE0, 0x0D, 0x90, 0x81, 0x46, 0xE0, 0x44, 0x01, +0xF0, 0x90, 0x81, 0x56, 0x74, 0xD0, 0xF0, 0x22, +0x12, 0x4D, 0x70, 0x7B, 0x24, 0x02, 0x4F, 0xEC, +0x7B, 0x25, 0x02, 0x4F, 0xEC, 0xAE, 0x07, 0x12, +0x54, 0x44, 0xBF, 0x01, 0x0F, 0xD1, 0xD7, 0x20, +0xE0, 0x0A, 0xAF, 0x06, 0x7D, 0x01, 0x12, 0x4B, +0x1C, 0x7F, 0x01, 0x22, 0x7F, 0x00, 0x22, 0x90, +0x81, 0x41, 0xE0, 0xC4, 0x13, 0x13, 0x54, 0x03, +0x22, 0x90, 0x80, 0x46, 0xE0, 0xFF, 0x90, 0x82, +0x8A, 0xE0, 0xFB, 0x90, 0x82, 0x95, 0x74, 0x0A, +0xF0, 0x7D, 0x01, 0x12, 0x66, 0x0E, 0x90, 0x82, +0x8B, 0xEE, 0xF0, 0xFC, 0xA3, 0xEF, 0xF0, 0xFD, +0x90, 0x82, 0x89, 0xE0, 0xFF, 0x12, 0x67, 0x02, +0x90, 0x82, 0x8B, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, +0x90, 0x04, 0x80, 0xE0, 0x54, 0x0F, 0xFD, 0xAC, +0x07, 0xF1, 0x7C, 0x44, 0x01, 0xF0, 0xF1, 0x7C, +0x54, 0xFB, 0xF0, 0xAC, 0x07, 0x74, 0x16, 0x2C, +0x12, 0x67, 0x48, 0xE0, 0x44, 0xFA, 0xF0, 0x74, +0x15, 0x2C, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, +0x83, 0xE0, 0x44, 0x1F, 0xF0, 0xAC, 0x07, 0x74, +0x06, 0x2C, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, +0x83, 0xE0, 0x44, 0x0F, 0xF0, 0x90, 0x04, 0x53, +0xE4, 0xF0, 0x90, 0x04, 0x52, 0xF0, 0x90, 0x04, +0x51, 0x74, 0xFF, 0xF0, 0x90, 0x04, 0x50, 0x74, +0xFD, 0xF0, 0x74, 0x14, 0x2C, 0xF1, 0x74, 0xE0, +0x54, 0xC0, 0x4D, 0xFD, 0x74, 0x14, 0x2F, 0xF1, +0x74, 0xED, 0xF0, 0x22, 0xF5, 0x82, 0xE4, 0x34, +0xFC, 0xF5, 0x83, 0x22, 0x74, 0x11, 0x2C, 0xF5, +0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x22, +0xE4, 0xFE, 0xEF, 0xC3, 0x13, 0xFD, 0xEF, 0x30, +0xE0, 0x02, 0x7E, 0x80, 0x90, 0xFD, 0x10, 0xED, +0xF0, 0xAF, 0x06, 0x22, 0x7E, 0x00, 0x7F, 0x04, +0x7D, 0x00, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0xB7, +0x22, 0xE0, 0x90, 0x01, 0xBA, 0xF0, 0x90, 0x81, +0x4D, 0xE0, 0x90, 0x01, 0xBB, 0x22, 0xEF, 0x13, +0x13, 0x13, 0x54, 0x1F, 0xFE, 0xEF, 0x54, 0x07, +0xFF, 0x22, 0x90, 0x81, 0xAF, 0xE0, 0xC3, 0x13, +0x22, 0x90, 0x82, 0x3B, 0x12, 0x45, 0x26, 0x02, +0x1F, 0xA4, 0xAB, 0x54, 0xAA, 0x55, 0xA9, 0x56, +0x02, 0x1F, 0xA4, 0x90, 0x06, 0x04, 0xE0, 0x54, +0x7F, 0xF0, 0x22, 0x90, 0x06, 0x04, 0xE0, 0x44, +0x40, 0xF0, 0x22, 0x90, 0x81, 0x46, 0xE0, 0x54, +0xBF, 0xF0, 0x22, 0x7D, 0x01, 0x7F, 0x04, 0x02, +0x4B, 0x1C, 0x0D, 0xBC +}; + +u32 array_length_mp_8188e_t_fw_nic_89em = 14364; + +#ifdef CONFIG_WOWLAN + +u8 array_mp_8188e_t_fw_wowlan[] = { +0xE1, 0x88, 0x30, 0x00, 0x1C, 0x00, 0x00, 0x00, +0x05, 0x05, 0x14, 0x27, 0xE4, 0x3F, 0x00, 0x00, +0xA5, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x02, 0x47, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xE1, 0xFD, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xE1, 0xAD, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x02, 0x50, 0x02, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xE7, 0x09, 0xF6, 0x08, 0xDF, 0xFA, 0x80, 0x46, +0xE7, 0x09, 0xF2, 0x08, 0xDF, 0xFA, 0x80, 0x3E, +0x88, 0x82, 0x8C, 0x83, 0xE7, 0x09, 0xF0, 0xA3, +0xDF, 0xFA, 0x80, 0x32, 0xE3, 0x09, 0xF6, 0x08, +0xDF, 0xFA, 0x80, 0x78, 0xE3, 0x09, 0xF2, 0x08, +0xDF, 0xFA, 0x80, 0x70, 0x88, 0x82, 0x8C, 0x83, +0xE3, 0x09, 0xF0, 0xA3, 0xDF, 0xFA, 0x80, 0x64, +0x89, 0x82, 0x8A, 0x83, 0xE0, 0xA3, 0xF6, 0x08, +0xDF, 0xFA, 0x80, 0x58, 0x89, 0x82, 0x8A, 0x83, +0xE0, 0xA3, 0xF2, 0x08, 0xDF, 0xFA, 0x80, 0x4C, +0x80, 0xD2, 0x80, 0xFA, 0x80, 0xC6, 0x80, 0xD4, +0x80, 0x69, 0x80, 0xF2, 0x80, 0x33, 0x80, 0x10, +0x80, 0xA6, 0x80, 0xEA, 0x80, 0x9A, 0x80, 0xA8, +0x80, 0xDA, 0x80, 0xE2, 0x80, 0xCA, 0x80, 0x33, +0x89, 0x82, 0x8A, 0x83, 0xEC, 0xFA, 0xE4, 0x93, +0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, 0xC5, 0x83, +0xCC, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, +0xC5, 0x83, 0xCC, 0xDF, 0xE9, 0xDE, 0xE7, 0x80, +0x0D, 0x89, 0x82, 0x8A, 0x83, 0xE4, 0x93, 0xA3, +0xF6, 0x08, 0xDF, 0xF9, 0xEC, 0xFA, 0xA9, 0xF0, +0xED, 0xFB, 0x22, 0x89, 0x82, 0x8A, 0x83, 0xEC, +0xFA, 0xE0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, +0xC5, 0x83, 0xCC, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, +0xC8, 0xCC, 0xC5, 0x83, 0xCC, 0xDF, 0xEA, 0xDE, +0xE8, 0x80, 0xDB, 0x89, 0x82, 0x8A, 0x83, 0xE4, +0x93, 0xA3, 0xF2, 0x08, 0xDF, 0xF9, 0x80, 0xCC, +0x88, 0xF0, 0xEF, 0x60, 0x01, 0x0E, 0x4E, 0x60, +0xC3, 0x88, 0xF0, 0xED, 0x24, 0x02, 0xB4, 0x04, +0x00, 0x50, 0xB9, 0xF5, 0x82, 0xEB, 0x24, 0x02, +0xB4, 0x04, 0x00, 0x50, 0xAF, 0x23, 0x23, 0x45, +0x82, 0x23, 0x90, 0x41, 0x50, 0x73, 0xC5, 0xF0, +0xF8, 0xA3, 0xE0, 0x28, 0xF0, 0xC5, 0xF0, 0xF8, +0xE5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83, +0xE0, 0x38, 0xF0, 0x22, 0xC3, 0xEF, 0x9B, 0xFF, +0xEE, 0x9A, 0xFE, 0xED, 0x99, 0xFD, 0xEC, 0x98, +0xFC, 0x22, 0xEF, 0x4B, 0xFF, 0xEE, 0x4A, 0xFE, +0xED, 0x49, 0xFD, 0xEC, 0x48, 0xFC, 0x22, 0xEB, +0x9F, 0xF5, 0xF0, 0xEA, 0x9E, 0x42, 0xF0, 0xE9, +0x9D, 0x42, 0xF0, 0xE8, 0x9C, 0x45, 0xF0, 0x22, +0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, +0xA3, 0xE0, 0xFF, 0x22, 0xE0, 0xF8, 0xA3, 0xE0, +0xF9, 0xA3, 0xE0, 0xFA, 0xA3, 0xE0, 0xFB, 0x22, +0xA4, 0x25, 0x82, 0xF5, 0x82, 0xE5, 0xF0, 0x35, +0x83, 0xF5, 0x83, 0x22, 0xE0, 0xFB, 0xA3, 0xE0, +0xFA, 0xA3, 0xE0, 0xF9, 0x22, 0xEB, 0xF0, 0xA3, +0xEA, 0xF0, 0xA3, 0xE9, 0xF0, 0x22, 0xD0, 0x83, +0xD0, 0x82, 0xF8, 0xE4, 0x93, 0x70, 0x12, 0x74, +0x01, 0x93, 0x70, 0x0D, 0xA3, 0xA3, 0x93, 0xF8, +0x74, 0x01, 0x93, 0xF5, 0x82, 0x88, 0x83, 0xE4, +0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xEF, 0xA3, +0xA3, 0xA3, 0x80, 0xDF, 0xE3, 0xF5, 0xF0, 0x09, +0xE2, 0x08, 0xB5, 0xF0, 0x6B, 0xDF, 0xF5, 0x80, +0x67, 0xE3, 0xF5, 0xF0, 0x09, 0xE6, 0x08, 0xB5, +0xF0, 0x5E, 0xDF, 0xF5, 0x80, 0x5A, 0x87, 0xF0, +0x09, 0xE6, 0x08, 0xB5, 0xF0, 0x52, 0xDF, 0xF6, +0x80, 0x4E, 0x87, 0xF0, 0x09, 0xE2, 0x08, 0xB5, +0xF0, 0x46, 0xDF, 0xF6, 0x80, 0x42, 0x88, 0x82, +0x8C, 0x83, 0x87, 0xF0, 0x09, 0xE0, 0xA3, 0xB5, +0xF0, 0x36, 0xDF, 0xF6, 0x80, 0x32, 0x88, 0x82, +0x8C, 0x83, 0x87, 0xF0, 0x09, 0xE4, 0x93, 0xA3, +0xB5, 0xF0, 0x25, 0xDF, 0xF5, 0x80, 0x21, 0x88, +0x82, 0x8C, 0x83, 0xE3, 0xF5, 0xF0, 0x09, 0xE0, +0xA3, 0xB5, 0xF0, 0x14, 0xDF, 0xF5, 0x80, 0x10, +0x88, 0x82, 0x8C, 0x83, 0xE3, 0xF5, 0xF0, 0x09, +0xE4, 0x93, 0xA3, 0xB5, 0xF0, 0x02, 0xDF, 0xF4, +0x02, 0x43, 0xC3, 0x80, 0x87, 0x80, 0xE9, 0x80, +0x90, 0x80, 0xD4, 0x80, 0x3E, 0x80, 0x15, 0x80, +0x6E, 0x80, 0x7E, 0x80, 0x9D, 0x80, 0xB7, 0x80, +0x8D, 0x80, 0xA3, 0x80, 0x51, 0x80, 0x74, 0x80, +0x3C, 0x02, 0x43, 0xCF, 0x89, 0x82, 0x8A, 0x83, +0xEC, 0xFA, 0xE4, 0x93, 0xF5, 0xF0, 0xA3, 0xC8, +0xC5, 0x82, 0xC8, 0xCC, 0xC5, 0x83, 0xCC, 0xE4, +0x93, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, 0xC5, +0x83, 0xCC, 0xB5, 0xF0, 0x76, 0xDF, 0xE3, 0xDE, +0xE1, 0x80, 0x70, 0x89, 0x82, 0x8A, 0x83, 0xE4, +0x93, 0xF5, 0xF0, 0xA3, 0xE2, 0x08, 0xB5, 0xF0, +0x62, 0xDF, 0xF4, 0x80, 0x5E, 0x89, 0x82, 0x8A, +0x83, 0xE0, 0xF5, 0xF0, 0xA3, 0xE6, 0x08, 0xB5, +0xF0, 0x51, 0xDF, 0xF5, 0x80, 0x4D, 0x89, 0x82, +0x8A, 0x83, 0xE0, 0xF5, 0xF0, 0xA3, 0xE2, 0x08, +0xB5, 0xF0, 0x40, 0xDF, 0xF5, 0x80, 0x3C, 0x89, +0x82, 0x8A, 0x83, 0xE4, 0x93, 0xF5, 0xF0, 0xA3, +0xE6, 0x08, 0xB5, 0xF0, 0x2E, 0xDF, 0xF4, 0x80, +0x2A, 0x80, 0x02, 0x80, 0x57, 0x89, 0x82, 0x8A, +0x83, 0xEC, 0xFA, 0xE4, 0x93, 0xF5, 0xF0, 0xA3, +0xC8, 0xC5, 0x82, 0xC8, 0xCC, 0xC5, 0x83, 0xCC, +0xE0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, 0xC5, +0x83, 0xCC, 0xB5, 0xF0, 0x06, 0xDF, 0xE4, 0xDE, +0xE2, 0x80, 0x00, 0x7F, 0xFF, 0xB5, 0xF0, 0x02, +0x0F, 0x22, 0x40, 0x02, 0x7F, 0x01, 0x22, 0x89, +0x82, 0x8A, 0x83, 0xEC, 0xFA, 0xE0, 0xF5, 0xF0, +0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, 0xC5, 0x83, +0xCC, 0xE0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, +0xC5, 0x83, 0xCC, 0xB5, 0xF0, 0xD5, 0xDF, 0xE5, +0xDE, 0xE3, 0x80, 0xCF, 0x89, 0x82, 0x8A, 0x83, +0xEC, 0xFA, 0xE0, 0xF5, 0xF0, 0xA3, 0xC8, 0xC5, +0x82, 0xC8, 0xCC, 0xC5, 0x83, 0xCC, 0xE4, 0x93, +0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, 0xC5, 0x83, +0xCC, 0xB5, 0xF0, 0xAF, 0xDF, 0xE4, 0xDE, 0xE2, +0x80, 0xA9, 0x88, 0xF0, 0xEF, 0x60, 0x01, 0x0E, +0x4E, 0x60, 0xAB, 0xED, 0x24, 0x02, 0xB4, 0x04, +0x00, 0x50, 0x98, 0xF5, 0x82, 0xEB, 0x24, 0x02, +0xB4, 0x04, 0x00, 0x50, 0x8E, 0x23, 0x23, 0x45, +0x82, 0x23, 0x90, 0x43, 0x0B, 0x73, 0xEF, 0x4E, +0x60, 0x12, 0xEF, 0x60, 0x01, 0x0E, 0xED, 0xBB, +0x01, 0x0B, 0x89, 0x82, 0x8A, 0x83, 0xF0, 0xA3, +0xDF, 0xFC, 0xDE, 0xFA, 0x22, 0x89, 0xF0, 0x50, +0x07, 0xF7, 0x09, 0xDF, 0xFC, 0xA9, 0xF0, 0x22, +0xBB, 0xFE, 0xFC, 0xF3, 0x09, 0xDF, 0xFC, 0xA9, +0xF0, 0x22, 0xC2, 0xAF, 0x80, 0xFE, 0x32, 0x12, +0x44, 0x6E, 0x85, 0xD0, 0x0B, 0x75, 0xD0, 0x08, +0xAA, 0xE0, 0xC2, 0x8C, 0xE5, 0x8A, 0x24, 0x67, +0xF5, 0x8A, 0xE5, 0x8C, 0x34, 0x79, 0xF5, 0x8C, +0xD2, 0x8C, 0xEC, 0x24, 0x87, 0xF8, 0xE6, 0xBC, +0x02, 0x02, 0x74, 0xFF, 0xC3, 0x95, 0x81, 0xB4, +0x40, 0x00, 0x40, 0xCE, 0x79, 0x03, 0x78, 0x80, +0x16, 0xE6, 0x08, 0x70, 0x0B, 0xC2, 0xAF, 0xE6, +0x30, 0xE1, 0x03, 0x44, 0x18, 0xF6, 0xD2, 0xAF, +0x08, 0xD9, 0xED, 0xEA, 0x8B, 0xD0, 0x22, 0xE5, +0x0C, 0xFF, 0x23, 0x24, 0x81, 0xF8, 0x0F, 0x08, +0x08, 0xBF, 0x03, 0x04, 0x7F, 0x00, 0x78, 0x81, +0xE6, 0x30, 0xE4, 0xF2, 0x00, 0xE5, 0x0C, 0xC3, +0x9F, 0x50, 0x20, 0x05, 0x0C, 0x74, 0x86, 0x25, +0x0C, 0xF8, 0xE6, 0xFD, 0xA6, 0x81, 0x08, 0xE6, +0xAE, 0x0C, 0xBE, 0x02, 0x02, 0x74, 0xFF, 0xCD, +0xF8, 0xE8, 0x6D, 0x60, 0xE0, 0x08, 0xE6, 0xC0, +0xE0, 0x80, 0xF6, 0xE5, 0x0C, 0xD3, 0x9F, 0x40, +0x27, 0xE5, 0x0C, 0x24, 0x87, 0xF8, 0xE6, 0xAE, +0x0C, 0xBE, 0x02, 0x02, 0x74, 0xFF, 0xFD, 0x18, +0xE6, 0xCD, 0xF8, 0xE5, 0x81, 0x6D, 0x60, 0x06, +0xD0, 0xE0, 0xF6, 0x18, 0x80, 0xF5, 0xE5, 0x0C, +0x24, 0x86, 0xC8, 0xF6, 0x15, 0x0C, 0x80, 0xD3, +0xE5, 0x0C, 0x23, 0x24, 0x81, 0xF8, 0x7F, 0x04, +0xC2, 0xAF, 0xE6, 0x30, 0xE0, 0x03, 0x10, 0xE2, +0x0C, 0x7F, 0x00, 0x30, 0xE1, 0x07, 0x30, 0xE3, +0x04, 0x7F, 0x08, 0x54, 0xF4, 0x54, 0x7C, 0xC6, +0xD2, 0xAF, 0x54, 0x80, 0x42, 0x07, 0x22, 0x78, +0x86, 0xA6, 0x81, 0x74, 0x02, 0x60, 0x06, 0xFF, +0x08, 0x76, 0xFF, 0xDF, 0xFB, 0x7F, 0x03, 0xE4, +0x78, 0x80, 0xF6, 0x08, 0xF6, 0x08, 0xDF, 0xFA, +0x78, 0x81, 0x76, 0x30, 0x90, 0x47, 0xA7, 0x74, +0x01, 0x93, 0xC0, 0xE0, 0xE4, 0x93, 0xC0, 0xE0, +0x43, 0x89, 0x01, 0x75, 0x8A, 0x60, 0x75, 0x8C, +0x79, 0xD2, 0x8C, 0xD2, 0xAF, 0x22, 0x02, 0xEF, +0xD3, 0x94, 0x02, 0x40, 0x03, 0x7F, 0xFF, 0x22, +0x74, 0x81, 0x2F, 0x2F, 0xF8, 0xE6, 0x20, 0xE5, +0xF4, 0xC2, 0xAF, 0xE6, 0x44, 0x30, 0xF6, 0xD2, +0xAF, 0xAE, 0x0C, 0xEE, 0xC3, 0x9F, 0x50, 0x21, +0x0E, 0x74, 0x86, 0x2E, 0xF8, 0xE6, 0xF9, 0x08, +0xE6, 0x18, 0xBE, 0x02, 0x02, 0x74, 0xFF, 0xFD, +0xED, 0x69, 0x60, 0x09, 0x09, 0xE7, 0x19, 0x19, +0xF7, 0x09, 0x09, 0x80, 0xF3, 0x16, 0x16, 0x80, +0xDA, 0xEE, 0xD3, 0x9F, 0x40, 0x04, 0x05, 0x81, +0x05, 0x81, 0xEE, 0xD3, 0x9F, 0x40, 0x22, 0x74, +0x86, 0x2E, 0xF8, 0x08, 0xE6, 0xF9, 0xEE, 0xB5, +0x0C, 0x02, 0xA9, 0x81, 0x18, 0x06, 0x06, 0xE6, +0xFD, 0xED, 0x69, 0x60, 0x09, 0x19, 0x19, 0xE7, +0x09, 0x09, 0xF7, 0x19, 0x80, 0xF3, 0x1E, 0x80, +0xD9, 0xEF, 0x24, 0x86, 0xF8, 0xE6, 0x04, 0xF8, +0xEF, 0x2F, 0x04, 0x90, 0x47, 0xA7, 0x93, 0xF6, +0x08, 0xEF, 0x2F, 0x93, 0xF6, 0x7F, 0x00, 0x22, +0xEF, 0xD3, 0x94, 0x02, 0x40, 0x03, 0x7F, 0xFF, +0x22, 0xEF, 0x23, 0x24, 0x81, 0xF8, 0xE6, 0x30, +0xE5, 0xF4, 0xC2, 0xAF, 0xE6, 0x54, 0x8C, 0xF6, +0xD2, 0xAF, 0xE5, 0x0C, 0xB5, 0x07, 0x0A, 0x74, +0x86, 0x2F, 0xF8, 0xE6, 0xF5, 0x81, 0x02, 0x44, +0xB7, 0x50, 0x2E, 0x74, 0x87, 0x2F, 0xF8, 0xE6, +0xBF, 0x02, 0x02, 0x74, 0xFF, 0xFD, 0x18, 0xE6, +0xF9, 0x74, 0x86, 0x2F, 0xF8, 0xFB, 0xE6, 0xFC, +0xE9, 0x6C, 0x60, 0x08, 0xA8, 0x05, 0xE7, 0xF6, +0x1D, 0x19, 0x80, 0xF4, 0xA8, 0x03, 0xA6, 0x05, +0x1F, 0xE5, 0x0C, 0xB5, 0x07, 0xE3, 0x7F, 0x00, +0x22, 0x74, 0x87, 0x2F, 0xF8, 0xE6, 0xFD, 0x18, +0x86, 0x01, 0x0F, 0x74, 0x86, 0x2F, 0xF8, 0xA6, +0x01, 0x08, 0x86, 0x04, 0xE5, 0x0C, 0xB5, 0x07, +0x02, 0xAC, 0x81, 0xED, 0x6C, 0x60, 0x08, 0x0D, +0x09, 0xA8, 0x05, 0xE6, 0xF7, 0x80, 0xF4, 0xE5, +0x0C, 0xB5, 0x07, 0xDE, 0x89, 0x81, 0x7F, 0x00, +0x22, 0xEF, 0xD3, 0x94, 0x02, 0x40, 0x03, 0x7F, +0xFF, 0x22, 0xEF, 0x23, 0x24, 0x81, 0xF8, 0xC2, +0xAF, 0xE6, 0x30, 0xE5, 0x05, 0x30, 0xE0, 0x02, +0xD2, 0xE4, 0xD2, 0xE2, 0xC6, 0xD2, 0xAF, 0x7F, +0x00, 0x30, 0xE2, 0x01, 0x0F, 0x02, 0x44, 0xB6, +0x8F, 0xF0, 0xE4, 0xFF, 0xFE, 0xE5, 0x0C, 0x23, +0x24, 0x80, 0xF8, 0xC2, 0xA9, 0x30, 0xF7, 0x0D, +0x7F, 0x08, 0xE6, 0x60, 0x0B, 0x2D, 0xF6, 0x60, +0x30, 0x50, 0x2E, 0x80, 0x07, 0x30, 0xF1, 0x06, +0xED, 0xF6, 0x60, 0x25, 0x7E, 0x02, 0x08, 0x30, +0xF0, 0x10, 0xC2, 0xAF, 0xE6, 0x10, 0xE7, 0x23, +0x0E, 0x30, 0xE2, 0x0C, 0xD2, 0xAF, 0x7F, 0x04, +0x80, 0x12, 0xC2, 0xAF, 0xE6, 0x10, 0xE7, 0x13, +0x54, 0xEC, 0x4E, 0xF6, 0xD2, 0xAF, 0x02, 0x44, +0xB7, 0x7F, 0x08, 0x08, 0xEF, 0x44, 0x83, 0xF4, +0xC2, 0xAF, 0x56, 0xC6, 0xD2, 0xAF, 0x54, 0x80, +0x4F, 0xFF, 0x22, 0x02, 0x47, 0x51, 0x02, 0x45, +0x47, 0xE4, 0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, +0x40, 0x03, 0xF6, 0x80, 0x01, 0xF2, 0x08, 0xDF, +0xF4, 0x80, 0x29, 0xE4, 0x93, 0xA3, 0xF8, 0x54, +0x07, 0x24, 0x0C, 0xC8, 0xC3, 0x33, 0xC4, 0x54, +0x0F, 0x44, 0x20, 0xC8, 0x83, 0x40, 0x04, 0xF4, +0x56, 0x80, 0x01, 0x46, 0xF6, 0xDF, 0xE4, 0x80, +0x0B, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, +0x80, 0x90, 0x47, 0x96, 0xE4, 0x7E, 0x01, 0x93, +0x60, 0xBC, 0xA3, 0xFF, 0x54, 0x3F, 0x30, 0xE5, +0x09, 0x54, 0x1F, 0xFE, 0xE4, 0x93, 0xA3, 0x60, +0x01, 0x0E, 0xCF, 0x54, 0xC0, 0x25, 0xE0, 0x60, +0xA8, 0x40, 0xB8, 0xE4, 0x93, 0xA3, 0xFA, 0xE4, +0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0xC8, 0xC5, +0x82, 0xC8, 0xCA, 0xC5, 0x83, 0xCA, 0xF0, 0xA3, +0xC8, 0xC5, 0x82, 0xC8, 0xCA, 0xC5, 0x83, 0xCA, +0xDF, 0xE9, 0xDE, 0xE7, 0x80, 0xBE, 0x41, 0x84, +0x92, 0x00, 0x41, 0x84, 0x93, 0x00, 0x41, 0x84, +0xA3, 0x00, 0x41, 0x84, 0xA4, 0x00, 0x00, 0x60, +0x16, 0x67, 0xFC, 0x6A, 0x33, 0xC0, 0xE0, 0xC0, +0xF0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0xD0, 0x75, +0xD0, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x02, +0xC0, 0x03, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, +0xC0, 0x07, 0x90, 0x01, 0xC4, 0x74, 0xAD, 0xF0, +0x74, 0x47, 0xA3, 0xF0, 0x12, 0x78, 0x9A, 0x74, +0xAD, 0x04, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x47, +0xA3, 0xF0, 0xD0, 0x07, 0xD0, 0x06, 0xD0, 0x05, +0xD0, 0x04, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, +0xD0, 0x00, 0xD0, 0xD0, 0xD0, 0x82, 0xD0, 0x83, +0xD0, 0xF0, 0xD0, 0xE0, 0x32, 0xC0, 0xE0, 0xC0, +0xF0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0xD0, 0x75, +0xD0, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x02, +0xC0, 0x03, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, +0xC0, 0x07, 0x90, 0x01, 0xC4, 0x74, 0xFD, 0xF0, +0x74, 0x47, 0xA3, 0xF0, 0x12, 0x78, 0xD4, 0xE5, +0x41, 0x30, 0xE3, 0x03, 0x12, 0x79, 0x31, 0xE5, +0x41, 0x30, 0xE4, 0x03, 0x12, 0x50, 0xDE, 0xE5, +0x43, 0x30, 0xE0, 0x03, 0x12, 0x79, 0x7A, 0xE5, +0x43, 0x30, 0xE1, 0x02, 0x11, 0x9B, 0xE5, 0x43, +0x30, 0xE2, 0x03, 0x12, 0x77, 0x6F, 0xE5, 0x43, +0x30, 0xE3, 0x02, 0xF1, 0xE1, 0xE5, 0x43, 0x30, +0xE4, 0x03, 0x12, 0x72, 0x73, 0xE5, 0x43, 0x30, +0xE5, 0x03, 0x12, 0x71, 0x2B, 0xE5, 0x43, 0x30, +0xE6, 0x03, 0x12, 0x72, 0x38, 0xE5, 0x44, 0x30, +0xE1, 0x03, 0x12, 0x77, 0x43, 0x74, 0xFD, 0x04, +0x90, 0x01, 0xC4, 0xF0, 0x74, 0x47, 0xA3, 0xF0, +0xD0, 0x07, 0xD0, 0x06, 0xD0, 0x05, 0xD0, 0x04, +0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, +0xD0, 0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, +0xD0, 0xE0, 0x32, 0x90, 0x81, 0x0A, 0xE0, 0x70, +0x02, 0x21, 0x2B, 0x90, 0x81, 0x21, 0xE0, 0x04, +0x31, 0x37, 0x12, 0x42, 0x1A, 0xC0, 0x04, 0xC0, +0x05, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x05, 0x62, +0x31, 0x51, 0x78, 0x10, 0x12, 0x20, 0xBB, 0xD0, +0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, +0x42, 0x1A, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, +0xC0, 0x07, 0xA3, 0x31, 0x51, 0x78, 0x18, 0x12, +0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, +0xD0, 0x00, 0x12, 0x42, 0x1A, 0x90, 0x81, 0x55, +0x12, 0x7F, 0x4E, 0x54, 0x7F, 0xF0, 0xA3, 0xE0, +0x30, 0xE0, 0x0C, 0x12, 0x76, 0xFA, 0x74, 0x05, +0xF0, 0x12, 0x75, 0xBF, 0x12, 0x77, 0x12, 0x12, +0x73, 0x7C, 0x54, 0x1F, 0x30, 0xE0, 0x0D, 0x90, +0x01, 0x3B, 0xE0, 0x30, 0xE4, 0x06, 0x12, 0x6F, +0xB5, 0x12, 0x6F, 0xDB, 0x90, 0x84, 0x9C, 0xE0, +0x04, 0xF0, 0xE0, 0xC3, 0x94, 0x80, 0x40, 0x0B, +0x90, 0x01, 0x98, 0xE0, 0x54, 0xFE, 0xF0, 0xE0, +0x44, 0x01, 0xF0, 0x12, 0x74, 0x45, 0x12, 0x7B, +0xD6, 0xE4, 0x90, 0x83, 0xC7, 0xF0, 0x22, 0xF0, +0x90, 0x05, 0x61, 0xE0, 0xFF, 0xE4, 0xFC, 0xFD, +0xFE, 0x78, 0x08, 0x12, 0x20, 0xBB, 0xA8, 0x04, +0xA9, 0x05, 0xAA, 0x06, 0xAB, 0x07, 0x90, 0x05, +0x60, 0xE0, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x22, +0xE4, 0x90, 0x83, 0xDD, 0xF0, 0x90, 0x81, 0x0A, +0xE0, 0x60, 0x59, 0xF1, 0xA8, 0x64, 0x01, 0x70, +0x53, 0x12, 0x77, 0x22, 0x31, 0x37, 0x12, 0x42, +0x1A, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, +0x07, 0x90, 0x05, 0x62, 0x31, 0x51, 0x78, 0x10, +0x12, 0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0, +0x01, 0xD0, 0x00, 0x12, 0x42, 0x1A, 0xC0, 0x04, +0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0xA3, 0x31, +0x51, 0x78, 0x18, 0x12, 0x20, 0xBB, 0xD0, 0x03, +0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, 0x7F, +0x48, 0x44, 0x80, 0xF0, 0x90, 0x83, 0xDD, 0x74, +0x01, 0xF0, 0xE4, 0x90, 0x81, 0x11, 0xF0, 0x04, +0x60, 0x02, 0x51, 0x24, 0x22, 0xE4, 0xF5, 0x4E, +0x90, 0x81, 0x0A, 0xE0, 0x60, 0x5D, 0xF1, 0xA8, +0x64, 0x01, 0x70, 0x57, 0x31, 0x38, 0x12, 0x42, +0x1A, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, +0x07, 0x90, 0x05, 0x62, 0x31, 0x51, 0x78, 0x10, +0x12, 0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0, +0x01, 0xD0, 0x00, 0x12, 0x42, 0x1A, 0xC0, 0x04, +0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0xA3, 0x31, +0x51, 0x78, 0x18, 0x12, 0x20, 0xBB, 0xD0, 0x03, +0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, 0x7F, +0x48, 0x44, 0x80, 0xF0, 0x12, 0x77, 0x3A, 0x60, +0x09, 0x90, 0x81, 0x06, 0x12, 0x77, 0x2A, 0x20, +0xE0, 0x03, 0x75, 0x4E, 0x01, 0xE5, 0x4E, 0x60, +0x02, 0x51, 0x24, 0x22, 0x90, 0x81, 0x0E, 0xE0, +0x44, 0x10, 0xF0, 0x90, 0x81, 0x13, 0xE0, 0x60, +0x04, 0x64, 0x01, 0x70, 0x11, 0xE4, 0xF5, 0x1D, +0x90, 0x81, 0x13, 0xE0, 0x51, 0x63, 0x51, 0x72, +0x90, 0x81, 0x13, 0xE0, 0x80, 0x0D, 0xE4, 0xF5, +0x1D, 0x12, 0x76, 0x8F, 0x51, 0x63, 0x51, 0x72, +0x12, 0x76, 0x8F, 0x51, 0x63, 0x90, 0x81, 0x23, +0xF0, 0x90, 0x81, 0x0D, 0xE0, 0x20, 0xE2, 0x02, +0x91, 0x45, 0x22, 0xFF, 0x90, 0x81, 0x12, 0xE0, +0x2F, 0x22, 0xF0, 0xE4, 0xF5, 0x1D, 0x90, 0x81, +0x68, 0xE0, 0xF5, 0x1E, 0xE4, 0xFB, 0xFD, 0x7F, +0x54, 0x7E, 0x01, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x8E, 0x19, 0x8F, 0x1A, 0xE5, 0x1E, +0x51, 0xD0, 0x85, 0x19, 0x83, 0x85, 0x1A, 0x82, +0xF0, 0xE5, 0x1D, 0x51, 0xD0, 0xFF, 0xE5, 0x1E, +0x13, 0x13, 0x13, 0x54, 0x1F, 0x4F, 0xA3, 0xF0, +0xEB, 0x51, 0xD0, 0xFF, 0xE5, 0x1D, 0x13, 0x13, +0x13, 0x54, 0x1F, 0x4F, 0x51, 0xD7, 0xF0, 0xBD, +0x01, 0x0D, 0x85, 0x1A, 0x82, 0x8E, 0x83, 0xA3, +0xA3, 0xA3, 0x74, 0x03, 0xF0, 0x80, 0x06, 0x51, +0xD7, 0xA3, 0x74, 0x01, 0xF0, 0x51, 0xD7, 0xA3, +0x74, 0x05, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x54, 0x07, 0xC4, 0x33, 0x54, 0xE0, 0x22, 0x85, +0x1A, 0x82, 0x85, 0x19, 0x83, 0xA3, 0xA3, 0x22, +0x31, 0x38, 0x12, 0x42, 0x1A, 0xC0, 0x04, 0xC0, +0x05, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x05, 0x62, +0x31, 0x51, 0x78, 0x10, 0x12, 0x20, 0xBB, 0xD0, +0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, +0x42, 0x1A, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, +0xC0, 0x07, 0xA3, 0x31, 0x51, 0x78, 0x18, 0x12, +0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, +0xD0, 0x00, 0x12, 0x42, 0x1A, 0x90, 0x81, 0x59, +0x12, 0x20, 0xCE, 0x90, 0x81, 0x5D, 0x12, 0x42, +0x38, 0x90, 0x81, 0x59, 0x12, 0x42, 0x44, 0xC3, +0x12, 0x42, 0x27, 0x40, 0x48, 0x90, 0x81, 0x05, +0xE0, 0x90, 0x81, 0x5D, 0x30, 0xE0, 0x11, 0x12, +0x7F, 0x19, 0xFF, 0x90, 0x81, 0x27, 0xE0, 0x24, +0x04, 0x2F, 0xFF, 0x90, 0x81, 0x61, 0x80, 0x07, +0x12, 0x7F, 0x19, 0xFF, 0x90, 0x81, 0x62, 0xE0, +0xFE, 0xC3, 0xEF, 0x9E, 0x90, 0x83, 0xD8, 0xF0, +0x90, 0x83, 0xD8, 0xE0, 0xFF, 0xC3, 0x94, 0x2D, +0x50, 0x13, 0x74, 0x28, 0x2F, 0xF5, 0x82, 0xE4, +0x34, 0x81, 0xF5, 0x83, 0xE0, 0x04, 0xF0, 0x90, +0x81, 0x20, 0xE0, 0x04, 0xF0, 0x90, 0x81, 0x20, +0xE0, 0xFF, 0xD3, 0x90, 0x81, 0x64, 0xE0, 0x9F, +0x90, 0x81, 0x63, 0xE0, 0x94, 0x00, 0x40, 0x02, +0x81, 0x44, 0xE4, 0xFF, 0xFE, 0x12, 0x7F, 0x35, +0xEF, 0xD3, 0x9D, 0x40, 0x07, 0x90, 0x83, 0xD9, +0xEE, 0xF0, 0x80, 0x05, 0x0E, 0xEE, 0xB4, 0x2D, +0xEC, 0xE4, 0xFF, 0xFE, 0x12, 0x7F, 0x35, 0xC3, +0x90, 0x81, 0x64, 0xE0, 0x9D, 0xFD, 0x90, 0x81, +0x63, 0xE0, 0x94, 0x00, 0xFC, 0xEF, 0xD3, 0x9D, +0xE4, 0x9C, 0x40, 0x07, 0x90, 0x83, 0xDA, 0xEE, +0xF0, 0x80, 0x05, 0x0E, 0xEE, 0xB4, 0x2D, 0xDC, +0x90, 0x83, 0xD9, 0xE0, 0x90, 0x81, 0x25, 0xF0, +0x90, 0x83, 0xDA, 0xE0, 0x90, 0x81, 0x26, 0x12, +0x7F, 0xD1, 0x94, 0x0A, 0x40, 0x0A, 0xEF, 0x24, +0xF6, 0x90, 0x81, 0x1D, 0xF0, 0xE4, 0x80, 0x0A, +0xE4, 0x90, 0x81, 0x1D, 0x12, 0x7F, 0xD1, 0x74, +0x0A, 0x9F, 0x90, 0x81, 0x1C, 0xF0, 0x90, 0x81, +0x25, 0xE0, 0xFF, 0xA3, 0xE0, 0xC3, 0x9F, 0x90, +0x81, 0x23, 0xF0, 0x90, 0x81, 0x05, 0xE0, 0x30, +0xE0, 0x05, 0x90, 0x81, 0x61, 0x80, 0x03, 0x90, +0x81, 0x62, 0xE0, 0x04, 0xFF, 0x90, 0x81, 0x23, +0xE0, 0x2F, 0xF0, 0x90, 0x81, 0x23, 0xE0, 0xC3, +0x94, 0x10, 0x50, 0x03, 0x74, 0x10, 0xF0, 0x90, +0x81, 0x23, 0xE0, 0x24, 0x02, 0xF0, 0x12, 0x76, +0xFA, 0x74, 0x03, 0xF0, 0x12, 0x75, 0xBF, 0xE4, +0xFF, 0x12, 0x7B, 0x1C, 0x22, 0x7D, 0x01, 0x7F, +0x04, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x90, 0x84, 0x9F, 0xED, 0xF0, 0x90, 0x81, 0x05, +0xE0, 0xFE, 0xC4, 0x13, 0x13, 0x54, 0x03, 0x30, +0xE0, 0x02, 0xA1, 0x93, 0xEE, 0x12, 0x5F, 0x49, +0x30, 0xE0, 0x02, 0xA1, 0x93, 0x90, 0x81, 0x0D, +0xE0, 0xFE, 0x6F, 0x70, 0x02, 0xA1, 0x93, 0xEF, +0x70, 0x02, 0xA1, 0x07, 0x24, 0xFE, 0x70, 0x02, +0xA1, 0x41, 0x24, 0xFE, 0x60, 0x49, 0x24, 0xFC, +0x70, 0x02, 0xA1, 0x7C, 0x24, 0xFC, 0x60, 0x02, +0xA1, 0x8C, 0xEE, 0xB4, 0x0E, 0x02, 0xB1, 0xDF, +0x90, 0x81, 0x0D, 0xE0, 0x70, 0x04, 0x7F, 0x01, +0xD1, 0x1F, 0x90, 0x81, 0x0D, 0xE0, 0xB4, 0x06, +0x02, 0xB1, 0xFC, 0x90, 0x81, 0x0D, 0xE0, 0xB4, +0x04, 0x0E, 0x90, 0x84, 0x9F, 0xE0, 0xFF, 0x60, +0x05, 0x12, 0x77, 0xAD, 0x80, 0x02, 0xF1, 0xAE, +0x90, 0x81, 0x0D, 0xE0, 0x64, 0x08, 0x60, 0x02, +0xA1, 0x8C, 0x12, 0x7B, 0x59, 0xA1, 0x8C, 0x90, +0x81, 0x0D, 0xE0, 0x70, 0x04, 0x7F, 0x01, 0xD1, +0x1F, 0x90, 0x81, 0x0D, 0xE0, 0xB4, 0x06, 0x02, +0xB1, 0xFC, 0x90, 0x81, 0x0D, 0xE0, 0xB4, 0x0E, +0x07, 0xB1, 0x98, 0xBF, 0x01, 0x02, 0xB1, 0xDF, +0x90, 0x81, 0x0D, 0xE0, 0x64, 0x0C, 0x60, 0x02, +0xA1, 0x8C, 0xB1, 0x98, 0xEF, 0x64, 0x01, 0x60, +0x02, 0xA1, 0x8C, 0xD1, 0x53, 0xA1, 0x8C, 0x90, +0x81, 0x0D, 0xE0, 0xB4, 0x0E, 0x07, 0xB1, 0x98, +0xBF, 0x01, 0x02, 0xB1, 0xDF, 0x90, 0x81, 0x0D, +0xE0, 0xB4, 0x06, 0x02, 0xB1, 0xFC, 0x90, 0x81, +0x0D, 0xE0, 0xB4, 0x0C, 0x07, 0xB1, 0x98, 0xBF, +0x01, 0x02, 0xD1, 0x53, 0x90, 0x81, 0x0D, 0xE0, +0x64, 0x04, 0x70, 0x58, 0x12, 0x7A, 0x66, 0xEF, +0x64, 0x01, 0x70, 0x50, 0x12, 0x6E, 0xDC, 0x80, +0x4B, 0x90, 0x81, 0x0D, 0xE0, 0xB4, 0x0E, 0x07, +0xB1, 0x98, 0xBF, 0x01, 0x02, 0xB1, 0xDF, 0x90, +0x81, 0x0D, 0xE0, 0xB4, 0x06, 0x02, 0xB1, 0xFC, +0x90, 0x81, 0x0D, 0xE0, 0xB4, 0x0C, 0x07, 0xB1, +0x98, 0xBF, 0x01, 0x02, 0xD1, 0x53, 0x90, 0x81, +0x0D, 0xE0, 0x70, 0x04, 0x7F, 0x01, 0xD1, 0x1F, +0x90, 0x81, 0x0D, 0xE0, 0xB4, 0x04, 0x15, 0x12, +0x7A, 0xF3, 0x80, 0x10, 0x90, 0x81, 0x0D, 0xE0, +0xB4, 0x0C, 0x09, 0x12, 0x73, 0x85, 0x30, 0xE0, +0x03, 0x12, 0x6E, 0xCF, 0x90, 0x81, 0x0D, 0x12, +0x77, 0x62, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, +0x7A, 0x4D, 0xEF, 0x64, 0x01, 0x60, 0x05, 0x75, +0x1F, 0x01, 0x80, 0x20, 0x12, 0x77, 0x32, 0x54, +0x1F, 0x30, 0xE0, 0x05, 0x75, 0x1F, 0x02, 0x80, +0x13, 0x90, 0x81, 0x0C, 0xE0, 0xD3, 0x94, 0x04, +0x40, 0x05, 0x75, 0x1F, 0x08, 0x80, 0x05, 0x12, +0x7A, 0xCD, 0x80, 0x0E, 0x90, 0x01, 0xB9, 0x74, +0x02, 0xF0, 0x90, 0x01, 0xB8, 0xE5, 0x1F, 0xF0, +0x7F, 0x00, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, +0x81, 0x06, 0xE0, 0xC3, 0x13, 0x20, 0xE0, 0x04, +0x7D, 0x0C, 0x80, 0x05, 0x12, 0x7B, 0xCA, 0x7D, +0x04, 0x7F, 0x01, 0xD1, 0x86, 0xE4, 0xFB, 0xFD, +0x7F, 0xFF, 0x80, 0x41, 0x90, 0x81, 0x06, 0xE0, +0x90, 0x06, 0x04, 0x20, 0xE0, 0x08, 0xE0, 0x44, +0x40, 0xF0, 0x7D, 0x04, 0x80, 0x06, 0xE0, 0x54, +0x7F, 0xF0, 0x7D, 0x0C, 0x7F, 0x01, 0xD1, 0x86, +0xE4, 0xFB, 0xFD, 0x7F, 0xFF, 0x80, 0x1E, 0x90, +0x84, 0x9E, 0xEF, 0xF0, 0x12, 0x6E, 0x36, 0x90, +0x84, 0x9E, 0xE0, 0x60, 0x02, 0xD1, 0x38, 0x7D, +0x04, 0x7F, 0x01, 0x80, 0x51, 0x12, 0x6E, 0x36, +0xE4, 0xFB, 0xFD, 0x7F, 0xFF, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x05, 0x22, 0xED, +0xF0, 0x90, 0x80, 0x05, 0xEB, 0xF0, 0xD0, 0xD0, +0x92, 0xAF, 0x22, 0xF1, 0xA8, 0x64, 0x01, 0x70, +0x28, 0x90, 0x81, 0x06, 0xE0, 0x54, 0xFD, 0xF0, +0x7B, 0x2C, 0x12, 0x7A, 0xFE, 0x7D, 0x08, 0x7F, +0x01, 0x12, 0x66, 0x6B, 0xBF, 0x01, 0x0D, 0x90, +0x81, 0x05, 0xE0, 0x44, 0x80, 0xF0, 0x7D, 0x0E, +0x7F, 0x01, 0x80, 0x0A, 0x12, 0x74, 0xCB, 0x04, +0xF0, 0x22, 0x7D, 0x0C, 0x7F, 0x01, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xAC, 0x07, 0xEF, +0x14, 0x60, 0x15, 0x14, 0x60, 0x19, 0x24, 0x02, +0x70, 0x1A, 0xED, 0x54, 0x01, 0xFE, 0x90, 0x81, +0x05, 0xE0, 0x54, 0xFE, 0x4E, 0xF0, 0x80, 0x0C, +0x90, 0x81, 0x0D, 0xED, 0xF0, 0x80, 0x05, 0x90, +0x81, 0x0C, 0xED, 0xF0, 0x90, 0x00, 0x8F, 0xE0, +0x30, 0xE4, 0x2E, 0xEC, 0x14, 0x60, 0x07, 0x14, +0x60, 0x1D, 0x24, 0x02, 0x70, 0x23, 0x90, 0x81, +0x05, 0xE0, 0x54, 0x01, 0xC4, 0x33, 0x33, 0x33, +0x54, 0x80, 0xFF, 0x90, 0x81, 0x0D, 0xE0, 0x54, +0x7F, 0x4F, 0xFD, 0x7F, 0x88, 0x80, 0x07, 0x90, +0x81, 0x0C, 0xE0, 0xFD, 0x7F, 0x89, 0x12, 0x32, +0x1E, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x7E, 0x00, +0x7F, 0x62, 0x7D, 0x00, 0x7B, 0x01, 0x7A, 0x81, +0x79, 0x05, 0x12, 0x44, 0x3E, 0x90, 0x81, 0x09, +0x74, 0x02, 0xF0, 0x90, 0x81, 0x10, 0x14, 0xF0, +0xA3, 0xF0, 0xA3, 0x74, 0x10, 0xF0, 0x90, 0x81, +0x16, 0xE4, 0xF0, 0xA3, 0x74, 0x02, 0x12, 0x7F, +0x68, 0xF0, 0x12, 0x7B, 0x05, 0xE4, 0xFD, 0xFF, +0xD1, 0x86, 0x7D, 0x0C, 0x7F, 0x02, 0xD1, 0x86, +0xD1, 0x82, 0x90, 0x80, 0x07, 0xE0, 0xFF, 0xB4, +0x01, 0x08, 0x90, 0x81, 0x15, 0x74, 0x99, 0xF0, +0x80, 0x29, 0xEF, 0xB4, 0x03, 0x08, 0x90, 0x81, +0x15, 0x74, 0x90, 0xF0, 0x80, 0x1D, 0x90, 0x81, +0x15, 0x74, 0x40, 0xF0, 0x90, 0x00, 0x2C, 0xE0, +0x54, 0x0F, 0xFF, 0xBF, 0x05, 0x08, 0x90, 0x81, +0x27, 0x74, 0x02, 0xF0, 0x80, 0x05, 0xE4, 0x90, +0x81, 0x27, 0xF0, 0x90, 0x81, 0x67, 0x74, 0x03, +0xF0, 0xA3, 0x74, 0x0F, 0xF0, 0xA3, 0xE0, 0x54, +0x01, 0x44, 0x28, 0xF0, 0xA3, 0x74, 0x07, 0x12, +0x7F, 0x68, 0xF0, 0x7F, 0x01, 0x12, 0x7B, 0x1C, +0x90, 0x05, 0x58, 0x74, 0x02, 0xF0, 0x7E, 0x00, +0xFF, 0x7D, 0x00, 0x7B, 0x01, 0x7A, 0x81, 0x79, +0x6B, 0x12, 0x44, 0x3E, 0xF1, 0xFA, 0x12, 0x7F, +0xC1, 0x7B, 0x56, 0xE4, 0xFD, 0x7F, 0xFF, 0xD1, +0x3D, 0xE4, 0x90, 0x81, 0x6D, 0xF0, 0x22, 0xF0, +0xE4, 0xFF, 0xF1, 0xB8, 0xEF, 0x22, 0xF1, 0xFA, +0xD1, 0x38, 0x7D, 0x0C, 0x7F, 0x01, 0xC1, 0x86, +0x12, 0x77, 0x0B, 0xFE, 0xEF, 0x54, 0x07, 0xFF, +0x12, 0x60, 0xDF, 0xE0, 0xFD, 0x7C, 0x00, 0x12, +0x77, 0x4E, 0x80, 0x05, 0xC3, 0x33, 0xCE, 0x33, +0xCE, 0xD8, 0xF9, 0xFF, 0xEE, 0x5C, 0xFE, 0xEF, +0x5D, 0x4E, 0x7F, 0x00, 0x60, 0x02, 0x7F, 0x01, +0x22, 0xF1, 0xA8, 0x64, 0x01, 0x70, 0x12, 0x90, +0x81, 0x0A, 0xE0, 0x60, 0x0C, 0x90, 0x81, 0x0E, +0xE0, 0x20, 0xE4, 0x05, 0x12, 0x73, 0x8F, 0x51, +0x6A, 0x22, 0x90, 0x06, 0x04, 0xE0, 0x54, 0x7F, +0xF0, 0x22, 0xC0, 0xE0, 0xC0, 0xF0, 0xC0, 0x83, +0xC0, 0x82, 0xC0, 0xD0, 0x75, 0xD0, 0x00, 0xC0, +0x00, 0xC0, 0x01, 0xC0, 0x02, 0xC0, 0x03, 0xC0, +0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0x90, +0x01, 0xC4, 0x74, 0x02, 0xF0, 0x74, 0x50, 0xA3, +0xF0, 0x12, 0x79, 0x01, 0xE5, 0x49, 0x30, 0xE1, +0x02, 0x11, 0x89, 0xE5, 0x49, 0x30, 0xE2, 0x03, +0x12, 0x70, 0xCD, 0xE5, 0x4A, 0x30, 0xE0, 0x03, +0x12, 0x76, 0xB1, 0xE5, 0x4C, 0x30, 0xE1, 0x04, +0x7F, 0x04, 0x11, 0xCF, 0xE5, 0x4C, 0x30, 0xE4, +0x02, 0x11, 0x93, 0xE5, 0x4C, 0x30, 0xE5, 0x03, +0x12, 0x73, 0x9A, 0xE5, 0x4C, 0x30, 0xE6, 0x03, +0x12, 0x74, 0x0F, 0x74, 0x02, 0x04, 0x90, 0x01, +0xC4, 0xF0, 0x74, 0x50, 0xA3, 0xF0, 0xD0, 0x07, +0xD0, 0x06, 0xD0, 0x05, 0xD0, 0x04, 0xD0, 0x03, +0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0xD0, 0xD0, +0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0, 0xE0, +0x32, 0x90, 0x81, 0x0A, 0xE0, 0x60, 0x03, 0x12, +0x71, 0xC7, 0x22, 0x12, 0x49, 0x58, 0x12, 0x6F, +0x04, 0x7F, 0x01, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x81, 0x07, 0xE0, 0xFE, 0xC3, +0x13, 0x30, 0xE0, 0x1E, 0x90, 0x84, 0x37, 0x74, +0x1E, 0xF0, 0x90, 0x84, 0x45, 0x74, 0x01, 0xF0, +0x90, 0x84, 0x39, 0xEF, 0xF0, 0x7B, 0x01, 0x7A, +0x84, 0x79, 0x37, 0x12, 0x6B, 0xB1, 0x7F, 0x04, +0x11, 0xCF, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x8F, +0x0F, 0x7F, 0x02, 0x12, 0x46, 0x91, 0x90, 0x80, +0x01, 0xE0, 0x45, 0x0F, 0xF0, 0x22, 0x11, 0xE4, +0x7F, 0x02, 0x80, 0xEB, 0x90, 0x01, 0xCC, 0xE0, +0x54, 0x0F, 0x90, 0x84, 0x94, 0xF0, 0x90, 0x84, +0x94, 0xE0, 0xFD, 0x70, 0x02, 0x21, 0xE2, 0x90, +0x80, 0x60, 0xE0, 0xFF, 0x70, 0x06, 0xA3, 0xE0, +0x64, 0x09, 0x60, 0x0A, 0xEF, 0x14, 0xFF, 0x90, +0x80, 0x61, 0xE0, 0xB5, 0x07, 0x04, 0x7F, 0x01, +0x80, 0x02, 0x7F, 0x00, 0xEF, 0x60, 0x08, 0x90, +0x01, 0xC1, 0xE0, 0x44, 0x01, 0xF0, 0x22, 0x90, +0x84, 0x92, 0x12, 0x77, 0x4C, 0x80, 0x05, 0xC3, +0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, 0xEF, +0x5D, 0x70, 0x02, 0x21, 0xC5, 0xE4, 0x90, 0x84, +0x95, 0xF0, 0x90, 0x84, 0x95, 0xE0, 0xF9, 0xC3, +0x94, 0x04, 0x50, 0x36, 0xF1, 0xC9, 0xA4, 0xFF, +0xE9, 0xFD, 0x7C, 0x00, 0x2F, 0xFF, 0xEC, 0x35, +0xF0, 0xFE, 0x74, 0xD0, 0x12, 0x7F, 0x56, 0x90, +0x80, 0x10, 0x12, 0x7F, 0x77, 0xF1, 0xC8, 0xA4, +0x2D, 0xFF, 0xEC, 0x35, 0xF0, 0xFE, 0x74, 0xF0, +0x12, 0x7F, 0x56, 0x90, 0x80, 0x14, 0x12, 0x7F, +0x77, 0xF0, 0x90, 0x84, 0x95, 0xE0, 0x04, 0xF0, +0x80, 0xC0, 0x90, 0x84, 0x94, 0xE0, 0xFF, 0x90, +0x84, 0x92, 0xE0, 0xFE, 0x74, 0x01, 0xA8, 0x06, +0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xF4, +0x5F, 0x90, 0x84, 0x94, 0xF0, 0x90, 0x84, 0x92, +0x31, 0xE9, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, +0x90, 0x01, 0xCC, 0xF0, 0x90, 0x84, 0x92, 0xE0, +0x04, 0xF0, 0xE0, 0x54, 0x03, 0xF0, 0x90, 0x80, +0x61, 0x12, 0x6B, 0x4D, 0xB4, 0x0A, 0x02, 0x7F, +0x01, 0xEF, 0x70, 0x02, 0x01, 0xEE, 0xE4, 0x90, +0x80, 0x61, 0xF0, 0x01, 0xEE, 0x90, 0x01, 0xC0, +0xE0, 0x44, 0x02, 0xF0, 0x90, 0x84, 0x92, 0xE0, +0x44, 0x80, 0x90, 0x00, 0x8A, 0xF1, 0xC8, 0x90, +0x01, 0xD0, 0x12, 0x42, 0x50, 0xE0, 0x90, 0x01, +0xC3, 0xF0, 0x22, 0x12, 0x32, 0x1E, 0x90, 0x84, +0x96, 0xE0, 0xFF, 0x74, 0x01, 0xA8, 0x07, 0x08, +0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x90, 0x84, 0x97, 0xED, 0xF0, 0x90, 0x84, 0x96, +0xEF, 0xF0, 0xD3, 0x94, 0x07, 0x50, 0x4C, 0x31, +0xE9, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xF4, +0xFF, 0x90, 0x00, 0x47, 0xE0, 0x5F, 0xFD, 0x7F, +0x47, 0x31, 0xE3, 0x80, 0x02, 0xC3, 0x33, 0xD8, +0xFC, 0xFF, 0x90, 0x00, 0x46, 0xE0, 0x4F, 0xFD, +0x7F, 0x46, 0x12, 0x7F, 0xD9, 0x60, 0x10, 0x31, +0xE6, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xFF, +0x90, 0x00, 0x45, 0xE0, 0x4F, 0x80, 0x0F, 0x31, +0xE6, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xF4, +0xFF, 0x90, 0x00, 0x45, 0xE0, 0x5F, 0xFD, 0x7F, +0x45, 0x80, 0x63, 0x90, 0x84, 0x96, 0xE0, 0x24, +0xF8, 0xF0, 0xE0, 0x24, 0x04, 0x31, 0xEA, 0x80, +0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xF4, 0xFF, 0x90, +0x00, 0x43, 0xE0, 0x5F, 0xFD, 0x7F, 0x43, 0x31, +0xE3, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xFF, +0x90, 0x00, 0x43, 0xE0, 0x4F, 0xFD, 0x7F, 0x43, +0x12, 0x7F, 0xD9, 0x60, 0x19, 0x90, 0x84, 0x96, +0xE0, 0x24, 0x04, 0x31, 0xEA, 0x80, 0x02, 0xC3, +0x33, 0xD8, 0xFC, 0xFF, 0x90, 0x00, 0x42, 0xE0, +0x4F, 0xFD, 0x7F, 0x42, 0x80, 0x18, 0x90, 0x84, +0x96, 0xE0, 0x24, 0x04, 0x31, 0xEA, 0x80, 0x02, +0xC3, 0x33, 0xD8, 0xFC, 0xF4, 0xFF, 0x90, 0x00, +0x42, 0xE0, 0x5F, 0xFD, 0x7F, 0x42, 0x12, 0x32, +0x1E, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x12, 0x5E, +0xAB, 0x90, 0x84, 0x00, 0xEB, 0xF0, 0x90, 0x83, +0xFF, 0xED, 0xF0, 0x60, 0x13, 0xF1, 0x7B, 0x78, +0x03, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, +0xF0, 0xEE, 0x90, 0x83, 0xFD, 0xF0, 0x80, 0x19, +0xF1, 0x7B, 0x78, 0x06, 0xC3, 0x33, 0xCE, 0x33, +0xCE, 0xD8, 0xF9, 0xF0, 0xEE, 0x90, 0x83, 0xFD, +0xF0, 0x74, 0xFF, 0x75, 0xF0, 0xD0, 0x12, 0x41, +0xF6, 0x71, 0x98, 0x54, 0x07, 0x7D, 0x00, 0x20, +0xE0, 0x02, 0x7D, 0x01, 0x31, 0xF1, 0x71, 0x98, +0x54, 0x01, 0xFD, 0x31, 0xF1, 0x90, 0x84, 0x01, +0xE0, 0x60, 0x57, 0x71, 0x8B, 0x54, 0x07, 0x7D, +0x00, 0x20, 0xE0, 0x02, 0x7D, 0x01, 0x31, 0xF1, +0x90, 0x84, 0x02, 0xE0, 0x60, 0x1D, 0x90, 0x81, +0x71, 0xE0, 0x30, 0xE0, 0x3D, 0x90, 0x01, 0xC6, +0xE0, 0x20, 0xE4, 0x36, 0x71, 0x6B, 0x54, 0x07, +0x7D, 0x00, 0x20, 0xE0, 0x02, 0x7D, 0x01, 0x31, +0xF1, 0x80, 0xE3, 0xE4, 0x90, 0x84, 0x03, 0xF0, +0x90, 0x84, 0x00, 0xE0, 0xFF, 0x90, 0x84, 0x03, +0xE0, 0xC3, 0x9F, 0x50, 0x15, 0x71, 0x6B, 0x54, +0x07, 0x7D, 0x00, 0x20, 0xE0, 0x02, 0x7D, 0x01, +0x31, 0xF1, 0x90, 0x84, 0x03, 0xE0, 0x04, 0xF0, +0x80, 0xDE, 0x22, 0x90, 0x83, 0xFD, 0xE0, 0xFE, +0xA3, 0xE0, 0xFF, 0xA3, 0xE0, 0xFD, 0x71, 0xA7, +0x90, 0x81, 0x72, 0xE0, 0x54, 0x7F, 0xFF, 0x90, +0x81, 0x71, 0xE0, 0xFE, 0xC4, 0x13, 0x54, 0x01, +0xFD, 0x31, 0xF1, 0x90, 0x83, 0xFD, 0xE0, 0xFE, +0xA3, 0xE0, 0xFF, 0xA3, 0xE0, 0xFD, 0x71, 0xA7, +0x90, 0x81, 0x72, 0xE0, 0x54, 0x7F, 0xFF, 0x90, +0x81, 0x71, 0xE0, 0xFE, 0xC4, 0x13, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x8E, 0x0D, +0x8F, 0x0E, 0xBD, 0x01, 0x05, 0x12, 0x32, 0x06, +0x80, 0x07, 0xAF, 0x0E, 0xAE, 0x0D, 0x12, 0x32, +0xAA, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x67, 0xEA, +0x12, 0x1F, 0xA4, 0x20, 0xE0, 0x1E, 0x54, 0x01, +0xFF, 0x90, 0x81, 0x71, 0xE0, 0x54, 0xFE, 0x4F, +0xF0, 0xA3, 0x71, 0x9B, 0x54, 0x07, 0x7D, 0x00, +0x20, 0xE0, 0x02, 0x7D, 0x01, 0x31, 0xF1, 0x12, +0x61, 0x91, 0x81, 0xEF, 0x12, 0x7C, 0x3A, 0xFE, +0x90, 0x81, 0x71, 0xF1, 0x5E, 0xF1, 0xE6, 0xFF, +0x90, 0x81, 0x71, 0x12, 0x7F, 0x93, 0xF1, 0x6C, +0x12, 0x7F, 0x9D, 0x90, 0x81, 0x71, 0xF1, 0xD1, +0xF1, 0x6C, 0x12, 0x7F, 0xA6, 0x90, 0x81, 0x71, +0x12, 0x7F, 0xB8, 0xD1, 0x79, 0x54, 0x80, 0xFF, +0x90, 0x81, 0x72, 0xE0, 0x54, 0x7F, 0x4F, 0xB1, +0x81, 0xFF, 0x54, 0x02, 0xFE, 0x90, 0x81, 0x75, +0xE0, 0x54, 0xFD, 0x4E, 0xFE, 0xF0, 0xEF, 0x54, +0x08, 0xFF, 0xEE, 0x54, 0xF7, 0x4F, 0xF1, 0xB9, +0x90, 0x81, 0x76, 0xB1, 0x81, 0x54, 0x10, 0xFF, +0x90, 0x81, 0x75, 0xE0, 0x54, 0xEF, 0x4F, 0xF0, +0x12, 0x1F, 0xA4, 0xFF, 0x13, 0x13, 0x54, 0x3F, +0x30, 0xE0, 0x07, 0x90, 0x06, 0x90, 0xE0, 0x44, +0x04, 0xF0, 0x12, 0x77, 0x0B, 0x30, 0xE0, 0x07, +0x90, 0x06, 0x90, 0xE0, 0x44, 0x08, 0xF0, 0x90, +0x80, 0x07, 0xE0, 0xB4, 0x02, 0x06, 0x12, 0x5F, +0x45, 0x20, 0xE0, 0x55, 0x90, 0x83, 0xEF, 0x12, +0x42, 0x5C, 0xD1, 0x7B, 0x54, 0x7F, 0xFF, 0x90, +0x81, 0x72, 0xE0, 0x54, 0x80, 0xF1, 0x73, 0xFF, +0x54, 0x7F, 0xFE, 0x90, 0x81, 0x73, 0xE0, 0x54, +0x80, 0xF1, 0xC0, 0xFE, 0x54, 0x01, 0xFD, 0x90, +0x81, 0x74, 0xF1, 0xF6, 0x54, 0xFE, 0xFE, 0xED, +0x54, 0x01, 0x4E, 0xB1, 0x81, 0x54, 0x04, 0xFE, +0x90, 0x81, 0x75, 0xE0, 0x54, 0xFB, 0x4E, 0xF0, +0xEF, 0x54, 0x80, 0xFF, 0x90, 0x81, 0x73, 0xE0, +0x54, 0x7F, 0x4F, 0xF0, 0x71, 0x98, 0x54, 0x07, +0x7D, 0x00, 0x20, 0xE0, 0x02, 0x7D, 0x01, 0x31, +0xF1, 0x90, 0x80, 0x07, 0xE0, 0xB4, 0x01, 0x07, +0x90, 0xFE, 0x10, 0xE0, 0x44, 0x04, 0xF0, 0x90, +0x83, 0xAD, 0x74, 0x05, 0xF0, 0x12, 0x7F, 0xAF, +0x7A, 0x82, 0x79, 0x8C, 0x12, 0x44, 0x3E, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x90, 0x83, 0xEC, 0x12, +0x42, 0x65, 0x90, 0x83, 0xEB, 0xEF, 0xF0, 0x12, +0x42, 0x6E, 0x55, 0x2D, 0x00, 0x55, 0x32, 0x01, +0x55, 0x37, 0x03, 0x55, 0x3C, 0x04, 0x55, 0x41, +0x14, 0x55, 0x46, 0x20, 0x55, 0x4B, 0x25, 0x55, +0x54, 0x80, 0x55, 0x50, 0x81, 0x55, 0x58, 0x82, +0x55, 0x5D, 0x83, 0x55, 0x61, 0x84, 0x55, 0x66, +0x88, 0x00, 0x00, 0x55, 0x6B, 0xB1, 0x7B, 0x02, +0x70, 0x19, 0xB1, 0x7B, 0x02, 0x70, 0x5D, 0xB1, +0x7B, 0x02, 0x7C, 0x15, 0xB1, 0x7B, 0x02, 0x7C, +0x47, 0xB1, 0x7B, 0x02, 0x77, 0xE8, 0xB1, 0x7B, +0x02, 0x74, 0xD5, 0xB1, 0x7B, 0x02, 0x77, 0xF7, +0xB1, 0x7B, 0xC1, 0x81, 0xB1, 0x7B, 0x61, 0xC6, +0xB1, 0x7B, 0x02, 0x7E, 0x66, 0xB1, 0x7B, 0xE1, +0x83, 0xB1, 0x7B, 0x02, 0x7E, 0x74, 0xB1, 0x7B, +0x02, 0x7E, 0xC8, 0x90, 0x01, 0xC0, 0xE0, 0x44, +0x01, 0xF0, 0x90, 0x83, 0xEB, 0xE0, 0x90, 0x01, +0xC2, 0xF0, 0x22, 0x90, 0x83, 0xEC, 0x02, 0x42, +0x5C, 0xF0, 0x90, 0x00, 0x04, 0x02, 0x1F, 0xBD, +0x90, 0x84, 0x46, 0x12, 0x42, 0x65, 0x90, 0x84, +0x4A, 0xE0, 0xFE, 0x64, 0x04, 0x70, 0x0C, 0xD1, +0x73, 0x12, 0x1F, 0xA4, 0x90, 0x84, 0x4B, 0xD1, +0x7A, 0x80, 0x10, 0xEE, 0x64, 0x02, 0x70, 0x2F, +0xD1, 0x73, 0xF1, 0x75, 0x90, 0x84, 0x4B, 0xF0, +0x12, 0x1F, 0xA4, 0x90, 0x84, 0x4C, 0xB1, 0x81, +0x90, 0x84, 0x4D, 0xF1, 0xB9, 0x90, 0x84, 0x4E, +0xF0, 0x90, 0x00, 0x06, 0x12, 0x1F, 0xBD, 0x90, +0x84, 0x4F, 0xF0, 0x90, 0x00, 0x07, 0x12, 0x1F, +0xBD, 0x90, 0x84, 0x50, 0xF1, 0xC1, 0xFF, 0xED, +0x70, 0x19, 0xFE, 0xF1, 0xDB, 0xE0, 0xB4, 0xFF, +0x06, 0xF1, 0xDB, 0xE4, 0xF0, 0x80, 0x07, 0xF1, +0xDB, 0xE0, 0x04, 0xF0, 0x80, 0x05, 0x0E, 0xEE, +0xB4, 0x06, 0xE8, 0x90, 0x84, 0x4A, 0xE0, 0xFE, +0xB4, 0x04, 0x18, 0xA3, 0xE0, 0xFD, 0xD1, 0x73, +0xED, 0xF1, 0xEE, 0xFD, 0xD1, 0x73, 0x90, 0x00, +0x01, 0xED, 0x12, 0x1F, 0xFC, 0x90, 0x00, 0x02, +0xE4, 0x80, 0x20, 0xEE, 0xB4, 0x02, 0x1F, 0x90, +0x84, 0x4C, 0xD1, 0x71, 0xEE, 0xF1, 0xEE, 0x44, +0x20, 0x54, 0x7F, 0xD1, 0x72, 0x90, 0x00, 0x01, +0xEE, 0x12, 0x1F, 0xFC, 0x90, 0x84, 0x4B, 0xE0, +0x90, 0x00, 0x02, 0x12, 0x1F, 0xFC, 0xD1, 0x73, +0xE9, 0x24, 0x03, 0xF9, 0xE4, 0x3A, 0xFA, 0x12, +0x1F, 0xA4, 0x44, 0x20, 0x12, 0x1F, 0xEA, 0x90, +0x84, 0x4D, 0xD1, 0x71, 0x90, 0x00, 0x04, 0xEE, +0x12, 0x1F, 0xFC, 0x90, 0x84, 0x4E, 0xE0, 0x90, +0x00, 0x05, 0x12, 0x1F, 0xFC, 0x90, 0x84, 0x4F, +0xE0, 0x90, 0x00, 0x06, 0x12, 0x1F, 0xFC, 0x90, +0x84, 0x50, 0xE0, 0x90, 0x00, 0x07, 0x02, 0x1F, +0xFC, 0xE0, 0xFE, 0x90, 0x84, 0x46, 0x02, 0x42, +0x5C, 0x4E, 0xF0, 0x90, 0x00, 0x01, 0x02, 0x1F, +0xBD, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x12, 0x7C, 0x40, 0xFE, 0x90, 0x81, 0x6E, 0xF1, +0x5E, 0xF1, 0xE6, 0xFF, 0x90, 0x81, 0x6E, 0x12, +0x7F, 0x93, 0xF1, 0x6C, 0x12, 0x7F, 0x9D, 0x90, +0x81, 0x6E, 0xF1, 0xD1, 0xF1, 0x6C, 0x12, 0x7F, +0xA6, 0x90, 0x81, 0x6E, 0x12, 0x7F, 0xB8, 0x4E, +0xF1, 0x74, 0xFF, 0x54, 0x01, 0xFE, 0x90, 0x81, +0x70, 0xE0, 0x54, 0xFE, 0xD1, 0x79, 0xFE, 0x54, +0x01, 0xFD, 0x90, 0x81, 0x6F, 0xF1, 0xF6, 0x54, +0x04, 0xFE, 0xED, 0x54, 0xFB, 0x4E, 0xFE, 0xD1, +0x7A, 0xFD, 0x54, 0x08, 0xFC, 0xEE, 0x54, 0xF7, +0x4C, 0xFE, 0x90, 0x81, 0x6F, 0xF0, 0xED, 0x54, +0x10, 0xFD, 0xEE, 0x54, 0xEF, 0x4D, 0xF0, 0xEF, +0x54, 0x10, 0xFF, 0xA3, 0xE0, 0x54, 0xEF, 0x4F, +0xFF, 0xF1, 0x74, 0xF1, 0xD3, 0x90, 0x81, 0x70, +0xD1, 0x7A, 0x54, 0x02, 0xFF, 0x90, 0x81, 0x6F, +0xE0, 0x54, 0xFD, 0x4F, 0x12, 0x7D, 0x4B, 0x12, +0x7F, 0xC9, 0x90, 0x81, 0x6E, 0xE0, 0xC3, 0x13, +0x54, 0x01, 0xFF, 0x12, 0x7F, 0x0D, 0x12, 0x5F, +0x9B, 0x13, 0x54, 0x1F, 0x30, 0xE0, 0x23, 0x90, +0x81, 0x6E, 0xE0, 0xFF, 0x13, 0x13, 0x13, 0x54, +0x1F, 0x20, 0xE0, 0x0E, 0xEF, 0xC3, 0x13, 0x20, +0xE0, 0x08, 0xE0, 0x13, 0x13, 0x54, 0x3F, 0x30, +0xE0, 0x04, 0x7F, 0x01, 0x80, 0x0E, 0x7F, 0x00, +0x80, 0x0A, 0x90, 0x81, 0x6E, 0xE0, 0x13, 0x13, +0x13, 0x54, 0x01, 0xFF, 0x12, 0x67, 0xC1, 0x90, +0x81, 0x6E, 0xE0, 0x54, 0x01, 0xFF, 0x12, 0x61, +0xBC, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xE0, 0x54, +0xFE, 0x4E, 0xFE, 0xF0, 0xEF, 0x54, 0x02, 0xFF, +0xEE, 0x54, 0xFD, 0x4F, 0xFF, 0xF0, 0x12, 0x1F, +0xA4, 0xFE, 0x22, 0x4F, 0xF0, 0x90, 0x00, 0x02, +0x02, 0x1F, 0xBD, 0x90, 0x83, 0xFD, 0xE0, 0xFE, +0xA3, 0xE0, 0x22, 0x12, 0x7E, 0xBA, 0x90, 0x83, +0xB3, 0xD1, 0x7A, 0xFF, 0xED, 0x2F, 0x90, 0x83, +0xB4, 0xF1, 0x74, 0xFF, 0xED, 0x2F, 0x90, 0x83, +0xB5, 0xF1, 0xC1, 0xFF, 0xED, 0x2F, 0x90, 0x83, +0xB6, 0xB1, 0x81, 0xFF, 0xED, 0x2F, 0x90, 0x83, +0xB7, 0xF1, 0xB9, 0xFF, 0xED, 0x2F, 0x90, 0x83, +0xB8, 0x12, 0x7E, 0xAD, 0x90, 0x83, 0xB9, 0xF0, +0x22, 0xF0, 0x90, 0x00, 0x05, 0x02, 0x1F, 0xBD, +0x4E, 0xF0, 0x90, 0x00, 0x03, 0x02, 0x1F, 0xBD, +0xF0, 0x90, 0x84, 0x92, 0xE0, 0x75, 0xF0, 0x04, +0x22, 0xF0, 0xEE, 0x54, 0x20, 0xFE, 0xEF, 0x54, +0xDF, 0x4E, 0x22, 0x74, 0x4B, 0x2E, 0xF5, 0x82, +0xE4, 0x34, 0x84, 0xF5, 0x83, 0x22, 0x54, 0x04, +0xFD, 0xEF, 0x54, 0xFB, 0x4D, 0x22, 0x12, 0x1F, +0xEA, 0x90, 0x84, 0x4C, 0xE0, 0x22, 0xE0, 0x54, +0xFE, 0x4D, 0xFD, 0xF0, 0xEE, 0x22, 0x90, 0x00, +0xF7, 0xE0, 0x20, 0xE7, 0x09, 0xE0, 0x7F, 0x01, +0x20, 0xE6, 0x0C, 0x7F, 0x02, 0x22, 0x90, 0x00, +0xF7, 0xE0, 0x30, 0xE6, 0x02, 0x7F, 0x03, 0x22, +0x12, 0x57, 0xFE, 0x90, 0x80, 0x07, 0xEF, 0xF0, +0x11, 0x39, 0x90, 0x01, 0x64, 0x74, 0x01, 0xF0, +0x90, 0x00, 0x12, 0xE0, 0x54, 0xC7, 0x44, 0x20, +0xFD, 0x7F, 0x12, 0x12, 0x32, 0x1E, 0x02, 0x2D, +0xA7, 0x90, 0x00, 0x08, 0xE0, 0x54, 0xEF, 0xF0, +0x11, 0x72, 0xD1, 0xC8, 0x12, 0x78, 0x0D, 0x12, +0x78, 0x2C, 0xE4, 0xF5, 0x35, 0xF5, 0x37, 0xF5, +0x36, 0xF5, 0x37, 0x75, 0x38, 0x80, 0xAD, 0x35, +0x7F, 0x50, 0x12, 0x32, 0x1E, 0xAD, 0x36, 0x7F, +0x51, 0x12, 0x32, 0x1E, 0xAD, 0x37, 0x7F, 0x52, +0x12, 0x32, 0x1E, 0xAD, 0x38, 0x7F, 0x53, 0x02, +0x32, 0x1E, 0x90, 0x01, 0x30, 0xE4, 0x11, 0x98, +0x90, 0x01, 0x38, 0x11, 0x98, 0xFD, 0x7F, 0x50, +0x12, 0x32, 0x1E, 0xE4, 0xFD, 0x7F, 0x51, 0x12, +0x32, 0x1E, 0xE4, 0xFD, 0x7F, 0x52, 0x12, 0x32, +0x1E, 0xE4, 0xFD, 0x7F, 0x53, 0x02, 0x32, 0x1E, +0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, +0x83, 0xF3, 0x74, 0x08, 0xF0, 0xE4, 0xA3, 0x11, +0x98, 0x90, 0x83, 0xFA, 0xF0, 0xA3, 0xF0, 0xA3, +0xF0, 0x12, 0x7D, 0x88, 0x12, 0x7D, 0x54, 0x90, +0x83, 0xEB, 0x12, 0x7D, 0x7F, 0x90, 0x83, 0xF2, +0xF0, 0x90, 0x81, 0x6E, 0xE0, 0x20, 0xE0, 0x02, +0x41, 0xC9, 0xE4, 0x90, 0x83, 0xF1, 0xF0, 0x90, +0x83, 0xF2, 0xE0, 0xFF, 0x90, 0x83, 0xF1, 0xE0, +0xC3, 0x9F, 0x40, 0x02, 0x41, 0xC9, 0xD1, 0xB4, +0xFD, 0xEC, 0xFF, 0x90, 0xFD, 0x11, 0xF0, 0xAE, +0x05, 0xAA, 0x06, 0x90, 0x83, 0xF5, 0xEF, 0xF0, +0x74, 0x02, 0x2A, 0x12, 0x7D, 0xA9, 0x54, 0xF8, +0xFF, 0x74, 0x03, 0x2A, 0x12, 0x7D, 0x91, 0xFE, +0xEF, 0x24, 0x18, 0x2E, 0x90, 0x83, 0xFA, 0xF0, +0xE0, 0xFF, 0x2A, 0x90, 0x83, 0xED, 0xF0, 0x7E, +0x00, 0xD1, 0xB4, 0x2F, 0xFF, 0xEE, 0x3C, 0x90, +0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x83, +0xED, 0xE0, 0xFD, 0x24, 0x00, 0xF1, 0xAA, 0xFE, +0x54, 0xFC, 0x90, 0x83, 0xF0, 0xF0, 0xAF, 0x06, +0xF1, 0xBC, 0xFD, 0x90, 0x83, 0xED, 0xE0, 0xF1, +0xA2, 0x12, 0x64, 0x17, 0x90, 0x83, 0xF4, 0xEF, +0xF0, 0x74, 0x01, 0x2A, 0xF1, 0xBF, 0xFE, 0x74, +0x00, 0x2A, 0xF5, 0x82, 0xE4, 0x34, 0xFB, 0xF5, +0x83, 0x12, 0x7D, 0x54, 0x54, 0x3F, 0xFE, 0x90, +0x83, 0xF6, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x83, +0xFA, 0xE0, 0x2F, 0xFF, 0xEC, 0x3E, 0xFE, 0x12, +0x7D, 0x5D, 0x74, 0x0F, 0x2A, 0xF5, 0x82, 0xE4, +0x34, 0xFB, 0xF5, 0x83, 0xE0, 0xFD, 0x90, 0x83, +0xEB, 0x12, 0x7D, 0xB7, 0x90, 0x83, 0xEB, 0xE0, +0xFA, 0xA3, 0xE0, 0xD3, 0x9F, 0xEA, 0x9E, 0x40, +0x22, 0x90, 0x83, 0xEB, 0xE0, 0xFE, 0xA3, 0xE0, +0xFF, 0x90, 0x80, 0xFA, 0xE0, 0xFA, 0xA3, 0xE0, +0x24, 0x01, 0xFB, 0xE4, 0x3A, 0xFA, 0xC3, 0xEF, +0x9B, 0xFF, 0xEE, 0x9A, 0x90, 0x83, 0xEB, 0xF0, +0xA3, 0xEF, 0xF0, 0xED, 0x30, 0xE7, 0x08, 0x51, +0xCF, 0x90, 0x01, 0xC7, 0x74, 0x21, 0xF0, 0xED, +0x30, 0xE6, 0x08, 0x51, 0xCF, 0x90, 0x01, 0xC7, +0x74, 0x22, 0xF0, 0xED, 0x30, 0xE5, 0x08, 0x51, +0xCF, 0x90, 0x01, 0xC7, 0x74, 0x23, 0xF0, 0x90, +0x83, 0xF0, 0xE0, 0x24, 0xF8, 0x60, 0x23, 0x24, +0x80, 0x60, 0x1F, 0x24, 0xC8, 0x60, 0x04, 0x24, +0x20, 0x70, 0x7B, 0x90, 0x81, 0x71, 0xE0, 0xFF, +0xF1, 0x49, 0x30, 0xE0, 0x71, 0xD1, 0x8B, 0x60, +0x6D, 0x90, 0x83, 0xF0, 0xE0, 0xFF, 0xF1, 0xD9, +0x80, 0x64, 0xD1, 0x8B, 0x60, 0x1A, 0x51, 0xD7, +0x90, 0x83, 0xF3, 0xE0, 0xFB, 0x90, 0x83, 0xF5, +0xE0, 0x90, 0x84, 0x01, 0xF0, 0x51, 0xE5, 0xEF, +0x60, 0x06, 0x90, 0x83, 0xFC, 0x74, 0x01, 0xF0, +0x90, 0x81, 0x6E, 0xE0, 0xC3, 0x13, 0x30, 0xE0, +0x0D, 0x51, 0xD7, 0x91, 0x30, 0xEF, 0x60, 0x06, +0x90, 0x83, 0xFC, 0x74, 0x01, 0xF0, 0x90, 0x81, +0x6E, 0xF1, 0x48, 0x30, 0xE0, 0x15, 0x90, 0x83, +0xFC, 0xE0, 0x70, 0x0F, 0x51, 0xD7, 0xD1, 0x94, +0xEF, 0x60, 0x08, 0x51, 0xCF, 0x90, 0x01, 0xC7, +0x74, 0x22, 0xF0, 0x51, 0xD7, 0x71, 0x92, 0xEF, +0x60, 0x0C, 0x90, 0x81, 0x79, 0xE0, 0x54, 0xFE, +0xF0, 0x90, 0x01, 0xC7, 0xE4, 0xF0, 0x90, 0x81, +0x79, 0xE0, 0x30, 0xE0, 0x19, 0x90, 0x80, 0x07, +0xE0, 0xB4, 0x01, 0x0E, 0x90, 0xFD, 0x01, 0xE0, +0x20, 0xE6, 0x07, 0x90, 0xFD, 0x00, 0xE0, 0x44, +0x10, 0xF0, 0x7F, 0x01, 0xD1, 0xF7, 0x12, 0x7D, +0xC6, 0xEF, 0x64, 0x01, 0x70, 0x3B, 0xF1, 0xF9, +0x90, 0x83, 0xFB, 0xEF, 0xF0, 0x64, 0x01, 0x60, +0x22, 0x51, 0xCF, 0x90, 0x83, 0xFB, 0xE0, 0xFF, +0xB4, 0x02, 0x08, 0x90, 0x01, 0xC7, 0x74, 0x42, +0xF0, 0x80, 0x0A, 0xEF, 0xB4, 0x04, 0x06, 0x90, +0x01, 0xC7, 0x74, 0x43, 0xF0, 0x7F, 0x01, 0xD1, +0xF7, 0x80, 0x0E, 0x90, 0x83, 0xEB, 0x12, 0x7C, +0x8C, 0x90, 0x83, 0xF1, 0xE0, 0x04, 0xF0, 0x01, +0xD7, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xF0, 0x90, +0x81, 0x79, 0xE0, 0x44, 0x01, 0xF0, 0x22, 0x90, +0x83, 0xEE, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90, +0x83, 0xF4, 0xE0, 0xFD, 0x22, 0x90, 0x83, 0xFF, +0xED, 0xF0, 0xA3, 0xEB, 0xD1, 0xAA, 0xE4, 0x90, +0x84, 0x02, 0xF0, 0x90, 0x84, 0x01, 0xF0, 0xFD, +0x71, 0x68, 0xEF, 0x54, 0x0C, 0x64, 0x08, 0x70, +0x53, 0x12, 0x57, 0x7B, 0xFF, 0xA3, 0xE0, 0xD1, +0x48, 0x64, 0x88, 0x70, 0x47, 0x12, 0x57, 0x7B, +0xFF, 0xA3, 0xE0, 0x24, 0x07, 0xFD, 0x71, 0x68, +0xEF, 0x64, 0x8E, 0x70, 0x37, 0x90, 0x84, 0x02, +0x04, 0xF0, 0x12, 0x57, 0x7B, 0xD1, 0xBC, 0x04, +0xFD, 0x71, 0x68, 0xEF, 0x64, 0x03, 0x70, 0x24, +0x12, 0x57, 0x7B, 0xD1, 0xBC, 0xD1, 0x48, 0x30, +0xE3, 0x07, 0x90, 0x01, 0xC7, 0x74, 0x01, 0x80, +0x11, 0x90, 0x81, 0x71, 0xE0, 0xC4, 0x13, 0x13, +0x54, 0x03, 0x30, 0xE0, 0x07, 0x90, 0x01, 0xC7, +0x74, 0x02, 0x51, 0xCE, 0x90, 0x84, 0x02, 0xE0, +0xFF, 0x22, 0xCD, 0x34, 0x00, 0xFC, 0x7E, 0x00, +0xED, 0x2F, 0xFF, 0xEE, 0x3C, 0xFE, 0xE4, 0xFD, +0xAB, 0x07, 0xAA, 0x06, 0xED, 0x2B, 0xFB, 0xE4, +0x3A, 0xFA, 0xC3, 0x90, 0x80, 0xFB, 0xE0, 0x9B, +0x90, 0x80, 0xFA, 0xE0, 0x9A, 0x50, 0x0A, 0xA3, +0x12, 0x7D, 0x9C, 0xEB, 0x9F, 0xFB, 0xEA, 0x9E, +0xFA, 0xF1, 0xF1, 0x74, 0x00, 0x2F, 0xF1, 0xAA, +0xFF, 0x22, 0xD1, 0xA6, 0xD1, 0x5B, 0xEF, 0x70, +0x02, 0x81, 0x2D, 0x12, 0x57, 0x7B, 0xB1, 0xA9, +0xEF, 0x70, 0x02, 0x81, 0x2D, 0xB1, 0x7C, 0xCF, +0x24, 0x08, 0xCF, 0x34, 0x00, 0x90, 0x84, 0x02, +0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x81, 0x6F, 0xE0, +0xC4, 0x54, 0x0F, 0x30, 0xE0, 0x2F, 0xB1, 0x8E, +0x7D, 0x09, 0x71, 0x68, 0xEF, 0x64, 0x06, 0x70, +0x24, 0xB1, 0x8E, 0x7D, 0x14, 0x71, 0x68, 0xEF, +0x70, 0x1B, 0xB1, 0x8E, 0x7D, 0x15, 0x71, 0x68, +0xEF, 0x64, 0x50, 0x70, 0x10, 0xB1, 0x8E, 0x7D, +0x21, 0x71, 0x68, 0xEF, 0x20, 0xE0, 0x03, 0x30, +0xE2, 0x03, 0x7F, 0x01, 0x22, 0xF1, 0x9B, 0x54, +0x3F, 0x30, 0xE0, 0x39, 0xB1, 0x8E, 0x7D, 0x09, +0x71, 0x68, 0xEF, 0x64, 0x11, 0x70, 0x2E, 0x90, +0x84, 0x03, 0xE0, 0x24, 0x14, 0xFF, 0x90, 0x84, +0x02, 0xE0, 0x34, 0x00, 0xFE, 0x90, 0x84, 0x00, +0xF0, 0xA3, 0xEF, 0xF0, 0x7D, 0x02, 0x71, 0x68, +0xEF, 0x70, 0x12, 0x90, 0x84, 0x00, 0xE0, 0xFE, +0xA3, 0xE0, 0xFF, 0x7D, 0x03, 0x71, 0x68, 0xBF, +0x89, 0x03, 0x7F, 0x01, 0x22, 0x7F, 0x00, 0x22, +0xD1, 0xAB, 0xA3, 0xED, 0xF0, 0x78, 0x06, 0x7C, +0x84, 0x7D, 0x01, 0x7B, 0xFF, 0x7A, 0x40, 0x79, +0xC0, 0xF1, 0xEA, 0x78, 0x0C, 0x7C, 0x84, 0x7D, +0x01, 0x7B, 0xFF, 0x7A, 0x40, 0x79, 0xC6, 0xD1, +0x41, 0x78, 0x10, 0x7C, 0x84, 0x7D, 0x01, 0x7B, +0xFF, 0x7A, 0x40, 0x79, 0xCA, 0xD1, 0x41, 0xE4, +0x90, 0x84, 0x15, 0xF0, 0xB1, 0x7C, 0xCF, 0x24, +0x06, 0xCF, 0xD1, 0x38, 0x64, 0x08, 0x60, 0x02, +0xA1, 0x76, 0xB1, 0x7C, 0xCF, 0x24, 0x07, 0xCF, +0xD1, 0x38, 0x64, 0x06, 0x60, 0x02, 0xA1, 0x76, +0x90, 0x84, 0x15, 0x04, 0xF0, 0xE4, 0x90, 0x84, +0x14, 0xF0, 0xB1, 0x97, 0x94, 0x06, 0x50, 0x1C, +0x90, 0x83, 0xFE, 0xE0, 0x24, 0x0A, 0xFD, 0x90, +0x83, 0xFD, 0xE0, 0x71, 0x5B, 0x90, 0x84, 0x14, +0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x84, +0xB1, 0x9E, 0x80, 0xDE, 0x78, 0x00, 0x7C, 0x84, +0x7D, 0x01, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0x80, +0xF1, 0xB3, 0x60, 0x02, 0xA1, 0x76, 0x90, 0x84, +0x14, 0xF0, 0xB1, 0x97, 0x94, 0x04, 0x50, 0x18, +0xD1, 0x4F, 0xB1, 0x87, 0xCD, 0x24, 0x20, 0x71, +0x5A, 0x90, 0x84, 0x14, 0xE0, 0x24, 0x10, 0xF5, +0x82, 0xE4, 0x34, 0x84, 0xB1, 0x9E, 0x80, 0xE2, +0x78, 0x10, 0x7C, 0x84, 0xF1, 0xC8, 0x60, 0x02, +0xA1, 0x6D, 0x90, 0x06, 0x30, 0xE0, 0x44, 0x01, +0x54, 0xDF, 0xF0, 0x90, 0x81, 0x70, 0xE0, 0x30, +0xE0, 0x02, 0x80, 0x0F, 0x90, 0x83, 0xB1, 0xE0, +0xB4, 0x02, 0x11, 0xF1, 0x9B, 0x13, 0x54, 0x1F, +0x20, 0xE0, 0x09, 0x90, 0x01, 0xC7, 0x74, 0x09, +0x51, 0xCE, 0x80, 0x62, 0xE4, 0x90, 0x84, 0x14, +0xF0, 0xB1, 0x97, 0x94, 0x06, 0x50, 0x18, 0xD1, +0x4F, 0xB1, 0x87, 0xCD, 0x24, 0x10, 0x71, 0x5A, +0x90, 0x84, 0x14, 0xE0, 0x24, 0x06, 0xF5, 0x82, +0xE4, 0x34, 0x84, 0xB1, 0x9E, 0x80, 0xE2, 0xE4, +0x90, 0x84, 0x14, 0xF0, 0xB1, 0x97, 0x94, 0x04, +0x50, 0x18, 0xD1, 0x4F, 0xB1, 0x87, 0xCD, 0x24, +0x16, 0x71, 0x5A, 0x90, 0x84, 0x14, 0xE0, 0x24, +0x0C, 0xF5, 0x82, 0xE4, 0x34, 0x84, 0xB1, 0x9E, +0x80, 0xE2, 0x7B, 0x01, 0x7A, 0x84, 0x79, 0x06, +0x12, 0x7F, 0x86, 0xF0, 0x7A, 0x84, 0x79, 0x0C, +0x12, 0x62, 0xAB, 0x80, 0x09, 0x90, 0x06, 0x30, +0xE0, 0x44, 0x21, 0x54, 0xEF, 0xF0, 0x90, 0x84, +0x15, 0xE0, 0xFF, 0x22, 0x90, 0x83, 0xFF, 0xE0, +0xFF, 0x90, 0x83, 0xFE, 0xE0, 0x2F, 0xFF, 0x90, +0x83, 0xFD, 0xE0, 0x34, 0x00, 0x22, 0x90, 0x84, +0x02, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x22, 0x90, +0x84, 0x14, 0xE0, 0xFF, 0xC3, 0x22, 0xF5, 0x83, +0xEF, 0xF0, 0x90, 0x84, 0x14, 0xE0, 0x04, 0xF0, +0x22, 0xFF, 0xA3, 0xE0, 0xFD, 0x90, 0x84, 0x04, +0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xA3, 0xED, 0xF0, +0x78, 0x08, 0x7C, 0x84, 0x7D, 0x01, 0x7B, 0xFF, +0x7A, 0x40, 0x79, 0xD4, 0xD1, 0x41, 0x90, 0x84, +0x06, 0xE0, 0xFF, 0x90, 0x84, 0x05, 0xE0, 0x2F, +0xFF, 0x90, 0x84, 0x04, 0xE0, 0x34, 0x00, 0xFE, +0x90, 0x84, 0x0C, 0xF0, 0xA3, 0xEF, 0xF0, 0x24, +0x06, 0xFF, 0xE4, 0x3E, 0xD1, 0x3A, 0x64, 0x08, +0x70, 0x4D, 0x90, 0x84, 0x0D, 0xE0, 0x24, 0x07, +0xFF, 0x90, 0x84, 0x0C, 0xE0, 0xD1, 0x38, 0x70, +0x3E, 0x90, 0x84, 0x07, 0xF0, 0x90, 0x84, 0x07, +0xE0, 0xFF, 0xC3, 0x94, 0x04, 0x50, 0x24, 0x90, +0x84, 0x0D, 0xE0, 0x24, 0x18, 0xFD, 0x90, 0x84, +0x0C, 0xE0, 0x71, 0x5B, 0x90, 0x84, 0x07, 0xE0, +0x24, 0x08, 0xF5, 0x82, 0xE4, 0x34, 0x84, 0xF5, +0x83, 0xEF, 0xF0, 0x90, 0x84, 0x07, 0xE0, 0x04, +0xF0, 0x80, 0xD2, 0x78, 0x08, 0x7C, 0x84, 0xF1, +0xC8, 0x7F, 0x00, 0x70, 0x02, 0x7F, 0x01, 0x22, +0x34, 0x00, 0xFE, 0xE4, 0xFD, 0x71, 0x68, 0xEF, +0x22, 0x7E, 0x00, 0x7F, 0x04, 0x02, 0x41, 0xD0, +0x24, 0x06, 0xFD, 0x71, 0x68, 0xEF, 0x22, 0x90, +0x83, 0xFF, 0xE0, 0xFD, 0x90, 0x83, 0xFE, 0xE0, +0x2D, 0xFD, 0x22, 0xE4, 0xFE, 0xEF, 0x2E, 0xF1, +0xA2, 0xF5, 0x83, 0xE0, 0xFD, 0x74, 0x04, 0x2E, +0xF5, 0x82, 0xE4, 0x34, 0x84, 0xF5, 0x83, 0xED, +0xF0, 0x0E, 0xEE, 0xB4, 0x06, 0xE7, 0x78, 0x7A, +0x7C, 0x81, 0x7D, 0x01, 0x7B, 0x01, 0x7A, 0x84, +0x79, 0x04, 0xF1, 0xB3, 0x7F, 0x00, 0x70, 0x02, +0x7F, 0x01, 0x22, 0x90, 0x83, 0xED, 0xE0, 0xFF, +0xD1, 0x5B, 0xEF, 0x22, 0xD1, 0xA6, 0xD1, 0x5B, +0xEF, 0x60, 0x0A, 0x12, 0x57, 0x7B, 0xB1, 0xA9, +0xEF, 0x60, 0x02, 0x7F, 0x01, 0x22, 0x90, 0x83, +0xFF, 0xED, 0xF0, 0x90, 0x83, 0xFD, 0xEE, 0xF0, +0xA3, 0xEF, 0xF0, 0x22, 0x90, 0x83, 0xEB, 0xE0, +0xFC, 0xA3, 0xE0, 0x22, 0xFF, 0x90, 0x84, 0x00, +0xE0, 0xFD, 0x90, 0x83, 0xFF, 0xE0, 0x2D, 0x22, +0x90, 0x01, 0x34, 0x74, 0xFF, 0x11, 0x98, 0x90, +0x01, 0x3C, 0x11, 0x98, 0xFD, 0x7F, 0x54, 0x12, +0x32, 0x1E, 0x7D, 0xFF, 0x7F, 0x55, 0x12, 0x32, +0x1E, 0x7D, 0xFF, 0x7F, 0x56, 0x12, 0x32, 0x1E, +0x7D, 0xFF, 0x7F, 0x57, 0x02, 0x32, 0x1E, 0x90, +0x01, 0xC7, 0x74, 0x10, 0xF0, 0x7F, 0x01, 0x90, +0x84, 0xA2, 0xEF, 0xF0, 0x90, 0x80, 0x07, 0xE0, +0x64, 0x02, 0x70, 0x1D, 0x90, 0x84, 0xA2, 0xE0, +0xFD, 0x64, 0x01, 0x70, 0x30, 0x51, 0xCF, 0xF1, +0x45, 0x30, 0xE0, 0x09, 0x90, 0x01, 0x4D, 0xE0, +0x64, 0x80, 0xF0, 0x80, 0x20, 0xAF, 0x05, 0x80, +0x19, 0x90, 0x01, 0x00, 0x74, 0xFF, 0xF0, 0x7F, +0x64, 0x7E, 0x00, 0x12, 0x32, 0xAA, 0x90, 0x06, +0x90, 0xE0, 0x44, 0x01, 0xF0, 0x90, 0x84, 0xA2, +0xE0, 0xFF, 0x12, 0x7A, 0x16, 0x90, 0x83, 0xC8, +0xE0, 0x54, 0xFE, 0xF0, 0x22, 0x90, 0x81, 0x72, +0xE0, 0xC4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x22, +0xF1, 0xF9, 0xAD, 0x07, 0x90, 0x01, 0xC4, 0x74, +0x50, 0xF0, 0x74, 0x5F, 0xA3, 0xF0, 0xED, 0x64, +0x01, 0x60, 0x1C, 0x51, 0xCF, 0xED, 0xB4, 0x02, +0x08, 0x90, 0x01, 0xC7, 0x74, 0x40, 0xF0, 0x80, +0x0A, 0xED, 0xB4, 0x04, 0x06, 0x90, 0x01, 0xC7, +0x74, 0x41, 0xF0, 0x7F, 0x01, 0xC1, 0xF7, 0x12, +0x7C, 0x9F, 0x90, 0x02, 0x87, 0xE0, 0x70, 0xF7, +0x90, 0x06, 0x90, 0xE0, 0x44, 0x02, 0xF0, 0x74, +0x50, 0x04, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x5F, +0xA3, 0xF0, 0x22, 0x90, 0x81, 0x6F, 0xE0, 0x13, +0x13, 0x22, 0x24, 0x04, 0xF5, 0x82, 0xE4, 0x34, +0xFB, 0x22, 0xF5, 0x82, 0xE4, 0x34, 0xFB, 0xF5, +0x83, 0xE0, 0x22, 0x7E, 0x00, 0x7F, 0x06, 0x12, +0x44, 0x1A, 0xEF, 0x22, 0x74, 0x01, 0x2D, 0xF5, +0x82, 0xE4, 0x34, 0xFB, 0xF5, 0x83, 0xE0, 0x22, +0x7D, 0x01, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0x9B, +0x7E, 0x00, 0x7F, 0x04, 0x12, 0x44, 0x1A, 0xEF, +0x22, 0xEF, 0x90, 0x01, 0xC7, 0xB4, 0xA0, 0x05, +0x74, 0x04, 0xF0, 0x80, 0x03, 0x74, 0x08, 0xF0, +0x41, 0xCF, 0x7E, 0x00, 0x7F, 0x06, 0x02, 0x41, +0xD0, 0xEA, 0x90, 0xFD, 0x11, 0xF0, 0xAF, 0x03, +0x22, 0x90, 0x02, 0x86, 0xE0, 0x20, 0xE2, 0x03, +0x7F, 0x04, 0x22, 0x90, 0x02, 0x86, 0xE0, 0x7F, +0x01, 0x20, 0xE1, 0x02, 0x7F, 0x02, 0x22, 0x75, +0xE8, 0x03, 0x75, 0xA8, 0x84, 0x22, 0x90, 0x00, +0x80, 0xE0, 0x44, 0x80, 0xFD, 0x7F, 0x80, 0x12, +0x32, 0x1E, 0x90, 0xFD, 0x00, 0xE0, 0x54, 0xBF, +0xF0, 0x12, 0x78, 0x4B, 0x12, 0x32, 0x77, 0xF1, +0xE7, 0x12, 0x78, 0x86, 0x7F, 0x01, 0x12, 0x45, +0x7F, 0x90, 0x83, 0xC3, 0x74, 0x02, 0xF0, 0xFF, +0x12, 0x45, 0x7F, 0x90, 0x83, 0xC3, 0xE0, 0x04, +0xF0, 0x12, 0x58, 0x18, 0x11, 0x70, 0x90, 0x01, +0xCC, 0x74, 0x0F, 0xF0, 0x90, 0x00, 0x80, 0xE0, +0x44, 0x40, 0xFD, 0x7F, 0x80, 0x12, 0x32, 0x1E, +0x75, 0x20, 0xFF, 0x11, 0x0F, 0x12, 0x78, 0x58, +0x12, 0x78, 0x90, 0xE4, 0xFF, 0x02, 0x46, 0x08, +0x11, 0x9B, 0x12, 0x77, 0xFF, 0x12, 0x4E, 0xEE, +0x31, 0x68, 0x31, 0x40, 0x31, 0x53, 0x90, 0x83, +0xD0, 0xE0, 0x54, 0x7F, 0xF0, 0x54, 0xBF, 0xF0, +0x54, 0xDF, 0xF0, 0x54, 0xF0, 0xF0, 0xE4, 0x90, +0x83, 0xD2, 0xF0, 0x90, 0x83, 0xD0, 0xE0, 0x54, +0xEF, 0xF0, 0x22, 0xE4, 0xFD, 0xFF, 0x12, 0x77, +0x0B, 0xFE, 0xEF, 0x54, 0x07, 0xFF, 0xED, 0x70, +0x12, 0x11, 0xDF, 0xC0, 0x83, 0xC0, 0x82, 0x11, +0xD7, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xF4, +0x5E, 0x80, 0x0F, 0x11, 0xDF, 0xC0, 0x83, 0xC0, +0x82, 0x11, 0xD7, 0x80, 0x02, 0xC3, 0x33, 0xD8, +0xFC, 0x4E, 0xD0, 0x82, 0xD0, 0x83, 0xF0, 0x11, +0xEA, 0x90, 0x81, 0x04, 0xEF, 0xF0, 0x22, 0xE0, +0xFE, 0x74, 0x01, 0xA8, 0x07, 0x08, 0x22, 0x74, +0xFC, 0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x80, 0xF5, +0x83, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x7D, 0x08, 0xED, 0x14, 0xF9, 0x24, 0xFC, +0x11, 0xE2, 0xE0, 0x60, 0x3A, 0x7C, 0x08, 0xEC, +0x14, 0x90, 0x84, 0x9B, 0xF0, 0x74, 0xFC, 0x29, +0x11, 0xE2, 0xE0, 0xFB, 0x7A, 0x00, 0x90, 0x84, +0x9B, 0x12, 0x77, 0x4C, 0x80, 0x05, 0xC3, 0x33, +0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, 0xEE, 0x5A, +0xFE, 0xEF, 0x5B, 0x4E, 0x60, 0x0F, 0xE9, 0x75, +0xF0, 0x08, 0xA4, 0xFF, 0x90, 0x84, 0x9B, 0xE0, +0x2F, 0x04, 0xFF, 0x80, 0x06, 0xDC, 0xC8, 0xDD, +0xBA, 0x7F, 0x00, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x90, 0x83, 0xC4, 0xE0, 0x54, 0xFE, 0xF0, 0x54, +0x7F, 0xF0, 0x54, 0xFB, 0xF0, 0xA3, 0x74, 0x0A, +0x02, 0x6A, 0x2C, 0x12, 0x7F, 0xAF, 0x7A, 0x83, +0x79, 0xC8, 0x12, 0x44, 0x3E, 0x90, 0x83, 0xC9, +0x74, 0x08, 0xF0, 0xA3, 0x74, 0x03, 0xF0, 0x22, +0x7E, 0x00, 0x7F, 0x27, 0x7D, 0x00, 0x7B, 0x01, +0x7A, 0x81, 0x79, 0x6E, 0x12, 0x44, 0x3E, 0x90, +0x06, 0x90, 0xE0, 0x44, 0x20, 0xF0, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xE4, 0xFD, 0x7F, +0x8F, 0x12, 0x32, 0x1E, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x31, 0x7E, 0x90, 0x83, 0xC2, 0xE0, 0xFF, +0x12, 0x7E, 0x1C, 0x90, 0x01, 0x3F, 0x74, 0x04, +0xF0, 0x90, 0x80, 0x07, 0xE0, 0xFF, 0xB4, 0x01, +0x07, 0x90, 0xFD, 0x00, 0xE0, 0x54, 0xEF, 0xF0, +0xEF, 0xB4, 0x01, 0x07, 0x90, 0xFE, 0x10, 0xE0, +0x54, 0xFB, 0xF0, 0x22, 0xEF, 0x60, 0x47, 0x90, +0x04, 0xEC, 0xE0, 0x54, 0xDD, 0xF0, 0x90, 0x83, +0xB3, 0xE0, 0xFF, 0x60, 0x02, 0x51, 0x28, 0x90, +0x01, 0xC7, 0xE4, 0x12, 0x7D, 0x4B, 0x12, 0x7F, +0xC9, 0x90, 0x06, 0x09, 0xE0, 0x54, 0xFE, 0xF0, +0x7B, 0x35, 0x12, 0x6E, 0xF7, 0x12, 0x6C, 0x1A, +0x90, 0x02, 0x86, 0xE0, 0x44, 0x04, 0xF0, 0x12, +0x5F, 0x50, 0xF1, 0xE8, 0x12, 0x4E, 0x35, 0x12, +0x7E, 0xDA, 0x90, 0x01, 0x34, 0x74, 0x08, 0xF0, +0xFD, 0xE4, 0xFF, 0x02, 0x6F, 0x08, 0x90, 0x04, +0xEC, 0xE0, 0x44, 0x22, 0xF0, 0x7D, 0x08, 0xE4, +0xFF, 0x12, 0x6F, 0xB9, 0x90, 0x06, 0x90, 0xE0, +0x54, 0xF0, 0xF0, 0x90, 0x02, 0x86, 0xE0, 0x54, +0xFB, 0xF0, 0x31, 0x91, 0xF1, 0xE9, 0x21, 0x68, +0xF1, 0xF0, 0x51, 0x38, 0x75, 0x16, 0x08, 0x7B, +0x01, 0x7A, 0x83, 0x79, 0x7D, 0x02, 0x2B, 0xED, +0x75, 0x13, 0x01, 0xF5, 0x14, 0x89, 0x15, 0x22, +0xF1, 0x83, 0x90, 0x84, 0x8F, 0xE4, 0xF0, 0xA3, +0xEF, 0xF0, 0x90, 0x84, 0x8F, 0x71, 0xF5, 0x90, +0x84, 0x91, 0xEF, 0xF0, 0x90, 0x84, 0x8F, 0x71, +0xDF, 0x51, 0x38, 0x75, 0x16, 0x06, 0x7B, 0x01, +0x7A, 0x81, 0x79, 0x95, 0x71, 0xD7, 0x51, 0xA4, +0x24, 0x36, 0xF9, 0xE4, 0x34, 0xFC, 0x51, 0x38, +0x75, 0x16, 0x04, 0x7B, 0x01, 0x7A, 0x81, 0x79, +0x9B, 0x71, 0xD7, 0x51, 0xA4, 0x71, 0xC9, 0x51, +0x38, 0x75, 0x16, 0x06, 0x7B, 0x01, 0x7A, 0x81, +0x79, 0x9F, 0x71, 0xD7, 0x51, 0xA4, 0x71, 0xD0, +0x51, 0x38, 0x75, 0x16, 0x04, 0x7B, 0x01, 0x7A, +0x81, 0x79, 0xA5, 0x02, 0x2B, 0xED, 0x12, 0x2B, +0xED, 0x90, 0x84, 0x1E, 0xA3, 0xE0, 0xFF, 0xA3, +0xE0, 0x2F, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x84, 0x16, 0x12, 0x42, 0x65, +0x78, 0x22, 0x7C, 0x84, 0x7D, 0x01, 0x7B, 0xFF, +0x7A, 0x40, 0x79, 0xCE, 0x12, 0x5F, 0xEA, 0x90, +0x05, 0x22, 0xE0, 0x90, 0x84, 0x21, 0xF0, 0x90, +0x04, 0x1D, 0xE0, 0x60, 0x08, 0x7B, 0x33, 0xF1, +0x0D, 0x70, 0x1B, 0x80, 0x00, 0x90, 0x83, 0xB4, +0xE0, 0xFF, 0x90, 0x84, 0x83, 0x74, 0x10, 0xF0, +0x7B, 0x18, 0x7D, 0x01, 0xB1, 0x3A, 0x90, 0x84, +0x1E, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x84, +0x1E, 0x71, 0xF5, 0x90, 0x84, 0x20, 0xEF, 0xF0, +0x90, 0x84, 0x1E, 0xA3, 0xE0, 0x24, 0x20, 0xF9, +0xE4, 0x34, 0xFC, 0xFA, 0x7B, 0x01, 0x90, 0x84, +0x1C, 0xE0, 0xFD, 0x91, 0x9F, 0x90, 0x84, 0x1D, +0xE0, 0x70, 0x49, 0x71, 0xDE, 0xFA, 0x7B, 0x01, +0xC0, 0x03, 0xC0, 0x02, 0xC0, 0x01, 0x71, 0xE8, +0x75, 0x16, 0x06, 0xD0, 0x01, 0xD0, 0x02, 0xD0, +0x03, 0x51, 0x9E, 0x71, 0xC9, 0xFA, 0x7B, 0x01, +0xC0, 0x03, 0xC0, 0x02, 0xC0, 0x01, 0x71, 0xE8, +0x75, 0x16, 0x06, 0xD0, 0x01, 0xD0, 0x02, 0xD0, +0x03, 0x51, 0x9E, 0x71, 0xD0, 0xFA, 0x7B, 0x01, +0xC0, 0x03, 0xC0, 0x02, 0xC0, 0x01, 0x90, 0x84, +0x16, 0x71, 0xEB, 0x75, 0x16, 0x04, 0xD0, 0x01, +0xD0, 0x02, 0x80, 0x46, 0x90, 0x84, 0x1D, 0xE0, +0x64, 0x01, 0x70, 0x43, 0x71, 0xDE, 0xFA, 0x7B, +0x01, 0xC0, 0x03, 0x8B, 0x13, 0x75, 0x14, 0x81, +0x75, 0x15, 0x95, 0x75, 0x16, 0x06, 0xD0, 0x03, +0x51, 0x9E, 0x71, 0xC9, 0xFA, 0x7B, 0x01, 0xC0, +0x03, 0x8B, 0x13, 0x75, 0x14, 0x81, 0x75, 0x15, +0x9F, 0x75, 0x16, 0x06, 0xD0, 0x03, 0x51, 0x9E, +0x71, 0xD0, 0xFA, 0x7B, 0x01, 0xC0, 0x03, 0x8B, +0x13, 0x75, 0x14, 0x81, 0x75, 0x15, 0xA5, 0x75, +0x16, 0x04, 0xD0, 0x03, 0x12, 0x2B, 0xED, 0x90, +0x06, 0x30, 0xE0, 0x44, 0x10, 0xF0, 0x90, 0x84, +0x21, 0xE0, 0xFD, 0x7B, 0x34, 0xE4, 0xFF, 0x12, +0x4E, 0x3D, 0xF1, 0xB3, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x24, 0x3A, 0xF9, 0xE4, 0x34, 0xFC, 0x22, +0x24, 0x40, 0xF9, 0xE4, 0x34, 0xFC, 0x22, 0x12, +0x2B, 0xED, 0x90, 0x84, 0x8F, 0x22, 0xA3, 0xA3, +0xE0, 0x24, 0x30, 0xF9, 0xE4, 0x34, 0xFC, 0x22, +0x90, 0x84, 0x19, 0x12, 0x42, 0x5C, 0x8B, 0x13, +0x8A, 0x14, 0x89, 0x15, 0x22, 0xA3, 0xE0, 0xFE, +0x24, 0x20, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, +0x83, 0xE0, 0xFF, 0x74, 0x21, 0x2E, 0xF5, 0x82, +0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0xFD, 0x74, +0x24, 0x2E, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, +0x83, 0xE0, 0xFB, 0xE4, 0xFE, 0xEF, 0x30, 0xE7, +0x04, 0x7C, 0x02, 0x80, 0x02, 0xE4, 0xFC, 0xED, +0x30, 0xE6, 0x09, 0xAF, 0x03, 0x12, 0x7D, 0xDD, +0xAE, 0x07, 0x80, 0x02, 0xE4, 0xFE, 0xEC, 0x24, +0x18, 0x2E, 0xFF, 0x22, 0x90, 0x84, 0x60, 0xED, +0xF0, 0x90, 0x84, 0x5D, 0x12, 0x42, 0x65, 0x12, +0x57, 0xC2, 0x90, 0x84, 0x64, 0xF0, 0x90, 0x84, +0x5D, 0x71, 0xEB, 0x75, 0x16, 0x03, 0x7B, 0x01, +0x7A, 0x84, 0x79, 0x61, 0x12, 0x2B, 0xED, 0x90, +0x84, 0x60, 0xE0, 0x70, 0x2E, 0xFF, 0x91, 0x94, +0xE0, 0xB4, 0xFF, 0x06, 0x91, 0x94, 0xE4, 0xF0, +0x80, 0x07, 0x91, 0x94, 0xE0, 0x04, 0xF0, 0x80, +0x05, 0x0F, 0xEF, 0xB4, 0x03, 0xE8, 0x75, 0x13, +0x01, 0x75, 0x14, 0x84, 0x75, 0x15, 0x61, 0x75, +0x16, 0x03, 0x90, 0x84, 0x5D, 0x12, 0x42, 0x5C, +0x12, 0x2B, 0xED, 0x22, 0x74, 0x61, 0x2F, 0xF5, +0x82, 0xE4, 0x34, 0x84, 0xF5, 0x83, 0x22, 0x90, +0x84, 0x74, 0xED, 0xF0, 0x90, 0x84, 0x71, 0x12, +0x42, 0x65, 0xE4, 0x90, 0x84, 0x75, 0xF0, 0xA3, +0xF0, 0x12, 0x1F, 0xA4, 0xFF, 0x12, 0x56, 0x7B, +0xFD, 0x12, 0x55, 0x82, 0xFB, 0x91, 0x1B, 0x90, +0x84, 0x75, 0xEF, 0xF0, 0x90, 0x84, 0x71, 0x12, +0x42, 0x5C, 0x12, 0x55, 0x82, 0xFF, 0x12, 0x7D, +0xDD, 0x90, 0x84, 0x76, 0xEF, 0xF0, 0x90, 0x83, +0xAE, 0xE0, 0x24, 0xFE, 0x60, 0x14, 0x24, 0xFE, +0x60, 0x10, 0x14, 0x60, 0x07, 0x14, 0x60, 0x04, +0x24, 0x05, 0x70, 0x41, 0xB1, 0x2E, 0x91, 0x3C, +0x80, 0x0D, 0xB1, 0x2E, 0x90, 0x83, 0xAE, 0xE0, +0x90, 0x84, 0x4A, 0xF0, 0x12, 0x55, 0x88, 0x90, +0x84, 0x76, 0xE0, 0xFF, 0x90, 0x84, 0x71, 0x12, +0x42, 0x5C, 0x90, 0x84, 0x75, 0xE0, 0x7C, 0x00, +0x29, 0xF9, 0xEC, 0x3A, 0xFA, 0xC3, 0xE9, 0x9F, +0xF9, 0xEA, 0x94, 0x00, 0xFA, 0x75, 0x13, 0x01, +0x75, 0x14, 0x83, 0x75, 0x15, 0x7D, 0xA3, 0xE0, +0xF5, 0x16, 0x12, 0x2B, 0xED, 0x22, 0x7B, 0x01, +0x7A, 0x83, 0x79, 0x7D, 0x90, 0x84, 0x74, 0xE0, +0xFD, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0x90, 0x84, 0x81, 0xED, 0xF0, 0xA3, 0xEB, +0xF0, 0x90, 0x84, 0x80, 0xEF, 0xF0, 0xE4, 0xFD, +0xFC, 0xF1, 0xBA, 0x90, 0x84, 0x80, 0xE0, 0x90, +0x04, 0x25, 0xF0, 0x90, 0x84, 0x81, 0xE0, 0x60, +0x0E, 0x74, 0x0F, 0x2F, 0xF5, 0x82, 0xE4, 0x34, +0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x80, 0xF0, 0xAF, +0x05, 0x74, 0x08, 0x2F, 0xF5, 0x82, 0xE4, 0x34, +0xFC, 0xF5, 0x83, 0xE4, 0xF0, 0x74, 0x09, 0x2F, +0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, +0x54, 0xF0, 0xF0, 0xAF, 0x05, 0xB1, 0xCC, 0xE0, +0x20, 0xE1, 0x15, 0x54, 0x01, 0xFE, 0x90, 0x84, +0x82, 0xE0, 0x25, 0xE0, 0x25, 0xE0, 0xFB, 0xEE, +0x44, 0x02, 0x4B, 0xFE, 0xB1, 0xCC, 0xEE, 0xF0, +0x90, 0x84, 0x83, 0xE0, 0xFF, 0xAE, 0x05, 0x74, +0x1E, 0x2E, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, +0x83, 0xEF, 0xF0, 0x74, 0x21, 0x2E, 0xD1, 0xF0, +0x54, 0xF7, 0xF0, 0xAE, 0x04, 0xAF, 0x05, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x74, 0x16, 0x2F, 0xF5, +0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0x22, 0x90, +0x80, 0x0B, 0xE0, 0xFF, 0x90, 0x84, 0x78, 0xE0, +0xFB, 0x90, 0x84, 0x83, 0x74, 0x0A, 0xF0, 0x7D, +0x01, 0xB1, 0x3A, 0x90, 0x84, 0x79, 0xEE, 0xF0, +0xFC, 0xA3, 0xEF, 0xF0, 0xFD, 0x90, 0x84, 0x77, +0xE0, 0xFF, 0xD1, 0xB5, 0x90, 0x84, 0x79, 0xE0, +0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x04, 0x80, 0xE0, +0x54, 0x0F, 0xFD, 0xAC, 0x07, 0xF1, 0x01, 0x44, +0x01, 0xF0, 0xF1, 0x01, 0x54, 0xFB, 0xF0, 0xAC, +0x07, 0x74, 0x16, 0x2C, 0xB1, 0xCF, 0xE0, 0x44, +0xFA, 0xF0, 0x74, 0x15, 0x2C, 0xF5, 0x82, 0xE4, +0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x1F, 0xF0, +0xAC, 0x07, 0x74, 0x06, 0x2C, 0xF5, 0x82, 0xE4, +0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x0F, 0xF0, +0x90, 0x04, 0x53, 0xE4, 0xF0, 0x90, 0x04, 0x52, +0xF0, 0x90, 0x04, 0x51, 0x74, 0xFF, 0xF0, 0x90, +0x04, 0x50, 0x74, 0xFD, 0xF0, 0x74, 0x14, 0x2C, +0xD1, 0xF9, 0xE0, 0x54, 0xC0, 0x4D, 0xFD, 0x74, +0x14, 0x2F, 0xD1, 0xF9, 0xED, 0xF0, 0x22, 0x7D, +0x08, 0xE4, 0xFF, 0xD3, 0x10, 0xAF, 0x01, 0xC3, +0xC0, 0xD0, 0x90, 0x84, 0x77, 0xEF, 0xF0, 0xA3, +0xED, 0xF0, 0x90, 0x80, 0x03, 0xE0, 0x04, 0xF0, +0x90, 0x04, 0x1D, 0xE0, 0x60, 0x21, 0x90, 0x05, +0x22, 0xE0, 0x90, 0x84, 0x7B, 0xF0, 0x7B, 0x26, +0xF1, 0x0D, 0x70, 0x02, 0xB1, 0xD7, 0x90, 0x84, +0x7B, 0xE0, 0xFD, 0x7B, 0x27, 0xE4, 0xFF, 0x12, +0x4E, 0x3D, 0x12, 0x7B, 0x63, 0x80, 0x05, 0x12, +0x7B, 0x63, 0xB1, 0xD7, 0xF1, 0xB3, 0x7F, 0x01, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD1, 0xE1, 0x54, +0x3F, 0xF0, 0xBF, 0x01, 0x02, 0x80, 0x17, 0xEF, +0x70, 0x02, 0x80, 0x07, 0x90, 0x81, 0x0D, 0xE0, +0x30, 0xE3, 0x0B, 0xD1, 0xED, 0x54, 0xEF, 0xF0, +0xD1, 0xE1, 0x44, 0x40, 0xF0, 0x22, 0xD1, 0xED, +0x44, 0x10, 0xF0, 0xD1, 0xE1, 0x44, 0x80, 0xF0, +0x22, 0x74, 0x1F, 0x2D, 0xF5, 0x82, 0xE4, 0x34, +0xFC, 0xF5, 0x83, 0xE0, 0x22, 0x74, 0x21, 0x2D, +0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, +0x22, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, +0x22, 0x74, 0x11, 0x2C, 0xF5, 0x82, 0xE4, 0x34, +0xFC, 0xF5, 0x83, 0xE0, 0x22, 0x7D, 0xFF, 0xE4, +0xFF, 0x12, 0x4E, 0x3D, 0xF1, 0x1A, 0xEF, 0x64, +0x01, 0x22, 0xE4, 0x90, 0x84, 0x8C, 0xF0, 0xA3, +0xF0, 0x90, 0x05, 0x22, 0xE0, 0x90, 0x84, 0x8E, +0xF0, 0x7B, 0x47, 0x7D, 0xFF, 0xE4, 0xFF, 0x12, +0x4E, 0x3D, 0x90, 0x05, 0xF8, 0xE0, 0x70, 0x1B, +0xA3, 0xE0, 0x70, 0x17, 0xA3, 0xE0, 0x70, 0x13, +0xA3, 0xE0, 0x70, 0x0F, 0x90, 0x84, 0x8E, 0xE0, +0xFD, 0x7B, 0x48, 0xE4, 0xFF, 0x12, 0x4E, 0x3D, +0x7F, 0x01, 0x22, 0xD3, 0x90, 0x84, 0x8D, 0xE0, +0x94, 0xE8, 0x90, 0x84, 0x8C, 0xE0, 0x94, 0x03, +0x40, 0x16, 0x90, 0x01, 0xC0, 0xE0, 0x44, 0x20, +0xF0, 0x90, 0x84, 0x8E, 0xE0, 0xFD, 0x7B, 0x5B, +0xE4, 0xFF, 0x12, 0x4E, 0x3D, 0x7F, 0x00, 0x22, +0x12, 0x6F, 0xE1, 0x90, 0x84, 0x8C, 0x12, 0x69, +0xA3, 0x80, 0xAF, 0xE4, 0xFE, 0xEF, 0xC3, 0x13, +0xFD, 0xEF, 0x30, 0xE0, 0x02, 0x7E, 0x80, 0x90, +0xFD, 0x10, 0xED, 0xF0, 0xAF, 0x06, 0x22, 0x90, +0x83, 0xC4, 0x12, 0x73, 0x88, 0x30, 0xE0, 0x0D, +0x7B, 0x00, 0x7A, 0x00, 0x79, 0x00, 0x12, 0x7F, +0x86, 0x04, 0xF0, 0x41, 0xAB, 0x7D, 0x08, 0x7F, +0x02, 0xC1, 0x6B, 0x90, 0x04, 0x1F, 0x74, 0x20, +0xF0, 0x22, 0xF1, 0x83, 0x7C, 0x00, 0xAD, 0x07, +0x22, 0xE4, 0xFD, 0xFC, 0xEF, 0x60, 0x1F, 0x90, +0x83, 0xB7, 0xE0, 0xFF, 0xF1, 0xBA, 0xF1, 0xF4, +0xFA, 0x7B, 0x01, 0xF1, 0xEA, 0x90, 0x83, 0xEF, +0x71, 0xEB, 0x75, 0x16, 0x42, 0x7B, 0x01, 0x7A, +0x82, 0x79, 0x41, 0x12, 0x2B, 0xED, 0x22, 0x22, +0x22, 0x22, 0x90, 0x83, 0xEF, 0x02, 0x42, 0x65, +0xF1, 0x83, 0x7E, 0x00, 0x74, 0x00, 0x2F, 0xF9, +0xE4, 0x34, 0xFC, 0x22, 0xE4, 0x90, 0x83, 0xE4, +0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0x90, 0x83, 0xE4, +0xE0, 0x64, 0x01, 0xF0, 0x24, 0xFC, 0x90, 0x01, +0xC4, 0xF0, 0x74, 0x67, 0xA3, 0xF0, 0x90, 0x81, +0x0A, 0xE0, 0x60, 0x0F, 0x90, 0x81, 0x0D, 0xE0, +0xFF, 0x90, 0x81, 0x0C, 0xE0, 0x6F, 0x60, 0x03, +0x12, 0x72, 0x2E, 0xC2, 0xAF, 0x12, 0x78, 0x5F, +0xBF, 0x01, 0x02, 0x11, 0x3E, 0xD2, 0xAF, 0x31, +0xA2, 0x12, 0x44, 0xB7, 0x80, 0xC7, 0x90, 0x81, +0x05, 0xE0, 0x30, 0xE0, 0x02, 0x11, 0x48, 0x22, +0x90, 0x81, 0x0D, 0xE0, 0xFF, 0x60, 0x03, 0xB4, +0x08, 0x0D, 0x31, 0x3D, 0xBF, 0x01, 0x08, 0x11, +0x60, 0x90, 0x01, 0xE5, 0xE0, 0x04, 0xF0, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x11, +0xE5, 0x11, 0x70, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x12, 0x79, 0xF9, 0x90, 0x81, 0x15, 0xE0, 0x20, +0xE0, 0x0C, 0x90, 0x00, 0x26, 0xE0, 0x54, 0x7F, +0xFD, 0x7F, 0x26, 0x12, 0x32, 0x1E, 0x90, 0x00, +0x08, 0xE0, 0x54, 0xEF, 0xFD, 0x7F, 0x08, 0x12, +0x32, 0x1E, 0xE4, 0xFF, 0x90, 0x83, 0xE7, 0x51, +0x2B, 0x90, 0x01, 0x09, 0xE0, 0x7F, 0x00, 0x30, +0xE7, 0x02, 0x7F, 0x01, 0x90, 0x83, 0xE7, 0xE0, +0x6F, 0x60, 0x39, 0xC3, 0x90, 0x83, 0xE9, 0xE0, +0x94, 0x88, 0x90, 0x83, 0xE8, 0xE0, 0x94, 0x13, +0x40, 0x08, 0x90, 0x01, 0xC0, 0xE0, 0x44, 0x10, +0xF0, 0x22, 0x90, 0x83, 0xE8, 0x31, 0xA3, 0x7F, +0x14, 0x7E, 0x00, 0x12, 0x32, 0xAA, 0xD3, 0x90, +0x83, 0xE9, 0xE0, 0x94, 0x32, 0x90, 0x83, 0xE8, +0xE0, 0x94, 0x00, 0x40, 0xBC, 0x90, 0x01, 0xC6, +0xE0, 0x30, 0xE0, 0xB5, 0x22, 0x90, 0x81, 0x15, +0xE0, 0xFD, 0x7F, 0x93, 0x12, 0x32, 0x1E, 0x90, +0x81, 0x0B, 0xE0, 0x60, 0x12, 0x90, 0x01, 0x2F, +0xE0, 0x30, 0xE7, 0x05, 0x74, 0x10, 0xF0, 0x80, +0x06, 0x90, 0x01, 0x2F, 0x74, 0x90, 0xF0, 0x90, +0x00, 0x08, 0xE0, 0x44, 0x10, 0xFD, 0x7F, 0x08, +0x12, 0x32, 0x1E, 0x7F, 0x01, 0x11, 0x94, 0x90, +0x81, 0x15, 0xE0, 0x20, 0xE0, 0x0C, 0x90, 0x00, +0x26, 0xE0, 0x44, 0x80, 0xFD, 0x7F, 0x26, 0x12, +0x32, 0x1E, 0x90, 0x00, 0x90, 0xE0, 0x44, 0x01, +0xFD, 0x7F, 0x90, 0x12, 0x32, 0x1E, 0x7F, 0x14, +0x7E, 0x00, 0x02, 0x32, 0xAA, 0x90, 0x02, 0x87, +0xE0, 0x60, 0x02, 0x80, 0x08, 0x90, 0x01, 0x00, +0xE0, 0x64, 0x3F, 0x60, 0x05, 0x75, 0x51, 0x01, +0x80, 0x41, 0x90, 0x81, 0x6E, 0xE0, 0x30, 0xE0, +0x0B, 0x90, 0x02, 0x82, 0xE0, 0x60, 0x05, 0x75, +0x51, 0x02, 0x80, 0x2F, 0x90, 0x81, 0x79, 0xE0, +0x30, 0xE0, 0x05, 0x75, 0x51, 0x08, 0x80, 0x23, +0x90, 0x02, 0x86, 0xE0, 0x20, 0xE1, 0x02, 0x80, +0x07, 0x90, 0x02, 0x86, 0xE0, 0x30, 0xE3, 0x05, +0x75, 0x51, 0x04, 0x80, 0x0E, 0x90, 0x04, 0x1D, +0xE0, 0x60, 0x05, 0x75, 0x51, 0x40, 0x80, 0x03, +0x02, 0x7A, 0xCD, 0x90, 0x01, 0xB9, 0x74, 0x08, +0xF0, 0x90, 0x01, 0xB8, 0xE5, 0x51, 0xF0, 0x7F, +0x00, 0x22, 0x22, 0xE4, 0x75, 0xF0, 0x01, 0x02, +0x41, 0xF6, 0xE4, 0x90, 0x84, 0x98, 0xF0, 0xA3, +0xF0, 0x90, 0x02, 0x86, 0xE0, 0x20, 0xE1, 0x22, +0xC3, 0x90, 0x84, 0x99, 0xE0, 0x94, 0xD0, 0x90, +0x84, 0x98, 0xE0, 0x94, 0x07, 0x40, 0x0A, 0x90, +0x01, 0xC1, 0xE0, 0x44, 0x04, 0xF0, 0x7F, 0x00, +0x22, 0x90, 0x84, 0x98, 0x31, 0xA3, 0x51, 0x24, +0x80, 0xD7, 0x7F, 0x01, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x84, 0x7C, 0xEE, +0xF0, 0xA3, 0x51, 0x2B, 0x90, 0x84, 0x7C, 0xE0, +0xFE, 0xA3, 0xE0, 0xF5, 0x82, 0x8E, 0x83, 0xE0, +0x60, 0x23, 0xC3, 0x90, 0x84, 0x7F, 0xE0, 0x94, +0xE8, 0x90, 0x84, 0x7E, 0xE0, 0x94, 0x03, 0x40, +0x0B, 0x90, 0x01, 0xC0, 0xE0, 0x44, 0x80, 0xF0, +0x7F, 0x00, 0x80, 0x0B, 0x90, 0x84, 0x7E, 0x31, +0xA3, 0x51, 0x24, 0x80, 0xCF, 0x7F, 0x01, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0x7F, 0x0A, 0x7E, 0x00, +0x02, 0x32, 0xAA, 0xEF, 0xF0, 0xE4, 0xA3, 0xF0, +0xA3, 0xF0, 0x22, 0xE4, 0xFB, 0xFA, 0xFD, 0x7F, +0x01, 0x12, 0x46, 0xB8, 0x90, 0x83, 0xEA, 0xEF, +0xF0, 0x60, 0xF0, 0x90, 0x80, 0x01, 0xE0, 0xFF, +0x70, 0x04, 0xA3, 0xE0, 0x60, 0xE5, 0xC2, 0xAF, +0xEF, 0x30, 0xE1, 0x09, 0x90, 0x80, 0x01, 0xE0, +0x54, 0xFD, 0xF0, 0x51, 0x85, 0x51, 0x7B, 0x30, +0xE2, 0x05, 0x54, 0xFB, 0xF0, 0x51, 0xE6, 0x51, +0x7B, 0x30, 0xE4, 0x0B, 0x54, 0xEF, 0xF0, 0x31, +0xAA, 0xBF, 0x01, 0x03, 0x12, 0x58, 0xA0, 0xD2, +0xAF, 0x80, 0xC8, 0xD2, 0xAF, 0xC2, 0xAF, 0x90, +0x80, 0x01, 0xE0, 0xFF, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x80, 0x61, 0xE0, +0xFF, 0x90, 0x80, 0x60, 0xE0, 0xB5, 0x07, 0x04, +0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x70, +0x40, 0x90, 0x80, 0x60, 0xE0, 0xFE, 0x75, 0xF0, +0x08, 0x90, 0x80, 0x10, 0x12, 0x42, 0x50, 0xE0, +0xFD, 0xEE, 0x75, 0xF0, 0x08, 0xA4, 0x24, 0x11, +0xF9, 0x74, 0x80, 0x35, 0xF0, 0xFA, 0x7B, 0x01, +0xAF, 0x05, 0x12, 0x54, 0xF4, 0x90, 0x80, 0x60, +0x71, 0x4D, 0xB4, 0x0A, 0x02, 0x7F, 0x01, 0xEF, +0x60, 0x05, 0xE4, 0x90, 0x80, 0x60, 0xF0, 0x12, +0x50, 0xE4, 0x90, 0x80, 0x01, 0xE0, 0x44, 0x02, +0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xE4, 0xFF, 0x90, +0x80, 0xF9, 0xE0, 0xFE, 0x90, 0x80, 0xF8, 0xE0, +0xFD, 0xB5, 0x06, 0x04, 0x7E, 0x01, 0x80, 0x02, +0x7E, 0x00, 0xEE, 0x64, 0x01, 0x60, 0x41, 0x90, +0x01, 0xAF, 0xE0, 0x70, 0x0A, 0xED, 0x91, 0x0E, +0xFA, 0x7B, 0x01, 0x71, 0x54, 0x7F, 0x01, 0xEF, +0x60, 0x2E, 0x90, 0x80, 0xF8, 0x71, 0x4D, 0xB4, +0x0A, 0x02, 0x7F, 0x01, 0xEF, 0x60, 0x05, 0xE4, +0x90, 0x80, 0xF8, 0xF0, 0x90, 0x80, 0xF9, 0xE0, +0xFF, 0x90, 0x80, 0xF8, 0xE0, 0xB5, 0x07, 0x04, +0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x70, +0x07, 0x90, 0x80, 0x01, 0xE0, 0x44, 0x04, 0xF0, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xE0, 0x04, 0xF0, +0xE0, 0x7F, 0x00, 0x22, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x90, 0x83, 0xEB, 0x12, 0x42, +0x65, 0x90, 0x84, 0x93, 0xE0, 0xFF, 0x04, 0xF0, +0x90, 0x00, 0x01, 0xEF, 0x12, 0x1F, 0xFC, 0x7F, +0xAF, 0x7E, 0x01, 0x31, 0xDD, 0xEF, 0x60, 0x34, +0x90, 0x83, 0xEB, 0x12, 0x63, 0xEB, 0x90, 0x00, +0x0E, 0x12, 0x1F, 0xBD, 0x24, 0x02, 0xF5, 0x16, +0x7B, 0x01, 0x7A, 0x01, 0x79, 0xA0, 0x12, 0x2B, +0xED, 0x90, 0x83, 0xEB, 0x12, 0x42, 0x5C, 0x90, +0x00, 0x0E, 0x12, 0x1F, 0xBD, 0x90, 0x01, 0xAE, +0xF0, 0xA3, 0x74, 0xFF, 0xF0, 0x90, 0x01, 0xCB, +0xE0, 0x64, 0x80, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, +0x90, 0x80, 0xF8, 0xE0, 0xFF, 0x70, 0x06, 0xA3, +0xE0, 0x64, 0x09, 0x60, 0x0A, 0xEF, 0x14, 0xFF, +0x90, 0x80, 0xF9, 0xE0, 0xB5, 0x07, 0x04, 0x7F, +0x01, 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x60, 0x09, +0x90, 0x01, 0xC1, 0xE0, 0x44, 0x02, 0xF0, 0x80, +0x28, 0xC0, 0x01, 0x90, 0x80, 0xF9, 0xE0, 0x91, +0x0E, 0xA8, 0x01, 0xFC, 0x7D, 0x01, 0xD0, 0x01, +0x7E, 0x00, 0x7F, 0x0F, 0x12, 0x41, 0xD0, 0x90, +0x80, 0xF9, 0x71, 0x4D, 0xB4, 0x0A, 0x02, 0x7F, +0x01, 0xEF, 0x60, 0x05, 0xE4, 0x90, 0x80, 0xF9, +0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x75, 0xF0, +0x0F, 0xA4, 0x24, 0x62, 0xF9, 0x74, 0x80, 0x35, +0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, +0xD0, 0xE4, 0x90, 0x84, 0x6B, 0xF0, 0xA3, 0xF0, +0x12, 0x67, 0x1A, 0x90, 0x85, 0xBB, 0x12, 0x20, +0xDA, 0xCC, 0xF0, 0x00, 0xC0, 0x7F, 0x8C, 0xD1, +0x2D, 0x12, 0x20, 0xDA, 0x00, 0x00, 0x00, 0x14, +0xD1, 0xC4, 0x12, 0x20, 0xDA, 0x00, 0x00, 0x00, +0x00, 0xE4, 0xFD, 0xFF, 0xD1, 0x8F, 0x7F, 0xE8, +0x7E, 0x08, 0x12, 0x2D, 0x5C, 0xEF, 0x54, 0x0E, +0xFF, 0xE4, 0xFE, 0xED, 0x54, 0xF4, 0xFD, 0xEC, +0x54, 0x03, 0xFC, 0xE4, 0xFB, 0xFA, 0xF9, 0xF8, +0xC3, 0x12, 0x42, 0x27, 0x60, 0x17, 0xD3, 0x91, +0xB8, 0x40, 0x09, 0x90, 0x01, 0xC3, 0xE0, 0x44, +0x02, 0xF0, 0x80, 0x09, 0xF1, 0xE1, 0x90, 0x84, +0x6B, 0x31, 0xA3, 0x80, 0xC9, 0xC3, 0x91, 0xB8, +0x50, 0x17, 0xD1, 0xB1, 0x44, 0x80, 0xFC, 0x90, +0x84, 0x6D, 0x12, 0x20, 0xCE, 0x90, 0x84, 0x6D, +0x91, 0xC5, 0x7F, 0x7C, 0x7E, 0x08, 0x12, 0x2E, +0xA2, 0x90, 0x01, 0x00, 0x74, 0x3F, 0xF0, 0xA3, +0xE0, 0x54, 0xFD, 0xF0, 0x90, 0x05, 0x53, 0xE0, +0x44, 0x20, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, 0x22, +0x90, 0x84, 0x6C, 0xE0, 0x94, 0xE8, 0x90, 0x84, +0x6B, 0xE0, 0x94, 0x03, 0x22, 0x12, 0x42, 0x38, +0x90, 0x85, 0xBB, 0x02, 0x20, 0xCE, 0x90, 0x84, +0x28, 0xEF, 0xF0, 0xA3, 0xED, 0xF0, 0xA3, 0x12, +0x20, 0xDA, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x90, +0x84, 0x36, 0xF0, 0x7F, 0x24, 0x7E, 0x08, 0x12, +0x2D, 0x5C, 0x90, 0x84, 0x2E, 0x12, 0x20, 0xCE, +0x90, 0x84, 0x28, 0xE0, 0xFB, 0x70, 0x04, 0xB1, +0xB1, 0x80, 0x06, 0xEB, 0xB1, 0xB7, 0x12, 0x2D, +0x5C, 0x90, 0x84, 0x32, 0x12, 0x20, 0xCE, 0x90, +0x84, 0x29, 0x12, 0x49, 0x51, 0x78, 0x17, 0xD1, +0xBA, 0xAB, 0x07, 0x90, 0x84, 0x32, 0x12, 0x42, +0x38, 0xED, 0x54, 0x7F, 0xFD, 0xEC, 0x54, 0x80, +0xFC, 0x12, 0x42, 0x1A, 0xEC, 0x44, 0x80, 0xFC, +0x90, 0x84, 0x32, 0x12, 0x20, 0xCE, 0xB1, 0xB1, +0xEC, 0x54, 0x7F, 0xFC, 0x91, 0xC8, 0xB1, 0xCA, +0xB1, 0xB7, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x84, +0x32, 0x91, 0xC5, 0xD0, 0x07, 0xD0, 0x06, 0x12, +0x2E, 0xA2, 0xB1, 0xB1, 0xEC, 0x44, 0x80, 0xFC, +0x91, 0xC8, 0xB1, 0xCA, 0x70, 0x04, 0x7F, 0x20, +0x80, 0x09, 0x90, 0x84, 0x28, 0xE0, 0xB4, 0x01, +0x16, 0x7F, 0x28, 0x7E, 0x08, 0x12, 0x2D, 0x5C, +0x78, 0x08, 0x12, 0x20, 0xA8, 0xEF, 0x54, 0x01, +0xFF, 0xE4, 0x90, 0x84, 0x36, 0xEF, 0xF0, 0x90, +0x84, 0x36, 0xE0, 0x90, 0x84, 0x28, 0x60, 0x0E, +0xE0, 0x75, 0xF0, 0x08, 0xA4, 0x24, 0x66, 0xF5, +0x82, 0xE4, 0x34, 0x87, 0x80, 0x0C, 0xE0, 0x75, +0xF0, 0x08, 0xA4, 0x24, 0x64, 0xF5, 0x82, 0xE4, +0x34, 0x87, 0xB1, 0xC2, 0x12, 0x2D, 0x5C, 0xED, +0x54, 0x0F, 0xFD, 0xE4, 0xFC, 0x90, 0x84, 0x2A, +0x12, 0x20, 0xCE, 0x90, 0x84, 0x2A, 0x02, 0x42, +0x38, 0x90, 0x84, 0x2E, 0x02, 0x42, 0x38, 0x75, +0xF0, 0x08, 0xA4, 0x24, 0x62, 0xF5, 0x82, 0xE4, +0x34, 0x87, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, +0xFF, 0x22, 0x7F, 0x24, 0x7E, 0x08, 0x12, 0x2E, +0xA2, 0x90, 0x84, 0x28, 0xE0, 0x22, 0x90, 0x84, +0x53, 0xEF, 0xF0, 0xAB, 0x05, 0x90, 0x84, 0x59, +0x12, 0x20, 0xDA, 0x00, 0x00, 0x00, 0x00, 0xAF, +0x03, 0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x14, 0xD1, +0xBA, 0xAB, 0x07, 0x90, 0x84, 0x55, 0x12, 0x42, +0x38, 0xED, 0x54, 0x0F, 0xFD, 0xE4, 0xFC, 0x12, +0x42, 0x1A, 0xEC, 0x54, 0x0F, 0xFC, 0x90, 0x84, +0x59, 0x12, 0x20, 0xCE, 0x90, 0x84, 0x53, 0xE0, +0x75, 0xF0, 0x08, 0xA4, 0x24, 0x60, 0xF5, 0x82, +0xE4, 0x34, 0x87, 0xB1, 0xC2, 0xC0, 0x06, 0xC0, +0x07, 0x90, 0x84, 0x59, 0x91, 0xC5, 0xD0, 0x07, +0xD0, 0x06, 0x02, 0x2E, 0xA2, 0x7E, 0x08, 0x12, +0x2E, 0xA2, 0x90, 0x85, 0xBB, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x01, 0x01, +0xE0, 0x44, 0x02, 0xF0, 0x90, 0x01, 0x00, 0x74, +0xFF, 0xF0, 0x90, 0x06, 0xB7, 0x74, 0x09, 0xF0, +0x90, 0x06, 0xB4, 0x74, 0x86, 0xF0, 0xD1, 0xB1, +0x54, 0x7F, 0xFC, 0x90, 0x84, 0x84, 0x12, 0x20, +0xCE, 0x90, 0x84, 0x84, 0x91, 0xC5, 0x7F, 0x7C, +0xD1, 0x2D, 0x12, 0x20, 0xDA, 0xCC, 0xC0, 0x00, +0xC0, 0x7F, 0x8C, 0xD1, 0x2D, 0x12, 0x20, 0xDA, +0x00, 0xC0, 0x00, 0x14, 0xD1, 0xC4, 0x12, 0x20, +0xDA, 0x00, 0x03, 0x3E, 0x60, 0xE4, 0xFD, 0xFF, +0xD1, 0x8F, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xC0, 0x07, +0xC0, 0x05, 0x90, 0x84, 0x67, 0x12, 0x42, 0x38, +0x90, 0x84, 0x55, 0x12, 0x20, 0xCE, 0xD0, 0x05, +0xD0, 0x07, 0xB1, 0xD6, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x7F, 0x7C, 0x7E, 0x08, 0x12, 0x2D, 0x5C, +0xEC, 0x22, 0x12, 0x20, 0xBB, 0xA8, 0x04, 0xA9, +0x05, 0xAA, 0x06, 0x22, 0x7F, 0x70, 0x7E, 0x0E, +0x12, 0x2E, 0xA2, 0x90, 0x84, 0x67, 0x22, 0x7B, +0x2F, 0xD1, 0xF7, 0x91, 0x1A, 0x7D, 0x08, 0x7F, +0x01, 0x02, 0x4E, 0x86, 0x7B, 0x2D, 0xD1, 0xF7, +0x12, 0x67, 0x1A, 0x90, 0x01, 0x37, 0x74, 0x02, +0xF0, 0xFD, 0x7F, 0x03, 0xF1, 0x08, 0x91, 0x1A, +0xE4, 0xFD, 0x7F, 0x01, 0x02, 0x4E, 0x86, 0x7D, +0xFF, 0x7F, 0xFF, 0x02, 0x4E, 0x3D, 0x7D, 0x01, +0x7F, 0x02, 0xF1, 0x08, 0x7D, 0x02, 0x7F, 0x02, +0x74, 0x3D, 0x2F, 0xF8, 0xE6, 0x4D, 0xFE, 0xF6, +0x74, 0x30, 0xF1, 0xCA, 0xEE, 0xF0, 0x22, 0x90, +0x81, 0x05, 0xE0, 0x54, 0xFB, 0xF0, 0xE4, 0x90, +0x81, 0x13, 0xF0, 0xA3, 0xF0, 0x90, 0x81, 0x0E, +0xF0, 0x90, 0x81, 0x06, 0xE0, 0x54, 0xF7, 0xF0, +0x54, 0xBF, 0xF0, 0xD1, 0xFE, 0x7D, 0x10, 0x7F, +0x03, 0x74, 0x45, 0xF1, 0xD3, 0xF1, 0xC6, 0xEE, +0xF0, 0x22, 0x90, 0x01, 0x36, 0x74, 0x78, 0xF0, +0xA3, 0x74, 0x02, 0xF0, 0x7D, 0x78, 0xFF, 0xF1, +0x08, 0x7D, 0x02, 0x7F, 0x03, 0xF1, 0x08, 0x90, +0x06, 0x0A, 0xE0, 0x44, 0x07, 0x12, 0x76, 0x9A, +0xE4, 0xFF, 0x12, 0x4F, 0xB8, 0xBF, 0x01, 0x10, +0xF1, 0xE8, 0x90, 0x81, 0x0D, 0xE0, 0x20, 0xE2, +0x0A, 0x7D, 0x01, 0x7F, 0x04, 0x02, 0x4C, 0x49, +0x12, 0x77, 0x1A, 0x22, 0xEF, 0x70, 0x34, 0x7D, +0x78, 0x7F, 0x02, 0xF1, 0xB9, 0x7D, 0x02, 0x7F, +0x03, 0xF1, 0xB9, 0x7D, 0xC8, 0x7F, 0x02, 0xF1, +0x39, 0x12, 0x73, 0x8F, 0x12, 0x4F, 0xA7, 0x70, +0x0D, 0xD1, 0x36, 0x12, 0x4F, 0xAE, 0x12, 0x7B, +0xC2, 0x54, 0x7F, 0xF0, 0x80, 0x07, 0x7D, 0x01, +0x7F, 0x0C, 0x12, 0x4C, 0x49, 0x12, 0x70, 0xC5, +0x02, 0x7F, 0xC1, 0x80, 0x8D, 0x7D, 0x02, 0x7F, +0x02, 0x74, 0x3D, 0xF1, 0xD3, 0xFE, 0xF6, 0x74, +0x30, 0xF1, 0xCA, 0xEE, 0xF0, 0x22, 0xFE, 0xF6, +0x74, 0x38, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x01, +0xF5, 0x83, 0x22, 0x2F, 0xF8, 0xE6, 0xFE, 0xED, +0xF4, 0x5E, 0x22, 0x7D, 0x01, 0x7F, 0x02, 0x80, +0xD8, 0x7F, 0x32, 0x7E, 0x00, 0x02, 0x32, 0xAA, +0x90, 0x81, 0x06, 0xE0, 0x54, 0xFB, 0xF0, 0x22, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x91, +0xCE, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x84, +0x9A, 0xEF, 0xF0, 0x7F, 0x02, 0x12, 0x46, 0x91, +0x90, 0x80, 0x01, 0xE0, 0xFF, 0x90, 0x84, 0x9A, +0xE0, 0xFE, 0xEF, 0x4E, 0x90, 0x80, 0x01, 0xF0, +0x22, 0x90, 0x02, 0x09, 0xE0, 0xF5, 0x52, 0x12, +0x1F, 0xA4, 0x25, 0x52, 0x90, 0x80, 0x09, 0x12, +0x56, 0x7A, 0x25, 0x52, 0x90, 0x80, 0x0A, 0x12, +0x57, 0x74, 0x25, 0x52, 0x90, 0x80, 0x0B, 0x12, +0x57, 0xC1, 0x25, 0x52, 0x90, 0x80, 0x0C, 0x12, +0x55, 0x81, 0x25, 0x52, 0x90, 0x80, 0x0D, 0x12, +0x57, 0xB9, 0x25, 0x52, 0x90, 0x80, 0x0E, 0xF0, +0x90, 0x00, 0x06, 0x12, 0x1F, 0xBD, 0x25, 0x52, +0x90, 0x80, 0x0F, 0xF0, 0x22, 0x8B, 0x52, 0x8A, +0x53, 0x89, 0x54, 0x12, 0x56, 0x7B, 0xFF, 0xF5, +0x56, 0x12, 0x1F, 0xA4, 0xFE, 0xC3, 0x13, 0x30, +0xE0, 0x07, 0x12, 0x57, 0x75, 0xF5, 0x57, 0x80, +0x02, 0x8F, 0x57, 0x85, 0x56, 0x55, 0xE5, 0x55, +0xD3, 0x95, 0x57, 0x50, 0x25, 0xAB, 0x52, 0xAA, +0x53, 0xA9, 0x54, 0x12, 0x1F, 0xA4, 0x54, 0x01, +0xFD, 0xAF, 0x55, 0x12, 0x60, 0x9E, 0xAF, 0x55, +0x12, 0x4F, 0xB8, 0xEF, 0xAF, 0x55, 0x70, 0x04, +0x91, 0x44, 0x80, 0x02, 0x11, 0xC4, 0x05, 0x55, +0x80, 0xD4, 0xE5, 0x56, 0x70, 0x15, 0xFF, 0x12, +0x4F, 0xB8, 0xEF, 0x70, 0x0E, 0x12, 0x6E, 0x36, +0x12, 0x4F, 0xAE, 0x11, 0xC5, 0x54, 0xBF, 0xF0, +0x54, 0x7F, 0xF0, 0x22, 0x22, 0x90, 0x81, 0x05, +0xE0, 0x54, 0xF7, 0xF0, 0x22, 0x90, 0x81, 0x0A, +0xE0, 0x60, 0x0D, 0x90, 0x06, 0x92, 0xE0, 0x30, +0xE1, 0x02, 0x80, 0x05, 0x11, 0xC5, 0x51, 0x2E, +0x22, 0xF1, 0x32, 0x54, 0x1F, 0x30, 0xE0, 0x05, +0x90, 0x01, 0x5B, 0xE4, 0xF0, 0x90, 0x06, 0x92, +0x74, 0x02, 0xF0, 0x90, 0x01, 0x3C, 0x74, 0x04, +0xF0, 0xE4, 0xF5, 0x1D, 0x90, 0x81, 0x69, 0xE0, +0xC3, 0x13, 0x54, 0x7F, 0xF5, 0x1E, 0xE4, 0xFB, +0xFD, 0x7F, 0x58, 0x7E, 0x01, 0x12, 0x4A, 0x7B, +0x90, 0x81, 0x05, 0xE0, 0x44, 0x08, 0xF0, 0x22, +0x11, 0xE1, 0x90, 0x81, 0x0D, 0xE0, 0x64, 0x0C, +0x60, 0x08, 0x31, 0x61, 0x12, 0x4E, 0x38, 0x12, +0x66, 0x67, 0x22, 0xE4, 0xFF, 0x12, 0x4F, 0xB8, +0xBF, 0x01, 0x10, 0x90, 0x81, 0x0A, 0xE0, 0x60, +0x0A, 0x31, 0x69, 0x64, 0x02, 0x60, 0x02, 0x41, +0x4F, 0x31, 0x18, 0x22, 0x90, 0x81, 0x0A, 0xE0, +0x64, 0x01, 0x70, 0x14, 0x31, 0x69, 0x60, 0x07, +0x31, 0x61, 0x12, 0x4E, 0x38, 0x80, 0x8A, 0x90, +0x81, 0x0D, 0xE0, 0x70, 0x03, 0x12, 0x4C, 0x45, +0x22, 0xE4, 0xFD, 0x7F, 0x0C, 0x02, 0x4C, 0x49, +0xF0, 0x90, 0x81, 0x08, 0xE0, 0x54, 0x0F, 0x22, +0x90, 0x06, 0xA9, 0xE0, 0xF5, 0x4E, 0x54, 0xC0, +0x70, 0x07, 0x31, 0xBF, 0x54, 0xFD, 0xF0, 0x41, +0x2E, 0xE5, 0x4E, 0x30, 0xE6, 0x1C, 0x90, 0x81, +0x0A, 0xE0, 0x64, 0x01, 0x70, 0x16, 0x90, 0x81, +0x0E, 0xE0, 0x44, 0x01, 0x31, 0x68, 0x64, 0x02, +0x60, 0x04, 0x51, 0x4F, 0x80, 0x06, 0x31, 0x18, +0x80, 0x02, 0x31, 0xBF, 0xE5, 0x4E, 0x90, 0x81, +0x0E, 0x30, 0xE7, 0x0E, 0xE0, 0x44, 0x02, 0x12, +0x4A, 0x6A, 0x90, 0x81, 0x05, 0xE0, 0x44, 0x04, +0xF0, 0x22, 0xE0, 0x54, 0xFD, 0xF0, 0x22, 0x90, +0x81, 0x0E, 0xE0, 0x54, 0xFE, 0xF0, 0x22, 0x71, +0x7C, 0x54, 0x1F, 0x30, 0xE0, 0x0C, 0xEF, 0xC4, +0x13, 0x13, 0x54, 0x03, 0x30, 0xE0, 0x03, 0x12, +0x6F, 0xB5, 0x90, 0x81, 0x05, 0x71, 0x88, 0x30, +0xE0, 0x0A, 0xEF, 0x51, 0x98, 0xF0, 0x54, 0x07, +0x70, 0x43, 0x80, 0x3F, 0x90, 0x81, 0x13, 0xE0, +0x04, 0xF0, 0x90, 0x81, 0x0E, 0xE0, 0x54, 0xEF, +0xF0, 0xD1, 0xA5, 0x40, 0x2E, 0x12, 0x4F, 0xA8, +0x64, 0x01, 0x70, 0x29, 0xB1, 0x87, 0x31, 0x69, +0x70, 0x03, 0x02, 0x6F, 0xE8, 0x90, 0x81, 0x14, +0xE0, 0x04, 0xF0, 0xE0, 0xD3, 0x94, 0x02, 0x40, +0x0A, 0x12, 0x6F, 0xE8, 0xE4, 0x90, 0x81, 0x14, +0xF0, 0x80, 0x02, 0x31, 0x18, 0xE4, 0x90, 0x81, +0x13, 0xF0, 0x22, 0x51, 0x2E, 0x22, 0x90, 0x81, +0x0C, 0xE0, 0xFF, 0x7D, 0x01, 0x02, 0x4C, 0x49, +0xE4, 0xFF, 0x12, 0x4F, 0xB8, 0xBF, 0x01, 0x0E, +0x90, 0x81, 0x0A, 0xE0, 0x60, 0x08, 0x31, 0xBF, +0x54, 0x07, 0x70, 0x02, 0x51, 0x2E, 0x22, 0x90, +0x04, 0x1D, 0xE0, 0x70, 0x1D, 0x90, 0x80, 0x0A, +0xE0, 0xFF, 0x90, 0x84, 0x83, 0x74, 0x09, 0xF0, +0x7B, 0x18, 0xE4, 0xFD, 0x12, 0x65, 0x3A, 0x90, +0x83, 0xD8, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x12, +0x67, 0xB3, 0x22, 0x12, 0x4F, 0xA8, 0x64, 0x01, +0x70, 0x1D, 0x90, 0x81, 0x0A, 0xE0, 0x60, 0x17, +0x90, 0x81, 0x0E, 0xE0, 0x20, 0xE4, 0x10, 0x71, +0x8F, 0xF0, 0x90, 0x81, 0x05, 0xE0, 0x51, 0x98, +0xF0, 0x54, 0x07, 0x70, 0x02, 0x51, 0x2E, 0x22, +0x54, 0xFB, 0xF0, 0x90, 0x81, 0x0E, 0xE0, 0x54, +0xFD, 0x22, 0x90, 0x05, 0x62, 0xE0, 0xFE, 0x90, +0x05, 0x61, 0xE0, 0xFD, 0xED, 0x78, 0x02, 0xCE, +0xC3, 0x13, 0xCE, 0x13, 0xD8, 0xF9, 0xFF, 0x90, +0x83, 0xD6, 0xEE, 0xF0, 0xA3, 0xEF, 0x12, 0x4F, +0xA7, 0x64, 0x01, 0x60, 0x02, 0x61, 0x68, 0x90, +0x81, 0x0A, 0xE0, 0x70, 0x02, 0x61, 0x68, 0xF1, +0x3A, 0x64, 0x01, 0x70, 0x22, 0x90, 0x06, 0xAB, +0xE0, 0x90, 0x81, 0x11, 0xF0, 0x90, 0x06, 0xAA, +0xE0, 0x90, 0x81, 0x10, 0xF0, 0xA3, 0xE0, 0xFF, +0x70, 0x08, 0x90, 0x81, 0x10, 0xE0, 0xFE, 0xFF, +0x80, 0x00, 0x90, 0x81, 0x11, 0xEF, 0xF0, 0x12, +0x4A, 0xE0, 0xE4, 0x90, 0x81, 0x13, 0xF0, 0xA3, +0xD1, 0x9A, 0x71, 0x8F, 0x51, 0x9A, 0xF0, 0x54, +0xEF, 0xF0, 0x31, 0x70, 0x71, 0x7C, 0x54, 0x1F, +0x30, 0xE0, 0x53, 0xEF, 0xC4, 0x13, 0x13, 0x54, +0x03, 0x20, 0xE0, 0x20, 0x71, 0x69, 0x6F, 0x70, +0x45, 0x90, 0x81, 0x06, 0xE0, 0x44, 0x40, 0xF0, +0xF1, 0x22, 0x71, 0x71, 0xF1, 0x56, 0x12, 0x6F, +0xDB, 0x12, 0x6F, 0xB5, 0x90, 0x81, 0x11, 0xE0, +0x14, 0xF0, 0x80, 0x2A, 0x90, 0x81, 0x08, 0xE0, +0xC4, 0x54, 0x0F, 0x64, 0x01, 0x70, 0x1F, 0x71, +0x69, 0xFE, 0x6F, 0x60, 0x19, 0x90, 0x05, 0x73, +0xE0, 0xFF, 0xEE, 0x6F, 0x60, 0x10, 0x71, 0x85, +0x30, 0xE0, 0x0B, 0xEF, 0x54, 0xBF, 0x71, 0x71, +0x12, 0x6F, 0x39, 0x12, 0x6E, 0xFE, 0xF1, 0x1A, +0x22, 0x90, 0x81, 0x10, 0xE0, 0xFF, 0xA3, 0xE0, +0x22, 0xF0, 0x90, 0x01, 0x3F, 0x74, 0x10, 0xF0, +0xFD, 0x7F, 0x03, 0x22, 0x90, 0x81, 0x06, 0xE0, +0xFF, 0x13, 0x13, 0x13, 0x22, 0x90, 0x81, 0x06, +0xE0, 0xFF, 0x13, 0x13, 0x54, 0x3F, 0x22, 0x90, +0x01, 0x57, 0xE4, 0xF0, 0x90, 0x01, 0x3C, 0x74, +0x02, 0x22, 0x90, 0x81, 0x05, 0xF1, 0x2A, 0x30, +0xE0, 0x19, 0xEF, 0x54, 0xBF, 0x91, 0xC2, 0x30, +0xE0, 0x06, 0xE0, 0x44, 0x01, 0xF0, 0x80, 0x09, +0xE0, 0x54, 0xFE, 0xF0, 0x91, 0xCB, 0x74, 0x04, +0xF0, 0x51, 0x2E, 0xE4, 0xFF, 0x90, 0x83, 0xC8, +0xE0, 0xFD, 0x30, 0xE0, 0x49, 0x90, 0x83, 0xCD, +0xE0, 0xFC, 0x60, 0x42, 0xF1, 0x4E, 0x80, 0x05, +0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0xFF, +0x90, 0x04, 0xE0, 0xE0, 0xFB, 0xEF, 0x5B, 0x60, +0x0B, 0xE4, 0x90, 0x83, 0xCD, 0xF0, 0x90, 0x83, +0xCF, 0x04, 0xF0, 0x22, 0x90, 0x83, 0xCA, 0xE0, +0xD3, 0x9C, 0x50, 0x18, 0xED, 0x13, 0x13, 0x13, +0x54, 0x1F, 0x30, 0xE0, 0x04, 0x91, 0x3C, 0x80, +0x03, 0x12, 0x5E, 0xEF, 0x90, 0x83, 0xC8, 0xE0, +0x54, 0xFE, 0xF0, 0x22, 0xB1, 0x48, 0x22, 0x90, +0x81, 0x05, 0xE0, 0xFF, 0x12, 0x5F, 0x49, 0x30, +0xE0, 0x1E, 0xEF, 0x54, 0x7F, 0x91, 0xC2, 0x30, +0xE1, 0x06, 0xE0, 0x44, 0x02, 0xF0, 0x80, 0x08, +0xE0, 0x54, 0xFD, 0xF0, 0x91, 0xCB, 0x04, 0xF0, +0x90, 0x81, 0x0A, 0xE0, 0x60, 0x02, 0x51, 0x2E, +0x7F, 0x01, 0x80, 0x81, 0xE4, 0xFD, 0xFF, 0x12, +0x60, 0x9E, 0xE4, 0xFF, 0x22, 0x90, 0x83, 0xC8, +0xE0, 0x30, 0xE0, 0x75, 0x90, 0x83, 0xCC, 0xE0, +0x04, 0xF0, 0x90, 0x83, 0xCF, 0xE0, 0x64, 0x01, +0x70, 0x34, 0x90, 0x83, 0xC8, 0x71, 0x88, 0x30, +0xE0, 0x2C, 0x90, 0x83, 0xCE, 0xE0, 0x70, 0x26, +0x90, 0x83, 0xCB, 0xE0, 0xFE, 0xA3, 0xE0, 0xC3, +0x9E, 0x40, 0x1B, 0xF1, 0x0B, 0x30, 0xE0, 0x0B, +0x91, 0x3C, 0x90, 0x83, 0xC8, 0xE0, 0x54, 0xFE, +0xF0, 0x80, 0x0B, 0x12, 0x5E, 0xEF, 0x90, 0x83, +0xC8, 0xE0, 0x54, 0xFE, 0xF0, 0x22, 0x90, 0x83, +0xCC, 0xE0, 0xFF, 0x90, 0x83, 0xC9, 0xE0, 0xD3, +0x9F, 0x50, 0x26, 0x90, 0x06, 0x92, 0xE0, 0x20, +0xE2, 0x10, 0x90, 0x83, 0xCE, 0xE0, 0x70, 0x0A, +0xB1, 0x48, 0x90, 0x83, 0xC7, 0xE0, 0x04, 0xF0, +0x80, 0x06, 0x90, 0x06, 0x92, 0x74, 0x04, 0xF0, +0xE4, 0x90, 0x83, 0xCC, 0xF0, 0x90, 0x83, 0xCE, +0xF0, 0x22, 0xF0, 0x90, 0x04, 0xE0, 0xE0, 0x90, +0x81, 0x06, 0x22, 0x90, 0x01, 0xB9, 0x74, 0x01, +0xF0, 0x90, 0x01, 0xB8, 0x22, 0x12, 0x67, 0xEA, +0x12, 0x1F, 0xA4, 0xFF, 0x54, 0x7F, 0x90, 0x81, +0x0A, 0xF0, 0xEF, 0x12, 0x5F, 0x49, 0xA3, 0x12, +0x56, 0x7A, 0xFD, 0x54, 0xF0, 0xC4, 0x54, 0x0F, +0xFF, 0x90, 0x81, 0x08, 0xE0, 0x54, 0xF0, 0x4F, +0x12, 0x57, 0xC1, 0xFC, 0x54, 0x01, 0x25, 0xE0, +0xFF, 0x90, 0x81, 0x05, 0xE0, 0x54, 0xFD, 0x4F, +0xF0, 0xEC, 0x54, 0x04, 0xC3, 0x13, 0xFF, 0x90, +0x81, 0x07, 0xE0, 0x54, 0xFD, 0x4F, 0xF0, 0xED, +0x54, 0x0F, 0xC4, 0x54, 0xF0, 0xFF, 0xA3, 0xE0, +0x54, 0x0F, 0x12, 0x57, 0x73, 0x90, 0x81, 0x09, +0x12, 0x55, 0x81, 0xFD, 0x7F, 0x02, 0x12, 0x4E, +0x86, 0x90, 0x83, 0xEF, 0x12, 0x42, 0x5C, 0xB1, +0x56, 0x91, 0xCB, 0xF0, 0x90, 0x81, 0x0A, 0xF1, +0x62, 0x31, 0x68, 0x90, 0x01, 0xBE, 0xF0, 0x22, +0x7D, 0x08, 0x7F, 0x02, 0x12, 0x66, 0x6B, 0x90, +0x83, 0xCD, 0xE0, 0x04, 0xF0, 0x22, 0x90, 0x83, +0xF2, 0x12, 0x42, 0x65, 0x12, 0x6F, 0x17, 0x90, +0x81, 0x0A, 0xE0, 0xFF, 0x12, 0x6F, 0x7C, 0x90, +0x81, 0x0A, 0xE0, 0x60, 0x19, 0x90, 0x83, 0xF2, +0x12, 0x42, 0x5C, 0x12, 0x56, 0x7B, 0x54, 0x0F, +0xFF, 0x12, 0x57, 0x75, 0xFD, 0xF1, 0x80, 0xD1, +0xFA, 0x74, 0x01, 0xF0, 0xB1, 0xBF, 0x22, 0xD1, +0xA5, 0x40, 0x33, 0x90, 0x81, 0x24, 0xE0, 0x04, +0xF0, 0x90, 0x81, 0x66, 0xE0, 0xFF, 0x90, 0x81, +0x24, 0xE0, 0xD3, 0x9F, 0x50, 0x20, 0x90, 0x81, +0x1C, 0xE0, 0x04, 0xF0, 0xD1, 0x8F, 0x12, 0x4A, +0x63, 0x90, 0x81, 0x23, 0xF0, 0xFB, 0x90, 0x81, +0x1C, 0xE0, 0xFF, 0xA3, 0xE0, 0xFD, 0x90, 0x84, +0x8B, 0x74, 0x04, 0xF0, 0xB1, 0xBF, 0x22, 0xD3, +0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xAC, 0x07, +0x90, 0x81, 0x06, 0x12, 0x5F, 0x48, 0x30, 0xE0, +0x02, 0xC1, 0x78, 0x90, 0x81, 0x05, 0xE0, 0x30, +0xE0, 0x16, 0x90, 0x81, 0x27, 0xE0, 0x24, 0x04, +0x90, 0x81, 0x1F, 0xF0, 0x90, 0x81, 0x27, 0xE0, +0x24, 0x03, 0x90, 0x81, 0x1E, 0xF0, 0x80, 0x0D, +0x90, 0x81, 0x1F, 0x74, 0x02, 0xF0, 0x90, 0x81, +0x1E, 0x14, 0xF0, 0x0B, 0x0B, 0x90, 0x81, 0x1E, +0xE0, 0xFA, 0x90, 0x81, 0x1D, 0xE0, 0xD3, 0x9A, +0x50, 0x0E, 0x90, 0x81, 0x12, 0xEB, 0xF0, 0x90, +0x81, 0x1F, 0xE0, 0xC3, 0x9D, 0x2C, 0x80, 0x11, +0xC3, 0xED, 0x9A, 0x2B, 0x90, 0x81, 0x12, 0xF0, +0x90, 0x81, 0x1E, 0xE0, 0xFF, 0xA3, 0xE0, 0xC3, +0x9F, 0x90, 0x81, 0x22, 0xF0, 0x90, 0x81, 0x1F, +0xE0, 0xFF, 0x24, 0x0A, 0xFD, 0xE4, 0x33, 0xFC, +0x90, 0x81, 0x22, 0xD1, 0x84, 0x40, 0x04, 0xEF, +0x24, 0x0A, 0xF0, 0x90, 0x81, 0x22, 0xE0, 0xFF, +0x24, 0x23, 0xFD, 0xE4, 0x33, 0xFC, 0x90, 0x81, +0x12, 0xD1, 0x84, 0x40, 0x04, 0xEF, 0x24, 0x23, +0xF0, 0x90, 0x81, 0x22, 0xE0, 0xFF, 0x7E, 0x00, +0x90, 0x81, 0x16, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, +0x90, 0x05, 0x58, 0xE0, 0x6F, 0x70, 0x01, 0xE4, +0x60, 0x02, 0xD1, 0x9B, 0xF1, 0x12, 0x80, 0x07, +0x90, 0x81, 0x07, 0xE0, 0x44, 0x01, 0xF0, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0xE0, 0xD3, 0x9D, 0xEC, +0x64, 0x80, 0xF8, 0x74, 0x80, 0x98, 0x22, 0x90, +0x81, 0x13, 0xE0, 0x75, 0xF0, 0x03, 0xA4, 0x24, +0xFE, 0x22, 0xF0, 0x90, 0x81, 0x16, 0xA3, 0xE0, +0x90, 0x05, 0x58, 0xF0, 0x22, 0x90, 0x81, 0x67, +0xE0, 0xFF, 0x90, 0x81, 0x13, 0xE0, 0xD3, 0x9F, +0x22, 0x12, 0x79, 0xB8, 0x90, 0x83, 0xDD, 0xEF, +0xF0, 0x30, 0xE0, 0x05, 0x7D, 0x01, 0xE4, 0x80, +0x02, 0xE4, 0xFD, 0xFF, 0x12, 0x4E, 0x86, 0x90, +0x83, 0xDD, 0xE0, 0x30, 0xE6, 0x11, 0x90, 0x01, +0x2F, 0xE0, 0x30, 0xE7, 0x04, 0xE4, 0xF0, 0x80, +0x06, 0x90, 0x01, 0x2F, 0x74, 0x80, 0xF0, 0x90, +0x81, 0x05, 0xE0, 0x90, 0x04, 0xEC, 0x30, 0xE0, +0x06, 0xE0, 0x54, 0xDD, 0xF0, 0x80, 0x04, 0xE0, +0x44, 0x22, 0xF0, 0xD1, 0xFA, 0x74, 0x02, 0xF0, +0xA1, 0xBF, 0x90, 0x81, 0x1C, 0xE0, 0xFF, 0xA3, +0xE0, 0xFD, 0x90, 0x81, 0x23, 0xE0, 0xFB, 0x90, +0x84, 0x8B, 0x22, 0xEF, 0x13, 0x13, 0x13, 0x54, +0x1F, 0x22, 0x90, 0x81, 0x07, 0xE0, 0x54, 0xFE, +0xF0, 0x22, 0x90, 0x81, 0x06, 0xE0, 0x44, 0x04, +0xF0, 0x22, 0x90, 0x81, 0x10, 0xE0, 0x90, 0x05, +0x73, 0x22, 0xE0, 0xFF, 0xC4, 0x13, 0x13, 0x54, +0x03, 0x22, 0x90, 0x81, 0x05, 0xE0, 0x13, 0x13, +0x13, 0x22, 0x90, 0x81, 0x08, 0xE0, 0xFF, 0xC4, +0x54, 0x0F, 0x22, 0x90, 0x81, 0x0A, 0xE0, 0x60, +0x02, 0x31, 0x44, 0x22, 0xE0, 0xFF, 0x74, 0x01, +0x7E, 0x00, 0xA8, 0x07, 0x08, 0x22, 0x74, 0x45, +0x2F, 0xF8, 0xE6, 0x4D, 0x12, 0x6F, 0xC6, 0xEE, +0xF0, 0x22, 0xE0, 0x90, 0x01, 0xBA, 0xF0, 0x90, +0x81, 0x0C, 0xE0, 0x90, 0x01, 0xBB, 0x22, 0x90, +0x83, 0xCE, 0xE0, 0x04, 0xF0, 0x90, 0x81, 0x0D, +0xE0, 0x64, 0x02, 0x60, 0x02, 0x51, 0xA2, 0x22, +0xEF, 0x24, 0xFE, 0x60, 0x0B, 0x04, 0x70, 0x24, +0x90, 0x81, 0x10, 0x74, 0x02, 0xF0, 0x80, 0x13, +0xED, 0x70, 0x06, 0x90, 0x81, 0x6A, 0xE0, 0x80, +0x02, 0xED, 0x14, 0x90, 0x81, 0x10, 0xF0, 0x90, +0x81, 0x10, 0xE0, 0xA3, 0xF0, 0x90, 0x81, 0x06, +0xE0, 0x44, 0x08, 0xF0, 0x22, 0xEF, 0x60, 0x37, +0x12, 0x4F, 0xA8, 0x64, 0x01, 0x70, 0x30, 0x90, +0x81, 0x06, 0xE0, 0x54, 0xFE, 0xF0, 0x7B, 0x2B, +0x7D, 0x0F, 0x7F, 0xFF, 0x12, 0x4E, 0x3D, 0x90, +0x06, 0x04, 0xE0, 0x54, 0xBF, 0xF0, 0x12, 0x66, +0x67, 0xBF, 0x01, 0x0E, 0x90, 0x81, 0x05, 0xE0, +0x44, 0x40, 0xF0, 0x7D, 0x06, 0x7F, 0x01, 0x02, +0x4E, 0x86, 0x91, 0xCB, 0x74, 0x08, 0xF0, 0x22, +0x12, 0x1F, 0xA4, 0x54, 0x01, 0xFF, 0x90, 0x83, +0xD5, 0xE0, 0x54, 0xFE, 0x4F, 0xF0, 0x22, 0x12, +0x1F, 0xA4, 0x90, 0x81, 0x6D, 0xF0, 0x22, 0xE4, +0x90, 0x80, 0xF8, 0xF0, 0xA3, 0xF0, 0x90, 0x80, +0x60, 0xF0, 0xA3, 0xF0, 0x22, 0x75, 0x3D, 0x10, +0xE4, 0xF5, 0x3E, 0x75, 0x3F, 0x07, 0x75, 0x40, +0x02, 0x90, 0x01, 0x30, 0xE5, 0x3D, 0xF0, 0xA3, +0xE5, 0x3E, 0xF0, 0xA3, 0xE5, 0x3F, 0xF0, 0xA3, +0xE5, 0x40, 0xF0, 0x22, 0x75, 0x45, 0x07, 0x75, +0x46, 0x01, 0x75, 0x47, 0x03, 0x75, 0x48, 0x62, +0x90, 0x01, 0x38, 0xE5, 0x45, 0xF0, 0xA3, 0xE5, +0x46, 0xF0, 0xA3, 0xE5, 0x47, 0xF0, 0xA3, 0xE5, +0x48, 0xF0, 0x22, 0x90, 0x01, 0x94, 0xE0, 0x44, +0x01, 0xF0, 0x90, 0x01, 0xC7, 0xE4, 0xF0, 0x22, +0x90, 0x01, 0xC7, 0x74, 0xFE, 0xF0, 0x22, 0x7F, +0x02, 0x90, 0x83, 0xC3, 0xE0, 0xFE, 0xEF, 0xC3, +0x9E, 0x50, 0x18, 0xEF, 0x25, 0xE0, 0x24, 0x81, +0xF8, 0xE6, 0x30, 0xE4, 0x0B, 0x90, 0x01, 0xB8, +0x74, 0x08, 0xF0, 0xA3, 0xF0, 0x7F, 0x00, 0x22, +0x0F, 0x80, 0xDE, 0x7F, 0x01, 0x22, 0xE4, 0x90, +0x80, 0x01, 0x12, 0x58, 0x98, 0xA3, 0xF0, 0x22, +0x90, 0x01, 0xE4, 0x74, 0x1C, 0xF0, 0xA3, 0xE4, +0xF0, 0x22, 0x90, 0x00, 0x54, 0xE0, 0x55, 0x35, +0xF5, 0x39, 0xA3, 0xE0, 0x55, 0x36, 0xF5, 0x3A, +0xA3, 0xE0, 0x55, 0x37, 0xF5, 0x3B, 0xA3, 0xE0, +0x55, 0x38, 0xF5, 0x3C, 0xAD, 0x39, 0x7F, 0x54, +0x12, 0x32, 0x1E, 0xAD, 0x3A, 0x7F, 0x55, 0x12, +0x32, 0x1E, 0xAD, 0x3B, 0x7F, 0x56, 0x12, 0x32, +0x1E, 0xAD, 0x3C, 0x7F, 0x57, 0x12, 0x32, 0x1E, +0x53, 0x91, 0xEF, 0x22, 0x90, 0x01, 0x34, 0xE0, +0x55, 0x3D, 0xF5, 0x41, 0xA3, 0xE0, 0x55, 0x3E, +0xF5, 0x42, 0xA3, 0xE0, 0x55, 0x3F, 0xF5, 0x43, +0xA3, 0xE0, 0x55, 0x40, 0xF5, 0x44, 0x90, 0x01, +0x34, 0xE5, 0x41, 0xF0, 0xA3, 0xE5, 0x42, 0xF0, +0xA3, 0xE5, 0x43, 0xF0, 0xA3, 0xE5, 0x44, 0xF0, +0x22, 0x90, 0x01, 0x3C, 0xE0, 0x55, 0x45, 0xF5, +0x49, 0xA3, 0xE0, 0x55, 0x46, 0xF5, 0x4A, 0xA3, +0xE0, 0x55, 0x47, 0xF5, 0x4B, 0xA3, 0xE0, 0x55, +0x48, 0xF5, 0x4C, 0x90, 0x01, 0x3C, 0xE5, 0x49, +0xF0, 0xA3, 0xE5, 0x4A, 0xF0, 0xA3, 0xE5, 0x4B, +0xF0, 0xA3, 0xE5, 0x4C, 0xF0, 0x53, 0x91, 0xDF, +0x22, 0x90, 0x81, 0x6E, 0xE0, 0x30, 0xE0, 0x05, +0x7F, 0x10, 0x12, 0x50, 0xCF, 0x22, 0x90, 0x01, +0xCF, 0xE0, 0x90, 0x84, 0x9D, 0xF0, 0xE0, 0xFF, +0x30, 0xE0, 0x07, 0x90, 0x01, 0xCF, 0xE0, 0x54, +0xFE, 0xF0, 0xEF, 0x30, 0xE5, 0x23, 0x90, 0x01, +0xCF, 0xE0, 0x54, 0xDF, 0xF0, 0x90, 0x01, 0x34, +0x74, 0x20, 0xF0, 0xE4, 0xF5, 0xA8, 0xF5, 0xE8, +0x12, 0x58, 0x72, 0x90, 0x00, 0x03, 0xE0, 0x54, +0xFB, 0xFD, 0x7F, 0x03, 0x12, 0x32, 0x1E, 0x80, +0xFE, 0x22, 0x12, 0x49, 0xBD, 0xE4, 0xFF, 0x02, +0x50, 0x9B, 0xC3, 0xEE, 0x94, 0x01, 0x40, 0x0A, +0x0D, 0xED, 0x13, 0x90, 0xFD, 0x10, 0xF0, 0xE4, +0x2F, 0xFF, 0x22, 0xC3, 0xEE, 0x94, 0x01, 0x40, +0x1E, 0x90, 0xFD, 0x11, 0xE0, 0xB5, 0x05, 0x14, +0x90, 0x01, 0x17, 0xE0, 0xB5, 0x05, 0x07, 0x90, +0xFD, 0x11, 0xE4, 0xF0, 0x80, 0x06, 0xED, 0x04, +0x90, 0xFD, 0x11, 0xF0, 0xE4, 0x2F, 0xFF, 0x22, +0xE4, 0x90, 0x83, 0xDF, 0xF0, 0xA3, 0xF0, 0x90, +0x00, 0x83, 0xE0, 0x90, 0x83, 0xDE, 0xF0, 0x90, +0x00, 0x83, 0xE0, 0xFE, 0x90, 0x83, 0xDE, 0xE0, +0xFF, 0xB5, 0x06, 0x01, 0x22, 0xC3, 0x90, 0x83, +0xE0, 0xE0, 0x94, 0x64, 0x90, 0x83, 0xDF, 0xE0, +0x94, 0x00, 0x40, 0x0D, 0x90, 0x01, 0xC0, 0xE0, +0x44, 0x40, 0xF0, 0x90, 0x83, 0xDE, 0xE0, 0xFF, +0x22, 0x90, 0x83, 0xDF, 0x12, 0x69, 0xA3, 0x80, +0xC6, 0x90, 0x01, 0xC4, 0x74, 0xF9, 0xF0, 0x74, +0x79, 0xA3, 0xF0, 0x90, 0x00, 0x90, 0xE0, 0x20, +0xE0, 0xF9, 0x74, 0xF9, 0x04, 0x90, 0x01, 0xC4, +0xF0, 0x74, 0x79, 0xA3, 0xF0, 0x22, 0xEF, 0x64, +0x01, 0x70, 0x31, 0x90, 0x81, 0x73, 0xE0, 0xFA, +0x54, 0x7F, 0xFF, 0x7E, 0x00, 0xC0, 0x07, 0x90, +0x81, 0x75, 0xE0, 0x13, 0x13, 0x54, 0x01, 0xFD, +0x90, 0x81, 0x74, 0xE0, 0xF9, 0xC3, 0x13, 0x54, +0x7F, 0xFB, 0xE9, 0x54, 0x01, 0x90, 0x84, 0x01, +0xF0, 0xEA, 0x12, 0x5F, 0x49, 0xA3, 0xF0, 0xD0, +0x07, 0x12, 0x52, 0xBE, 0x22, 0x90, 0x04, 0x1A, +0xE0, 0xF4, 0x60, 0x03, 0x7F, 0x00, 0x22, 0x90, +0x04, 0x1B, 0xE0, 0x54, 0x07, 0x64, 0x07, 0x7F, +0x01, 0x60, 0x02, 0x7F, 0x00, 0x22, 0xD3, 0x10, +0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x51, 0x4D, 0xEF, +0x64, 0x01, 0x60, 0x05, 0x75, 0x58, 0x01, 0x80, +0x41, 0x90, 0x81, 0x0E, 0xE0, 0xFF, 0x54, 0x03, +0x60, 0x05, 0x75, 0x58, 0x02, 0x80, 0x33, 0xEF, +0x30, 0xE2, 0x05, 0x75, 0x58, 0x08, 0x80, 0x2A, +0x90, 0x81, 0x0E, 0xE0, 0x30, 0xE4, 0x05, 0x75, +0x58, 0x10, 0x80, 0x1E, 0x12, 0x73, 0x85, 0x20, +0xE0, 0x05, 0x75, 0x58, 0x20, 0x80, 0x13, 0x51, +0xD5, 0x8F, 0x59, 0xE5, 0x59, 0x64, 0x01, 0x60, +0x05, 0x85, 0x59, 0x58, 0x80, 0x04, 0x51, 0xCD, +0x80, 0x0E, 0x90, 0x01, 0xB9, 0x74, 0x04, 0xF0, +0x90, 0x01, 0xB8, 0xE5, 0x58, 0xF0, 0x7F, 0x00, +0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x01, 0xB8, +0xE4, 0xF0, 0x7F, 0x01, 0x22, 0x90, 0x81, 0x0C, +0xE0, 0xD3, 0x94, 0x00, 0x40, 0x06, 0x75, 0x52, +0x04, 0x7F, 0xFF, 0x22, 0x90, 0x81, 0x6D, 0xE0, +0x60, 0x06, 0x75, 0x52, 0x80, 0x7F, 0xFF, 0x22, +0x7F, 0x01, 0x22, 0x7B, 0x2E, 0x51, 0xFE, 0x7D, +0x02, 0x7F, 0x01, 0x02, 0x4E, 0x86, 0x7D, 0x6F, +0x7F, 0xFF, 0x02, 0x4E, 0x3D, 0x90, 0x81, 0x61, +0x74, 0x04, 0xF0, 0xA3, 0x14, 0xF0, 0xA3, 0xE4, +0xF0, 0xA3, 0x74, 0x64, 0xF0, 0xA3, 0x74, 0x05, +0xF0, 0xA3, 0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01, +0xC3, 0xC0, 0xD0, 0x90, 0x84, 0xA0, 0xEF, 0xF0, +0x7E, 0x00, 0x7F, 0x2D, 0x7D, 0x00, 0x7B, 0x01, +0x7A, 0x81, 0x79, 0x28, 0x12, 0x44, 0x3E, 0xE4, +0x90, 0x81, 0x21, 0xF0, 0x90, 0x81, 0x20, 0xF0, +0x90, 0x81, 0x24, 0xF0, 0x90, 0x84, 0xA0, 0xE0, +0xB4, 0x01, 0x09, 0x90, 0x81, 0x25, 0x74, 0x2D, +0xF0, 0xE4, 0xA3, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, +0x22, 0x12, 0x4E, 0x35, 0x7D, 0x0C, 0x7F, 0x01, +0x02, 0x4E, 0x86, 0x90, 0x84, 0x77, 0xE0, 0xFF, +0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, +0x84, 0xA1, 0xEF, 0xF0, 0xC3, 0x94, 0x02, 0x50, +0x44, 0x90, 0x80, 0x0B, 0xE0, 0xFF, 0x90, 0x04, +0x1C, 0xE0, 0x6F, 0x70, 0x38, 0x90, 0x81, 0x0D, +0xE0, 0x64, 0x0E, 0x70, 0x15, 0x90, 0x84, 0xA1, +0xE0, 0x70, 0x2A, 0x90, 0x81, 0x05, 0xE0, 0x54, +0x7F, 0xF0, 0x12, 0x4F, 0xFA, 0x12, 0x4E, 0x82, +0x80, 0x18, 0x90, 0x81, 0x0D, 0xE0, 0x64, 0x06, +0x70, 0x13, 0x90, 0x84, 0xA1, 0xE0, 0x60, 0x0D, +0x71, 0xC2, 0x71, 0xCA, 0x90, 0x81, 0x0D, 0x74, +0x04, 0xF0, 0x12, 0x4E, 0x38, 0xD0, 0xD0, 0x92, +0xAF, 0x22, 0x90, 0x81, 0x05, 0xE0, 0x54, 0xBF, +0xF0, 0x22, 0x90, 0x06, 0x04, 0xE0, 0x44, 0x40, +0xF0, 0xE0, 0x44, 0x80, 0xF0, 0x22, 0x90, 0x83, +0xC4, 0xE0, 0x30, 0xE0, 0x37, 0x12, 0x4F, 0xA8, +0x64, 0x01, 0x70, 0x30, 0x90, 0x84, 0xA3, 0xE0, +0x04, 0xF0, 0xE0, 0xB4, 0x0A, 0x0B, 0x90, 0x83, +0xC6, 0xE0, 0x04, 0xF0, 0xE4, 0x90, 0x84, 0xA3, +0xF0, 0x90, 0x83, 0xC6, 0xE0, 0xFF, 0x90, 0x83, +0xC5, 0xE0, 0xD3, 0x9F, 0x50, 0x0E, 0x90, 0x83, +0xC7, 0xE0, 0x70, 0x08, 0xE4, 0x90, 0x83, 0xC6, +0xF0, 0x12, 0x67, 0x97, 0x22, 0x91, 0x40, 0xFE, +0x90, 0x83, 0xC4, 0xE0, 0x54, 0xFE, 0x4E, 0xFE, +0xF0, 0xEF, 0x54, 0x04, 0xFF, 0xEE, 0x54, 0xFB, +0x4F, 0xF0, 0x12, 0x1F, 0xA4, 0xC3, 0x13, 0x30, +0xE0, 0x07, 0x12, 0x56, 0x7B, 0x90, 0x83, 0xC5, +0xF0, 0x22, 0x90, 0x83, 0xEF, 0x12, 0x42, 0x5C, +0x12, 0x1F, 0xA4, 0xFF, 0x54, 0x01, 0x22, 0x12, +0x67, 0xEA, 0x12, 0x61, 0x53, 0x91, 0x3A, 0xFE, +0x90, 0x83, 0xC8, 0xE0, 0x54, 0xFE, 0x4E, 0xF0, +0xEF, 0xC3, 0x13, 0x30, 0xE0, 0x2D, 0x12, 0x56, +0x7B, 0x90, 0x83, 0xC9, 0x12, 0x57, 0x74, 0x90, +0x83, 0xCA, 0xF0, 0x12, 0x1F, 0xA4, 0xFF, 0x54, +0x04, 0xFE, 0x90, 0x83, 0xC8, 0xE0, 0x54, 0xFB, +0x12, 0x57, 0xC0, 0x90, 0x83, 0xCB, 0xF0, 0xEF, +0x54, 0x08, 0xFF, 0x90, 0x83, 0xC8, 0xE0, 0x54, +0xF7, 0x4F, 0xF0, 0x22, 0xE0, 0xFE, 0xA3, 0xE0, +0xFF, 0x90, 0x02, 0x84, 0xEF, 0xF0, 0xEE, 0xA3, +0xF0, 0xA3, 0xE0, 0x44, 0x01, 0xF0, 0x22, 0xB1, +0x88, 0xB1, 0x54, 0x90, 0x83, 0xEF, 0xB1, 0x7F, +0x90, 0x83, 0xF3, 0xF0, 0x90, 0x81, 0x6E, 0xE0, +0x20, 0xE0, 0x02, 0xA1, 0x4A, 0x90, 0x83, 0xF3, +0xE0, 0xFF, 0xEC, 0xC3, 0x9F, 0x40, 0x02, 0xA1, +0x4A, 0x90, 0x83, 0xEF, 0xE0, 0xFA, 0xA3, 0xE0, +0xFB, 0x12, 0x5F, 0xF1, 0xAD, 0x07, 0x74, 0x02, +0x2D, 0xB1, 0xA9, 0x54, 0xF8, 0xF9, 0x12, 0x5F, +0xBC, 0xFE, 0x74, 0x00, 0x2D, 0x12, 0x5F, 0xAA, +0x7A, 0x00, 0x24, 0x00, 0xFF, 0xEA, 0x3E, 0x54, +0x3F, 0x90, 0x83, 0xF1, 0xF0, 0xA3, 0xEF, 0xF0, +0x74, 0x03, 0x2D, 0xB1, 0x91, 0xFF, 0x7E, 0x00, +0xAD, 0x01, 0xED, 0x24, 0x18, 0xFB, 0xEA, 0x33, +0xCB, 0x2F, 0xFF, 0xEE, 0x3B, 0x90, 0x83, 0xF1, +0x8F, 0xF0, 0x12, 0x41, 0xF6, 0x90, 0x83, 0xF1, +0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xB1, 0x5D, 0x90, +0x83, 0xF1, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, +0x83, 0xEF, 0xB1, 0xB7, 0xD3, 0x90, 0x83, 0xF0, +0xE0, 0x9F, 0x90, 0x83, 0xEF, 0xE0, 0x9E, 0x40, +0x11, 0x90, 0x80, 0xFB, 0xB1, 0x9C, 0x90, 0x83, +0xF0, 0xE0, 0x9F, 0xF0, 0x90, 0x83, 0xEF, 0xE0, +0x9E, 0xF0, 0x90, 0x83, 0xEF, 0x91, 0x8C, 0x0C, +0x81, 0xB5, 0x22, 0xF0, 0x90, 0x01, 0x17, 0xE0, +0xFE, 0x90, 0x01, 0x16, 0xE0, 0x7C, 0x00, 0x24, +0x00, 0xFF, 0xEC, 0x3E, 0x22, 0x7D, 0x7F, 0xEF, +0x5D, 0xC3, 0x60, 0x0A, 0xB1, 0x72, 0x24, 0x80, +0xFF, 0xE4, 0x3E, 0xFE, 0x80, 0x03, 0xB1, 0x72, +0xFF, 0x22, 0x74, 0xFF, 0x9D, 0xFD, 0x74, 0xFF, +0x94, 0x00, 0x5E, 0xFE, 0xED, 0x5F, 0x22, 0xF0, +0xA3, 0xEF, 0xF0, 0x90, 0x02, 0x87, 0xE0, 0x22, +0x90, 0x01, 0x1F, 0xE0, 0xFE, 0x90, 0x01, 0x1E, +0x22, 0xF5, 0x82, 0xE4, 0x34, 0xFB, 0xF5, 0x83, +0xE0, 0x54, 0x03, 0x22, 0xE0, 0x24, 0x01, 0xFF, +0x90, 0x80, 0xFA, 0xE0, 0x34, 0x00, 0xFE, 0xC3, +0x22, 0xF5, 0x82, 0xE4, 0x34, 0xFB, 0xF5, 0x83, +0xE0, 0x54, 0x0F, 0x33, 0x33, 0x33, 0x22, 0xEE, +0x8F, 0xF0, 0x12, 0x41, 0xF6, 0x90, 0x80, 0xFA, +0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x22, 0x90, 0x81, +0x79, 0xE0, 0x30, 0xE0, 0x0D, 0x90, 0x81, 0x71, +0xE0, 0xC4, 0x54, 0x0F, 0x20, 0xE0, 0x03, 0x7F, +0x00, 0x22, 0x7F, 0x01, 0x22, 0xD3, 0x10, 0xAF, +0x01, 0xC3, 0xC0, 0xD0, 0xEF, 0x20, 0xE0, 0x05, +0x90, 0x83, 0xB1, 0x80, 0x03, 0x90, 0x83, 0xB2, +0xE0, 0x90, 0x83, 0xAE, 0xF0, 0x90, 0x83, 0xAE, +0xE0, 0x14, 0x60, 0x13, 0x14, 0x60, 0x14, 0x24, +0xFE, 0x60, 0x10, 0x14, 0x60, 0x09, 0x14, 0x60, +0x06, 0x24, 0x06, 0xE4, 0xFE, 0x80, 0x06, 0x7E, +0x04, 0x80, 0x02, 0x7E, 0x08, 0xAF, 0x06, 0xD0, +0xD0, 0x92, 0xAF, 0x22, 0xE4, 0xFE, 0x74, 0x7D, +0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x83, 0xF5, 0x83, +0xE0, 0xFD, 0x74, 0xA4, 0x2E, 0x12, 0x6F, 0xCB, +0xED, 0xF0, 0x0E, 0xEE, 0xB4, 0x08, 0xE7, 0x90, +0x83, 0xAD, 0xE0, 0x90, 0x04, 0x4C, 0xF0, 0x90, +0x83, 0xAF, 0xE0, 0x90, 0x04, 0x4D, 0xF0, 0x90, +0x83, 0xC2, 0xE0, 0x60, 0x18, 0x12, 0x67, 0xF0, +0xFA, 0x7B, 0x01, 0xC0, 0x03, 0x8B, 0x13, 0x75, +0x14, 0x83, 0x75, 0x15, 0x7D, 0x75, 0x16, 0x34, +0xD0, 0x03, 0x12, 0x2B, 0xED, 0x22, 0x12, 0x1F, +0xA4, 0x90, 0x83, 0xB1, 0x12, 0x56, 0x7A, 0x90, +0x83, 0xB2, 0xF0, 0x22, 0xD1, 0xBA, 0x90, 0x83, +0xBA, 0x12, 0x56, 0x7A, 0xFF, 0xED, 0x2F, 0x90, +0x83, 0xBB, 0x12, 0x57, 0x74, 0xFF, 0xED, 0x2F, +0x90, 0x83, 0xBC, 0x12, 0x57, 0xC1, 0xFF, 0xED, +0x2F, 0x90, 0x83, 0xBD, 0x12, 0x55, 0x81, 0xFF, +0xED, 0x2F, 0x90, 0x83, 0xBE, 0x12, 0x57, 0xB9, +0xFF, 0xED, 0x2F, 0x90, 0x83, 0xBF, 0xD1, 0xAD, +0x90, 0x83, 0xC0, 0xF0, 0x22, 0xF0, 0x90, 0x00, +0x06, 0x12, 0x1F, 0xBD, 0xFF, 0xAE, 0x05, 0xED, +0x2F, 0x22, 0x90, 0x02, 0x09, 0xE0, 0xFD, 0x12, +0x1F, 0xA4, 0xFE, 0xAF, 0x05, 0xED, 0x2E, 0x22, +0xD1, 0xBA, 0x90, 0x83, 0xC1, 0x12, 0x56, 0x7A, +0xFF, 0xAE, 0x05, 0xED, 0x2F, 0x90, 0x83, 0xC2, +0xF0, 0x22, 0xE4, 0xFF, 0x74, 0x18, 0xF1, 0x02, +0x74, 0x80, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x81, +0xF5, 0x83, 0xEE, 0xF0, 0x74, 0x10, 0xF1, 0x02, +0x74, 0x7A, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x81, +0xF5, 0x83, 0xEE, 0xF0, 0x0F, 0xEF, 0xB4, 0x06, +0xDB, 0x22, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x06, +0xF5, 0x83, 0xE0, 0xFE, 0x22, 0xEF, 0x60, 0x08, +0x90, 0x83, 0xB4, 0xE0, 0xFF, 0x12, 0x62, 0x40, +0x22, 0x12, 0x42, 0x44, 0x90, 0x81, 0x59, 0x12, +0x42, 0x38, 0x12, 0x42, 0x0C, 0x78, 0x0A, 0x12, +0x20, 0xA8, 0x90, 0x81, 0x22, 0xE0, 0xFE, 0xC3, +0x74, 0x0A, 0x9E, 0x2F, 0x22, 0x74, 0x28, 0x2E, +0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0, +0x2F, 0xFF, 0x90, 0x81, 0x65, 0xE0, 0xFD, 0x22, +0x12, 0x42, 0x1A, 0x90, 0x81, 0x5D, 0x12, 0x20, +0xCE, 0x90, 0x81, 0x06, 0xE0, 0x22, 0x2F, 0xF5, +0x82, 0x74, 0x01, 0x3E, 0xF5, 0x83, 0xE0, 0xFF, +0x90, 0x80, 0x61, 0xE0, 0x75, 0xF0, 0x08, 0x22, +0xF0, 0x90, 0x81, 0x27, 0xE0, 0x24, 0x04, 0x90, +0x81, 0x22, 0xF0, 0xA3, 0x74, 0x10, 0x22, 0x12, +0x42, 0x50, 0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE4, +0x35, 0x83, 0xF5, 0x83, 0xEF, 0x22, 0x90, 0x84, +0x19, 0x12, 0x42, 0x65, 0xE4, 0x90, 0x84, 0x1C, +0xF0, 0xA3, 0x22, 0xF0, 0xEE, 0x54, 0x08, 0xFE, +0xEF, 0x54, 0xF7, 0x4E, 0x22, 0x54, 0x10, 0xFD, +0xEF, 0x54, 0xEF, 0x4D, 0xFF, 0x22, 0x54, 0x40, +0xFD, 0xEF, 0x54, 0xBF, 0x4D, 0xFF, 0x22, 0x7E, +0x00, 0x7F, 0x08, 0x7D, 0x00, 0x7B, 0x01, 0x22, +0xF0, 0xEE, 0x54, 0x80, 0xFE, 0xEF, 0x54, 0x7F, +0x22, 0x90, 0x06, 0x0A, 0xE0, 0x54, 0xF8, 0xF0, +0x22, 0x90, 0x80, 0xFA, 0xF0, 0xA3, 0xEF, 0xF0, +0x22, 0xF0, 0x90, 0x81, 0x25, 0xE0, 0xFF, 0xC3, +0x22, 0x12, 0x32, 0x1E, 0x90, 0x84, 0x97, 0xE0, +0x22, 0x00, 0xE0, 0x5B +}; + +u32 array_length_mp_8188e_t_fw_wowlan = 16388; + +#endif /*CONFIG_WOWLAN*/ + +#endif /* end of LOAD_FW_HEADER_FROM_DRIVER */ + diff --git a/drivers/staging/rtl8188eu/hal/hal8188e_t_fw.h b/drivers/staging/rtl8188eu/hal/hal8188e_t_fw.h new file mode 100644 index 000000000000..c64221332ab1 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal8188e_t_fw.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef _FW_HEADER_8188E_T_H +#define _FW_HEADER_8188E_T_H + +#ifdef LOAD_FW_HEADER_FROM_DRIVER +#if (defined(CONFIG_AP_WOWLAN)) +extern u8 array_mp_8188e_t_fw_ap[15502]; +extern u32 array_length_mp_8188e_t_fw_ap; +#endif + +extern u8 array_mp_8188e_t_fw_nic[15262]; +extern u32 array_length_mp_8188e_t_fw_nic; +extern u8 array_mp_8188e_t_fw_nic_89em[14364]; +extern u32 array_length_mp_8188e_t_fw_nic_89em; +#ifdef CONFIG_WOWLAN +extern u8 array_mp_8188e_t_fw_wowlan[16388]; +extern u32 array_length_mp_8188e_t_fw_wowlan; +#endif /*CONFIG_WOWLAN*/ +#endif /* end of LOAD_FW_HEADER_FROM_DRIVER */ + +#endif + diff --git a/drivers/staging/rtl8188eu/hal/hal8188erateadaptive.c b/drivers/staging/rtl8188eu/hal/hal8188erateadaptive.c new file mode 100644 index 000000000000..5ab02885ba7b --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal8188erateadaptive.c @@ -0,0 +1,1022 @@ +/*++ +Copyright (c) Realtek Semiconductor Corp. All rights reserved. + +Module Name: + rate_adaptive.c + +Abstract: + Implement rate Adaptive functions for common operations. + +Major Change History: + When Who What + ---------- --------------- ------------------------------- + 2011-08-12 Page Create. + 2015-04-23 Wilson Fine tune (SD9 Family) + +--*/ +#include "mp_precomp.h" + +#include "phydm_precomp.h" + + +#if (RATE_ADAPTIVE_SUPPORT == 1) +/* rate adaptive parameters */ + + +static u8 RETRY_PENALTY[PERENTRY][RETRYSIZE + 1] = {{5, 4, 3, 2, 0, 3}, /* 92 , idx=0 */ + {6, 5, 4, 3, 0, 4}, /* 86 , idx=1 */ + {6, 5, 4, 2, 0, 4}, /* 81 , idx=2 */ + {8, 7, 6, 4, 0, 6}, /* 75 , idx=3 */ + {10, 9, 8, 6, 0, 8}, /* 71 , idx=4 */ + {10, 9, 8, 4, 0, 8}, /* 66 , idx=5 */ + {10, 9, 8, 2, 0, 8}, /* 62 , idx=6 */ + {10, 9, 8, 0, 0, 8}, /* 59 , idx=7 */ + {18, 17, 16, 8, 0, 16}, /* 53 , idx=8 */ + {26, 25, 24, 16, 0, 24}, /* 50 , idx=9 */ + {34, 33, 32, 24, 0, 32}, /* 47 , idx=0x0a */ + {34, 31, 28, 20, 0, 32}, /* 43 , idx=0x0b */ + {34, 31, 27, 18, 0, 32}, /* 40 , idx=0x0c */ + {34, 31, 26, 16, 0, 32}, /* 37 , idx=0x0d */ + {34, 30, 22, 16, 0, 32}, /* 32 , idx=0x0e */ + {34, 30, 24, 16, 0, 32}, /* 26 , idx=0x0f */ + {49, 46, 40, 16, 0, 48}, /* 20 , idx=0x10 */ + {49, 45, 32, 0, 0, 48}, /* 17 , idx=0x11 */ + {49, 45, 22, 18, 0, 48}, /* 15 , idx=0x12 */ + {49, 40, 24, 16, 0, 48}, /* 12 , idx=0x13 */ + {49, 32, 18, 12, 0, 48}, /* 9 , idx=0x14 */ + {49, 22, 18, 14, 0, 48}, /* 6 , idx=0x15 */ + {49, 16, 16, 0, 0, 48} +};/* 3 */ /* 3, idx=0x16 */ + +static u8 RETRY_PENALTY_UP[RETRYSIZE + 1] = {49, 44, 16, 16, 0, 48}; /* 12% for rate up */ + +static u8 PT_PENALTY[RETRYSIZE + 1] = {34, 31, 30, 24, 0, 32}; + +/* wilson modify */ + +static u8 RETRY_PENALTY_IDX[2][RATESIZE] = {{ + 4, 4, 4, 5, 4, 4, 5, 7, 7, 7, 8, 0x0a, /* SS>TH */ + 4, 4, 4, 4, 6, 0x0a, 0x0b, 0x0d, + 5, 5, 7, 7, 8, 0x0b, 0x0d, 0x0f + }, /* 0329 R01 */ + { + 0x0a, 0x0a, 0x0b, 0x0c, 0x0a, 0x0a, 0x0b, 0x0c, 0x0d, 0x10, 0x13, 0x13, /* SSTH */ + 0x0f, 0x10, 0x10, 0x12, 0x12, 0x13, 0x14, 0x15, + 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, 0x15 + }; + +static u8 RSSI_THRESHOLD[RATESIZE] = {0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x24, 0x26, 0x2a, + 0x18, 0x1a, 0x1d, 0x1f, 0x21, 0x27, 0x29, 0x2a, + 0, 0, 0, 0x1f, 0x23, 0x28, 0x2a, 0x2c + }; + +static u16 N_THRESHOLD_HIGH[RATESIZE] = {4, 4, 8, 16, + 24, 36, 48, 72, 96, 144, 192, 216, + 60, 80, 100, 160, 240, 400, 600, 800, + 300, 320, 480, 720, 1000, 1200, 1600, 2000 + }; +static u16 N_THRESHOLD_LOW[RATESIZE] = {2, 2, 4, 8, + 12, 18, 24, 36, 48, 72, 96, 108, + 30, 40, 50, 80, 120, 200, 300, 400, + 150, 160, 240, 360, 500, 600, 800, 1000 + }; +static u8 TRYING_NECESSARY[RATESIZE] = {2, 2, 2, 2, + 2, 2, 3, 3, 4, 4, 5, 7, + 4, 4, 7, 10, 10, 12, 12, 18, + 5, 7, 7, 8, 11, 18, 36, 60 + }; /* 0329 */ /* 1207 */ +static u8 DROPING_NECESSARY[RATESIZE] = {1, 1, 1, 1, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 5, 6, 7, 8, 9, 10, 11, 12 + }; + + +static u32 INIT_RATE_FALLBACK_TABLE[16] = {0x0f8ff015, /* 0: 40M BGN mode */ + 0x0f8ff010, /* 1: 40M GN mode */ + 0x0f8ff005, /* 2: BN mode/ 40M BGN mode */ + 0x0f8ff000, /* 3: N mode */ + 0x00000ff5, /* 4: BG mode */ + 0x00000ff0, /* 5: G mode */ + 0x0000000d, /* 6: B mode */ + 0, /* 7: */ + 0, /* 8: */ + 0, /* 9: */ + 0, /* 10: */ + 0, /* 11: */ + 0, /* 12: */ + 0, /* 13: */ + 0, /* 14: */ + 0, /* 15: */ + + }; +static u8 pending_for_rate_up_fail[5] = {2, 10, 24, 40, 60}; +static u16 dynamic_tx_rpt_timing[6] = {0x186a, 0x30d4, 0x493e, 0x61a8, 0x7a12, 0x927c}; /*200ms-1200ms*/ + +/* End rate adaptive parameters */ + +static void +odm_set_tx_rpt_timing_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + struct _odm_ra_info_ *p_ra_info, + u8 extend +) +{ + u8 idx = 0; + + for (idx = 0; idx < 5; idx++) + if (dynamic_tx_rpt_timing[idx] == p_ra_info->rpt_time) + break; + + if (extend == 0) /* back to default timing */ + idx = 0; /* 200ms */ + else if (extend == 1) { /* increase the timing */ + idx += 1; + if (idx > 5) + idx = 5; + } else if (extend == 2) { /* decrease the timing */ + if (idx != 0) + idx -= 1; + } + p_ra_info->rpt_time = dynamic_tx_rpt_timing[idx]; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("p_ra_info->rpt_time=0x%x\n", p_ra_info->rpt_time)); +} + +static int +odm_rate_down_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + struct _odm_ra_info_ *p_ra_info +) +{ + u8 rate_id, lowest_rate, highest_rate; + s8 i; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("=====>odm_rate_down_8188e()\n")); + if (NULL == p_ra_info) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("odm_rate_down_8188e(): p_ra_info is NULL\n")); + return -1; + } + rate_id = p_ra_info->pre_rate; + lowest_rate = p_ra_info->lowest_rate; + highest_rate = p_ra_info->highest_rate; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, + (" rate_id=%d lowest_rate=%d highest_rate=%d rate_sgi=%d\n", + rate_id, lowest_rate, highest_rate, p_ra_info->rate_sgi)); + if (rate_id > highest_rate) + rate_id = highest_rate; + else if (p_ra_info->rate_sgi) + p_ra_info->rate_sgi = 0; + else if (rate_id > lowest_rate) { + if (rate_id > 0) { + for (i = rate_id - 1; i >= lowest_rate; i--) { + if (p_ra_info->ra_use_rate & BIT(i)) { + rate_id = i; + goto rate_down_finish; + + } + } + } + } else if (rate_id <= lowest_rate) + rate_id = lowest_rate; +rate_down_finish: + if (p_ra_info->ra_waiting_counter == 1) { + p_ra_info->ra_waiting_counter += 1; + p_ra_info->ra_pending_counter += 1; + } else if (p_ra_info->ra_waiting_counter == 0) { + } else { + p_ra_info->ra_waiting_counter = 0; + p_ra_info->ra_pending_counter = 0; + } + if (p_ra_info->ra_pending_counter >= 4) + p_ra_info->ra_pending_counter = 4; + p_ra_info->ra_drop_after_down = 1; + p_ra_info->decision_rate = rate_id; + odm_set_tx_rpt_timing_8188e(p_dm_odm, p_ra_info, 2); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("rate down, Decrease RPT Timing\n")); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("ra_waiting_counter %d, ra_pending_counter %d RADrop %d", p_ra_info->ra_waiting_counter, p_ra_info->ra_pending_counter, p_ra_info->ra_drop_after_down)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("rate down to rate_id %d rate_sgi %d\n", rate_id, p_ra_info->rate_sgi)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("<=====odm_rate_down_8188e()\n")); + return 0; +} + +static int +odm_rate_up_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + struct _odm_ra_info_ *p_ra_info +) +{ + u8 rate_id, highest_rate; + u8 i; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("=====>odm_rate_up_8188e()\n")); + if (NULL == p_ra_info) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("odm_rate_up_8188e(): p_ra_info is NULL\n")); + return -1; + } + rate_id = p_ra_info->pre_rate; + highest_rate = p_ra_info->highest_rate; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, + (" rate_id=%d highest_rate=%d\n", + rate_id, highest_rate)); + if (p_ra_info->ra_waiting_counter == 1) { + p_ra_info->ra_waiting_counter = 0; + p_ra_info->ra_pending_counter = 0; + } else if (p_ra_info->ra_waiting_counter > 1) { + p_ra_info->pre_rssi_sta_ra = p_ra_info->rssi_sta_ra; + goto rate_up_finish; + } + odm_set_tx_rpt_timing_8188e(p_dm_odm, p_ra_info, 0); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("odm_rate_up_8188e(): default RPT Timing\n")); + + if (rate_id < highest_rate) { + for (i = rate_id + 1; i <= highest_rate; i++) { + if (p_ra_info->ra_use_rate & BIT(i)) { + rate_id = i; + goto rate_up_finish; + } + } + } else if (rate_id == highest_rate) { + if (p_ra_info->sgi_enable && (p_ra_info->rate_sgi != 1)) + p_ra_info->rate_sgi = 1; + else if ((p_ra_info->sgi_enable) != 1) + p_ra_info->rate_sgi = 0; + } else /* if((sta_info_ra->Decision_rate) > (sta_info_ra->Highest_rate)) */ + rate_id = highest_rate; + +rate_up_finish: + /* if(p_ra_info->ra_waiting_counter==10) */ + if (p_ra_info->ra_waiting_counter == (4 + pending_for_rate_up_fail[p_ra_info->ra_pending_counter])) { + p_ra_info->ra_waiting_counter = 0; + } else + p_ra_info->ra_waiting_counter++; + + p_ra_info->decision_rate = rate_id; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("rate up to rate_id %d\n", rate_id)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("ra_waiting_counter %d, ra_pending_counter %d", p_ra_info->ra_waiting_counter, p_ra_info->ra_pending_counter)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("<=====odm_rate_up_8188e()\n")); + return 0; +} + +static void odm_reset_ra_counter_8188e(struct _odm_ra_info_ *p_ra_info) +{ + u8 rate_id; + rate_id = p_ra_info->decision_rate; + p_ra_info->nsc_up = (N_THRESHOLD_HIGH[rate_id] + N_THRESHOLD_LOW[rate_id]) >> 1; + p_ra_info->nsc_down = (N_THRESHOLD_HIGH[rate_id] + N_THRESHOLD_LOW[rate_id]) >> 1; +} + +static void +odm_rate_decision_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + struct _odm_ra_info_ *p_ra_info +) +{ + u8 rate_id = 0, rty_pt_id = 0, penalty_id1 = 0, penalty_id2 = 0; + /* u32 pool_retry; */ + static u8 dynamic_tx_rpt_timing_counter = 0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("=====>odm_rate_decision_8188e()\n")); + + if (p_ra_info->active && (p_ra_info->TOTAL > 0)) { /* STA used and data packet exits */ + if (p_ra_info->ra_drop_after_down) { + p_ra_info->ra_drop_after_down--; + odm_reset_ra_counter_8188e(p_ra_info); + return; + } + if ((p_ra_info->rssi_sta_ra < (p_ra_info->pre_rssi_sta_ra - 3)) || (p_ra_info->rssi_sta_ra > (p_ra_info->pre_rssi_sta_ra + 3))) { + p_ra_info->pre_rssi_sta_ra = p_ra_info->rssi_sta_ra; + p_ra_info->ra_waiting_counter = 0; + p_ra_info->ra_pending_counter = 0; + } + + /* Start RA decision */ + if (p_ra_info->pre_rate > p_ra_info->highest_rate) + rate_id = p_ra_info->highest_rate; + else + rate_id = p_ra_info->pre_rate; + if (p_ra_info->rssi_sta_ra > RSSI_THRESHOLD[rate_id]) + rty_pt_id = 0; + else + rty_pt_id = 1; + penalty_id1 = RETRY_PENALTY_IDX[rty_pt_id][rate_id]; /* TODO by page */ + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, + (" nsc_down init is %d\n", p_ra_info->nsc_down)); + /* pool_retry=p_ra_info->RTY[2]+p_ra_info->RTY[3]+p_ra_info->RTY[4]+p_ra_info->DROP; */ + p_ra_info->nsc_down += p_ra_info->RTY[0] * RETRY_PENALTY[penalty_id1][0]; + p_ra_info->nsc_down += p_ra_info->RTY[1] * RETRY_PENALTY[penalty_id1][1]; + p_ra_info->nsc_down += p_ra_info->RTY[2] * RETRY_PENALTY[penalty_id1][2]; + p_ra_info->nsc_down += p_ra_info->RTY[3] * RETRY_PENALTY[penalty_id1][3]; + p_ra_info->nsc_down += p_ra_info->RTY[4] * RETRY_PENALTY[penalty_id1][4]; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, + (" nsc_down is %d, total*penalty[5] is %d\n", + p_ra_info->nsc_down, (p_ra_info->TOTAL * RETRY_PENALTY[penalty_id1][5]))); + if (p_ra_info->nsc_down > (p_ra_info->TOTAL * RETRY_PENALTY[penalty_id1][5])) + p_ra_info->nsc_down -= p_ra_info->TOTAL * RETRY_PENALTY[penalty_id1][5]; + else + p_ra_info->nsc_down = 0; + + /* rate up */ + penalty_id2 = RETRY_PENALTY_UP_IDX[rate_id]; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, + (" nsc_up init is %d\n", p_ra_info->nsc_up)); + p_ra_info->nsc_up += p_ra_info->RTY[0] * RETRY_PENALTY[penalty_id2][0]; + p_ra_info->nsc_up += p_ra_info->RTY[1] * RETRY_PENALTY[penalty_id2][1]; + p_ra_info->nsc_up += p_ra_info->RTY[2] * RETRY_PENALTY[penalty_id2][2]; + p_ra_info->nsc_up += p_ra_info->RTY[3] * RETRY_PENALTY[penalty_id2][3]; + p_ra_info->nsc_up += p_ra_info->RTY[4] * RETRY_PENALTY[penalty_id2][4]; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, + ("nsc_up is %d, total*up[5] is %d\n", + p_ra_info->nsc_up, (p_ra_info->TOTAL * RETRY_PENALTY[penalty_id2][5]))); + if (p_ra_info->nsc_up > (p_ra_info->TOTAL * RETRY_PENALTY[penalty_id2][5])) + p_ra_info->nsc_up -= p_ra_info->TOTAL * RETRY_PENALTY[penalty_id2][5]; + else + p_ra_info->nsc_up = 0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE | ODM_COMP_INIT, ODM_DBG_LOUD, + (" RssiStaRa= %d rty_pt_id=%d penalty_id1=0x%x penalty_id2=0x%x rate_id=%d nsc_down=%d nsc_up=%d SGI=%d\n", + p_ra_info->rssi_sta_ra, rty_pt_id, penalty_id1, penalty_id2, rate_id, p_ra_info->nsc_down, p_ra_info->nsc_up, p_ra_info->rate_sgi)); + if ((p_ra_info->nsc_down < N_THRESHOLD_LOW[rate_id]) || (p_ra_info->DROP > DROPING_NECESSARY[rate_id])) + odm_rate_down_8188e(p_dm_odm, p_ra_info); + /* else if ((p_ra_info->nsc_up > N_THRESHOLD_HIGH[rate_id])&&(pool_retrynsc_up > N_THRESHOLD_HIGH[rate_id]) + odm_rate_up_8188e(p_dm_odm, p_ra_info); + + if ((p_ra_info->decision_rate) == (p_ra_info->pre_rate)) + dynamic_tx_rpt_timing_counter += 1; + else + dynamic_tx_rpt_timing_counter = 0; + + if (dynamic_tx_rpt_timing_counter >= 4) { + odm_set_tx_rpt_timing_8188e(p_dm_odm, p_ra_info, 1); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("<=====rate don't change 4 times, Extend RPT Timing\n")); + dynamic_tx_rpt_timing_counter = 0; + } + + p_ra_info->pre_rate = p_ra_info->decision_rate; /* YJ,add,120120 */ + + odm_reset_ra_counter_8188e(p_ra_info); + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("<=====odm_rate_decision_8188e()\n")); +} + +static int +odm_arfb_refresh_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + struct _odm_ra_info_ *p_ra_info +) +{ + /* Wilson 2011/10/26 */ + u32 mask_from_reg; + u8 i; + + switch (p_ra_info->rate_id) { + case RATR_INX_WIRELESS_NGB: + p_ra_info->ra_use_rate = (p_ra_info->rate_mask) & 0x0f8fe00f; + break; + case RATR_INX_WIRELESS_NG: + p_ra_info->ra_use_rate = (p_ra_info->rate_mask) & 0x0f8ff010; + break; + case RATR_INX_WIRELESS_NB: + p_ra_info->ra_use_rate = (p_ra_info->rate_mask) & 0x0f8fe00f; + break; + case RATR_INX_WIRELESS_N: + p_ra_info->ra_use_rate = (p_ra_info->rate_mask) & 0x0f8ff000; + break; + case RATR_INX_WIRELESS_GB: + p_ra_info->ra_use_rate = (p_ra_info->rate_mask) & 0x00000fef; + break; + case RATR_INX_WIRELESS_G: + p_ra_info->ra_use_rate = (p_ra_info->rate_mask) & 0x00000ff0; + break; + case RATR_INX_WIRELESS_B: + p_ra_info->ra_use_rate = (p_ra_info->rate_mask) & 0x0000000d; + break; + case 12: + mask_from_reg = odm_read_4byte(p_dm_odm, REG_ARFR0); + p_ra_info->ra_use_rate = (p_ra_info->rate_mask) & mask_from_reg; + break; + case 13: + mask_from_reg = odm_read_4byte(p_dm_odm, REG_ARFR1); + p_ra_info->ra_use_rate = (p_ra_info->rate_mask) & mask_from_reg; + break; + case 14: + mask_from_reg = odm_read_4byte(p_dm_odm, REG_ARFR2); + p_ra_info->ra_use_rate = (p_ra_info->rate_mask) & mask_from_reg; + break; + case 15: + mask_from_reg = odm_read_4byte(p_dm_odm, REG_ARFR3); + p_ra_info->ra_use_rate = (p_ra_info->rate_mask) & mask_from_reg; + break; + + default: + p_ra_info->ra_use_rate = (p_ra_info->rate_mask); + break; + } + /* Highest rate */ + if (p_ra_info->ra_use_rate) + for (i = RATESIZE ; i >= 0 ; i--) { + if ((p_ra_info->ra_use_rate) & BIT(i)) { + p_ra_info->highest_rate = i; + break; + } + } + else + p_ra_info->highest_rate = 0; + /* Lowest rate */ + if (p_ra_info->ra_use_rate) + for (i = 0; i < RATESIZE; i++) { + if ((p_ra_info->ra_use_rate) & BIT(i)) { + p_ra_info->lowest_rate = i; + break; + } + } + else + p_ra_info->lowest_rate = 0; + +#if POWER_TRAINING_ACTIVE == 1 + if (p_ra_info->highest_rate > 0x13) + p_ra_info->pt_mode_ss = 3; + else if (p_ra_info->highest_rate > 0x0b) + p_ra_info->pt_mode_ss = 2; + else if (p_ra_info->highest_rate > 0x0b) + p_ra_info->pt_mode_ss = 1; + else + p_ra_info->pt_mode_ss = 0; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, + ("ODM_ARFBRefresh_8188E(): pt_mode_ss=%d\n", p_ra_info->pt_mode_ss)); + +#endif + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, + ("ODM_ARFBRefresh_8188E(): rate_id=%d rate_mask=%8.8x ra_use_rate=%8.8x highest_rate=%d\n", + p_ra_info->rate_id, p_ra_info->rate_mask, p_ra_info->ra_use_rate, p_ra_info->highest_rate)); + return 0; +} + +#if POWER_TRAINING_ACTIVE == 1 +static void +odm_pt_try_state_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + struct _odm_ra_info_ *p_ra_info +) +{ + p_ra_info->pt_try_state = 0; + switch (p_ra_info->pt_mode_ss) { + case 3: + if (p_ra_info->decision_rate >= 0x19) + p_ra_info->pt_try_state = 1; + break; + case 2: + if (p_ra_info->decision_rate >= 0x11) + p_ra_info->pt_try_state = 1; + break; + case 1: + if (p_ra_info->decision_rate >= 0x0a) + p_ra_info->pt_try_state = 1; + break; + case 0: + if (p_ra_info->decision_rate >= 0x03) + p_ra_info->pt_try_state = 1; + break; + default: + p_ra_info->pt_try_state = 0; + } + + if (p_ra_info->rssi_sta_ra < 48) + p_ra_info->pt_stage = 0; + else if (p_ra_info->pt_try_state == 1) { + if ((p_ra_info->pt_stop_count >= 10) || (p_ra_info->pt_pre_rssi > p_ra_info->rssi_sta_ra + 5) + || (p_ra_info->pt_pre_rssi < p_ra_info->rssi_sta_ra - 5) || (p_ra_info->decision_rate != p_ra_info->pt_pre_rate)) { + if (p_ra_info->pt_stage == 0) + p_ra_info->pt_stage = 1; + else if (p_ra_info->pt_stage == 1) + p_ra_info->pt_stage = 3; + else + p_ra_info->pt_stage = 5; + + p_ra_info->pt_pre_rssi = p_ra_info->rssi_sta_ra; + p_ra_info->pt_stop_count = 0; + + } else { + p_ra_info->ra_stage = 0; + p_ra_info->pt_stop_count++; + } + } else { + p_ra_info->pt_stage = 0; + p_ra_info->ra_stage = 0; + } + p_ra_info->pt_pre_rate = p_ra_info->decision_rate; + + /* Disable power training when noisy environment */ + if (p_dm_odm->is_disable_power_training) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("odm_pt_try_state_8188e(): Disable power training when noisy environment\n")); + p_ra_info->pt_stage = 0; + p_ra_info->ra_stage = 0; + p_ra_info->pt_stop_count = 0; + } +} + +static void +odm_pt_decision_8188e( + struct _odm_ra_info_ *p_ra_info +) +{ + u8 stage_BUF; + u8 j; + u8 temp_stage; + u32 numsc; + u32 num_total; + u8 stage_id; + + stage_BUF = p_ra_info->pt_stage; + numsc = 0; + num_total = p_ra_info->TOTAL * PT_PENALTY[5]; + for (j = 0; j <= 4; j++) { + numsc += p_ra_info->RTY[j] * PT_PENALTY[j]; + if (numsc > num_total) + break; + } + + j = j >> 1; + temp_stage = (p_ra_info->pt_stage + 1) >> 1; + if (temp_stage > j) + stage_id = temp_stage - j; + else + stage_id = 0; + + p_ra_info->pt_smooth_factor = (p_ra_info->pt_smooth_factor >> 1) + (p_ra_info->pt_smooth_factor >> 2) + stage_id * 16 + 2; + if (p_ra_info->pt_smooth_factor > 192) + p_ra_info->pt_smooth_factor = 192; + stage_id = p_ra_info->pt_smooth_factor >> 6; + temp_stage = stage_id * 2; + if (temp_stage != 0) + temp_stage -= 1; + if (p_ra_info->DROP > 3) + temp_stage = 0; + p_ra_info->pt_stage = temp_stage; + +} +#endif + +static void +odm_ra_tx_rpt_timer_setting( + struct PHY_DM_STRUCT *p_dm_odm, + u16 min_rpt_time +) +{ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, (" =====>odm_ra_tx_rpt_timer_setting()\n")); + + + if (p_dm_odm->currmin_rpt_time != min_rpt_time) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, + (" currmin_rpt_time =0x%04x min_rpt_time=0x%04x\n", p_dm_odm->currmin_rpt_time, min_rpt_time)); + rtw_rpt_timer_cfg_cmd(p_dm_odm->adapter, min_rpt_time); + p_dm_odm->currmin_rpt_time = min_rpt_time; + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, (" <=====odm_ra_tx_rpt_timer_setting()\n")); +} + + +void +odm_ra_support_init( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("=====>odm_ra_support_init()\n")); + + /* 2012/02/14 MH Be noticed, the init must be after IC type is recognized!!!!! */ + if (p_dm_odm->support_ic_type == ODM_RTL8188E) + p_dm_odm->ra_support88e = true; + +} + + + +int +odm_ra_info_init( + struct PHY_DM_STRUCT *p_dm_odm, + u32 mac_id +) +{ + struct _odm_ra_info_ *p_ra_info = &p_dm_odm->ra_info[mac_id]; + p_ra_info->decision_rate = 0x13; + p_ra_info->pre_rate = 0x13; + p_ra_info->highest_rate = 0x13; + p_ra_info->lowest_rate = 0; + p_ra_info->rate_id = 0; + p_ra_info->rate_mask = 0xffffffff; + p_ra_info->rssi_sta_ra = 0; + p_ra_info->pre_rssi_sta_ra = 0; + p_ra_info->sgi_enable = 0; + p_ra_info->ra_use_rate = 0xffffffff; + p_ra_info->nsc_down = (N_THRESHOLD_HIGH[0x13] + N_THRESHOLD_LOW[0x13]) / 2; + p_ra_info->nsc_up = (N_THRESHOLD_HIGH[0x13] + N_THRESHOLD_LOW[0x13]) / 2; + p_ra_info->rate_sgi = 0; + p_ra_info->active = 1; /* active is not used at present. by page, 110819 */ + p_ra_info->rpt_time = 0x927c; + p_ra_info->DROP = 0; + p_ra_info->RTY[0] = 0; + p_ra_info->RTY[1] = 0; + p_ra_info->RTY[2] = 0; + p_ra_info->RTY[3] = 0; + p_ra_info->RTY[4] = 0; + p_ra_info->TOTAL = 0; + p_ra_info->ra_waiting_counter = 0; + p_ra_info->ra_pending_counter = 0; + p_ra_info->ra_drop_after_down = 0; +#if POWER_TRAINING_ACTIVE == 1 + p_ra_info->pt_active = 1; /* active when this STA is use */ + p_ra_info->pt_try_state = 0; + p_ra_info->pt_stage = 5; /* Need to fill into HW_PWR_STATUS */ + p_ra_info->pt_smooth_factor = 192; + p_ra_info->pt_stop_count = 0; + p_ra_info->pt_pre_rate = 0; + p_ra_info->pt_pre_rssi = 0; + p_ra_info->pt_mode_ss = 0; + p_ra_info->ra_stage = 0; +#endif + return 0; +} + +int +odm_ra_info_init_all( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u32 mac_id = 0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("=====>\n")); + p_dm_odm->currmin_rpt_time = 0; + + for (mac_id = 0; mac_id < ODM_ASSOCIATE_ENTRY_NUM; mac_id++) + odm_ra_info_init(p_dm_odm, mac_id); + + /* Redifine arrays for I-cut NIC */ + if (p_dm_odm->cut_version == ODM_CUT_I) { + u8 i; + u8 RETRY_PENALTY_IDX_S[2][RATESIZE] = {{ + 4, 4, 4, 5, + 4, 4, 5, 7, 7, 7, 8, 0x0a, /* SS>TH */ + 4, 4, 4, 4, 6, 0x0a, 0x0b, 0x0d, + 5, 5, 7, 7, 8, 0x0b, 0x0d, 0x0f + }, /* 0329 R01 */ + { + 0x0a, 0x0a, 0x0b, 0x0c, + 0x0a, 0x0a, 0x0b, 0x0c, 0x0d, 0x10, 0x13, 0x13, /* SSTH */ + 0x0b, 0x0b, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, + 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, 0x15 + }; + + for (i = 0; i < RATESIZE; i++) { + RETRY_PENALTY_IDX[0][i] = RETRY_PENALTY_IDX_S[0][i]; + RETRY_PENALTY_IDX[1][i] = RETRY_PENALTY_IDX_S[1][i]; + + RETRY_PENALTY_UP_IDX[i] = RETRY_PENALTY_UP_IDX_S[i]; + } + return 0; + } + return 0; +} + +u8 +odm_ra_get_sgi_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u8 mac_id +) +{ + if ((NULL == p_dm_odm) || (mac_id >= ASSOCIATE_ENTRY_NUM)) + return 0; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, + ("mac_id=%d SGI=%d\n", mac_id, p_dm_odm->ra_info[mac_id].rate_sgi)); + return p_dm_odm->ra_info[mac_id].rate_sgi; +} + +u8 +odm_ra_get_decision_rate_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u8 mac_id +) +{ + u8 decision_rate = 0; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + u8 cmd_buf[3]; + + if ((NULL == p_dm_odm) || (mac_id >= ASSOCIATE_ENTRY_NUM)) + return 0; + decision_rate = (p_dm_odm->ra_info[mac_id].decision_rate); + + if (decision_rate != p_ra_table->link_tx_rate[mac_id]) { + + cmd_buf[1] = mac_id; + cmd_buf[0] = decision_rate; + phydm_c2h_ra_report_handler(p_dm_odm, &(cmd_buf[0]), 3); + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, + (" mac_id=%d decision_rate=0x%x\n", mac_id, decision_rate)); + return decision_rate; +} + +u8 +odm_ra_get_hw_pwr_status_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u8 mac_id +) +{ + u8 pt_stage = 5; + if ((NULL == p_dm_odm) || (mac_id >= ASSOCIATE_ENTRY_NUM)) + return 0; + pt_stage = (p_dm_odm->ra_info[mac_id].pt_stage); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, + ("mac_id=%d pt_stage=0x%x\n", mac_id, pt_stage)); + return pt_stage; +} + +void +odm_ra_update_rate_info_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u8 mac_id, + u8 rate_id, + u32 rate_mask, + u8 sgi_enable +) +{ + struct _odm_ra_info_ *p_ra_info = NULL; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, + ("mac_id=%d rate_id=0x%x rate_mask=0x%x sgi_enable=%d\n", + mac_id, rate_id, rate_mask, sgi_enable)); + if ((NULL == p_dm_odm) || (mac_id >= ASSOCIATE_ENTRY_NUM)) + return; + + p_ra_info = &(p_dm_odm->ra_info[mac_id]); + p_ra_info->rate_id = rate_id; + p_ra_info->rate_mask = rate_mask; + p_ra_info->sgi_enable = sgi_enable; + odm_arfb_refresh_8188e(p_dm_odm, p_ra_info); +} + +void +odm_ra_set_rssi_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u8 mac_id, + u8 rssi +) +{ + struct _odm_ra_info_ *p_ra_info = NULL; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, + (" mac_id=%d rssi=%d\n", mac_id, rssi)); + if ((NULL == p_dm_odm) || (mac_id >= ASSOCIATE_ENTRY_NUM)) + return; + + p_ra_info = &(p_dm_odm->ra_info[mac_id]); + p_ra_info->rssi_sta_ra = rssi; +} + +void +odm_ra_set_tx_rpt_time( + struct PHY_DM_STRUCT *p_dm_odm, + u16 min_rpt_time +) +{ + odm_write_2byte(p_dm_odm, REG_TX_RPT_TIME, min_rpt_time); +} + +void odm_ra_tx_rpt2_handle_8188e(struct PHY_DM_STRUCT *p_dm_odm, + u8 *tx_rpt_buf, __le16 tx_rpt_len, + u32 mac_id_valid_entry0, + u32 mac_id_valid_entry1) +{ + struct _odm_ra_info_ *p_ra_info = NULL; + u8 mac_id = 0; + u8 *p_buffer = NULL; + u32 valid = 0, item_num = 0; + u16 min_rpt_time = 0x927c; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("=====>odm_ra_tx_rpt2_handle_8188e(): valid0=%d valid1=%d BufferLength=%d\n", + mac_id_valid_entry0, mac_id_valid_entry1, tx_rpt_len)); + + item_num = le16_to_cpu(tx_rpt_len) >> 3; + p_buffer = tx_rpt_buf; + + do { + valid = 0; + if (mac_id < 32) + valid = (1 << mac_id) & mac_id_valid_entry0; + else if (mac_id < 64) + valid = (1 << (mac_id - 32)) & mac_id_valid_entry1; + + p_ra_info = &(p_dm_odm->ra_info[mac_id]); + if (valid) { + p_ra_info->RTY[0] = (u16)GET_TX_REPORT_TYPE1_RERTY_0(p_buffer); + p_ra_info->RTY[1] = (u16)GET_TX_REPORT_TYPE1_RERTY_1(p_buffer); + p_ra_info->RTY[2] = (u16)GET_TX_REPORT_TYPE1_RERTY_2(p_buffer); + p_ra_info->RTY[3] = (u16)GET_TX_REPORT_TYPE1_RERTY_3(p_buffer); + p_ra_info->RTY[4] = (u16)GET_TX_REPORT_TYPE1_RERTY_4(p_buffer); + p_ra_info->DROP = (u16)GET_TX_REPORT_TYPE1_DROP_0(p_buffer); + + p_ra_info->TOTAL = p_ra_info->RTY[0] + \ + p_ra_info->RTY[1] + \ + p_ra_info->RTY[2] + \ + p_ra_info->RTY[3] + \ + p_ra_info->RTY[4] + \ + p_ra_info->DROP; +#if defined(TXRETRY_CNT) + extern struct stat_info *get_macidinfo(struct rtl8192cd_priv *priv, unsigned int aid); + + { + struct stat_info *pstat = get_macidinfo(p_dm_odm->priv, mac_id); + if (pstat) { + pstat->cur_tx_ok += p_ra_info->RTY[0]; + pstat->cur_tx_retry_pkts += p_ra_info->RTY[1] + p_ra_info->RTY[2] + p_ra_info->RTY[3] + p_ra_info->RTY[4]; + pstat->cur_tx_retry_cnt += p_ra_info->RTY[1] + p_ra_info->RTY[2] * 2 + p_ra_info->RTY[3] * 3 + p_ra_info->RTY[4] * 4; + pstat->total_tx_retry_cnt += pstat->cur_tx_retry_cnt; + pstat->total_tx_retry_pkts += pstat->cur_tx_retry_pkts; + pstat->cur_tx_fail += p_ra_info->DROP; + } + } +#endif + if (p_ra_info->TOTAL != 0) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, + ("macid=%d Total=%d R0=%d R1=%d R2=%d R3=%d R4=%d D0=%d valid0=%x valid1=%x\n", + mac_id, + p_ra_info->TOTAL, + p_ra_info->RTY[0], + p_ra_info->RTY[1], + p_ra_info->RTY[2], + p_ra_info->RTY[3], + p_ra_info->RTY[4], + p_ra_info->DROP, + mac_id_valid_entry0, + mac_id_valid_entry1)); +#if POWER_TRAINING_ACTIVE == 1 + if (p_ra_info->pt_active) { + if (p_ra_info->ra_stage < 5) + odm_rate_decision_8188e(p_dm_odm, p_ra_info); + else if (p_ra_info->ra_stage == 5) /* Power training try state */ + odm_pt_try_state_8188e(p_dm_odm, p_ra_info); + else /* ra_stage==6 */ + odm_pt_decision_8188e(p_ra_info); + + /* Stage_RA counter */ + if (p_ra_info->ra_stage <= 5) + p_ra_info->ra_stage++; + else + p_ra_info->ra_stage = 0; + } else + odm_rate_decision_8188e(p_dm_odm, p_ra_info); +#else + odm_rate_decision_8188e(p_dm_odm, p_ra_info); +#endif + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, + ("macid=%d R0=%d R1=%d R2=%d R3=%d R4=%d drop=%d valid0=%x rate_id=%d SGI=%d\n", + mac_id, + p_ra_info->RTY[0], + p_ra_info->RTY[1], + p_ra_info->RTY[2], + p_ra_info->RTY[3], + p_ra_info->RTY[4], + p_ra_info->DROP, + mac_id_valid_entry0, + p_ra_info->decision_rate, + p_ra_info->rate_sgi)); + } else + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, (" TOTAL=0!!!!\n")); + } + + if (min_rpt_time > p_ra_info->rpt_time) + min_rpt_time = p_ra_info->rpt_time; + + p_buffer += TX_RPT2_ITEM_SIZE; + mac_id++; + } while (mac_id < item_num); + + odm_ra_tx_rpt_timer_setting(p_dm_odm, min_rpt_time); + + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("<===== odm_ra_tx_rpt2_handle_8188e()\n")); +} + +#else + +static void +odm_ra_tx_rpt_timer_setting( + struct PHY_DM_STRUCT *p_dm_odm, + u16 min_rpt_time +) +{ + return; +} + + +void +odm_ra_support_init( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + return; +} + +int +odm_ra_info_init( + struct PHY_DM_STRUCT *p_dm_odm, + u32 mac_id +) +{ + return 0; +} + +int +odm_ra_info_init_all( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + return 0; +} + +u8 +odm_ra_get_sgi_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u8 mac_id +) +{ + return 0; +} + +u8 +odm_ra_get_decision_rate_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u8 mac_id +) +{ + return 0; +} +u8 +odm_ra_get_hw_pwr_status_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u8 mac_id +) +{ + return 0; +} + +void +odm_ra_update_rate_info_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u8 mac_id, + u8 rate_id, + u32 rate_mask, + u8 sgi_enable +) +{ + return; +} + +void +odm_ra_set_rssi_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u8 mac_id, + u8 rssi +) +{ + return; +} + +void +odm_ra_set_tx_rpt_time( + struct PHY_DM_STRUCT *p_dm_odm, + u16 min_rpt_time +) +{ + return; +} + +void +odm_ra_tx_rpt2_handle_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u8 *tx_rpt_buf, + __le16 tx_rpt_len, + u32 mac_id_valid_entry0, + u32 mac_id_valid_entry1 +) +{ +} + +#endif diff --git a/drivers/staging/rtl8188eu/hal/hal8188erateadaptive.h b/drivers/staging/rtl8188eu/hal/hal8188erateadaptive.h new file mode 100644 index 000000000000..2aee71ffffba --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal8188erateadaptive.h @@ -0,0 +1,65 @@ +#ifndef __INC_RA_H +#define __INC_RA_H +/*++ +Copyright (c) Realtek Semiconductor Corp. All rights reserved. + +Module Name: + rate_adaptive.h + +Abstract: + Prototype of RA and related data structure. + +Major Change History: + When Who What + ---------- --------------- ------------------------------- + 2011-08-12 Page Create. +--*/ + +/* rate adaptive define */ +#define PERENTRY 23 +#define RETRYSIZE 5 +#define RATESIZE 28 +#define TX_RPT2_ITEM_SIZE 8 + +#define DM_RA_RATE_UP 1 +#define DM_RA_RATE_DOWN 2 + +/* TX report 2 format in Rx desc */ +#define GET_TX_RPT2_DESC_PKT_LEN_88E(__prx_status_desc) \ + LE_BITS_TO_4BYTE(__prx_status_desc, 0, 9) +#define GET_TX_RPT2_DESC_MACID_VALID_1_88E(__prx_status_desc) \ + LE_BITS_TO_4BYTE(__prx_status_desc+16, 0, 32) +#define GET_TX_RPT2_DESC_MACID_VALID_2_88E(__prx_status_desc) \ + LE_BITS_TO_4BYTE(__prx_status_desc+20, 0, 32) + +#define GET_TX_REPORT_TYPE1_RERTY_0(__paddr) \ + LE_BITS_TO_4BYTE(__paddr, 0, 16) +#define GET_TX_REPORT_TYPE1_RERTY_1(__paddr) \ + LE_BITS_TO_1BYTE(__paddr+2, 0, 8) +#define GET_TX_REPORT_TYPE1_RERTY_2(__paddr) \ + LE_BITS_TO_1BYTE(__paddr+3, 0, 8) +#define GET_TX_REPORT_TYPE1_RERTY_3(__paddr) \ + LE_BITS_TO_1BYTE(__paddr+4, 0, 8) +#define GET_TX_REPORT_TYPE1_RERTY_4(__paddr) \ + LE_BITS_TO_1BYTE(__paddr+4+1, 0, 8) +#define GET_TX_REPORT_TYPE1_DROP_0(__paddr) \ + LE_BITS_TO_1BYTE(__paddr+4+2, 0, 8) +#define GET_TX_REPORT_TYPE1_DROP_1(__paddr) \ + LE_BITS_TO_1BYTE(__paddr+4+3, 0, 8) + +/* End rate adaptive define */ + +void odm_ra_support_init(struct PHY_DM_STRUCT *p_dm_odm); +int odm_ra_info_init_all(struct PHY_DM_STRUCT *p_dm_odm); +int odm_ra_info_init(struct PHY_DM_STRUCT *p_dm_odm, u32 mac_id); +u8 odm_ra_get_sgi_8188e(struct PHY_DM_STRUCT *p_dm_odm, u8 mac_id); +u8 odm_ra_get_decision_rate_8188e(struct PHY_DM_STRUCT *p_dm_odm, u8 mac_id); +u8 odm_ra_get_hw_pwr_status_8188e(struct PHY_DM_STRUCT *p_dm_odm, u8 mac_id); +void odm_ra_update_rate_info_8188e(struct PHY_DM_STRUCT *p_dm_odm, u8 mac_id, + u8 rate_id, u32 rate_mask, u8 sgi_enable); +void odm_ra_set_rssi_8188e(struct PHY_DM_STRUCT *p_dm_odm, u8 mac_id, u8 rssi); +void odm_ra_tx_rpt2_handle_8188e(struct PHY_DM_STRUCT *p_dm_odm, u8 *tx_rpt_buf, + __le16 tx_rpt_len, u32 mac_id_valid_entry0, u32 mac_id_valid_entry1); +void odm_ra_set_tx_rpt_time(struct PHY_DM_STRUCT *p_dm_odm, u16 min_rpt_time); + +#endif diff --git a/drivers/staging/rtl8188eu/hal/hal8188ereg.h b/drivers/staging/rtl8188eu/hal/hal8188ereg.h new file mode 100644 index 000000000000..f609da8b08b6 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal8188ereg.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +/* ************************************************************ + * File Name: hal8188ereg.h + * + * Description: + * + * This file is for RTL8188E register definition. + * + * + * ************************************************************ */ +#ifndef __HAL_8188E_REG_H__ +#define __HAL_8188E_REG_H__ + +/* + * Register Definition + * */ +#define TRX_ANTDIV_PATH 0x860 +#define RX_ANTDIV_PATH 0xb2c +#define ODM_R_A_AGC_CORE1_8188E 0xc50 + +#define REG_GPIO_EXT_CTRL 0x0060 + +#define REG_MCUFWDL_8188E 0x0080 +#define REG_FW_DBG_STATUS_8188E 0x0088 +#define REG_FW_DBG_CTRL_8188E 0x008F + +#define REG_CR_8188E 0x0100 + + +/* + * Bitmap Definition + * */ +#define BIT_FA_RESET_8188E BIT(0) +#define REG_ADAPTIVE_DATA_RATE_0 0x2B0 +#define REG_DBI_WDATA_8188 0x0348 /* DBI Write data */ +#define REG_DBI_RDATA_8188 0x034C /* DBI Read data */ +#define REG_DBI_ADDR_8188 0x0350 /* DBI Address */ +#define REG_DBI_FLAG_8188 0x0352 /* DBI Read/Write Flag */ +#define REG_MDIO_WDATA_8188E 0x0354 /* MDIO for Write PCIE PHY */ +#define REG_MDIO_RDATA_8188E 0x0356 /* MDIO for Reads PCIE PHY */ +#define REG_MDIO_CTL_8188E 0x0358 /* MDIO for Control */ + +/* [0-63] */ +#define REG_MACID_NO_LINK 0x484 /* No Link register (bit[x] enabled means dropping packets for MACID in HW queue) */ + +#endif diff --git a/drivers/staging/rtl8188eu/hal/hal_btcoex.c b/drivers/staging/rtl8188eu/hal/hal_btcoex.c new file mode 100644 index 000000000000..ff28b63ecded --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal_btcoex.c @@ -0,0 +1,3786 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#define __HAL_BTCOEX_C__ + +#ifdef CONFIG_BT_COEXIST + +#include +#include +#include "btc/mp_precomp.h" + +/* ************************************ + * Global variables + * ************************************ */ +const char *const BtProfileString[] = { + "NONE", + "A2DP", + "PAN", + "HID", + "SCO", +}; + +const char *const BtSpecString[] = { + "1.0b", + "1.1", + "1.2", + "2.0+EDR", + "2.1+EDR", + "3.0+HS", + "4.0", +}; + +const char *const BtLinkRoleString[] = { + "Master", + "Slave", +}; + +const char *const h2cStaString[] = { + "successful", + "h2c busy", + "rf off", + "fw not read", +}; + +const char *const ioStaString[] = { + "success", + "can not IO", + "rf off", + "fw not read", + "wait io timeout", + "invalid len", + "idle Q empty", + "insert waitQ fail", + "unknown fail", + "wrong level", + "h2c stopped", +}; + +const char *const GLBtcWifiBwString[] = { + "11bg", + "HT20", + "HT40", + "HT80", + "HT160" +}; + +const char *const GLBtcWifiFreqString[] = { + "2.4G", + "5G" +}; + +const char *const GLBtcIotPeerString[] = { + "UNKNOWN", + "REALTEK", + "REALTEK_92SE", + "BROADCOM", + "RALINK", + "ATHEROS", + "CISCO", + "MERU", + "MARVELL", + "REALTEK_SOFTAP", /* peer is RealTek SOFT_AP, by Bohn, 2009.12.17 */ + "SELF_SOFTAP", /* Self is SoftAP */ + "AIRGO", + "INTEL", + "RTK_APCLIENT", + "REALTEK_81XX", + "REALTEK_WOW", + "REALTEK_JAGUAR_BCUTAP", + "REALTEK_JAGUAR_CCUTAP" +}; + +const char *const coexOpcodeString[] = { + "Wifi status notify", + "Wifi progress", + "Wifi info", + "Power state", + "Set Control", + "Get Control" +}; + +const char *const coexIndTypeString[] = { + "bt info", + "pstdma", + "limited tx/rx", + "coex table", + "request" +}; + +const char *const coexH2cResultString[] = { + "ok", + "unknown", + "un opcode", + "opVer MM", + "par Err", + "par OoR", + "reqNum MM", + "halMac Fail", + "h2c TimeOut", + "Invalid c2h Len", + "data overflow" +}; + +#define HALBTCOUTSRC_AGG_CHK_WINDOW_IN_MS 8000 + +struct btc_coexist GLBtCoexist; +BTC_OFFLOAD gl_coex_offload; +u8 GLBtcWiFiInScanState; +u8 GLBtcWiFiInIQKState; +u8 GLBtcWiFiInIPS; +u8 GLBtcWiFiInLPS; +u8 GLBtcBtCoexAliveRegistered; + +/* + * BT control H2C/C2H + */ +/* EXT_EID */ +typedef enum _bt_ext_eid { + C2H_WIFI_FW_ACTIVE_RSP = 0, + C2H_TRIG_BY_BT_FW +} BT_EXT_EID; + +/* C2H_STATUS */ +typedef enum _bt_c2h_status { + BT_STATUS_OK = 0, + BT_STATUS_VERSION_MISMATCH, + BT_STATUS_UNKNOWN_OPCODE, + BT_STATUS_ERROR_PARAMETER +} BT_C2H_STATUS; + +/* C2H BT OP CODES */ +typedef enum _bt_op_code { + BT_OP_GET_BT_VERSION = 0x00, + BT_OP_WRITE_REG_ADDR = 0x0c, + BT_OP_WRITE_REG_VALUE = 0x0d, + + BT_OP_READ_REG = 0x11, + + BT_LO_OP_GET_AFH_MAP_L = 0x1e, + BT_LO_OP_GET_AFH_MAP_M = 0x1f, + BT_LO_OP_GET_AFH_MAP_H = 0x20, + + BT_OP_GET_BT_COEX_SUPPORTED_FEATURE = 0x2a, + BT_OP_GET_BT_COEX_SUPPORTED_VERSION = 0x2b, + BT_OP_GET_BT_ANT_DET_VAL = 0x2c, + BT_OP_GET_BT_BLE_SCAN_PARA = 0x2d, + BT_OP_GET_BT_BLE_SCAN_TYPE = 0x2e, + BT_OP_MAX +} BT_OP_CODE; + +#define BTC_MPOPER_TIMEOUT 50 /* unit: ms */ + +#define C2H_MAX_SIZE 16 +u8 GLBtcBtMpOperSeq; +_mutex GLBtcBtMpOperLock; +_timer GLBtcBtMpOperTimer; +_sema GLBtcBtMpRptSema; +u8 GLBtcBtMpRptSeq; +u8 GLBtcBtMpRptStatus; +u8 GLBtcBtMpRptRsp[C2H_MAX_SIZE]; +u8 GLBtcBtMpRptRspSize; +u8 GLBtcBtMpRptWait; +u8 GLBtcBtMpRptWiFiOK; +u8 GLBtcBtMpRptBTOK; + +/* + * Debug + */ +u32 GLBtcDbgType[COMP_MAX]; +u8 GLBtcDbgBuf[BT_TMP_BUF_SIZE]; +u8 gl_btc_trace_buf[BT_TMP_BUF_SIZE]; + +typedef struct _btcoexdbginfo { + u8 *info; + u32 size; /* buffer total size */ + u32 len; /* now used length */ +} BTCDBGINFO, *PBTCDBGINFO; + +BTCDBGINFO GLBtcDbgInfo; + +#define BT_Operation(Adapter) false + +static void DBG_BT_INFO_INIT(PBTCDBGINFO pinfo, u8 *pbuf, u32 size) +{ + if (NULL == pinfo) + return; + + memset(pinfo, 0, sizeof(BTCDBGINFO)); + + if (pbuf && size) { + pinfo->info = pbuf; + pinfo->size = size; + } +} + +void DBG_BT_INFO(u8 *dbgmsg) +{ + PBTCDBGINFO pinfo; + u32 msglen, buflen; + u8 *pbuf; + + + pinfo = &GLBtcDbgInfo; + + if (NULL == pinfo->info) + return; + + msglen = strlen(dbgmsg); + if (pinfo->len + msglen > pinfo->size) + return; + + pbuf = pinfo->info + pinfo->len; + memcpy(pbuf, dbgmsg, msglen); + pinfo->len += msglen; +} + +/* ************************************ + * Debug related function + * ************************************ */ +static u8 halbtcoutsrc_IsBtCoexistAvailable(PBTC_COEXIST pBtCoexist) +{ + if (!pBtCoexist->bBinded || + NULL == pBtCoexist->Adapter) + return false; + return true; +} + +static void halbtcoutsrc_DbgInit(void) +{ + u8 i; + + for (i = 0; i < COMP_MAX; i++) + GLBtcDbgType[i] = 0; +} + +static u8 halbtcoutsrc_IsCsrBtCoex(PBTC_COEXIST pBtCoexist) +{ + if (pBtCoexist->board_info.bt_chip_type == BTC_CHIP_CSR_BC4 + || pBtCoexist->board_info.bt_chip_type == BTC_CHIP_CSR_BC8 + ) + return true; + return false; +} + +static u8 halbtcoutsrc_IsHwMailboxExist(PBTC_COEXIST pBtCoexist) +{ + if (pBtCoexist->board_info.bt_chip_type == BTC_CHIP_CSR_BC4 + || pBtCoexist->board_info.bt_chip_type == BTC_CHIP_CSR_BC8 + ) + return false; + else if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) + return false; + else + return true; +} + +static void halbtcoutsrc_LeaveLps(PBTC_COEXIST pBtCoexist) +{ + PADAPTER padapter; + + + padapter = pBtCoexist->Adapter; + + pBtCoexist->bt_info.bt_ctrl_lps = true; + pBtCoexist->bt_info.bt_lps_on = false; + + rtw_btcoex_LPS_Leave(padapter); +} + +void halbtcoutsrc_EnterLps(PBTC_COEXIST pBtCoexist) +{ + PADAPTER padapter; + + + padapter = pBtCoexist->Adapter; + + if (pBtCoexist->bdontenterLPS == false) { + pBtCoexist->bt_info.bt_ctrl_lps = true; + pBtCoexist->bt_info.bt_lps_on = true; + + rtw_btcoex_LPS_Enter(padapter); + } +} + +void halbtcoutsrc_NormalLps(PBTC_COEXIST pBtCoexist) +{ + PADAPTER padapter; + + + + padapter = pBtCoexist->Adapter; + + if (pBtCoexist->bt_info.bt_ctrl_lps) { + pBtCoexist->bt_info.bt_lps_on = false; + rtw_btcoex_LPS_Leave(padapter); + pBtCoexist->bt_info.bt_ctrl_lps = false; + } +} + +/* + * Constraint: + * 1. this function will request pwrctrl->lock + */ +void halbtcoutsrc_LeaveLowPower(PBTC_COEXIST pBtCoexist) +{ +#ifdef CONFIG_LPS_LCLK + PADAPTER padapter; + PHAL_DATA_TYPE pHalData; + struct pwrctrl_priv *pwrctrl; + s32 ready; + u32 stime; + s32 utime; + u32 timeout; /* unit: ms */ + + + padapter = pBtCoexist->Adapter; + pHalData = GET_HAL_DATA(padapter); + pwrctrl = adapter_to_pwrctl(padapter); + ready = _FAIL; +#ifdef LPS_RPWM_WAIT_MS + timeout = LPS_RPWM_WAIT_MS; +#else /* !LPS_RPWM_WAIT_MS */ + timeout = 30; +#endif /* !LPS_RPWM_WAIT_MS */ + + if (GLBtcBtCoexAliveRegistered == true) + return; + + stime = jiffies; + do { + ready = rtw_register_task_alive(padapter, BTCOEX_ALIVE); + if (_SUCCESS == ready) + break; + + utime = rtw_get_passing_time_ms(stime); + if (utime > timeout) + break; + + rtw_msleep_os(1); + } while (1); + + GLBtcBtCoexAliveRegistered = true; +#endif /* CONFIG_LPS_LCLK */ +} + +/* + * Constraint: + * 1. this function will request pwrctrl->lock + */ +void halbtcoutsrc_NormalLowPower(PBTC_COEXIST pBtCoexist) +{ +#ifdef CONFIG_LPS_LCLK + PADAPTER padapter; + + if (GLBtcBtCoexAliveRegistered == false) + return; + + padapter = pBtCoexist->Adapter; + rtw_unregister_task_alive(padapter, BTCOEX_ALIVE); + + GLBtcBtCoexAliveRegistered = false; +#endif /* CONFIG_LPS_LCLK */ +} + +void halbtcoutsrc_DisableLowPower(PBTC_COEXIST pBtCoexist, u8 bLowPwrDisable) +{ + pBtCoexist->bt_info.bt_disable_low_pwr = bLowPwrDisable; + if (bLowPwrDisable) + halbtcoutsrc_LeaveLowPower(pBtCoexist); /* leave 32k low power. */ + else + halbtcoutsrc_NormalLowPower(pBtCoexist); /* original 32k low power behavior. */ +} + +void halbtcoutsrc_AggregationCheck(PBTC_COEXIST pBtCoexist) +{ + PADAPTER padapter; + bool bNeedToAct = false; + static u32 preTime = 0; + u32 curTime = 0; + + padapter = pBtCoexist->Adapter; + + /* ===================================== */ + /* To void continuous deleteBA=>addBA=>deleteBA=>addBA */ + /* This function is not allowed to continuous called. */ + /* It can only be called after 8 seconds. */ + /* ===================================== */ + + curTime = rtw_systime_to_ms(jiffies); + if ((curTime - preTime) < HALBTCOUTSRC_AGG_CHK_WINDOW_IN_MS) /* over 8 seconds you can execute this function again. */ + return; + else + preTime = curTime; + + if (pBtCoexist->bt_info.reject_agg_pkt) { + bNeedToAct = true; + pBtCoexist->bt_info.pre_reject_agg_pkt = pBtCoexist->bt_info.reject_agg_pkt; + } else { + if (pBtCoexist->bt_info.pre_reject_agg_pkt) { + bNeedToAct = true; + pBtCoexist->bt_info.pre_reject_agg_pkt = pBtCoexist->bt_info.reject_agg_pkt; + } + + if (pBtCoexist->bt_info.pre_bt_ctrl_agg_buf_size != + pBtCoexist->bt_info.bt_ctrl_agg_buf_size) { + bNeedToAct = true; + pBtCoexist->bt_info.pre_bt_ctrl_agg_buf_size = pBtCoexist->bt_info.bt_ctrl_agg_buf_size; + } + + if (pBtCoexist->bt_info.bt_ctrl_agg_buf_size) { + if (pBtCoexist->bt_info.pre_agg_buf_size != + pBtCoexist->bt_info.agg_buf_size) + bNeedToAct = true; + pBtCoexist->bt_info.pre_agg_buf_size = pBtCoexist->bt_info.agg_buf_size; + } + } + + if (bNeedToAct) + rtw_btcoex_rx_ampdu_apply(padapter); +} + +u8 halbtcoutsrc_is_autoload_fail(PBTC_COEXIST pBtCoexist) +{ + PADAPTER padapter; + PHAL_DATA_TYPE pHalData; + + padapter = pBtCoexist->Adapter; + pHalData = GET_HAL_DATA(padapter); + + return pHalData->bautoload_fail_flag; +} + +u8 halbtcoutsrc_is_fw_ready(PBTC_COEXIST pBtCoexist) +{ + PADAPTER padapter; + + padapter = pBtCoexist->Adapter; + + return padapter->bFWReady; +} + +u8 halbtcoutsrc_IsWifiBusy(PADAPTER padapter) +{ + if (rtw_mi_check_status(padapter, MI_AP_MODE)) + return true; + if (rtw_mi_busy_traffic_check(padapter, false)) + return true; + + return false; +} + +static u32 _halbtcoutsrc_GetWifiLinkStatus(PADAPTER padapter) +{ + struct mlme_priv *pmlmepriv; + u8 bp2p; + u32 portConnectedStatus; + + + pmlmepriv = &padapter->mlmepriv; + bp2p = false; + portConnectedStatus = 0; + +#ifdef CONFIG_P2P + if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE)) + bp2p = true; +#endif /* CONFIG_P2P */ + + if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == true) { + if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) { + if (bp2p) + portConnectedStatus |= WIFI_P2P_GO_CONNECTED; + else + portConnectedStatus |= WIFI_AP_CONNECTED; + } else { + if (bp2p) + portConnectedStatus |= WIFI_P2P_GC_CONNECTED; + else + portConnectedStatus |= WIFI_STA_CONNECTED; + } + } + + return portConnectedStatus; +} + +u32 halbtcoutsrc_GetWifiLinkStatus(PBTC_COEXIST pBtCoexist) +{ + /* ================================= */ + /* return value: */ + /* [31:16]=> connected port number */ + /* [15:0]=> port connected bit define */ + /* ================================ */ + + PADAPTER padapter; + u32 retVal; + u32 portConnectedStatus, numOfConnectedPort; + struct dvobj_priv *dvobj; + _adapter *iface; + int i; + + padapter = pBtCoexist->Adapter; + retVal = 0; + portConnectedStatus = 0; + numOfConnectedPort = 0; + dvobj = adapter_to_dvobj(padapter); + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if ((iface) && rtw_is_adapter_up(iface)) { + retVal = _halbtcoutsrc_GetWifiLinkStatus(iface); + if (retVal) { + portConnectedStatus |= retVal; + numOfConnectedPort++; + } + } + } + retVal = (numOfConnectedPort << 16) | portConnectedStatus; + + return retVal; +} + +static void _btmpoper_timer_hdl(void *p) +{ + if (GLBtcBtMpRptWait) { + GLBtcBtMpRptWait = 0; + up(&GLBtcBtMpRptSema); + } +} + +/* + * !IMPORTANT! + * Before call this function, caller should acquire "GLBtcBtMpOperLock"! + * Othrewise there will be racing problem and something may go wrong. + */ +static u8 _btmpoper_cmd(PBTC_COEXIST pBtCoexist, u8 opcode, u8 opcodever, u8 *cmd, u8 size) +{ + PADAPTER padapter; + u8 buf[H2C_BTMP_OPER_LEN] = {0}; + u8 buflen; + u8 seq; + u8 timer_cancelled; + s32 ret; + + + if (!cmd && size) + size = 0; + if ((size + 2) > H2C_BTMP_OPER_LEN) + return BT_STATUS_H2C_LENGTH_EXCEEDED; + buflen = size + 2; + + seq = GLBtcBtMpOperSeq & 0xF; + GLBtcBtMpOperSeq++; + + buf[0] = (opcodever & 0xF) | (seq << 4); + buf[1] = opcode; + if (cmd && size) + memcpy(buf + 2, cmd, size); + + GLBtcBtMpRptWait = 1; + GLBtcBtMpRptWiFiOK = 0; + GLBtcBtMpRptBTOK = 0; + GLBtcBtMpRptStatus = 0; + padapter = pBtCoexist->Adapter; + _set_timer(&GLBtcBtMpOperTimer, BTC_MPOPER_TIMEOUT); + if (rtw_hal_fill_h2c_cmd(padapter, H2C_BT_MP_OPER, buflen, buf) == _FAIL) { + _cancel_timer(&GLBtcBtMpOperTimer, &timer_cancelled); + ret = BT_STATUS_H2C_FAIL; + goto exit; + } + + _rtw_down_sema(&GLBtcBtMpRptSema); + /* GLBtcBtMpRptWait should be 0 here*/ + + if (!GLBtcBtMpRptWiFiOK) { + RTW_ERR("%s: Didn't get H2C Rsp Event!\n", __func__); + ret = BT_STATUS_H2C_TIMTOUT; + goto exit; + } + if (!GLBtcBtMpRptBTOK) { + RTW_ERR("%s: Didn't get BT response!\n", __func__); + ret = BT_STATUS_H2C_BT_NO_RSP; + goto exit; + } + if (seq != GLBtcBtMpRptSeq) { + RTW_ERR("%s: Sequence number not match!(%d!=%d)!\n", + __func__, seq, GLBtcBtMpRptSeq); + ret = BT_STATUS_C2H_REQNUM_MISMATCH; + goto exit; + } + + switch (GLBtcBtMpRptStatus) { + /* Examine the status reported from C2H */ + case BT_STATUS_OK: + ret = BT_STATUS_BT_OP_SUCCESS; + RTW_DBG("%s: C2H status = BT_STATUS_BT_OP_SUCCESS\n", __func__); + break; + case BT_STATUS_VERSION_MISMATCH: + ret = BT_STATUS_OPCODE_L_VERSION_MISMATCH; + RTW_DBG("%s: C2H status = BT_STATUS_OPCODE_L_VERSION_MISMATCH\n", __func__); + break; + case BT_STATUS_UNKNOWN_OPCODE: + ret = BT_STATUS_UNKNOWN_OPCODE_L; + RTW_DBG("%s: C2H status = MP_BT_STATUS_UNKNOWN_OPCODE_L\n", __func__); + break; + case BT_STATUS_ERROR_PARAMETER: + ret = BT_STATUS_PARAMETER_FORMAT_ERROR_L; + RTW_DBG("%s: C2H status = MP_BT_STATUS_PARAMETER_FORMAT_ERROR_L\n", __func__); + break; + default: + ret = BT_STATUS_UNKNOWN_STATUS_L; + RTW_DBG("%s: C2H status = MP_BT_STATUS_UNKNOWN_STATUS_L\n", __func__); + break; + } + +exit: + return ret; +} + +u32 halbtcoutsrc_GetBtPatchVer(PBTC_COEXIST pBtCoexist) +{ + if (pBtCoexist->bt_info.get_bt_fw_ver_cnt <= 5) { + if (halbtcoutsrc_IsHwMailboxExist(pBtCoexist) == true) { + unsigned long irqL; + u8 ret; + + _enter_critical_mutex(&GLBtcBtMpOperLock, &irqL); + + ret = _btmpoper_cmd(pBtCoexist, BT_OP_GET_BT_VERSION, 0, NULL, 0); + if (BT_STATUS_BT_OP_SUCCESS == ret) { + pBtCoexist->bt_info.bt_real_fw_ver = le16_to_cpu(*(u16 *)GLBtcBtMpRptRsp); + pBtCoexist->bt_info.bt_fw_ver = *(GLBtcBtMpRptRsp + 2); + pBtCoexist->bt_info.get_bt_fw_ver_cnt++; + } + + _exit_critical_mutex(&GLBtcBtMpOperLock, &irqL); + } else { +#ifdef CONFIG_BT_COEXIST_SOCKET_TRX + u8 dataLen = 2; + u8 buf[4] = {0}; + + buf[0] = 0x0; /* OP_Code */ + buf[1] = 0x0; /* OP_Code_Length */ + BT_SendEventExtBtCoexControl(pBtCoexist->Adapter, false, dataLen, &buf[0]); +#endif /* !CONFIG_BT_COEXIST_SOCKET_TRX */ + } + } + +exit: + return pBtCoexist->bt_info.bt_real_fw_ver; +} + +s32 halbtcoutsrc_GetWifiRssi(PADAPTER padapter) +{ + PHAL_DATA_TYPE pHalData; + s32 undecorated_smoothed_pwdb = 0; + + pHalData = GET_HAL_DATA(padapter); + + undecorated_smoothed_pwdb = pHalData->entry_min_undecorated_smoothed_pwdb; + + return undecorated_smoothed_pwdb; +} + +u32 halbtcoutsrc_GetBtCoexSupportedFeature(void *pBtcContext) +{ + PBTC_COEXIST pBtCoexist; + u32 ret = BT_STATUS_BT_OP_SUCCESS; + u32 data = 0; + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + + if (halbtcoutsrc_IsHwMailboxExist(pBtCoexist) == true) { + u8 buf[3] = {0}; + unsigned long irqL; + u8 op_code; + u8 status; + + _enter_critical_mutex(&GLBtcBtMpOperLock, &irqL); + + op_code = BT_OP_GET_BT_COEX_SUPPORTED_FEATURE; + status = _btmpoper_cmd(pBtCoexist, op_code, 0, buf, 0); + if (status == BT_STATUS_BT_OP_SUCCESS) + data = le16_to_cpu(*(u16 *)GLBtcBtMpRptRsp); + else + ret = SET_BT_MP_OPER_RET(op_code, status); + + _exit_critical_mutex(&GLBtcBtMpOperLock, &irqL); + + } else + ret = BT_STATUS_NOT_IMPLEMENT; + + return data; +} + +u32 halbtcoutsrc_GetBtCoexSupportedVersion(void *pBtcContext) +{ + PBTC_COEXIST pBtCoexist; + u32 ret = BT_STATUS_BT_OP_SUCCESS; + u32 data = 0xFFFF; + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + + if (halbtcoutsrc_IsHwMailboxExist(pBtCoexist) == true) { + u8 buf[3] = {0}; + unsigned long irqL; + u8 op_code; + u8 status; + + _enter_critical_mutex(&GLBtcBtMpOperLock, &irqL); + + op_code = BT_OP_GET_BT_COEX_SUPPORTED_VERSION; + status = _btmpoper_cmd(pBtCoexist, op_code, 0, buf, 0); + if (status == BT_STATUS_BT_OP_SUCCESS) + data = le16_to_cpu(*(u16 *)GLBtcBtMpRptRsp); + else + ret = SET_BT_MP_OPER_RET(op_code, status); + + _exit_critical_mutex(&GLBtcBtMpOperLock, &irqL); + + } else + ret = BT_STATUS_NOT_IMPLEMENT; + + return data; +} + +static u8 halbtcoutsrc_GetWifiScanAPNum(PADAPTER padapter) +{ + struct mlme_priv *pmlmepriv; + struct mlme_ext_priv *pmlmeext; + static u8 scan_AP_num = 0; + + + pmlmepriv = &padapter->mlmepriv; + pmlmeext = &padapter->mlmeextpriv; + + if (GLBtcWiFiInScanState == false) { + if (pmlmepriv->num_of_scanned > 0xFF) + scan_AP_num = 0xFF; + else + scan_AP_num = (u8)pmlmepriv->num_of_scanned; + } + + return scan_AP_num; +} + +u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf) +{ + PBTC_COEXIST pBtCoexist; + PADAPTER padapter; + PHAL_DATA_TYPE pHalData; + struct mlme_ext_priv *mlmeext; + u8 bSoftApExist, bVwifiExist; + u8 *pu8; + s32 *pS4Tmp; + u32 *pU4Tmp; + u8 *pU1Tmp; + u8 ret; + + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return false; + + padapter = pBtCoexist->Adapter; + pHalData = GET_HAL_DATA(padapter); + mlmeext = &padapter->mlmeextpriv; + bSoftApExist = false; + bVwifiExist = false; + pu8 = (u8 *)pOutBuf; + pS4Tmp = (s32 *)pOutBuf; + pU4Tmp = (u32 *)pOutBuf; + pU1Tmp = (u8 *)pOutBuf; + ret = true; + + switch (getType) { + case BTC_GET_BL_HS_OPERATION: + *pu8 = false; + ret = false; + break; + + case BTC_GET_BL_HS_CONNECTING: + *pu8 = false; + ret = false; + break; + + case BTC_GET_BL_WIFI_FW_READY: + *pu8 = halbtcoutsrc_is_fw_ready(pBtCoexist); + break; + + case BTC_GET_BL_WIFI_CONNECTED: + *pu8 = (rtw_mi_check_status(padapter, MI_LINKED)) ? true : false; + break; + + case BTC_GET_BL_WIFI_BUSY: + *pu8 = halbtcoutsrc_IsWifiBusy(padapter); + break; + + case BTC_GET_BL_WIFI_SCAN: + /* Use the value of the new variable GLBtcWiFiInScanState to judge whether WiFi is in scan state or not, since the originally used flag + WIFI_SITE_MONITOR in fwstate may not be cleared in time */ + *pu8 = GLBtcWiFiInScanState; + break; + + case BTC_GET_BL_WIFI_LINK: + *pu8 = (rtw_mi_check_status(padapter, MI_STA_LINKING)) ? true : false; + break; + + case BTC_GET_BL_WIFI_ROAM: + *pu8 = (rtw_mi_check_status(padapter, MI_STA_LINKING)) ? true : false; + break; + + case BTC_GET_BL_WIFI_4_WAY_PROGRESS: + *pu8 = false; + break; + + case BTC_GET_BL_WIFI_UNDER_5G: + *pu8 = (pHalData->current_band_type == 1) ? true : false; + break; + + case BTC_GET_BL_WIFI_AP_MODE_ENABLE: + *pu8 = (rtw_mi_check_status(padapter, MI_AP_MODE)) ? true : false; + break; + + case BTC_GET_BL_WIFI_ENABLE_ENCRYPTION: + *pu8 = padapter->securitypriv.dot11PrivacyAlgrthm == 0 ? false : true; + break; + + case BTC_GET_BL_WIFI_UNDER_B_MODE: + if (mlmeext->cur_wireless_mode == WIRELESS_11B) + *pu8 = true; + else + *pu8 = false; + break; + + case BTC_GET_BL_WIFI_IS_IN_MP_MODE: + if (padapter->registrypriv.mp_mode == 0) + *pu8 = false; + else + *pu8 = true; + break; + + case BTC_GET_BL_EXT_SWITCH: + *pu8 = false; + break; + case BTC_GET_BL_IS_ASUS_8723B: + /* Always return false in linux driver since this case is added only for windows driver */ + *pu8 = false; + break; + + case BTC_GET_S4_WIFI_RSSI: + *pS4Tmp = halbtcoutsrc_GetWifiRssi(padapter); + break; + + case BTC_GET_S4_HS_RSSI: + *pS4Tmp = 0; + ret = false; + break; + + case BTC_GET_U4_WIFI_BW: + if (IsLegacyOnly(mlmeext->cur_wireless_mode)) + *pU4Tmp = BTC_WIFI_BW_LEGACY; + else { + switch (pHalData->current_channel_bw) { + case CHANNEL_WIDTH_20: + *pU4Tmp = BTC_WIFI_BW_HT20; + break; + case CHANNEL_WIDTH_40: + *pU4Tmp = BTC_WIFI_BW_HT40; + break; + case CHANNEL_WIDTH_80: + *pU4Tmp = BTC_WIFI_BW_HT80; + break; + case CHANNEL_WIDTH_160: + *pU4Tmp = BTC_WIFI_BW_HT160; + break; + default: + RTW_INFO("[BTCOEX] unknown bandwidth(%d)\n", pHalData->current_channel_bw); + *pU4Tmp = BTC_WIFI_BW_HT40; + break; + } + + } + break; + + case BTC_GET_U4_WIFI_TRAFFIC_DIRECTION: { + PRT_LINK_DETECT_T plinkinfo; + plinkinfo = &padapter->mlmepriv.LinkDetectInfo; + + if (plinkinfo->NumTxOkInPeriod > plinkinfo->NumRxOkInPeriod) + *pU4Tmp = BTC_WIFI_TRAFFIC_TX; + else + *pU4Tmp = BTC_WIFI_TRAFFIC_RX; + } + break; + + case BTC_GET_U4_WIFI_FW_VER: + *pU4Tmp = pHalData->firmware_version << 16; + *pU4Tmp |= pHalData->firmware_sub_version; + break; + + case BTC_GET_U4_WIFI_LINK_STATUS: + *pU4Tmp = halbtcoutsrc_GetWifiLinkStatus(pBtCoexist); + break; + + case BTC_GET_U4_BT_PATCH_VER: + *pU4Tmp = halbtcoutsrc_GetBtPatchVer(pBtCoexist); + break; + + case BTC_GET_U4_VENDOR: + *pU4Tmp = BTC_VENDOR_OTHER; + break; + + case BTC_GET_U4_SUPPORTED_VERSION: + *pU4Tmp = halbtcoutsrc_GetBtCoexSupportedVersion(pBtCoexist); + break; + case BTC_GET_U4_SUPPORTED_FEATURE: + *pU4Tmp = halbtcoutsrc_GetBtCoexSupportedFeature(pBtCoexist); + break; + + case BTC_GET_U4_WIFI_IQK_TOTAL: + *pU4Tmp = pHalData->odmpriv.n_iqk_cnt; + break; + + case BTC_GET_U4_WIFI_IQK_OK: + *pU4Tmp = pHalData->odmpriv.n_iqk_ok_cnt; + break; + + case BTC_GET_U4_WIFI_IQK_FAIL: + *pU4Tmp = pHalData->odmpriv.n_iqk_fail_cnt; + break; + + case BTC_GET_U1_WIFI_DOT11_CHNL: + *pU1Tmp = padapter->mlmeextpriv.cur_channel; + break; + + case BTC_GET_U1_WIFI_CENTRAL_CHNL: + *pU1Tmp = pHalData->current_channel; + break; + + case BTC_GET_U1_WIFI_HS_CHNL: + *pU1Tmp = 0; + ret = false; + break; + + case BTC_GET_U1_WIFI_P2P_CHNL: +#ifdef CONFIG_P2P + { + struct wifidirect_info *pwdinfo = &(padapter->wdinfo); + + *pU1Tmp = pwdinfo->operating_channel; + } +#else + *pU1Tmp = 0; +#endif + break; + + case BTC_GET_U1_MAC_PHY_MODE: + /* *pU1Tmp = BTC_SMSP; + * *pU1Tmp = BTC_DMSP; + * *pU1Tmp = BTC_DMDP; + * *pU1Tmp = BTC_MP_UNKNOWN; */ + break; + + case BTC_GET_U1_AP_NUM: + *pU1Tmp = halbtcoutsrc_GetWifiScanAPNum(padapter); + break; + case BTC_GET_U1_ANT_TYPE: + switch (pHalData->bt_coexist.btAntisolation) { + case 0: + *pU1Tmp = (u8)BTC_ANT_TYPE_0; + pBtCoexist->board_info.ant_type = (u8)BTC_ANT_TYPE_0; + break; + case 1: + *pU1Tmp = (u8)BTC_ANT_TYPE_1; + pBtCoexist->board_info.ant_type = (u8)BTC_ANT_TYPE_1; + break; + case 2: + *pU1Tmp = (u8)BTC_ANT_TYPE_2; + pBtCoexist->board_info.ant_type = (u8)BTC_ANT_TYPE_2; + break; + case 3: + *pU1Tmp = (u8)BTC_ANT_TYPE_3; + pBtCoexist->board_info.ant_type = (u8)BTC_ANT_TYPE_3; + break; + case 4: + *pU1Tmp = (u8)BTC_ANT_TYPE_4; + pBtCoexist->board_info.ant_type = (u8)BTC_ANT_TYPE_4; + break; + } + break; + case BTC_GET_U1_IOT_PEER: + *pU1Tmp = mlmeext->mlmext_info.assoc_AP_vendor; + break; + + /* =======1Ant=========== */ + case BTC_GET_U1_LPS_MODE: + *pU1Tmp = padapter->dvobj->pwrctl_priv.pwr_mode; + break; + + default: + ret = false; + break; + } + + return ret; +} + +u8 halbtcoutsrc_Set(void *pBtcContext, u8 setType, void *pInBuf) +{ + PBTC_COEXIST pBtCoexist; + PADAPTER padapter; + PHAL_DATA_TYPE pHalData; + u8 *pu8; + u8 *pU1Tmp; + u32 *pU4Tmp; + u8 ret; + + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + padapter = pBtCoexist->Adapter; + pHalData = GET_HAL_DATA(padapter); + pu8 = (u8 *)pInBuf; + pU1Tmp = (u8 *)pInBuf; + pU4Tmp = (u32 *)pInBuf; + ret = true; + + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return false; + + switch (setType) { + /* set some u8 type variables. */ + case BTC_SET_BL_BT_DISABLE: + pBtCoexist->bt_info.bt_disabled = *pu8; + break; + + case BTC_SET_BL_BT_ENABLE_DISABLE_CHANGE: + pBtCoexist->bt_info.bt_enable_disable_change = *pu8; + break; + + case BTC_SET_BL_BT_TRAFFIC_BUSY: + pBtCoexist->bt_info.bt_busy = *pu8; + break; + + case BTC_SET_BL_BT_LIMITED_DIG: + pBtCoexist->bt_info.limited_dig = *pu8; + break; + + case BTC_SET_BL_FORCE_TO_ROAM: + pBtCoexist->bt_info.force_to_roam = *pu8; + break; + + case BTC_SET_BL_TO_REJ_AP_AGG_PKT: + pBtCoexist->bt_info.reject_agg_pkt = *pu8; + break; + + case BTC_SET_BL_BT_CTRL_AGG_SIZE: + pBtCoexist->bt_info.bt_ctrl_agg_buf_size = *pu8; + break; + + case BTC_SET_BL_INC_SCAN_DEV_NUM: + pBtCoexist->bt_info.increase_scan_dev_num = *pu8; + break; + + case BTC_SET_BL_BT_TX_RX_MASK: + pBtCoexist->bt_info.bt_tx_rx_mask = *pu8; + break; + + case BTC_SET_BL_MIRACAST_PLUS_BT: + pBtCoexist->bt_info.miracast_plus_bt = *pu8; + break; + + /* set some u8 type variables. */ + case BTC_SET_U1_RSSI_ADJ_VAL_FOR_AGC_TABLE_ON: + pBtCoexist->bt_info.rssi_adjust_for_agc_table_on = *pU1Tmp; + break; + + case BTC_SET_U1_AGG_BUF_SIZE: + pBtCoexist->bt_info.agg_buf_size = *pU1Tmp; + break; + + /* the following are some action which will be triggered */ + case BTC_SET_ACT_GET_BT_RSSI: + ret = false; + break; + + case BTC_SET_ACT_AGGREGATE_CTRL: + halbtcoutsrc_AggregationCheck(pBtCoexist); + break; + + /* =======1Ant=========== */ + /* set some u8 type variables. */ + case BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE: + pBtCoexist->bt_info.rssi_adjust_for_1ant_coex_type = *pU1Tmp; + break; + + case BTC_SET_U1_LPS_VAL: + pBtCoexist->bt_info.lps_val = *pU1Tmp; + break; + + case BTC_SET_U1_RPWM_VAL: + pBtCoexist->bt_info.rpwm_val = *pU1Tmp; + break; + + /* the following are some action which will be triggered */ + case BTC_SET_ACT_LEAVE_LPS: + halbtcoutsrc_LeaveLps(pBtCoexist); + break; + + case BTC_SET_ACT_ENTER_LPS: + halbtcoutsrc_EnterLps(pBtCoexist); + break; + + case BTC_SET_ACT_NORMAL_LPS: + halbtcoutsrc_NormalLps(pBtCoexist); + break; + + case BTC_SET_ACT_DISABLE_LOW_POWER: + halbtcoutsrc_DisableLowPower(pBtCoexist, *pu8); + break; + + case BTC_SET_ACT_UPDATE_RAMASK: + pBtCoexist->bt_info.ra_mask = *pU4Tmp; + + if (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE) == true) { + struct sta_info *psta; + PWLAN_BSSID_EX cur_network; + + cur_network = &padapter->mlmeextpriv.mlmext_info.network; + psta = rtw_get_stainfo(&padapter->stapriv, cur_network->MacAddress); + rtw_hal_update_ra_mask(psta, psta->rssi_level, false); + } + break; + + case BTC_SET_ACT_SEND_MIMO_PS: { + u8 newMimoPsMode = 3; + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + /* *pU1Tmp = 0 use SM_PS static type */ + /* *pU1Tmp = 1 disable SM_PS */ + if (*pU1Tmp == 0) + newMimoPsMode = WLAN_HT_CAP_SM_PS_STATIC; + else if (*pU1Tmp == 1) + newMimoPsMode = WLAN_HT_CAP_SM_PS_DISABLED; + + if (check_fwstate(&padapter->mlmepriv , WIFI_ASOC_STATE) == true) { + /* issue_action_SM_PS(padapter, get_my_bssid(&(pmlmeinfo->network)), newMimoPsMode); */ + issue_action_SM_PS_wait_ack(padapter , get_my_bssid(&(pmlmeinfo->network)) , newMimoPsMode, 3 , 1); + } + } + break; + + case BTC_SET_ACT_CTRL_BT_INFO: +#ifdef CONFIG_BT_COEXIST_SOCKET_TRX + { + u8 dataLen = *pU1Tmp; + u8 tmpBuf[BTC_TMP_BUF_SHORT]; + if (dataLen) + memcpy(tmpBuf, pU1Tmp + 1, dataLen); + BT_SendEventExtBtInfoControl(padapter, dataLen, &tmpBuf[0]); + } +#else /* !CONFIG_BT_COEXIST_SOCKET_TRX */ + ret = false; +#endif /* CONFIG_BT_COEXIST_SOCKET_TRX */ + break; + + case BTC_SET_ACT_CTRL_BT_COEX: +#ifdef CONFIG_BT_COEXIST_SOCKET_TRX + { + u8 dataLen = *pU1Tmp; + u8 tmpBuf[BTC_TMP_BUF_SHORT]; + if (dataLen) + memcpy(tmpBuf, pU1Tmp + 1, dataLen); + BT_SendEventExtBtCoexControl(padapter, false, dataLen, &tmpBuf[0]); + } +#else /* !CONFIG_BT_COEXIST_SOCKET_TRX */ + ret = false; +#endif /* CONFIG_BT_COEXIST_SOCKET_TRX */ + break; + case BTC_SET_ACT_CTRL_8723B_ANT: + ret = false; + break; + /* ===================== */ + default: + ret = false; + break; + } + + return ret; +} + +u8 halbtcoutsrc_UnderIps(PBTC_COEXIST pBtCoexist) +{ + PADAPTER padapter; + struct pwrctrl_priv *pwrpriv; + u8 bMacPwrCtrlOn; + + padapter = pBtCoexist->Adapter; + pwrpriv = &padapter->dvobj->pwrctl_priv; + bMacPwrCtrlOn = false; + + if ((pwrpriv->bips_processing) + && (IPS_NONE != pwrpriv->ips_mode_req) + ) + return true; + + if (rf_off == pwrpriv->rf_pwrstate) + return true; + + rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + if (false == bMacPwrCtrlOn) + return true; + + return false; +} + +u8 halbtcoutsrc_UnderLps(PBTC_COEXIST pBtCoexist) +{ + return GLBtcWiFiInLPS; +} + +u8 halbtcoutsrc_Under32K(PBTC_COEXIST pBtCoexist) +{ + /* todo: the method to check whether wifi is under 32K or not */ + return false; +} + +void halbtcoutsrc_DisplayCoexStatistics(PBTC_COEXIST pBtCoexist) +{ + PADAPTER padapter = pBtCoexist->Adapter; + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + u8 *cliBuf = pBtCoexist->cli_buf; + + if (pHalData->EEPROMBluetoothCoexist == 1) { + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Coex Status]============"); + CL_PRINTF(cliBuf); + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "IsBtDisabled", rtw_btcoex_IsBtDisabled(padapter)); + CL_PRINTF(cliBuf); + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "IsBtControlLps", rtw_btcoex_IsBtControlLps(padapter)); + CL_PRINTF(cliBuf); + } +} + +void halbtcoutsrc_DisplayBtLinkInfo(PBTC_COEXIST pBtCoexist) +{ +} + +void halbtcoutsrc_DisplayWifiStatus(PBTC_COEXIST pBtCoexist) +{ + PADAPTER padapter = pBtCoexist->Adapter; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); + u8 *cliBuf = pBtCoexist->cli_buf; + s32 wifiRssi = 0, btHsRssi = 0; + bool bScan = false, bLink = false, bRoam = false, bWifiBusy = false, bWifiUnderBMode = false; + u32 wifiBw = BTC_WIFI_BW_HT20, wifiTrafficDir = BTC_WIFI_TRAFFIC_TX, wifiFreq = BTC_FREQ_2_4G; + u32 wifiLinkStatus = 0x0; + bool bBtHsOn = false, bLowPower = false; + u8 wifiChnl = 0, wifiP2PChnl = 0, nScanAPNum = 0, FwPSState; + u32 iqk_cnt_total = 0, iqk_cnt_ok = 0, iqk_cnt_fail = 0; + + wifiLinkStatus = halbtcoutsrc_GetWifiLinkStatus(pBtCoexist); + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d/ %d/ %d/ %d/ %d", "STA/vWifi/HS/p2pGo/p2pGc", \ + ((wifiLinkStatus & WIFI_STA_CONNECTED) ? 1 : 0), ((wifiLinkStatus & WIFI_AP_CONNECTED) ? 1 : 0), + ((wifiLinkStatus & WIFI_HS_CONNECTED) ? 1 : 0), ((wifiLinkStatus & WIFI_P2P_GO_CONNECTED) ? 1 : 0), + ((wifiLinkStatus & WIFI_P2P_GC_CONNECTED) ? 1 : 0)); + CL_PRINTF(cliBuf); + + pBtCoexist->btc_get(pBtCoexist, BTC_GET_BL_WIFI_SCAN, &bScan); + pBtCoexist->btc_get(pBtCoexist, BTC_GET_BL_WIFI_LINK, &bLink); + pBtCoexist->btc_get(pBtCoexist, BTC_GET_BL_WIFI_ROAM, &bRoam); + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d/ %d/ %d ", "Link/ Roam/ Scan", \ + bLink, bRoam, bScan); + CL_PRINTF(cliBuf); + + pBtCoexist->btc_get(pBtCoexist, BTC_GET_U4_WIFI_IQK_TOTAL, &iqk_cnt_total); + pBtCoexist->btc_get(pBtCoexist, BTC_GET_U4_WIFI_IQK_OK, &iqk_cnt_ok); + pBtCoexist->btc_get(pBtCoexist, BTC_GET_U4_WIFI_IQK_FAIL, &iqk_cnt_fail); + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d/ %d/ %d %s %s", + "IQK All/ OK/ Fail/AutoLoad/FWDL", iqk_cnt_total, iqk_cnt_ok, iqk_cnt_fail, + ((halbtcoutsrc_is_autoload_fail(pBtCoexist) == true) ? "fail":"ok"), ((halbtcoutsrc_is_fw_ready(pBtCoexist) == true) ? "ok":"fail")); + CL_PRINTF(cliBuf); + + if (wifiLinkStatus & WIFI_STA_CONNECTED) { + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s", "IOT Peer", GLBtcIotPeerString[padapter->mlmeextpriv.mlmext_info.assoc_AP_vendor]); + CL_PRINTF(cliBuf); + } + + pBtCoexist->btc_get(pBtCoexist, BTC_GET_S4_WIFI_RSSI, &wifiRssi); + pBtCoexist->btc_get(pBtCoexist, BTC_GET_U1_WIFI_DOT11_CHNL, &wifiChnl); + if ((wifiLinkStatus & WIFI_P2P_GO_CONNECTED) || (wifiLinkStatus & WIFI_P2P_GC_CONNECTED)) + pBtCoexist->btc_get(pBtCoexist, BTC_GET_U1_WIFI_P2P_CHNL, &wifiP2PChnl); + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d dBm/ %d/ %d", "RSSI/ STA_Chnl/ P2P_Chnl", \ + wifiRssi -100, wifiChnl, wifiP2PChnl); + CL_PRINTF(cliBuf); + + pBtCoexist->btc_get(pBtCoexist, BTC_GET_BL_WIFI_UNDER_5G, &wifiFreq); + pBtCoexist->btc_get(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw); + pBtCoexist->btc_get(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy); + pBtCoexist->btc_get(pBtCoexist, BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, &wifiTrafficDir); + pBtCoexist->btc_get(pBtCoexist, BTC_GET_BL_WIFI_UNDER_B_MODE, &bWifiUnderBMode); + pBtCoexist->btc_get(pBtCoexist, BTC_GET_U1_AP_NUM, &nScanAPNum); + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s / %s/ %s/ %d ", "Band/ BW/ Traffic/ APCnt", \ + GLBtcWifiFreqString[wifiFreq], ((bWifiUnderBMode) ? "11b" : GLBtcWifiBwString[wifiBw]), + ((!bWifiBusy) ? "idle" : ((BTC_WIFI_TRAFFIC_TX == wifiTrafficDir) ? "uplink" : "downlink")), + nScanAPNum); + CL_PRINTF(cliBuf); + + /* power status */ + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s%s%s", "Power Status", \ + ((halbtcoutsrc_UnderIps(pBtCoexist) == true) ? "IPS ON" : "IPS OFF"), + ((halbtcoutsrc_UnderLps(pBtCoexist) == true) ? ", LPS ON" : ", LPS OFF"), + ((halbtcoutsrc_Under32K(pBtCoexist) == true) ? ", 32k" : "")); + CL_PRINTF(cliBuf); + + CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %02x %02x %02x %02x %02x %02x (0x%x/0x%x)", "Power mode cmd(lps/rpwm)", \ + pBtCoexist->pwrModeVal[0], pBtCoexist->pwrModeVal[1], + pBtCoexist->pwrModeVal[2], pBtCoexist->pwrModeVal[3], + pBtCoexist->pwrModeVal[4], pBtCoexist->pwrModeVal[5], + pBtCoexist->bt_info.lps_val, + pBtCoexist->bt_info.rpwm_val); + CL_PRINTF(cliBuf); +} + +void halbtcoutsrc_DisplayDbgMsg(void *pBtcContext, u8 dispType) +{ + PBTC_COEXIST pBtCoexist; + + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + switch (dispType) { + case BTC_DBG_DISP_COEX_STATISTICS: + halbtcoutsrc_DisplayCoexStatistics(pBtCoexist); + break; + case BTC_DBG_DISP_BT_LINK_INFO: + halbtcoutsrc_DisplayBtLinkInfo(pBtCoexist); + break; + case BTC_DBG_DISP_WIFI_STATUS: + halbtcoutsrc_DisplayWifiStatus(pBtCoexist); + break; + default: + break; + } +} + +/* ************************************ + * IO related function + * ************************************ */ +u8 halbtcoutsrc_Read1Byte(void *pBtcContext, u32 RegAddr) +{ + PBTC_COEXIST pBtCoexist; + PADAPTER padapter; + + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + padapter = pBtCoexist->Adapter; + + return rtw_read8(padapter, RegAddr); +} + +u16 halbtcoutsrc_Read2Byte(void *pBtcContext, u32 RegAddr) +{ + PBTC_COEXIST pBtCoexist; + PADAPTER padapter; + + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + padapter = pBtCoexist->Adapter; + + return rtw_read16(padapter, RegAddr); +} + +u32 halbtcoutsrc_Read4Byte(void *pBtcContext, u32 RegAddr) +{ + PBTC_COEXIST pBtCoexist; + PADAPTER padapter; + + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + padapter = pBtCoexist->Adapter; + + return rtw_read32(padapter, RegAddr); +} + +void halbtcoutsrc_Write1Byte(void *pBtcContext, u32 RegAddr, u8 Data) +{ + PBTC_COEXIST pBtCoexist; + PADAPTER padapter; + + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + padapter = pBtCoexist->Adapter; + + rtw_write8(padapter, RegAddr, Data); +} + +void halbtcoutsrc_BitMaskWrite1Byte(void *pBtcContext, u32 regAddr, u8 bitMask, u8 data1b) +{ + PBTC_COEXIST pBtCoexist; + PADAPTER padapter; + u8 originalValue, bitShift; + u8 i; + + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + padapter = pBtCoexist->Adapter; + originalValue = 0; + bitShift = 0; + + if (bitMask != 0xff) { + originalValue = rtw_read8(padapter, regAddr); + + for (i = 0; i <= 7; i++) { + if ((bitMask >> i) & 0x1) + break; + } + bitShift = i; + + data1b = (originalValue & ~bitMask) | ((data1b << bitShift) & bitMask); + } + + rtw_write8(padapter, regAddr, data1b); +} + +void halbtcoutsrc_Write2Byte(void *pBtcContext, u32 RegAddr, u16 Data) +{ + PBTC_COEXIST pBtCoexist; + PADAPTER padapter; + + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + padapter = pBtCoexist->Adapter; + + rtw_write16(padapter, RegAddr, Data); +} + +void halbtcoutsrc_Write4Byte(void *pBtcContext, u32 RegAddr, u32 Data) +{ + PBTC_COEXIST pBtCoexist; + PADAPTER padapter; + + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + padapter = pBtCoexist->Adapter; + + rtw_write32(padapter, RegAddr, Data); +} + +void halbtcoutsrc_WriteLocalReg1Byte(void *pBtcContext, u32 RegAddr, u8 Data) +{ + PBTC_COEXIST pBtCoexist = (PBTC_COEXIST)pBtcContext; + PADAPTER Adapter = pBtCoexist->Adapter; + + if (BTC_INTF_SDIO == pBtCoexist->chip_interface) + rtw_write8(Adapter, SDIO_LOCAL_BASE | RegAddr, Data); + else + rtw_write8(Adapter, RegAddr, Data); +} + +void halbtcoutsrc_SetBbReg(void *pBtcContext, u32 RegAddr, u32 BitMask, u32 Data) +{ + PBTC_COEXIST pBtCoexist; + PADAPTER padapter; + + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + padapter = pBtCoexist->Adapter; + + phy_set_bb_reg(padapter, RegAddr, BitMask, Data); +} + + +u32 halbtcoutsrc_GetBbReg(void *pBtcContext, u32 RegAddr, u32 BitMask) +{ + PBTC_COEXIST pBtCoexist; + PADAPTER padapter; + + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + padapter = pBtCoexist->Adapter; + + return phy_query_bb_reg(padapter, RegAddr, BitMask); +} + +void halbtcoutsrc_SetRfReg(void *pBtcContext, u8 eRFPath, u32 RegAddr, u32 BitMask, u32 Data) +{ + PBTC_COEXIST pBtCoexist; + PADAPTER padapter; + + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + padapter = pBtCoexist->Adapter; + + phy_set_rf_reg(padapter, eRFPath, RegAddr, BitMask, Data); +} + +u32 halbtcoutsrc_GetRfReg(void *pBtcContext, u8 eRFPath, u32 RegAddr, u32 BitMask) +{ + PBTC_COEXIST pBtCoexist; + PADAPTER padapter; + + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + padapter = pBtCoexist->Adapter; + + return phy_query_rf_reg(padapter, eRFPath, RegAddr, BitMask); +} + +u16 halbtcoutsrc_SetBtReg(void *pBtcContext, u8 RegType, u32 RegAddr, u32 Data) +{ + PBTC_COEXIST pBtCoexist; + u16 ret = BT_STATUS_BT_OP_SUCCESS; + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + + if (halbtcoutsrc_IsHwMailboxExist(pBtCoexist) == true) { + u8 buf[3] = {0}; + unsigned long irqL; + u8 op_code; + u8 status; + + _enter_critical_mutex(&GLBtcBtMpOperLock, &irqL); + + Data = cpu_to_le32(Data); + op_code = BT_OP_WRITE_REG_VALUE; + status = _btmpoper_cmd(pBtCoexist, op_code, 0, (u8 *)&Data, 3); + if (status != BT_STATUS_BT_OP_SUCCESS) + ret = SET_BT_MP_OPER_RET(op_code, status); + else { + buf[0] = RegType; + *(u16 *)(buf + 1) = cpu_to_le16((u16)RegAddr); + op_code = BT_OP_WRITE_REG_ADDR; + status = _btmpoper_cmd(pBtCoexist, op_code, 0, buf, 3); + if (status != BT_STATUS_BT_OP_SUCCESS) + ret = SET_BT_MP_OPER_RET(op_code, status); + } + + _exit_critical_mutex(&GLBtcBtMpOperLock, &irqL); + } else + ret = BT_STATUS_NOT_IMPLEMENT; + + return ret; +} + +u8 halbtcoutsrc_SetBtAntDetection(void *pBtcContext, u8 txTime, u8 btChnl) +{ + /* Always return false since we don't implement this yet */ + return false; +} + +bool +halbtcoutsrc_SetBtTRXMASK( + IN void * pBtcContext, + IN u8 bt_trx_mask + ) +{ + /* Always return false since we don't implement this yet */ + return false; +} + +u16 halbtcoutsrc_GetBtReg_with_status(void *pBtcContext, u8 RegType, u32 RegAddr, u32 *data) +{ + PBTC_COEXIST pBtCoexist; + u16 ret = BT_STATUS_BT_OP_SUCCESS; + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + + if (halbtcoutsrc_IsHwMailboxExist(pBtCoexist) == true) { + u8 buf[3] = {0}; + unsigned long irqL; + u8 op_code; + u8 status; + + buf[0] = RegType; + *(u16 *)(buf + 1) = cpu_to_le16((u16)RegAddr); + + _enter_critical_mutex(&GLBtcBtMpOperLock, &irqL); + + op_code = BT_OP_READ_REG; + status = _btmpoper_cmd(pBtCoexist, op_code, 0, buf, 3); + if (status == BT_STATUS_BT_OP_SUCCESS) + *data = le16_to_cpu(*(u16 *)GLBtcBtMpRptRsp); + else + ret = SET_BT_MP_OPER_RET(op_code, status); + + _exit_critical_mutex(&GLBtcBtMpOperLock, &irqL); + + } else + ret = BT_STATUS_NOT_IMPLEMENT; + + return ret; +} + +u32 halbtcoutsrc_GetBtReg(void *pBtcContext, u8 RegType, u32 RegAddr) +{ + u32 regVal; + + return (BT_STATUS_BT_OP_SUCCESS == halbtcoutsrc_GetBtReg_with_status(pBtcContext, RegType, RegAddr, ®Val)) ? regVal : 0xffffffff; +} + +void halbtcoutsrc_FillH2cCmd(void *pBtcContext, u8 elementId, u32 cmdLen, u8 *pCmdBuffer) +{ + PBTC_COEXIST pBtCoexist; + PADAPTER padapter; + + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + padapter = pBtCoexist->Adapter; + + rtw_hal_fill_h2c_cmd(padapter, elementId, cmdLen, pCmdBuffer); +} + +static void halbtcoutsrc_coex_offload_init(void) +{ + u8 i; + + gl_coex_offload.h2c_req_num = 0; + gl_coex_offload.cnt_h2c_sent = 0; + gl_coex_offload.cnt_c2h_ack = 0; + gl_coex_offload.cnt_c2h_ind = 0; + + for (i = 0; i < COL_MAX_H2C_REQ_NUM; i++) + init_completion(&gl_coex_offload.c2h_event[i]); +} + +static COL_H2C_STATUS halbtcoutsrc_send_h2c(PADAPTER Adapter, PCOL_H2C pcol_h2c, u16 h2c_cmd_len) +{ + COL_H2C_STATUS h2c_status = COL_STATUS_C2H_OK; + u8 i; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) + reinit_completion(&gl_coex_offload.c2h_event[pcol_h2c->req_num]); /* set event to un signaled state */ +#else + INIT_COMPLETION(gl_coex_offload.c2h_event[pcol_h2c->req_num]); +#endif + + return h2c_status; +} + +static COL_H2C_STATUS halbtcoutsrc_check_c2h_ack(PADAPTER Adapter, PCOL_SINGLE_H2C_RECORD pH2cRecord) +{ + COL_H2C_STATUS c2h_status = COL_STATUS_C2H_OK; + PCOL_H2C p_h2c_cmd = (PCOL_H2C)&pH2cRecord->h2c_buf[0]; + u8 req_num = p_h2c_cmd->req_num; + PCOL_C2H_ACK p_c2h_ack = (PCOL_C2H_ACK)&gl_coex_offload.c2h_ack_buf[req_num]; + + + if ((COL_C2H_ACK_HDR_LEN + p_c2h_ack->ret_len) > gl_coex_offload.c2h_ack_len[req_num]) { + c2h_status = COL_STATUS_COEX_DATA_OVERFLOW; + return c2h_status; + } + /* else */ + { + memmove(&pH2cRecord->c2h_ack_buf[0], &gl_coex_offload.c2h_ack_buf[req_num], gl_coex_offload.c2h_ack_len[req_num]); + pH2cRecord->c2h_ack_len = gl_coex_offload.c2h_ack_len[req_num]; + } + + + if (p_c2h_ack->req_num != p_h2c_cmd->req_num) { + c2h_status = COL_STATUS_C2H_REQ_NUM_MISMATCH; + } else if (p_c2h_ack->opcode_ver != p_h2c_cmd->opcode_ver) { + c2h_status = COL_STATUS_C2H_OPCODE_VER_MISMATCH; + } else { + c2h_status = p_c2h_ack->status; + } + + return c2h_status; +} + +COL_H2C_STATUS halbtcoutsrc_CoexH2cProcess(void *pBtCoexist, + u8 opcode, u8 opcode_ver, u8 *ph2c_par, u8 h2c_par_len) +{ + PADAPTER Adapter = ((struct btc_coexist *)pBtCoexist)->Adapter; + u8 H2C_Parameter[BTC_TMP_BUF_SHORT] = {0}; + PCOL_H2C pcol_h2c = (PCOL_H2C)&H2C_Parameter[0]; + u16 paraLen = 0; + COL_H2C_STATUS h2c_status = COL_STATUS_C2H_OK, c2h_status = COL_STATUS_C2H_OK; + COL_H2C_STATUS ret_status = COL_STATUS_C2H_OK; + u16 i, col_h2c_len = 0; + + pcol_h2c->opcode = opcode; + pcol_h2c->opcode_ver = opcode_ver; + pcol_h2c->req_num = gl_coex_offload.h2c_req_num; + gl_coex_offload.h2c_req_num++; + gl_coex_offload.h2c_req_num %= 16; + + memmove(&pcol_h2c->buf[0], ph2c_par, h2c_par_len); + + + col_h2c_len = h2c_par_len + 2; /* 2=sizeof(OPCode, OPCode_version and Request number) */ + BT_PrintData(Adapter, "[COL], H2C cmd: ", col_h2c_len, H2C_Parameter); + + gl_coex_offload.cnt_h2c_sent++; + + gl_coex_offload.h2c_record[opcode].count++; + gl_coex_offload.h2c_record[opcode].h2c_len = col_h2c_len; + memmove((void *)&gl_coex_offload.h2c_record[opcode].h2c_buf[0], (void *)pcol_h2c, col_h2c_len); + + h2c_status = halbtcoutsrc_send_h2c(Adapter, pcol_h2c, col_h2c_len); + + gl_coex_offload.h2c_record[opcode].c2h_ack_len = 0; + + if (COL_STATUS_C2H_OK == h2c_status) { + /* if reach here, it means H2C get the correct c2h response, */ + c2h_status = halbtcoutsrc_check_c2h_ack(Adapter, &gl_coex_offload.h2c_record[opcode]); + ret_status = c2h_status; + } else { + /* check h2c status error, return error status code to upper layer. */ + ret_status = h2c_status; + } + gl_coex_offload.h2c_record[opcode].status[ret_status]++; + gl_coex_offload.status[ret_status]++; + + return ret_status; +} + +u8 halbtcoutsrc_GetAntDetValFromBt(void *pBtcContext) +{ + /* Always return 0 since we don't implement this yet */ + return 0; +} + +u8 halbtcoutsrc_GetBleScanTypeFromBt(void *pBtcContext) +{ + PBTC_COEXIST pBtCoexist; + u32 ret = BT_STATUS_BT_OP_SUCCESS; + u8 data = 0; + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + + if (halbtcoutsrc_IsHwMailboxExist(pBtCoexist) == true) { + u8 buf[3] = {0}; + unsigned long irqL; + u8 op_code; + u8 status; + + + _enter_critical_mutex(&GLBtcBtMpOperLock, &irqL); + + op_code = BT_OP_GET_BT_BLE_SCAN_TYPE; + status = _btmpoper_cmd(pBtCoexist, op_code, 0, buf, 0); + if (status == BT_STATUS_BT_OP_SUCCESS) + data = *(u8 *)GLBtcBtMpRptRsp; + else + ret = SET_BT_MP_OPER_RET(op_code, status); + + _exit_critical_mutex(&GLBtcBtMpOperLock, &irqL); + + } else + ret = BT_STATUS_NOT_IMPLEMENT; + + return data; +} + +u32 halbtcoutsrc_GetBleScanParaFromBt(void *pBtcContext, u8 scanType) +{ + PBTC_COEXIST pBtCoexist; + u32 ret = BT_STATUS_BT_OP_SUCCESS; + u32 data = 0; + + pBtCoexist = (PBTC_COEXIST)pBtcContext; + + if (halbtcoutsrc_IsHwMailboxExist(pBtCoexist) == true) { + u8 buf[3] = {0}; + unsigned long irqL; + u8 op_code; + u8 status; + + + _enter_critical_mutex(&GLBtcBtMpOperLock, &irqL); + + op_code = BT_OP_GET_BT_BLE_SCAN_PARA; + status = _btmpoper_cmd(pBtCoexist, op_code, 0, buf, 0); + if (status == BT_STATUS_BT_OP_SUCCESS) + data = le32_to_cpu(*(u32 *)GLBtcBtMpRptRsp); + else + ret = SET_BT_MP_OPER_RET(op_code, status); + + _exit_critical_mutex(&GLBtcBtMpOperLock, &irqL); + + } else + ret = BT_STATUS_NOT_IMPLEMENT; + + return data; +} + +u8 halbtcoutsrc_GetBtAFHMapFromBt(void *pBtcContext, u8 mapType, u8 *afhMap) +{ + struct btc_coexist *pBtCoexist = (struct btc_coexist *)pBtcContext; + u8 buf[2] = {0}; + unsigned long irqL; + u8 op_code; + u32 *AfhMapL = (u32 *)&(afhMap[0]); + u32 *AfhMapM = (u32 *)&(afhMap[4]); + u16 *AfhMapH = (u16 *)&(afhMap[8]); + u8 status; + u32 ret = BT_STATUS_BT_OP_SUCCESS; + + if (halbtcoutsrc_IsHwMailboxExist(pBtCoexist) == false) + return false; + + buf[0] = 0; + buf[1] = mapType; + + _enter_critical_mutex(&GLBtcBtMpOperLock, &irqL); + + op_code = BT_LO_OP_GET_AFH_MAP_L; + status = _btmpoper_cmd(pBtCoexist, op_code, 0, buf, 0); + if (status == BT_STATUS_BT_OP_SUCCESS) + *AfhMapL = le32_to_cpu(*(u32 *)GLBtcBtMpRptRsp); + else { + ret = SET_BT_MP_OPER_RET(op_code, status); + goto exit; + } + + op_code = BT_LO_OP_GET_AFH_MAP_M; + status = _btmpoper_cmd(pBtCoexist, op_code, 0, buf, 0); + if (status == BT_STATUS_BT_OP_SUCCESS) + *AfhMapM = le32_to_cpu(*(u32 *)GLBtcBtMpRptRsp); + else { + ret = SET_BT_MP_OPER_RET(op_code, status); + goto exit; + } + + op_code = BT_LO_OP_GET_AFH_MAP_H; + status = _btmpoper_cmd(pBtCoexist, op_code, 0, buf, 0); + if (status == BT_STATUS_BT_OP_SUCCESS) + *AfhMapH = le16_to_cpu(*(u16 *)GLBtcBtMpRptRsp); + else { + ret = SET_BT_MP_OPER_RET(op_code, status); + goto exit; + } + +exit: + + _exit_critical_mutex(&GLBtcBtMpOperLock, &irqL); + + return (ret == BT_STATUS_BT_OP_SUCCESS) ? true : false; +} + +u32 halbtcoutsrc_GetPhydmVersion(void *pBtcContext) +{ + struct btc_coexist *pBtCoexist = (struct btc_coexist *)pBtcContext; + PADAPTER Adapter = pBtCoexist->Adapter; +} + +void halbtcoutsrc_phydm_modify_RA_PCR_threshold(void *pBtcContext, u8 RA_offset_direction, u8 RA_threshold_offset) +{ + struct btc_coexist *pBtCoexist = (struct btc_coexist *)pBtcContext; + +/* switch to #if 0 in case the phydm version does not provide the function */ + phydm_modify_RA_PCR_threshold(pBtCoexist->odm_priv, RA_offset_direction, RA_threshold_offset); +} + +u32 halbtcoutsrc_phydm_query_PHY_counter(void *pBtcContext, u8 info_type) +{ + struct btc_coexist *pBtCoexist = (struct btc_coexist *)pBtcContext; + +/* switch to #if 0 in case the phydm version does not provide the function */ + return phydm_cmn_info_query((struct PHY_DM_STRUCT *)pBtCoexist->odm_priv, (enum phydm_info_query_e)info_type); +} + +/* ************************************ + * Extern functions called by other module + * ************************************ */ +u8 EXhalbtcoutsrc_BindBtCoexWithAdapter(void *padapter) +{ + PBTC_COEXIST pBtCoexist = &GLBtCoexist; + u8 antNum = 1, chipType = 0, singleAntPath = 0; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA((PADAPTER)padapter); + + if (pBtCoexist->bBinded) + return false; + else + pBtCoexist->bBinded = true; + + pBtCoexist->statistics.cnt_bind++; + + pBtCoexist->Adapter = padapter; + pBtCoexist->odm_priv = (void *)&(pHalData->odmpriv); + + pBtCoexist->stack_info.profile_notified = false; + + pBtCoexist->bt_info.bt_ctrl_agg_buf_size = false; + pBtCoexist->bt_info.agg_buf_size = 5; + + pBtCoexist->bt_info.increase_scan_dev_num = false; + pBtCoexist->bt_info.miracast_plus_bt = false; + + antNum = rtw_btcoex_get_pg_ant_num((PADAPTER)padapter); + EXhalbtcoutsrc_SetAntNum(BT_COEX_ANT_TYPE_PG, antNum); + + if (antNum == 1) { + singleAntPath = rtw_btcoex_get_pg_single_ant_path((PADAPTER)padapter); + EXhalbtcoutsrc_SetSingleAntPath(singleAntPath); + } + + /* set default antenna position to main port */ + pBtCoexist->board_info.btdm_ant_pos = BTC_ANTENNA_AT_MAIN_PORT; + + pBtCoexist->board_info.btdm_ant_det_finish = false; + pBtCoexist->board_info.btdm_ant_num_by_ant_det = 1; + + pBtCoexist->board_info.tfbga_package = rtw_btcoex_is_tfbga_package_type((PADAPTER)padapter); + + pBtCoexist->board_info.rfe_type = rtw_btcoex_get_pg_rfe_type((PADAPTER)padapter); + + pBtCoexist->board_info.ant_div_cfg = rtw_btcoex_get_ant_div_cfg((PADAPTER)padapter); + + return true; +} + +u8 EXhalbtcoutsrc_InitlizeVariables(void *padapter) +{ + PBTC_COEXIST pBtCoexist = &GLBtCoexist; + + /* pBtCoexist->statistics.cntBind++; */ + + halbtcoutsrc_DbgInit(); + + halbtcoutsrc_coex_offload_init(); + + pBtCoexist->chip_interface = BTC_INTF_USB; + + EXhalbtcoutsrc_BindBtCoexWithAdapter(padapter); + + pBtCoexist->btc_read_1byte = halbtcoutsrc_Read1Byte; + pBtCoexist->btc_write_1byte = halbtcoutsrc_Write1Byte; + pBtCoexist->btc_write_1byte_bitmask = halbtcoutsrc_BitMaskWrite1Byte; + pBtCoexist->btc_read_2byte = halbtcoutsrc_Read2Byte; + pBtCoexist->btc_write_2byte = halbtcoutsrc_Write2Byte; + pBtCoexist->btc_read_4byte = halbtcoutsrc_Read4Byte; + pBtCoexist->btc_write_4byte = halbtcoutsrc_Write4Byte; + pBtCoexist->btc_write_local_reg_1byte = halbtcoutsrc_WriteLocalReg1Byte; + + pBtCoexist->btc_set_bb_reg = halbtcoutsrc_SetBbReg; + pBtCoexist->btc_get_bb_reg = halbtcoutsrc_GetBbReg; + + pBtCoexist->btc_set_rf_reg = halbtcoutsrc_SetRfReg; + pBtCoexist->btc_get_rf_reg = halbtcoutsrc_GetRfReg; + + pBtCoexist->btc_fill_h2c = halbtcoutsrc_FillH2cCmd; + pBtCoexist->btc_disp_dbg_msg = halbtcoutsrc_DisplayDbgMsg; + + pBtCoexist->btc_get = halbtcoutsrc_Get; + pBtCoexist->btc_set = halbtcoutsrc_Set; + pBtCoexist->btc_get_bt_reg = halbtcoutsrc_GetBtReg; + pBtCoexist->btc_set_bt_reg = halbtcoutsrc_SetBtReg; + pBtCoexist->btc_set_bt_ant_detection = halbtcoutsrc_SetBtAntDetection; + pBtCoexist->btc_set_bt_trx_mask = halbtcoutsrc_SetBtTRXMASK; + pBtCoexist->btc_coex_h2c_process = halbtcoutsrc_CoexH2cProcess; + pBtCoexist->btc_get_bt_coex_supported_feature = halbtcoutsrc_GetBtCoexSupportedFeature; + pBtCoexist->btc_get_bt_coex_supported_version= halbtcoutsrc_GetBtCoexSupportedVersion; + pBtCoexist->btc_get_ant_det_val_from_bt = halbtcoutsrc_GetAntDetValFromBt; + pBtCoexist->btc_get_ble_scan_type_from_bt = halbtcoutsrc_GetBleScanTypeFromBt; + pBtCoexist->btc_get_ble_scan_para_from_bt = halbtcoutsrc_GetBleScanParaFromBt; + pBtCoexist->btc_get_bt_afh_map_from_bt = halbtcoutsrc_GetBtAFHMapFromBt; + pBtCoexist->btc_get_bt_phydm_version = halbtcoutsrc_GetPhydmVersion; + pBtCoexist->btc_phydm_modify_RA_PCR_threshold = halbtcoutsrc_phydm_modify_RA_PCR_threshold; + pBtCoexist->btc_phydm_query_PHY_counter = halbtcoutsrc_phydm_query_PHY_counter; + + pBtCoexist->cli_buf = &GLBtcDbgBuf[0]; + + GLBtcWiFiInScanState = false; + + GLBtcWiFiInIQKState = false; + + GLBtcWiFiInIPS = false; + + GLBtcWiFiInLPS = false; + + GLBtcBtCoexAliveRegistered = false; + + /* BT Control H2C/C2H*/ + GLBtcBtMpOperSeq = 0; + _rtw_mutex_init(&GLBtcBtMpOperLock); + _init_timer(&GLBtcBtMpOperTimer, ((PADAPTER)padapter)->pnetdev, _btmpoper_timer_hdl, pBtCoexist); + sema_init(&GLBtcBtMpRptSema, 0); + GLBtcBtMpRptSeq = 0; + GLBtcBtMpRptStatus = 0; + memset(GLBtcBtMpRptRsp, 0, C2H_MAX_SIZE); + GLBtcBtMpRptRspSize = 0; + GLBtcBtMpRptWait = 0; + GLBtcBtMpRptWiFiOK = 0; + GLBtcBtMpRptBTOK = 0; + + return true; +} + +void EXhalbtcoutsrc_PowerOnSetting(PBTC_COEXIST pBtCoexist) +{ + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + /* Power on setting function is only added in 8723B currently */ + if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723b2ant_power_on_setting(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_power_on_setting(pBtCoexist); + } + + if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723d2ant_power_on_setting(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723d1ant_power_on_setting(pBtCoexist); + } + + if (IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_power_on_setting(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8822b2ant_power_on_setting(pBtCoexist); + } + + if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_power_on_setting(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_power_on_setting(pBtCoexist); + } +} + +void EXhalbtcoutsrc_PreLoadFirmware(PBTC_COEXIST pBtCoexist) +{ + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + pBtCoexist->statistics.cnt_pre_load_firmware++; + + if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723b2ant_pre_load_firmware(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_pre_load_firmware(pBtCoexist); + } + + if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723d2ant_pre_load_firmware(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723d1ant_pre_load_firmware(pBtCoexist); + } + + if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_pre_load_firmware(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_pre_load_firmware(pBtCoexist); + } +} + +void EXhalbtcoutsrc_init_hw_config(PBTC_COEXIST pBtCoexist, u8 bWifiOnly) +{ + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + pBtCoexist->statistics.cnt_init_hw_config++; + + if (IS_HARDWARE_TYPE_8821(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821a2ant_init_hw_config(pBtCoexist, bWifiOnly); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821a1ant_init_hw_config(pBtCoexist, bWifiOnly); + } else if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723b2ant_init_hw_config(pBtCoexist, bWifiOnly); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_init_hw_config(pBtCoexist, bWifiOnly); + } else if (IS_HARDWARE_TYPE_8703B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8703b1ant_init_hw_config(pBtCoexist, bWifiOnly); + } else if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723d2ant_init_hw_config(pBtCoexist, bWifiOnly); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723d1ant_init_hw_config(pBtCoexist, bWifiOnly); + } else if (IS_HARDWARE_TYPE_8192E(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8192e2ant_init_hw_config(pBtCoexist, bWifiOnly); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8192e1ant_init_hw_config(pBtCoexist, bWifiOnly); + } else if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8812a2ant_init_hw_config(pBtCoexist, bWifiOnly); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8812a1ant_init_hw_config(pBtCoexist, bWifiOnly); + } else if (IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_init_hw_config(pBtCoexist, bWifiOnly); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8822b2ant_init_hw_config(pBtCoexist, bWifiOnly); + #ifdef CONFIG_FW_MULTI_PORT_SUPPORT + rtw_hal_set_default_port_id_cmd(pBtCoexist->Adapter, 0); + rtw_hal_set_wifi_port_id_cmd(pBtCoexist->Adapter); + #endif + } else if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_init_hw_config(pBtCoexist, bWifiOnly); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_init_hw_config(pBtCoexist, bWifiOnly); + #ifdef CONFIG_FW_MULTI_PORT_SUPPORT + rtw_hal_set_default_port_id_cmd(pBtCoexist->Adapter, 0); + rtw_hal_set_wifi_port_id_cmd(pBtCoexist->Adapter); + #endif + } +} + +void EXhalbtcoutsrc_init_coex_dm(PBTC_COEXIST pBtCoexist) +{ + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + pBtCoexist->statistics.cnt_init_coex_dm++; + + if (IS_HARDWARE_TYPE_8821(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821a2ant_init_coex_dm(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821a1ant_init_coex_dm(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723b2ant_init_coex_dm(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_init_coex_dm(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8703B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8703b1ant_init_coex_dm(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723d2ant_init_coex_dm(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723d1ant_init_coex_dm(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8192E(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8192e2ant_init_coex_dm(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8192e1ant_init_coex_dm(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8812a2ant_init_coex_dm(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8812a1ant_init_coex_dm(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_init_coex_dm(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8822b2ant_init_coex_dm(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_init_coex_dm(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_init_coex_dm(pBtCoexist); + } + + pBtCoexist->initilized = true; +} + +void EXhalbtcoutsrc_ips_notify(PBTC_COEXIST pBtCoexist, u8 type) +{ + u8 ipsType; + + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + pBtCoexist->statistics.cnt_ips_notify++; + if (pBtCoexist->manual_control) + return; + + if (IPS_NONE == type) { + ipsType = BTC_IPS_LEAVE; + GLBtcWiFiInIPS = false; + } else { + ipsType = BTC_IPS_ENTER; + GLBtcWiFiInIPS = true; + } + + /* All notify is called in cmd thread, don't need to leave low power again + * halbtcoutsrc_LeaveLowPower(pBtCoexist); */ + + if (IS_HARDWARE_TYPE_8821(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821a2ant_ips_notify(pBtCoexist, ipsType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821a1ant_ips_notify(pBtCoexist, ipsType); + } else if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723b2ant_ips_notify(pBtCoexist, ipsType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_ips_notify(pBtCoexist, ipsType); + } else if (IS_HARDWARE_TYPE_8703B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8703b1ant_ips_notify(pBtCoexist, ipsType); + } else if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723d2ant_ips_notify(pBtCoexist, ipsType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723d1ant_ips_notify(pBtCoexist, ipsType); + } else if (IS_HARDWARE_TYPE_8192E(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8192e2ant_ips_notify(pBtCoexist, ipsType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8192e1ant_ips_notify(pBtCoexist, ipsType); + } else if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8812a2ant_ips_notify(pBtCoexist, ipsType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8812a1ant_ips_notify(pBtCoexist, ipsType); + } else if (IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_ips_notify(pBtCoexist, ipsType); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8822b2ant_ips_notify(pBtCoexist, ipsType); + } else if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_ips_notify(pBtCoexist, ipsType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_ips_notify(pBtCoexist, ipsType); + } + + /* halbtcoutsrc_NormalLowPower(pBtCoexist); */ +} + +void EXhalbtcoutsrc_lps_notify(PBTC_COEXIST pBtCoexist, u8 type) +{ + u8 lpsType; + + + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + pBtCoexist->statistics.cnt_lps_notify++; + if (pBtCoexist->manual_control) + return; + + if (PS_MODE_ACTIVE == type) { + lpsType = BTC_LPS_DISABLE; + GLBtcWiFiInLPS = false; + } else { + lpsType = BTC_LPS_ENABLE; + GLBtcWiFiInLPS = true; + } + + if (IS_HARDWARE_TYPE_8821(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821a2ant_lps_notify(pBtCoexist, lpsType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821a1ant_lps_notify(pBtCoexist, lpsType); + } else if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723b2ant_lps_notify(pBtCoexist, lpsType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_lps_notify(pBtCoexist, lpsType); + } else if (IS_HARDWARE_TYPE_8703B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8703b1ant_lps_notify(pBtCoexist, lpsType); + } else if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723d2ant_lps_notify(pBtCoexist, lpsType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723d1ant_lps_notify(pBtCoexist, lpsType); + } else if (IS_HARDWARE_TYPE_8192E(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8192e2ant_lps_notify(pBtCoexist, lpsType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8192e1ant_lps_notify(pBtCoexist, lpsType); + } else if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8812a2ant_lps_notify(pBtCoexist, lpsType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8812a1ant_lps_notify(pBtCoexist, lpsType); + } else if (IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_lps_notify(pBtCoexist, lpsType); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8822b2ant_lps_notify(pBtCoexist, lpsType); + } else if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_lps_notify(pBtCoexist, lpsType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_lps_notify(pBtCoexist, lpsType); + } +} + +void EXhalbtcoutsrc_scan_notify(PBTC_COEXIST pBtCoexist, u8 type) +{ + u8 scanType; + + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + pBtCoexist->statistics.cnt_scan_notify++; + if (pBtCoexist->manual_control) + return; + + if (type) { + scanType = BTC_SCAN_START; + GLBtcWiFiInScanState = true; + } else { + scanType = BTC_SCAN_FINISH; + GLBtcWiFiInScanState = false; + } + + /* All notify is called in cmd thread, don't need to leave low power again + * halbtcoutsrc_LeaveLowPower(pBtCoexist); */ + + if (IS_HARDWARE_TYPE_8821(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821a2ant_scan_notify(pBtCoexist, scanType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821a1ant_scan_notify(pBtCoexist, scanType); + } else if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723b2ant_scan_notify(pBtCoexist, scanType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_scan_notify(pBtCoexist, scanType); + } else if (IS_HARDWARE_TYPE_8703B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8703b1ant_scan_notify(pBtCoexist, scanType); + } else if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723d2ant_scan_notify(pBtCoexist, scanType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723d1ant_scan_notify(pBtCoexist, scanType); + } else if (IS_HARDWARE_TYPE_8192E(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8192e2ant_scan_notify(pBtCoexist, scanType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8192e1ant_scan_notify(pBtCoexist, scanType); + } else if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8812a2ant_scan_notify(pBtCoexist, scanType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8812a1ant_scan_notify(pBtCoexist, scanType); + } else if (IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_scan_notify(pBtCoexist, scanType); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8822b2ant_scan_notify(pBtCoexist, scanType); + } else if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_scan_notify(pBtCoexist, scanType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_scan_notify(pBtCoexist, scanType); + } + + /* halbtcoutsrc_NormalLowPower(pBtCoexist); */ +} + +void EXhalbtcoutsrc_SetAntennaPathNotify(PBTC_COEXIST pBtCoexist, u8 type) +{ +} + +void EXhalbtcoutsrc_connect_notify(PBTC_COEXIST pBtCoexist, u8 action) +{ + u8 assoType; + + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + pBtCoexist->statistics.cnt_connect_notify++; + if (pBtCoexist->manual_control) + return; + + if (action) + assoType = BTC_ASSOCIATE_START; + else + assoType = BTC_ASSOCIATE_FINISH; + + /* All notify is called in cmd thread, don't need to leave low power again + * halbtcoutsrc_LeaveLowPower(pBtCoexist); */ + + if (IS_HARDWARE_TYPE_8821(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821a2ant_connect_notify(pBtCoexist, assoType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821a1ant_connect_notify(pBtCoexist, assoType); + } else if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723b2ant_connect_notify(pBtCoexist, assoType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_connect_notify(pBtCoexist, assoType); + } else if (IS_HARDWARE_TYPE_8703B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8703b1ant_connect_notify(pBtCoexist, assoType); + } else if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723d2ant_connect_notify(pBtCoexist, assoType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723d1ant_connect_notify(pBtCoexist, assoType); + } else if (IS_HARDWARE_TYPE_8192E(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8192e2ant_connect_notify(pBtCoexist, assoType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8192e1ant_connect_notify(pBtCoexist, assoType); + } else if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8812a2ant_connect_notify(pBtCoexist, assoType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8812a1ant_connect_notify(pBtCoexist, assoType); + } else if (IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_connect_notify(pBtCoexist, assoType); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8822b2ant_connect_notify(pBtCoexist, assoType); + } else if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_connect_notify(pBtCoexist, assoType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_connect_notify(pBtCoexist, assoType); + } + + /* halbtcoutsrc_NormalLowPower(pBtCoexist); */ +} + +void EXhalbtcoutsrc_media_status_notify(PBTC_COEXIST pBtCoexist, RT_MEDIA_STATUS mediaStatus) +{ + u8 mStatus; + + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + pBtCoexist->statistics.cnt_media_status_notify++; + if (pBtCoexist->manual_control) + return; + + if (RT_MEDIA_CONNECT == mediaStatus) + mStatus = BTC_MEDIA_CONNECT; + else + mStatus = BTC_MEDIA_DISCONNECT; + + /* All notify is called in cmd thread, don't need to leave low power again + * halbtcoutsrc_LeaveLowPower(pBtCoexist); */ + + if (IS_HARDWARE_TYPE_8821(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821a2ant_media_status_notify(pBtCoexist, mStatus); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821a1ant_media_status_notify(pBtCoexist, mStatus); + } else if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723b2ant_media_status_notify(pBtCoexist, mStatus); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_media_status_notify(pBtCoexist, mStatus); + } else if (IS_HARDWARE_TYPE_8703B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8703b1ant_media_status_notify(pBtCoexist, mStatus); + } else if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723d2ant_media_status_notify(pBtCoexist, mStatus); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723d1ant_media_status_notify(pBtCoexist, mStatus); + } else if (IS_HARDWARE_TYPE_8192E(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8192e2ant_media_status_notify(pBtCoexist, mStatus); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8192e1ant_media_status_notify(pBtCoexist, mStatus); + } else if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8812a2ant_media_status_notify(pBtCoexist, mStatus); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8812a1ant_media_status_notify(pBtCoexist, mStatus); + } else if (IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_media_status_notify(pBtCoexist, mStatus); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8822b2ant_media_status_notify(pBtCoexist, mStatus); + } else if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_media_status_notify(pBtCoexist, mStatus); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_media_status_notify(pBtCoexist, mStatus); + } + + /* halbtcoutsrc_NormalLowPower(pBtCoexist); */ +} + +void EXhalbtcoutsrc_specific_packet_notify(PBTC_COEXIST pBtCoexist, u8 pktType) +{ + u8 packetType; + + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + pBtCoexist->statistics.cnt_specific_packet_notify++; + if (pBtCoexist->manual_control) + return; + + if (PACKET_DHCP == pktType) + packetType = BTC_PACKET_DHCP; + else if (PACKET_EAPOL == pktType) + packetType = BTC_PACKET_EAPOL; + else if (PACKET_ARP == pktType) + packetType = BTC_PACKET_ARP; + else { + packetType = BTC_PACKET_UNKNOWN; + return; + } + + /* All notify is called in cmd thread, don't need to leave low power again + * halbtcoutsrc_LeaveLowPower(pBtCoexist); */ + + if (IS_HARDWARE_TYPE_8821(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821a2ant_specific_packet_notify(pBtCoexist, packetType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821a1ant_specific_packet_notify(pBtCoexist, packetType); + } else if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723b2ant_specific_packet_notify(pBtCoexist, packetType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_specific_packet_notify(pBtCoexist, packetType); + } else if (IS_HARDWARE_TYPE_8703B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8703b1ant_specific_packet_notify(pBtCoexist, packetType); + } else if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723d2ant_specific_packet_notify(pBtCoexist, packetType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723d1ant_specific_packet_notify(pBtCoexist, packetType); + } else if (IS_HARDWARE_TYPE_8192E(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8192e2ant_specific_packet_notify(pBtCoexist, packetType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8192e1ant_specific_packet_notify(pBtCoexist, packetType); + } else if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8812a2ant_specific_packet_notify(pBtCoexist, packetType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8812a1ant_specific_packet_notify(pBtCoexist, packetType); + } else if (IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_specific_packet_notify(pBtCoexist, packetType); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8822b2ant_specific_packet_notify(pBtCoexist, packetType); + } else if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_specific_packet_notify(pBtCoexist, packetType); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_specific_packet_notify(pBtCoexist, packetType); + } + + /* halbtcoutsrc_NormalLowPower(pBtCoexist); */ +} + +void EXhalbtcoutsrc_bt_info_notify(PBTC_COEXIST pBtCoexist, u8 *tmpBuf, u8 length) +{ + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + pBtCoexist->statistics.cnt_bt_info_notify++; + + /* All notify is called in cmd thread, don't need to leave low power again + * halbtcoutsrc_LeaveLowPower(pBtCoexist); */ + + if (IS_HARDWARE_TYPE_8821(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821a2ant_bt_info_notify(pBtCoexist, tmpBuf, length); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821a1ant_bt_info_notify(pBtCoexist, tmpBuf, length); + } else if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723b2ant_bt_info_notify(pBtCoexist, tmpBuf, length); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_bt_info_notify(pBtCoexist, tmpBuf, length); + } else if (IS_HARDWARE_TYPE_8703B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8703b1ant_bt_info_notify(pBtCoexist, tmpBuf, length); + } else if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723d2ant_bt_info_notify(pBtCoexist, tmpBuf, length); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723d1ant_bt_info_notify(pBtCoexist, tmpBuf, length); + } else if (IS_HARDWARE_TYPE_8192E(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8192e2ant_bt_info_notify(pBtCoexist, tmpBuf, length); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8192e1ant_bt_info_notify(pBtCoexist, tmpBuf, length); + } else if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8812a2ant_bt_info_notify(pBtCoexist, tmpBuf, length); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8812a1ant_bt_info_notify(pBtCoexist, tmpBuf, length); + } else if (IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_bt_info_notify(pBtCoexist, tmpBuf, length); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8822b2ant_bt_info_notify(pBtCoexist, tmpBuf, length); + } else if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_bt_info_notify(pBtCoexist, tmpBuf, length); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_bt_info_notify(pBtCoexist, tmpBuf, length); + } + + /* halbtcoutsrc_NormalLowPower(pBtCoexist); */ +} + +void +EXhalbtcoutsrc_RfStatusNotify( + IN PBTC_COEXIST pBtCoexist, + IN u8 type +) +{ + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + pBtCoexist->statistics.cnt_rf_status_notify++; + + if (IS_HARDWARE_TYPE_8821(pBtCoexist->Adapter)) { + } else if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_rf_status_notify(pBtCoexist, type); + } else if (IS_HARDWARE_TYPE_8703B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8703b1ant_rf_status_notify(pBtCoexist, type); + } else if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723d1ant_rf_status_notify(pBtCoexist, type); + } else if (IS_HARDWARE_TYPE_8192E(pBtCoexist->Adapter)) { + } else if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) { + } else if (IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_rf_status_notify(pBtCoexist, type); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8822b2ant_rf_status_notify(pBtCoexist, type); + } else if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_rf_status_notify(pBtCoexist, type); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_rf_status_notify(pBtCoexist, type); + } +} + +void EXhalbtcoutsrc_StackOperationNotify(PBTC_COEXIST pBtCoexist, u8 type) +{ +} + +void EXhalbtcoutsrc_halt_notify(PBTC_COEXIST pBtCoexist) +{ + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + if (IS_HARDWARE_TYPE_8821(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821a2ant_halt_notify(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821a1ant_halt_notify(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723b2ant_halt_notify(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_halt_notify(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8703B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8703b1ant_halt_notify(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723d2ant_halt_notify(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723d1ant_halt_notify(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8192E(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8192e2ant_halt_notify(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8192e1ant_halt_notify(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8812a2ant_halt_notify(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8812a1ant_halt_notify(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_halt_notify(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8822b2ant_halt_notify(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_halt_notify(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_halt_notify(pBtCoexist); + } +} + +void EXhalbtcoutsrc_SwitchBtTRxMask(PBTC_COEXIST pBtCoexist) +{ + if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) { + halbtcoutsrc_SetBtReg(pBtCoexist, 0, 0x3c, 0x01); /* BT goto standby while GNT_BT 1-->0 */ + } else if (pBtCoexist->board_info.btdm_ant_num == 1) { + halbtcoutsrc_SetBtReg(pBtCoexist, 0, 0x3c, 0x15); /* BT goto standby while GNT_BT 1-->0 */ + } + } +} + +void EXhalbtcoutsrc_pnp_notify(PBTC_COEXIST pBtCoexist, u8 pnpState) +{ + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + /* */ + /* currently only 1ant we have to do the notification, */ + /* once pnp is notified to sleep state, we have to leave LPS that we can sleep normally. */ + /* */ + + if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_pnp_notify(pBtCoexist, pnpState); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723b2ant_pnp_notify(pBtCoexist, pnpState); + } else if (IS_HARDWARE_TYPE_8703B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8703b1ant_pnp_notify(pBtCoexist, pnpState); + } else if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723d1ant_pnp_notify(pBtCoexist, pnpState); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723d2ant_pnp_notify(pBtCoexist, pnpState); + } else if (IS_HARDWARE_TYPE_8821(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821a1ant_pnp_notify(pBtCoexist, pnpState); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821a2ant_pnp_notify(pBtCoexist, pnpState); + } else if (IS_HARDWARE_TYPE_8192E(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8192e1ant_pnp_notify(pBtCoexist, pnpState); + } else if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8812a1ant_pnp_notify(pBtCoexist, pnpState); + } else if (IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_pnp_notify(pBtCoexist, pnpState); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8822b2ant_pnp_notify(pBtCoexist, pnpState); + } else if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_pnp_notify(pBtCoexist, pnpState); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_pnp_notify(pBtCoexist, pnpState); + } +} + +void EXhalbtcoutsrc_CoexDmSwitch(PBTC_COEXIST pBtCoexist) +{ + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + pBtCoexist->statistics.cnt_coex_dm_switch++; + + halbtcoutsrc_LeaveLowPower(pBtCoexist); + + if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) { + pBtCoexist->stop_coex_dm = true; + ex_halbtc8723b1ant_coex_dm_reset(pBtCoexist); + EXhalbtcoutsrc_SetAntNum(BT_COEX_ANT_TYPE_DETECTED, 2); + ex_halbtc8723b2ant_init_hw_config(pBtCoexist, false); + ex_halbtc8723b2ant_init_coex_dm(pBtCoexist); + pBtCoexist->stop_coex_dm = false; + } + } else if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) { + pBtCoexist->stop_coex_dm = true; + ex_halbtc8723d1ant_coex_dm_reset(pBtCoexist); + EXhalbtcoutsrc_SetAntNum(BT_COEX_ANT_TYPE_DETECTED, 2); + ex_halbtc8723d2ant_init_hw_config(pBtCoexist, false); + ex_halbtc8723d2ant_init_coex_dm(pBtCoexist); + pBtCoexist->stop_coex_dm = false; + } + } + + halbtcoutsrc_NormalLowPower(pBtCoexist); +} + +void EXhalbtcoutsrc_periodical(PBTC_COEXIST pBtCoexist) +{ + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + pBtCoexist->statistics.cnt_periodical++; + + /* Periodical should be called in cmd thread, */ + /* don't need to leave low power again + * halbtcoutsrc_LeaveLowPower(pBtCoexist); */ + + if (IS_HARDWARE_TYPE_8821(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821a2ant_periodical(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) { + if (!halbtcoutsrc_UnderIps(pBtCoexist)) + ex_halbtc8821a1ant_periodical(pBtCoexist); + } + } else if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723b2ant_periodical(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_periodical(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723d2ant_periodical(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723d1ant_periodical(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8703B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8703b1ant_periodical(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8192E(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8192e2ant_periodical(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8192e1ant_periodical(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8812a2ant_periodical(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8812a1ant_periodical(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_periodical(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8822b2ant_periodical(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_periodical(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_periodical(pBtCoexist); + } + + /* halbtcoutsrc_NormalLowPower(pBtCoexist); */ +} + +void EXhalbtcoutsrc_dbg_control(PBTC_COEXIST pBtCoexist, u8 opCode, u8 opLen, u8 *pData) +{ + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + pBtCoexist->statistics.cnt_dbg_ctrl++; + + /* This function doesn't be called yet, */ + /* default no need to leave low power to avoid deadlock + * halbtcoutsrc_LeaveLowPower(pBtCoexist); */ + + if (IS_HARDWARE_TYPE_8192E(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8192e1ant_dbg_control(pBtCoexist, opCode, opLen, pData); + } else if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8812a2ant_dbg_control(pBtCoexist, opCode, opLen, pData); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8812a1ant_dbg_control(pBtCoexist, opCode, opLen, pData); + } else if(IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) + if(pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_dbg_control(pBtCoexist, opCode, opLen, pData); + + /* halbtcoutsrc_NormalLowPower(pBtCoexist); */ +} + +void EXhalbtcoutsrc_StackUpdateProfileInfo(void) +{ +#ifdef CONFIG_BT_COEXIST_SOCKET_TRX + PBTC_COEXIST pBtCoexist = &GLBtCoexist; + PADAPTER padapter = (PADAPTER)GLBtCoexist.Adapter; + PBT_MGNT pBtMgnt = &padapter->coex_info.BtMgnt; + u8 i; + + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + pBtCoexist->stack_info.profile_notified = true; + + pBtCoexist->stack_info.num_of_link = + pBtMgnt->ExtConfig.NumberOfACL + pBtMgnt->ExtConfig.NumberOfSCO; + + /* reset first */ + pBtCoexist->stack_info.bt_link_exist = false; + pBtCoexist->stack_info.sco_exist = false; + pBtCoexist->stack_info.acl_exist = false; + pBtCoexist->stack_info.a2dp_exist = false; + pBtCoexist->stack_info.hid_exist = false; + pBtCoexist->stack_info.num_of_hid = 0; + pBtCoexist->stack_info.pan_exist = false; + + if (!pBtMgnt->ExtConfig.NumberOfACL) + pBtCoexist->stack_info.min_bt_rssi = 0; + + if (pBtCoexist->stack_info.num_of_link) { + pBtCoexist->stack_info.bt_link_exist = true; + if (pBtMgnt->ExtConfig.NumberOfSCO) + pBtCoexist->stack_info.sco_exist = true; + if (pBtMgnt->ExtConfig.NumberOfACL) + pBtCoexist->stack_info.acl_exist = true; + } + + for (i = 0; i < pBtMgnt->ExtConfig.NumberOfACL; i++) { + if (BT_PROFILE_A2DP == pBtMgnt->ExtConfig.aclLink[i].BTProfile) + pBtCoexist->stack_info.a2dp_exist = true; + else if (BT_PROFILE_PAN == pBtMgnt->ExtConfig.aclLink[i].BTProfile) + pBtCoexist->stack_info.pan_exist = true; + else if (BT_PROFILE_HID == pBtMgnt->ExtConfig.aclLink[i].BTProfile) { + pBtCoexist->stack_info.hid_exist = true; + pBtCoexist->stack_info.num_of_hid++; + } else + pBtCoexist->stack_info.unknown_acl_exist = true; + } +#endif /* CONFIG_BT_COEXIST_SOCKET_TRX */ +} + +void EXhalbtcoutsrc_UpdateMinBtRssi(s8 btRssi) +{ + PBTC_COEXIST pBtCoexist = &GLBtCoexist; + + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + pBtCoexist->stack_info.min_bt_rssi = btRssi; +} + +void EXhalbtcoutsrc_SetHciVersion(u16 hciVersion) +{ + PBTC_COEXIST pBtCoexist = &GLBtCoexist; + + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + pBtCoexist->stack_info.hci_version = hciVersion; +} + +void EXhalbtcoutsrc_SetBtPatchVersion(u16 btHciVersion, u16 btPatchVersion) +{ + PBTC_COEXIST pBtCoexist = &GLBtCoexist; + + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + pBtCoexist->bt_info.bt_real_fw_ver = btPatchVersion; + pBtCoexist->bt_info.bt_hci_ver = btHciVersion; +} + +void EXhalbtcoutsrc_SetChipType(u8 chipType) +{ + switch (chipType) { + default: + case BT_2WIRE: + case BT_ISSC_3WIRE: + case BT_ACCEL: + case BT_RTL8756: + GLBtCoexist.board_info.bt_chip_type = BTC_CHIP_UNDEF; + break; + case BT_CSR_BC4: + GLBtCoexist.board_info.bt_chip_type = BTC_CHIP_CSR_BC4; + break; + case BT_CSR_BC8: + GLBtCoexist.board_info.bt_chip_type = BTC_CHIP_CSR_BC8; + break; + case BT_RTL8723A: + GLBtCoexist.board_info.bt_chip_type = BTC_CHIP_RTL8723A; + break; + case BT_RTL8821: + GLBtCoexist.board_info.bt_chip_type = BTC_CHIP_RTL8821; + break; + case BT_RTL8723B: + GLBtCoexist.board_info.bt_chip_type = BTC_CHIP_RTL8723B; + break; + } +} + +void EXhalbtcoutsrc_SetAntNum(u8 type, u8 antNum) +{ + if (BT_COEX_ANT_TYPE_PG == type) { + GLBtCoexist.board_info.pg_ant_num = antNum; + GLBtCoexist.board_info.btdm_ant_num = antNum; + } else if (BT_COEX_ANT_TYPE_ANTDIV == type) { + GLBtCoexist.board_info.btdm_ant_num = antNum; + } else if (BT_COEX_ANT_TYPE_DETECTED == type) { + GLBtCoexist.board_info.btdm_ant_num = antNum; + } +} + +/* + * Currently used by 8723b only, S0 or S1 + * */ +void EXhalbtcoutsrc_SetSingleAntPath(u8 singleAntPath) +{ + GLBtCoexist.board_info.single_ant_path = singleAntPath; +} + +void EXhalbtcoutsrc_DisplayBtCoexInfo(PBTC_COEXIST pBtCoexist) +{ + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + halbtcoutsrc_LeaveLowPower(pBtCoexist); + + if (IS_HARDWARE_TYPE_8821(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821a2ant_display_coex_info(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821a1ant_display_coex_info(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723b2ant_display_coex_info(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_display_coex_info(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8703B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8703b1ant_display_coex_info(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8723d2ant_display_coex_info(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723d1ant_display_coex_info(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8192E(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8192e2ant_display_coex_info(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8192e1ant_display_coex_info(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8812a2ant_display_coex_info(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8812a1ant_display_coex_info(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_display_coex_info(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8822b2ant_display_coex_info(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_display_coex_info(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_display_coex_info(pBtCoexist); + } + + halbtcoutsrc_NormalLowPower(pBtCoexist); +} + +void EXhalbtcoutsrc_DisplayAntDetection(PBTC_COEXIST pBtCoexist) +{ + if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + halbtcoutsrc_LeaveLowPower(pBtCoexist); + + if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8723b1ant_display_ant_detection(pBtCoexist); + } else if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_display_ant_detection(pBtCoexist); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_display_ant_detection(pBtCoexist); + } + + halbtcoutsrc_NormalLowPower(pBtCoexist); +} + +void ex_halbtcoutsrc_pta_off_on_notify(PBTC_COEXIST pBtCoexist, u8 bBTON) +{ + if (IS_HARDWARE_TYPE_8812(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8812a2ant_pta_off_on_notify(pBtCoexist, (bBTON == true) ? BTC_BT_ON : BTC_BT_OFF); + } +} + +void EXhalbtcoutsrc_set_rfe_type(u8 type) +{ + GLBtCoexist.board_info.rfe_type= type; +} + +void EXhalbtcoutsrc_switchband_notify(struct btc_coexist *pBtCoexist, u8 type) +{ + if(!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist)) + return; + + if(pBtCoexist->manual_control) + return; + + /* Driver should guarantee that the HW status isn't in low power mode */ + /* halbtcoutsrc_LeaveLowPower(pBtCoexist); */ + + if(IS_HARDWARE_TYPE_8822B(pBtCoexist->Adapter)) { + if(pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8822b1ant_switchband_notify(pBtCoexist, type); + else if(pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8822b2ant_switchband_notify(pBtCoexist, type); + } else if (IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) { + if (pBtCoexist->board_info.btdm_ant_num == 2) + ex_halbtc8821c2ant_switchband_notify(pBtCoexist, type); + else if (pBtCoexist->board_info.btdm_ant_num == 1) + ex_halbtc8821c1ant_switchband_notify(pBtCoexist, type); + } + + /* halbtcoutsrc_NormalLowPower(pBtCoexist); */ +} + +static void halbt_init_hw_config92C(PADAPTER padapter) +{ + PHAL_DATA_TYPE pHalData; + u8 u1Tmp; + + + pHalData = GET_HAL_DATA(padapter); + if ((pHalData->bt_coexist.btChipType == BT_CSR_BC4) || + (pHalData->bt_coexist.btChipType == BT_CSR_BC8)) { + if (pHalData->rf_type == RF_1T1R) { + /* Config to 1T1R */ + u1Tmp = rtw_read8(padapter, rOFDM0_TRxPathEnable); + u1Tmp &= ~BIT(1); + rtw_write8(padapter, rOFDM0_TRxPathEnable, u1Tmp); + RT_DISP(FBT, BT_TRACE, ("[BTCoex], BT write 0xC04 = 0x%x\n", u1Tmp)); + + u1Tmp = rtw_read8(padapter, rOFDM1_TRxPathEnable); + u1Tmp &= ~BIT(1); + rtw_write8(padapter, rOFDM1_TRxPathEnable, u1Tmp); + RT_DISP(FBT, BT_TRACE, ("[BTCoex], BT write 0xD04 = 0x%x\n", u1Tmp)); + } + } +} + +static void halbt_init_hw_config92D(PADAPTER padapter) +{ + PHAL_DATA_TYPE pHalData; + u8 u1Tmp; + + pHalData = GET_HAL_DATA(padapter); + if ((pHalData->bt_coexist.btChipType == BT_CSR_BC4) || + (pHalData->bt_coexist.btChipType == BT_CSR_BC8)) { + if (pHalData->rf_type == RF_1T1R) { + /* Config to 1T1R */ + u1Tmp = rtw_read8(padapter, rOFDM0_TRxPathEnable); + u1Tmp &= ~BIT(1); + rtw_write8(padapter, rOFDM0_TRxPathEnable, u1Tmp); + RT_DISP(FBT, BT_TRACE, ("[BTCoex], BT write 0xC04 = 0x%x\n", u1Tmp)); + + u1Tmp = rtw_read8(padapter, rOFDM1_TRxPathEnable); + u1Tmp &= ~BIT(1); + rtw_write8(padapter, rOFDM1_TRxPathEnable, u1Tmp); + RT_DISP(FBT, BT_TRACE, ("[BTCoex], BT write 0xD04 = 0x%x\n", u1Tmp)); + } + } +} + +/* + * Description: + * Run BT-Coexist mechansim or not + * + */ +void hal_btcoex_SetBTCoexist(PADAPTER padapter, u8 bBtExist) +{ + PHAL_DATA_TYPE pHalData; + + + pHalData = GET_HAL_DATA(padapter); + pHalData->bt_coexist.bBtExist = bBtExist; +} + +/* + * Dewcription: + * Check is co-exist mechanism enabled or not + * + * Return: + * true Enable BT co-exist mechanism + * false Disable BT co-exist mechanism + */ +u8 hal_btcoex_IsBtExist(PADAPTER padapter) +{ + PHAL_DATA_TYPE pHalData; + + + pHalData = GET_HAL_DATA(padapter); + return pHalData->bt_coexist.bBtExist; +} + +u8 hal_btcoex_IsBtDisabled(PADAPTER padapter) +{ + if (!hal_btcoex_IsBtExist(padapter)) + return true; + + if (GLBtCoexist.bt_info.bt_disabled) + return true; + else + return false; +} + +void hal_btcoex_SetChipType(PADAPTER padapter, u8 chipType) +{ + PHAL_DATA_TYPE pHalData; + + pHalData = GET_HAL_DATA(padapter); + pHalData->bt_coexist.btChipType = chipType; +} + +void hal_btcoex_SetPgAntNum(PADAPTER padapter, u8 antNum) +{ + PHAL_DATA_TYPE pHalData; + + pHalData = GET_HAL_DATA(padapter); + + pHalData->bt_coexist.btTotalAntNum = antNum; +} + +u8 hal_btcoex_Initialize(PADAPTER padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + u8 ret; + + memset(&GLBtCoexist, 0, sizeof(GLBtCoexist)); + + hal_btcoex_SetBTCoexist(padapter, rtw_btcoex_get_bt_coexist(padapter)); + hal_btcoex_SetChipType(padapter, rtw_btcoex_get_chip_type(padapter)); + hal_btcoex_SetPgAntNum(padapter, rtw_btcoex_get_pg_ant_num(padapter)); + + ret = EXhalbtcoutsrc_InitlizeVariables((void *)padapter); + + return ret; +} + +void hal_btcoex_PowerOnSetting(PADAPTER padapter) +{ + EXhalbtcoutsrc_PowerOnSetting(&GLBtCoexist); +} + +void hal_btcoex_PreLoadFirmware(PADAPTER padapter) +{ + EXhalbtcoutsrc_PreLoadFirmware(&GLBtCoexist); +} + +void hal_btcoex_InitHwConfig(PADAPTER padapter, u8 bWifiOnly) +{ + if (!hal_btcoex_IsBtExist(padapter)) + return; + + EXhalbtcoutsrc_init_hw_config(&GLBtCoexist, bWifiOnly); + EXhalbtcoutsrc_init_coex_dm(&GLBtCoexist); +} + +void hal_btcoex_IpsNotify(PADAPTER padapter, u8 type) +{ + EXhalbtcoutsrc_ips_notify(&GLBtCoexist, type); +} + +void hal_btcoex_LpsNotify(PADAPTER padapter, u8 type) +{ + EXhalbtcoutsrc_lps_notify(&GLBtCoexist, type); +} + +void hal_btcoex_ScanNotify(PADAPTER padapter, u8 type) +{ + EXhalbtcoutsrc_scan_notify(&GLBtCoexist, type); +} + +void hal_btcoex_ConnectNotify(PADAPTER padapter, u8 action) +{ + EXhalbtcoutsrc_connect_notify(&GLBtCoexist, action); +} + +void hal_btcoex_MediaStatusNotify(PADAPTER padapter, u8 mediaStatus) +{ + EXhalbtcoutsrc_media_status_notify(&GLBtCoexist, mediaStatus); +} + +void hal_btcoex_SpecialPacketNotify(PADAPTER padapter, u8 pktType) +{ + EXhalbtcoutsrc_specific_packet_notify(&GLBtCoexist, pktType); +} + +void hal_btcoex_IQKNotify(PADAPTER padapter, u8 state) +{ + GLBtcWiFiInIQKState = state; +} + +void hal_btcoex_BtInfoNotify(PADAPTER padapter, u8 length, u8 *tmpBuf) +{ + if (GLBtcWiFiInIQKState == true) + return; + + EXhalbtcoutsrc_bt_info_notify(&GLBtCoexist, tmpBuf, length); +} + +void hal_btcoex_BtMpRptNotify(PADAPTER padapter, u8 length, u8 *tmpBuf) +{ + u8 extid, status, len, seq; + + + if (!GLBtcBtMpRptWait) + return; + + if ((length < 3) || (!tmpBuf)) + return; + + extid = tmpBuf[0]; + /* not response from BT FW then exit*/ + switch (extid) { + case C2H_WIFI_FW_ACTIVE_RSP: + GLBtcBtMpRptWiFiOK = 1; + return; + + case C2H_TRIG_BY_BT_FW: + _cancel_timer_ex(&GLBtcBtMpOperTimer); + GLBtcBtMpRptWait = 0; + GLBtcBtMpRptBTOK = 1; + break; + + default: + return; + } + + status = tmpBuf[1] & 0xF; + len = length - 3; + seq = tmpBuf[2] >> 4; + + GLBtcBtMpRptSeq = seq; + GLBtcBtMpRptStatus = status; + memcpy(GLBtcBtMpRptRsp, tmpBuf + 3, len); + GLBtcBtMpRptRspSize = len; + up(&GLBtcBtMpRptSema); +} + +void hal_btcoex_SuspendNotify(PADAPTER padapter, u8 state) +{ + switch (state) { + case BTCOEX_SUSPEND_STATE_SUSPEND: + EXhalbtcoutsrc_pnp_notify(&GLBtCoexist, BTC_WIFI_PNP_SLEEP); + break; + case BTCOEX_SUSPEND_STATE_SUSPEND_KEEP_ANT: + /* should switch to "#if 1" once all ICs' coex. revision are upgraded to support the KEEP_ANT case */ + EXhalbtcoutsrc_pnp_notify(&GLBtCoexist, BTC_WIFI_PNP_SLEEP); + EXhalbtcoutsrc_pnp_notify(&GLBtCoexist, BTC_WIFI_PNP_SLEEP_KEEP_ANT); + break; + case BTCOEX_SUSPEND_STATE_RESUME: + EXhalbtcoutsrc_pnp_notify(&GLBtCoexist, BTC_WIFI_PNP_WAKE_UP); + break; + } +} + +void hal_btcoex_HaltNotify(PADAPTER padapter, u8 do_halt) +{ + if (do_halt == 1) + EXhalbtcoutsrc_halt_notify(&GLBtCoexist); + + GLBtCoexist.bBinded = false; + GLBtCoexist.Adapter = NULL; +} + +void hal_btcoex_SwitchBtTRxMask(PADAPTER padapter) +{ + EXhalbtcoutsrc_SwitchBtTRxMask(&GLBtCoexist); +} + +void hal_btcoex_Hanlder(PADAPTER padapter) +{ + u32 bt_patch_ver; + + EXhalbtcoutsrc_periodical(&GLBtCoexist); + + if (GLBtCoexist.bt_info.bt_get_fw_ver == 0) { + GLBtCoexist.btc_get(&GLBtCoexist, BTC_GET_U4_BT_PATCH_VER, &bt_patch_ver); + GLBtCoexist.bt_info.bt_get_fw_ver = bt_patch_ver; + } +} + +s32 hal_btcoex_IsBTCoexRejectAMPDU(PADAPTER padapter) +{ + return (s32)GLBtCoexist.bt_info.reject_agg_pkt; +} + +s32 hal_btcoex_IsBTCoexCtrlAMPDUSize(PADAPTER padapter) +{ + return (s32)GLBtCoexist.bt_info.bt_ctrl_agg_buf_size; +} + +u32 hal_btcoex_GetAMPDUSize(PADAPTER padapter) +{ + return (u32)GLBtCoexist.bt_info.agg_buf_size; +} + +void hal_btcoex_SetManualControl(PADAPTER padapter, u8 bmanual) +{ + GLBtCoexist.manual_control = bmanual; +} + +u8 hal_btcoex_1Ant(PADAPTER padapter) +{ + if (hal_btcoex_IsBtExist(padapter) == false) + return false; + + if (GLBtCoexist.board_info.btdm_ant_num == 1) + return true; + + return false; +} + +u8 hal_btcoex_IsBtControlLps(PADAPTER padapter) +{ + if (GLBtCoexist.bdontenterLPS == true) + return true; + + if (hal_btcoex_IsBtExist(padapter) == false) + return false; + + if (GLBtCoexist.bt_info.bt_disabled) + return false; + + if (GLBtCoexist.bt_info.bt_ctrl_lps) + return true; + + return false; +} + +u8 hal_btcoex_IsLpsOn(PADAPTER padapter) +{ + if (GLBtCoexist.bdontenterLPS == true) + return false; + + if (hal_btcoex_IsBtExist(padapter) == false) + return false; + + if (GLBtCoexist.bt_info.bt_disabled) + return false; + + if (GLBtCoexist.bt_info.bt_lps_on) + return true; + + return false; +} + +u8 hal_btcoex_RpwmVal(PADAPTER padapter) +{ + return GLBtCoexist.bt_info.rpwm_val; +} + +u8 hal_btcoex_LpsVal(PADAPTER padapter) +{ + return GLBtCoexist.bt_info.lps_val; +} + +u32 hal_btcoex_GetRaMask(PADAPTER padapter) +{ + if (!hal_btcoex_IsBtExist(padapter)) + return 0; + + if (GLBtCoexist.bt_info.bt_disabled) + return 0; + + /* Modify by YiWei , suggest by Cosa and Jenyu + * Remove the limit antenna number , because 2 antenna case (ex: 8192eu)also want to get BT coex report rate mask. + */ + /*if (GLBtCoexist.board_info.btdm_ant_num != 1) + return 0;*/ + + return GLBtCoexist.bt_info.ra_mask; +} + +void hal_btcoex_RecordPwrMode(PADAPTER padapter, u8 *pCmdBuf, u8 cmdLen) +{ + + memcpy(GLBtCoexist.pwrModeVal, pCmdBuf, cmdLen); +} + +void hal_btcoex_DisplayBtCoexInfo(PADAPTER padapter, u8 *pbuf, u32 bufsize) +{ + PBTCDBGINFO pinfo; + + + pinfo = &GLBtcDbgInfo; + DBG_BT_INFO_INIT(pinfo, pbuf, bufsize); + EXhalbtcoutsrc_DisplayBtCoexInfo(&GLBtCoexist); + DBG_BT_INFO_INIT(pinfo, NULL, 0); +} + +void hal_btcoex_SetDBG(PADAPTER padapter, u32 *pDbgModule) +{ + u32 i; + + + if (NULL == pDbgModule) + return; + + for (i = 0; i < COMP_MAX; i++) + GLBtcDbgType[i] = pDbgModule[i]; +} + +u32 hal_btcoex_GetDBG(PADAPTER padapter, u8 *pStrBuf, u32 bufSize) +{ + s32 count; + u8 *pstr; + u32 leftSize; + + + if ((NULL == pStrBuf) || (0 == bufSize)) + return 0; + + count = 0; + pstr = pStrBuf; + leftSize = bufSize; + /* RTW_INFO(FUNC_ADPT_FMT ": bufsize=%d\n", FUNC_ADPT_ARG(padapter), bufSize); */ + + count = rtw_sprintf(pstr, leftSize, "#define DBG\t%d\n", DBG); + if ((count < 0) || (count >= leftSize)) + goto exit; + pstr += count; + leftSize -= count; + + count = rtw_sprintf(pstr, leftSize, "BTCOEX Debug Setting:\n"); + if ((count < 0) || (count >= leftSize)) + goto exit; + pstr += count; + leftSize -= count; + + count = rtw_sprintf(pstr, leftSize, + "COMP_COEX: 0x%08X\n\n", + GLBtcDbgType[COMP_COEX]); + if ((count < 0) || (count >= leftSize)) + goto exit; + pstr += count; + leftSize -= count; + +exit: + count = pstr - pStrBuf; + return count; +} + +u8 hal_btcoex_IncreaseScanDeviceNum(PADAPTER padapter) +{ + if (!hal_btcoex_IsBtExist(padapter)) + return false; + + if (GLBtCoexist.bt_info.increase_scan_dev_num) + return true; + + return false; +} + +u8 hal_btcoex_IsBtLinkExist(PADAPTER padapter) +{ + if (GLBtCoexist.bt_link_info.bt_link_exist) + return true; + + return false; +} + +void hal_btcoex_SetBtPatchVersion(PADAPTER padapter, u16 btHciVer, u16 btPatchVer) +{ + EXhalbtcoutsrc_SetBtPatchVersion(btHciVer, btPatchVer); +} + +void hal_btcoex_SetHciVersion(PADAPTER padapter, u16 hciVersion) +{ + EXhalbtcoutsrc_SetHciVersion(hciVersion); +} + +void hal_btcoex_StackUpdateProfileInfo(void) +{ + EXhalbtcoutsrc_StackUpdateProfileInfo(); +} + +void hal_btcoex_pta_off_on_notify(PADAPTER padapter, u8 bBTON) +{ + ex_halbtcoutsrc_pta_off_on_notify(&GLBtCoexist, bBTON); +} + +/* + * Description: + * Setting BT coex antenna isolation type . + * coex mechanisn/ spital stream/ best throughput + * anttype = 0 , PSTDMA / 2SS / 0.5T , bad isolation , WiFi/BT ANT Distance<15cm , (<20dB) for 2,3 antenna + * anttype = 1 , PSTDMA / 1SS / 0.5T , normal isolaiton , 50cm>WiFi/BT ANT Distance>15cm , (>20dB) for 2 antenna + * anttype = 2 , TDMA / 2SS / T , normal isolaiton , 50cm>WiFi/BT ANT Distance>15cm , (>20dB) for 3 antenna + * anttype = 3 , no TDMA / 1SS / 0.5T , good isolation , WiFi/BT ANT Distance >50cm , (>40dB) for 2 antenna + * anttype = 4 , no TDMA / 2SS / T , good isolation , WiFi/BT ANT Distance >50cm , (>40dB) for 3 antenna + * wifi only throughput ~ T + * wifi/BT share one antenna with SPDT + */ +void hal_btcoex_SetAntIsolationType(PADAPTER padapter, u8 anttype) +{ + PHAL_DATA_TYPE pHalData; + PBTC_COEXIST pBtCoexist = &GLBtCoexist; + + /*RTW_INFO("####%s , anttype = %d , %d\n" , __func__ , anttype , __LINE__); */ + pHalData = GET_HAL_DATA(padapter); + + + pHalData->bt_coexist.btAntisolation = anttype; + + switch (pHalData->bt_coexist.btAntisolation) { + case 0: + pBtCoexist->board_info.ant_type = (u8)BTC_ANT_TYPE_0; + break; + case 1: + pBtCoexist->board_info.ant_type = (u8)BTC_ANT_TYPE_1; + break; + case 2: + pBtCoexist->board_info.ant_type = (u8)BTC_ANT_TYPE_2; + break; + case 3: + pBtCoexist->board_info.ant_type = (u8)BTC_ANT_TYPE_3; + break; + case 4: + pBtCoexist->board_info.ant_type = (u8)BTC_ANT_TYPE_4; + break; + } + +} + +#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE +int +hal_btcoex_ParseAntIsolationConfigFile( + PADAPTER Adapter, + char *buffer +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u32 i = 0 , j = 0; + char *szLine , *ptmp; + int rtStatus = _SUCCESS; + char param_value_string[10]; + u8 param_value; + u8 anttype = 4; + + u8 ant_num = 3 , ant_distance = 50 , rfe_type = 1; + + typedef struct ant_isolation { + char *param_name; /* antenna isolation config parameter name */ + u8 *value; /* antenna isolation config parameter value */ + } ANT_ISOLATION; + + ANT_ISOLATION ant_isolation_param[] = { + {"ANT_NUMBER" , &ant_num}, + {"ANT_DISTANCE" , &ant_distance}, + {"RFE_TYPE" , &rfe_type}, + {NULL , 0} + }; + + + + /* RTW_INFO("===>Hal_ParseAntIsolationConfigFile()\n" ); */ + + ptmp = buffer; + for (szLine = GetLineFromBuffer(ptmp) ; szLine != NULL; szLine = GetLineFromBuffer(ptmp)) { + /* skip comment */ + if (IsCommentString(szLine)) + continue; + + /* RTW_INFO("%s : szLine = %s , strlen(szLine) = %d\n" , __func__ , szLine , strlen(szLine));*/ + for (j = 0 ; ant_isolation_param[j].param_name != NULL ; j++) { + if (strstr(szLine , ant_isolation_param[j].param_name) != NULL) { + i = 0; + while (i < strlen(szLine)) { + if (szLine[i] != '"') + ++i; + else { + /* skip only has one " */ + if (strpbrk(szLine , "\"") == strrchr(szLine , '"')) { + RTW_INFO("Fail to parse parameters , format error!\n"); + break; + } + memset((void *)param_value_string , 0 , 10); + if (!ParseQualifiedString(szLine , &i , param_value_string , '"' , '"')) { + RTW_INFO("Fail to parse parameters\n"); + return _FAIL; + } else if (!GetU1ByteIntegerFromStringInDecimal(param_value_string , ant_isolation_param[j].value)) + RTW_INFO("Fail to GetU1ByteIntegerFromStringInDecimal\n"); + + break; + } + } + } + } + } + + /* YiWei 20140716 , for BT coex antenna isolation control */ + /* rfe_type = 0 was SPDT , rfe_type = 1 was coupler */ + if (ant_num == 3 && ant_distance >= 50) + anttype = 3; + else if (ant_num == 2 && ant_distance >= 50 && rfe_type == 1) + anttype = 2; + else if (ant_num == 3 && ant_distance >= 15 && ant_distance < 50) + anttype = 2; + else if (ant_num == 2 && ant_distance >= 15 && ant_distance < 50 && rfe_type == 1) + anttype = 2; + else if ((ant_num == 2 && ant_distance < 15 && rfe_type == 1) || (ant_num == 3 && ant_distance < 15)) + anttype = 1; + else if (ant_num == 2 && rfe_type == 0) + anttype = 0; + else + anttype = 0; + + hal_btcoex_SetAntIsolationType(Adapter, anttype); + + RTW_INFO("%s : ant_num = %d\n" , __func__ , ant_num); + RTW_INFO("%s : ant_distance = %d\n" , __func__ , ant_distance); + RTW_INFO("%s : rfe_type = %d\n" , __func__ , rfe_type); + /* RTW_INFO("<===Hal_ParseAntIsolationConfigFile()\n"); */ + return rtStatus; +} + + +int +hal_btcoex_AntIsolationConfig_ParaFile( + IN PADAPTER Adapter, + IN char *pFileName +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + int rlen = 0 , rtStatus = _FAIL; + + memset(pHalData->para_file_buf , 0 , MAX_PARA_FILE_BUF_LEN); + + rtw_get_phy_file_path(Adapter, pFileName); + if (rtw_is_file_readable(rtw_phy_para_file_path) == true) { + rlen = rtw_retrieve_from_file(rtw_phy_para_file_path, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN); + if (rlen > 0) + rtStatus = _SUCCESS; + } + + + if (rtStatus == _SUCCESS) { + /*RTW_INFO("%s(): read %s ok\n", __func__ , pFileName);*/ + rtStatus = hal_btcoex_ParseAntIsolationConfigFile(Adapter , pHalData->para_file_buf); + } else + RTW_INFO("%s(): No File %s, Load from *** Array!\n" , __func__ , pFileName); + + return rtStatus; +} +#endif /* CONFIG_LOAD_PHY_PARA_FROM_FILE */ + +u16 hal_btcoex_btreg_read(PADAPTER padapter, u8 type, u16 addr, u32 *data) +{ + u16 ret = 0; + + halbtcoutsrc_LeaveLowPower(&GLBtCoexist); + + ret = halbtcoutsrc_GetBtReg_with_status(&GLBtCoexist, type, addr, data); + + halbtcoutsrc_NormalLowPower(&GLBtCoexist); + + return ret; +} + +u16 hal_btcoex_btreg_write(PADAPTER padapter, u8 type, u16 addr, u16 val) +{ + u16 ret = 0; + + halbtcoutsrc_LeaveLowPower(&GLBtCoexist); + + ret = halbtcoutsrc_SetBtReg(&GLBtCoexist, type, addr, val); + + halbtcoutsrc_NormalLowPower(&GLBtCoexist); + + return ret; +} + +void hal_btcoex_set_rfe_type(u8 type) +{ + EXhalbtcoutsrc_set_rfe_type(type); +} +void hal_btcoex_switchband_notify(u8 under_scan, u8 band_type) +{ + switch (band_type) { + case BAND_ON_2_4G: + if (under_scan) + EXhalbtcoutsrc_switchband_notify(&GLBtCoexist, BTC_SWITCH_TO_24G); + else + EXhalbtcoutsrc_switchband_notify(&GLBtCoexist, BTC_SWITCH_TO_24G_NOFORSCAN); + break; + case BAND_ON_5G: + EXhalbtcoutsrc_switchband_notify(&GLBtCoexist, BTC_SWITCH_TO_5G); + break; + default: + RTW_INFO("[BTCOEX] unkown switch band type\n"); + break; + } +} +#endif /* CONFIG_BT_COEXIST */ diff --git a/drivers/staging/rtl8188eu/hal/hal_btcoex_wifionly.c b/drivers/staging/rtl8188eu/hal/hal_btcoex_wifionly.c new file mode 100644 index 000000000000..856ebd55bfb8 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal_btcoex_wifionly.c @@ -0,0 +1,131 @@ +#include "btc/mp_precomp.h" +#include + +static struct wifi_only_cfg GLBtCoexistWifiOnly; + +void halwifionly_write1byte(void * pwifionlyContext, u32 RegAddr, u8 Data) +{ + struct wifi_only_cfg *pwifionlycfg = (struct wifi_only_cfg *)pwifionlyContext; + PADAPTER Adapter = pwifionlycfg->Adapter; + + rtw_write8(Adapter, RegAddr, Data); +} + +void halwifionly_write2byte(void * pwifionlyContext, u32 RegAddr, u16 Data) +{ + struct wifi_only_cfg *pwifionlycfg = (struct wifi_only_cfg *)pwifionlyContext; + PADAPTER Adapter = pwifionlycfg->Adapter; + + rtw_write16(Adapter, RegAddr, Data); +} + +void halwifionly_write4byte(void * pwifionlyContext, u32 RegAddr, u32 Data) +{ + struct wifi_only_cfg *pwifionlycfg = (struct wifi_only_cfg *)pwifionlyContext; + PADAPTER Adapter = pwifionlycfg->Adapter; + + rtw_write32(Adapter, RegAddr, Data); +} + +u8 halwifionly_read1byte(void * pwifionlyContext, u32 RegAddr) +{ + struct wifi_only_cfg *pwifionlycfg = (struct wifi_only_cfg *)pwifionlyContext; + PADAPTER Adapter = pwifionlycfg->Adapter; + + return rtw_read8(Adapter, RegAddr); +} + +u16 halwifionly_read2byte(void * pwifionlyContext, u32 RegAddr) +{ + struct wifi_only_cfg *pwifionlycfg = (struct wifi_only_cfg *)pwifionlyContext; + PADAPTER Adapter = pwifionlycfg->Adapter; + + return rtw_read16(Adapter, RegAddr); +} + +u32 halwifionly_read4byte(void * pwifionlyContext, u32 RegAddr) +{ + struct wifi_only_cfg *pwifionlycfg = (struct wifi_only_cfg *)pwifionlyContext; + PADAPTER Adapter = pwifionlycfg->Adapter; + + return rtw_read32(Adapter, RegAddr); +} + +void halwifionly_bitmaskwrite1byte(void * pwifionlyContext, u32 regAddr, u8 bitMask, u8 data) +{ + u8 originalValue, bitShift = 0; + u8 i; + + struct wifi_only_cfg *pwifionlycfg = (struct wifi_only_cfg *)pwifionlyContext; + PADAPTER Adapter = pwifionlycfg->Adapter; + + if (bitMask != 0xff) { + originalValue = rtw_read8(Adapter, regAddr); + for (i = 0; i <= 7; i++) { + if ((bitMask >> i) & 0x1) + break; + } + bitShift = i; + data = ((originalValue) & (~bitMask)) | (((data << bitShift)) & bitMask); + } + rtw_write8(Adapter, regAddr, data); +} + +void halwifionly_phy_set_rf_reg(void * pwifionlyContext, u8 eRFPath, u32 RegAddr, u32 BitMask, u32 Data) +{ + struct wifi_only_cfg *pwifionlycfg = (struct wifi_only_cfg *)pwifionlyContext; + PADAPTER Adapter = pwifionlycfg->Adapter; + + phy_set_rf_reg(Adapter, eRFPath, RegAddr, BitMask, Data); +} + +void halwifionly_phy_set_bb_reg(void * pwifionlyContext, u32 RegAddr, u32 BitMask, u32 Data) +{ + struct wifi_only_cfg *pwifionlycfg = (struct wifi_only_cfg *)pwifionlyContext; + PADAPTER Adapter = pwifionlycfg->Adapter; + + phy_set_bb_reg(Adapter, RegAddr, BitMask, Data); +} + +void hal_btcoex_wifionly_switchband_notify(PADAPTER padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + u8 is_5g = false; + + if (pHalData->current_band_type == BAND_ON_5G) + is_5g = true; +} + +void hal_btcoex_wifionly_scan_notify(PADAPTER padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + u8 is_5g = false; + + if (pHalData->current_band_type == BAND_ON_5G) + is_5g = true; +} + +void hal_btcoex_wifionly_hw_config(PADAPTER padapter) +{ + struct wifi_only_cfg *pwifionlycfg = &GLBtCoexistWifiOnly; +} + +void hal_btcoex_wifionly_initlizevariables(PADAPTER padapter) +{ + struct wifi_only_cfg *pwifionlycfg = &GLBtCoexistWifiOnly; + struct wifi_only_haldata *pwifionly_haldata = &pwifionlycfg->haldata_info; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + memset(&GLBtCoexistWifiOnly, 0, sizeof(GLBtCoexistWifiOnly)); + + pwifionlycfg->Adapter = padapter; + + pwifionlycfg->chip_interface = WIFIONLY_INTF_USB; + + pwifionly_haldata->customer_id = CUSTOMER_NORMAL; + pwifionly_haldata->efuse_pg_antnum = pHalData->EEPROMBluetoothAntNum; + pwifionly_haldata->efuse_pg_antpath = pHalData->ant_path; + pwifionly_haldata->rfe_type = pHalData->rfe_type; + pwifionly_haldata->ant_div_cfg = pHalData->AntDivCfg; +} + diff --git a/drivers/staging/rtl8188eu/hal/hal_com.c b/drivers/staging/rtl8188eu/hal/hal_com.c new file mode 100644 index 000000000000..4e632edd211f --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal_com.c @@ -0,0 +1,10540 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#define _HAL_COM_C_ + +#include +#include "hal_com_h2c.h" + +#include "hal_data.h" + +#ifdef RTW_HALMAC +#include "../../hal/hal_halmac.h" +#endif + +void rtw_dump_fw_info(void *sel, _adapter *adapter) +{ + HAL_DATA_TYPE *hal_data = NULL; + + if (!adapter) + return; + + hal_data = GET_HAL_DATA(adapter); + if (adapter->bFWReady) + RTW_PRINT_SEL(sel, "FW VER -%d.%d\n", hal_data->firmware_version, hal_data->firmware_sub_version); + else + RTW_PRINT_SEL(sel, "FW not ready\n"); +} + +/* #define CONFIG_GTK_OL_DBG */ + +/*#define DBG_SEC_CAM_MOVE*/ +#ifdef DBG_SEC_CAM_MOVE +void rtw_hal_move_sta_gk_to_dk(_adapter *adapter) +{ + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + int cam_id, index = 0; + u8 *addr = NULL; + + if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) + return; + + addr = get_bssid(pmlmepriv); + + if (addr == NULL) { + RTW_INFO("%s: get bssid MAC addr fail!!\n", __func__); + return; + } + + rtw_clean_dk_section(adapter); + + do { + cam_id = rtw_camid_search(adapter, addr, index, 1); + + if (cam_id == -1) + RTW_INFO("%s: cam_id: %d, key_id:%d\n", __func__, cam_id, index); + else + rtw_sec_cam_swap(adapter, cam_id, index); + + index++; + } while (index < 4); + +} + +void rtw_hal_read_sta_dk_key(_adapter *adapter, u8 key_id) +{ + struct security_priv *psecuritypriv = &adapter->securitypriv; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl; + unsigned long irqL; + u8 get_key[16]; + + memset(get_key, 0, sizeof(get_key)); + + if (key_id > 4) { + RTW_INFO("%s [ERROR] gtk_keyindex:%d invalid\n", __func__, key_id); + rtw_warn_on(1); + return; + } + rtw_sec_read_cam_ent(adapter, key_id, NULL, NULL, get_key); + + /*update key into related sw variable*/ + _enter_critical_bh(&cam_ctl->lock, &irqL); + if (_rtw_camid_is_gk(adapter, key_id)) { + RTW_INFO("[HW KEY] -Key-id:%d "KEY_FMT"\n", key_id, KEY_ARG(get_key)); + RTW_INFO("[cam_cache KEY] - Key-id:%d "KEY_FMT"\n", key_id, KEY_ARG(&dvobj->cam_cache[key_id].key)); + } + _exit_critical_bh(&cam_ctl->lock, &irqL); + +} +#endif + + +#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE + char rtw_phy_para_file_path[PATH_LENGTH_MAX]; +#endif + +void dump_chip_info(HAL_VERSION ChipVersion) +{ + int cnt = 0; + u8 buf[128] = {0}; + + if (IS_8188E(ChipVersion)) + cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8188E_"); + else if (IS_8188F(ChipVersion)) + cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8188F_"); + else if (IS_8812_SERIES(ChipVersion)) + cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8812_"); + else if (IS_8192E(ChipVersion)) + cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8192E_"); + else if (IS_8821_SERIES(ChipVersion)) + cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8821_"); + else if (IS_8723B_SERIES(ChipVersion)) + cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8723B_"); + else if (IS_8703B_SERIES(ChipVersion)) + cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8703B_"); + else if (IS_8723D_SERIES(ChipVersion)) + cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8723D_"); + else if (IS_8814A_SERIES(ChipVersion)) + cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8814A_"); + else if (IS_8822B_SERIES(ChipVersion)) + cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8822B_"); + else if (IS_8821C_SERIES(ChipVersion)) + cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8821C_"); + else + cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_UNKNOWN_"); + + cnt += sprintf((buf + cnt), "%s_", IS_NORMAL_CHIP(ChipVersion) ? "Normal_Chip" : "Test_Chip"); + if (IS_CHIP_VENDOR_TSMC(ChipVersion)) + cnt += sprintf((buf + cnt), "%s_", "TSMC"); + else if (IS_CHIP_VENDOR_UMC(ChipVersion)) + cnt += sprintf((buf + cnt), "%s_", "UMC"); + else if (IS_CHIP_VENDOR_SMIC(ChipVersion)) + cnt += sprintf((buf + cnt), "%s_", "SMIC"); + + if (IS_A_CUT(ChipVersion)) + cnt += sprintf((buf + cnt), "A_CUT_"); + else if (IS_B_CUT(ChipVersion)) + cnt += sprintf((buf + cnt), "B_CUT_"); + else if (IS_C_CUT(ChipVersion)) + cnt += sprintf((buf + cnt), "C_CUT_"); + else if (IS_D_CUT(ChipVersion)) + cnt += sprintf((buf + cnt), "D_CUT_"); + else if (IS_E_CUT(ChipVersion)) + cnt += sprintf((buf + cnt), "E_CUT_"); + else if (IS_F_CUT(ChipVersion)) + cnt += sprintf((buf + cnt), "F_CUT_"); + else if (IS_I_CUT(ChipVersion)) + cnt += sprintf((buf + cnt), "I_CUT_"); + else if (IS_J_CUT(ChipVersion)) + cnt += sprintf((buf + cnt), "J_CUT_"); + else if (IS_K_CUT(ChipVersion)) + cnt += sprintf((buf + cnt), "K_CUT_"); + else + cnt += sprintf((buf + cnt), "UNKNOWN_CUT(%d)_", ChipVersion.CUTVersion); + + if (IS_1T1R(ChipVersion)) + cnt += sprintf((buf + cnt), "1T1R_"); + else if (IS_1T2R(ChipVersion)) + cnt += sprintf((buf + cnt), "1T2R_"); + else if (IS_2T2R(ChipVersion)) + cnt += sprintf((buf + cnt), "2T2R_"); + else if (IS_3T3R(ChipVersion)) + cnt += sprintf((buf + cnt), "3T3R_"); + else if (IS_3T4R(ChipVersion)) + cnt += sprintf((buf + cnt), "3T4R_"); + else if (IS_4T4R(ChipVersion)) + cnt += sprintf((buf + cnt), "4T4R_"); + else + cnt += sprintf((buf + cnt), "UNKNOWN_RFTYPE(%d)_", ChipVersion.RFType); + + cnt += sprintf((buf + cnt), "RomVer(%d)\n", ChipVersion.ROMVer); + + RTW_INFO("%s", buf); +} +void rtw_hal_config_rftype(PADAPTER padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + if (IS_1T1R(pHalData->version_id)) { + pHalData->rf_type = RF_1T1R; + pHalData->NumTotalRFPath = 1; + } else if (IS_2T2R(pHalData->version_id)) { + pHalData->rf_type = RF_2T2R; + pHalData->NumTotalRFPath = 2; + } else if (IS_1T2R(pHalData->version_id)) { + pHalData->rf_type = RF_1T2R; + pHalData->NumTotalRFPath = 2; + } else if (IS_3T3R(pHalData->version_id)) { + pHalData->rf_type = RF_3T3R; + pHalData->NumTotalRFPath = 3; + } else if (IS_4T4R(pHalData->version_id)) { + pHalData->rf_type = RF_4T4R; + pHalData->NumTotalRFPath = 4; + } else { + pHalData->rf_type = RF_1T1R; + pHalData->NumTotalRFPath = 1; + } + + RTW_INFO("%s RF_Type is %d TotalTxPath is %d\n", __func__, pHalData->rf_type, pHalData->NumTotalRFPath); +} + +#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 + +/* + * Description: + * Use hardware(efuse), driver parameter(registry) and default channel plan + * to decide which one should be used. + * + * Parameters: + * padapter pointer of adapter + * hw_alpha2 country code from HW (efuse/eeprom/mapfile) + * hw_chplan channel plan from HW (efuse/eeprom/mapfile) + * BIT[7] software configure mode; 0:Enable, 1:disable + * BIT[6:0] Channel Plan + * sw_alpha2 country code from HW (registry/module param) + * sw_chplan channel plan from SW (registry/module param) + * def_chplan channel plan used when HW/SW both invalid + * AutoLoadFail efuse autoload fail or not + * + * Return: + * Final channel plan decision + * + */ +u8 hal_com_config_channel_plan( + PADAPTER padapter, + char *hw_alpha2, + u8 hw_chplan, + char *sw_alpha2, + u8 sw_chplan, + u8 def_chplan, + bool AutoLoadFail +) +{ + PHAL_DATA_TYPE pHalData; + u8 force_hw_chplan = false; + int chplan = -1; + const struct country_chplan *country_ent = NULL, *ent; + + pHalData = GET_HAL_DATA(padapter); + + /* treat 0xFF as invalid value, bypass hw_chplan & force_hw_chplan parsing */ + if (hw_chplan == 0xFF) + goto chk_hw_country_code; + + if (AutoLoadFail == true) + goto chk_sw_config; + +#ifndef CONFIG_FORCE_SW_CHANNEL_PLAN + if (hw_chplan & EEPROM_CHANNEL_PLAN_BY_HW_MASK) + force_hw_chplan = true; +#endif + + hw_chplan &= (~EEPROM_CHANNEL_PLAN_BY_HW_MASK); + +chk_hw_country_code: + if (hw_alpha2 && !IS_ALPHA2_NO_SPECIFIED(hw_alpha2)) { + ent = rtw_get_chplan_from_country(hw_alpha2); + if (ent) { + /* get chplan from hw country code, by pass hw chplan setting */ + country_ent = ent; + chplan = ent->chplan; + goto chk_sw_config; + } else + RTW_PRINT("%s unsupported hw_alpha2:\"%c%c\"\n", __func__, hw_alpha2[0], hw_alpha2[1]); + } + + if (rtw_is_channel_plan_valid(hw_chplan)) + chplan = hw_chplan; + else if (force_hw_chplan == true) { + RTW_PRINT("%s unsupported hw_chplan:0x%02X\n", __func__, hw_chplan); + /* hw infomaton invalid, refer to sw information */ + force_hw_chplan = false; + } + +chk_sw_config: + if (force_hw_chplan == true) + goto done; + + if (sw_alpha2 && !IS_ALPHA2_NO_SPECIFIED(sw_alpha2)) { + ent = rtw_get_chplan_from_country(sw_alpha2); + if (ent) { + /* get chplan from sw country code, by pass sw chplan setting */ + country_ent = ent; + chplan = ent->chplan; + goto done; + } else + RTW_PRINT("%s unsupported sw_alpha2:\"%c%c\"\n", __func__, sw_alpha2[0], sw_alpha2[1]); + } + + if (rtw_is_channel_plan_valid(sw_chplan)) { + /* cancel hw_alpha2 because chplan is specified by sw_chplan*/ + country_ent = NULL; + chplan = sw_chplan; + } else if (sw_chplan != RTW_CHPLAN_MAX) + RTW_PRINT("%s unsupported sw_chplan:0x%02X\n", __func__, sw_chplan); + +done: + if (chplan == -1) { + RTW_PRINT("%s use def_chplan:0x%02X\n", __func__, def_chplan); + chplan = def_chplan; + } else if (country_ent) { + RTW_PRINT("%s country code:\"%c%c\" with chplan:0x%02X\n", __func__ + , country_ent->alpha2[0], country_ent->alpha2[1], country_ent->chplan); + } else + RTW_PRINT("%s chplan:0x%02X\n", __func__, chplan); + + padapter->mlmepriv.country_ent = country_ent; + pHalData->bDisableSWChannelPlan = force_hw_chplan; + + return chplan; +} + +bool +HAL_IsLegalChannel( + PADAPTER Adapter, + u32 Channel +) +{ + bool bLegalChannel = true; + + if (Channel > 14) { + if (is_supported_5g(Adapter->registrypriv.wireless_mode) == false) { + bLegalChannel = false; + RTW_INFO("Channel > 14 but wireless_mode do not support 5G\n"); + } + } else if ((Channel <= 14) && (Channel >= 1)) { + if (IsSupported24G(Adapter->registrypriv.wireless_mode) == false) { + bLegalChannel = false; + RTW_INFO("(Channel <= 14) && (Channel >=1) but wireless_mode do not support 2.4G\n"); + } + } else { + bLegalChannel = false; + RTW_INFO("Channel is Invalid !!!\n"); + } + + return bLegalChannel; +} + +u8 MRateToHwRate(u8 rate) +{ + u8 ret = DESC_RATE1M; + + switch (rate) { + case MGN_1M: + ret = DESC_RATE1M; + break; + case MGN_2M: + ret = DESC_RATE2M; + break; + case MGN_5_5M: + ret = DESC_RATE5_5M; + break; + case MGN_11M: + ret = DESC_RATE11M; + break; + case MGN_6M: + ret = DESC_RATE6M; + break; + case MGN_9M: + ret = DESC_RATE9M; + break; + case MGN_12M: + ret = DESC_RATE12M; + break; + case MGN_18M: + ret = DESC_RATE18M; + break; + case MGN_24M: + ret = DESC_RATE24M; + break; + case MGN_36M: + ret = DESC_RATE36M; + break; + case MGN_48M: + ret = DESC_RATE48M; + break; + case MGN_54M: + ret = DESC_RATE54M; + break; + + case MGN_MCS0: + ret = DESC_RATEMCS0; + break; + case MGN_MCS1: + ret = DESC_RATEMCS1; + break; + case MGN_MCS2: + ret = DESC_RATEMCS2; + break; + case MGN_MCS3: + ret = DESC_RATEMCS3; + break; + case MGN_MCS4: + ret = DESC_RATEMCS4; + break; + case MGN_MCS5: + ret = DESC_RATEMCS5; + break; + case MGN_MCS6: + ret = DESC_RATEMCS6; + break; + case MGN_MCS7: + ret = DESC_RATEMCS7; + break; + case MGN_MCS8: + ret = DESC_RATEMCS8; + break; + case MGN_MCS9: + ret = DESC_RATEMCS9; + break; + case MGN_MCS10: + ret = DESC_RATEMCS10; + break; + case MGN_MCS11: + ret = DESC_RATEMCS11; + break; + case MGN_MCS12: + ret = DESC_RATEMCS12; + break; + case MGN_MCS13: + ret = DESC_RATEMCS13; + break; + case MGN_MCS14: + ret = DESC_RATEMCS14; + break; + case MGN_MCS15: + ret = DESC_RATEMCS15; + break; + case MGN_MCS16: + ret = DESC_RATEMCS16; + break; + case MGN_MCS17: + ret = DESC_RATEMCS17; + break; + case MGN_MCS18: + ret = DESC_RATEMCS18; + break; + case MGN_MCS19: + ret = DESC_RATEMCS19; + break; + case MGN_MCS20: + ret = DESC_RATEMCS20; + break; + case MGN_MCS21: + ret = DESC_RATEMCS21; + break; + case MGN_MCS22: + ret = DESC_RATEMCS22; + break; + case MGN_MCS23: + ret = DESC_RATEMCS23; + break; + case MGN_MCS24: + ret = DESC_RATEMCS24; + break; + case MGN_MCS25: + ret = DESC_RATEMCS25; + break; + case MGN_MCS26: + ret = DESC_RATEMCS26; + break; + case MGN_MCS27: + ret = DESC_RATEMCS27; + break; + case MGN_MCS28: + ret = DESC_RATEMCS28; + break; + case MGN_MCS29: + ret = DESC_RATEMCS29; + break; + case MGN_MCS30: + ret = DESC_RATEMCS30; + break; + case MGN_MCS31: + ret = DESC_RATEMCS31; + break; + + case MGN_VHT1SS_MCS0: + ret = DESC_RATEVHTSS1MCS0; + break; + case MGN_VHT1SS_MCS1: + ret = DESC_RATEVHTSS1MCS1; + break; + case MGN_VHT1SS_MCS2: + ret = DESC_RATEVHTSS1MCS2; + break; + case MGN_VHT1SS_MCS3: + ret = DESC_RATEVHTSS1MCS3; + break; + case MGN_VHT1SS_MCS4: + ret = DESC_RATEVHTSS1MCS4; + break; + case MGN_VHT1SS_MCS5: + ret = DESC_RATEVHTSS1MCS5; + break; + case MGN_VHT1SS_MCS6: + ret = DESC_RATEVHTSS1MCS6; + break; + case MGN_VHT1SS_MCS7: + ret = DESC_RATEVHTSS1MCS7; + break; + case MGN_VHT1SS_MCS8: + ret = DESC_RATEVHTSS1MCS8; + break; + case MGN_VHT1SS_MCS9: + ret = DESC_RATEVHTSS1MCS9; + break; + case MGN_VHT2SS_MCS0: + ret = DESC_RATEVHTSS2MCS0; + break; + case MGN_VHT2SS_MCS1: + ret = DESC_RATEVHTSS2MCS1; + break; + case MGN_VHT2SS_MCS2: + ret = DESC_RATEVHTSS2MCS2; + break; + case MGN_VHT2SS_MCS3: + ret = DESC_RATEVHTSS2MCS3; + break; + case MGN_VHT2SS_MCS4: + ret = DESC_RATEVHTSS2MCS4; + break; + case MGN_VHT2SS_MCS5: + ret = DESC_RATEVHTSS2MCS5; + break; + case MGN_VHT2SS_MCS6: + ret = DESC_RATEVHTSS2MCS6; + break; + case MGN_VHT2SS_MCS7: + ret = DESC_RATEVHTSS2MCS7; + break; + case MGN_VHT2SS_MCS8: + ret = DESC_RATEVHTSS2MCS8; + break; + case MGN_VHT2SS_MCS9: + ret = DESC_RATEVHTSS2MCS9; + break; + case MGN_VHT3SS_MCS0: + ret = DESC_RATEVHTSS3MCS0; + break; + case MGN_VHT3SS_MCS1: + ret = DESC_RATEVHTSS3MCS1; + break; + case MGN_VHT3SS_MCS2: + ret = DESC_RATEVHTSS3MCS2; + break; + case MGN_VHT3SS_MCS3: + ret = DESC_RATEVHTSS3MCS3; + break; + case MGN_VHT3SS_MCS4: + ret = DESC_RATEVHTSS3MCS4; + break; + case MGN_VHT3SS_MCS5: + ret = DESC_RATEVHTSS3MCS5; + break; + case MGN_VHT3SS_MCS6: + ret = DESC_RATEVHTSS3MCS6; + break; + case MGN_VHT3SS_MCS7: + ret = DESC_RATEVHTSS3MCS7; + break; + case MGN_VHT3SS_MCS8: + ret = DESC_RATEVHTSS3MCS8; + break; + case MGN_VHT3SS_MCS9: + ret = DESC_RATEVHTSS3MCS9; + break; + case MGN_VHT4SS_MCS0: + ret = DESC_RATEVHTSS4MCS0; + break; + case MGN_VHT4SS_MCS1: + ret = DESC_RATEVHTSS4MCS1; + break; + case MGN_VHT4SS_MCS2: + ret = DESC_RATEVHTSS4MCS2; + break; + case MGN_VHT4SS_MCS3: + ret = DESC_RATEVHTSS4MCS3; + break; + case MGN_VHT4SS_MCS4: + ret = DESC_RATEVHTSS4MCS4; + break; + case MGN_VHT4SS_MCS5: + ret = DESC_RATEVHTSS4MCS5; + break; + case MGN_VHT4SS_MCS6: + ret = DESC_RATEVHTSS4MCS6; + break; + case MGN_VHT4SS_MCS7: + ret = DESC_RATEVHTSS4MCS7; + break; + case MGN_VHT4SS_MCS8: + ret = DESC_RATEVHTSS4MCS8; + break; + case MGN_VHT4SS_MCS9: + ret = DESC_RATEVHTSS4MCS9; + break; + default: + break; + } + + return ret; +} + +u8 hw_rate_to_m_rate(u8 rate) +{ + u8 ret_rate = MGN_1M; + + switch (rate) { + + case DESC_RATE1M: + ret_rate = MGN_1M; + break; + case DESC_RATE2M: + ret_rate = MGN_2M; + break; + case DESC_RATE5_5M: + ret_rate = MGN_5_5M; + break; + case DESC_RATE11M: + ret_rate = MGN_11M; + break; + case DESC_RATE6M: + ret_rate = MGN_6M; + break; + case DESC_RATE9M: + ret_rate = MGN_9M; + break; + case DESC_RATE12M: + ret_rate = MGN_12M; + break; + case DESC_RATE18M: + ret_rate = MGN_18M; + break; + case DESC_RATE24M: + ret_rate = MGN_24M; + break; + case DESC_RATE36M: + ret_rate = MGN_36M; + break; + case DESC_RATE48M: + ret_rate = MGN_48M; + break; + case DESC_RATE54M: + ret_rate = MGN_54M; + break; + case DESC_RATEMCS0: + ret_rate = MGN_MCS0; + break; + case DESC_RATEMCS1: + ret_rate = MGN_MCS1; + break; + case DESC_RATEMCS2: + ret_rate = MGN_MCS2; + break; + case DESC_RATEMCS3: + ret_rate = MGN_MCS3; + break; + case DESC_RATEMCS4: + ret_rate = MGN_MCS4; + break; + case DESC_RATEMCS5: + ret_rate = MGN_MCS5; + break; + case DESC_RATEMCS6: + ret_rate = MGN_MCS6; + break; + case DESC_RATEMCS7: + ret_rate = MGN_MCS7; + break; + case DESC_RATEMCS8: + ret_rate = MGN_MCS8; + break; + case DESC_RATEMCS9: + ret_rate = MGN_MCS9; + break; + case DESC_RATEMCS10: + ret_rate = MGN_MCS10; + break; + case DESC_RATEMCS11: + ret_rate = MGN_MCS11; + break; + case DESC_RATEMCS12: + ret_rate = MGN_MCS12; + break; + case DESC_RATEMCS13: + ret_rate = MGN_MCS13; + break; + case DESC_RATEMCS14: + ret_rate = MGN_MCS14; + break; + case DESC_RATEMCS15: + ret_rate = MGN_MCS15; + break; + case DESC_RATEMCS16: + ret_rate = MGN_MCS16; + break; + case DESC_RATEMCS17: + ret_rate = MGN_MCS17; + break; + case DESC_RATEMCS18: + ret_rate = MGN_MCS18; + break; + case DESC_RATEMCS19: + ret_rate = MGN_MCS19; + break; + case DESC_RATEMCS20: + ret_rate = MGN_MCS20; + break; + case DESC_RATEMCS21: + ret_rate = MGN_MCS21; + break; + case DESC_RATEMCS22: + ret_rate = MGN_MCS22; + break; + case DESC_RATEMCS23: + ret_rate = MGN_MCS23; + break; + case DESC_RATEMCS24: + ret_rate = MGN_MCS24; + break; + case DESC_RATEMCS25: + ret_rate = MGN_MCS25; + break; + case DESC_RATEMCS26: + ret_rate = MGN_MCS26; + break; + case DESC_RATEMCS27: + ret_rate = MGN_MCS27; + break; + case DESC_RATEMCS28: + ret_rate = MGN_MCS28; + break; + case DESC_RATEMCS29: + ret_rate = MGN_MCS29; + break; + case DESC_RATEMCS30: + ret_rate = MGN_MCS30; + break; + case DESC_RATEMCS31: + ret_rate = MGN_MCS31; + break; + case DESC_RATEVHTSS1MCS0: + ret_rate = MGN_VHT1SS_MCS0; + break; + case DESC_RATEVHTSS1MCS1: + ret_rate = MGN_VHT1SS_MCS1; + break; + case DESC_RATEVHTSS1MCS2: + ret_rate = MGN_VHT1SS_MCS2; + break; + case DESC_RATEVHTSS1MCS3: + ret_rate = MGN_VHT1SS_MCS3; + break; + case DESC_RATEVHTSS1MCS4: + ret_rate = MGN_VHT1SS_MCS4; + break; + case DESC_RATEVHTSS1MCS5: + ret_rate = MGN_VHT1SS_MCS5; + break; + case DESC_RATEVHTSS1MCS6: + ret_rate = MGN_VHT1SS_MCS6; + break; + case DESC_RATEVHTSS1MCS7: + ret_rate = MGN_VHT1SS_MCS7; + break; + case DESC_RATEVHTSS1MCS8: + ret_rate = MGN_VHT1SS_MCS8; + break; + case DESC_RATEVHTSS1MCS9: + ret_rate = MGN_VHT1SS_MCS9; + break; + case DESC_RATEVHTSS2MCS0: + ret_rate = MGN_VHT2SS_MCS0; + break; + case DESC_RATEVHTSS2MCS1: + ret_rate = MGN_VHT2SS_MCS1; + break; + case DESC_RATEVHTSS2MCS2: + ret_rate = MGN_VHT2SS_MCS2; + break; + case DESC_RATEVHTSS2MCS3: + ret_rate = MGN_VHT2SS_MCS3; + break; + case DESC_RATEVHTSS2MCS4: + ret_rate = MGN_VHT2SS_MCS4; + break; + case DESC_RATEVHTSS2MCS5: + ret_rate = MGN_VHT2SS_MCS5; + break; + case DESC_RATEVHTSS2MCS6: + ret_rate = MGN_VHT2SS_MCS6; + break; + case DESC_RATEVHTSS2MCS7: + ret_rate = MGN_VHT2SS_MCS7; + break; + case DESC_RATEVHTSS2MCS8: + ret_rate = MGN_VHT2SS_MCS8; + break; + case DESC_RATEVHTSS2MCS9: + ret_rate = MGN_VHT2SS_MCS9; + break; + case DESC_RATEVHTSS3MCS0: + ret_rate = MGN_VHT3SS_MCS0; + break; + case DESC_RATEVHTSS3MCS1: + ret_rate = MGN_VHT3SS_MCS1; + break; + case DESC_RATEVHTSS3MCS2: + ret_rate = MGN_VHT3SS_MCS2; + break; + case DESC_RATEVHTSS3MCS3: + ret_rate = MGN_VHT3SS_MCS3; + break; + case DESC_RATEVHTSS3MCS4: + ret_rate = MGN_VHT3SS_MCS4; + break; + case DESC_RATEVHTSS3MCS5: + ret_rate = MGN_VHT3SS_MCS5; + break; + case DESC_RATEVHTSS3MCS6: + ret_rate = MGN_VHT3SS_MCS6; + break; + case DESC_RATEVHTSS3MCS7: + ret_rate = MGN_VHT3SS_MCS7; + break; + case DESC_RATEVHTSS3MCS8: + ret_rate = MGN_VHT3SS_MCS8; + break; + case DESC_RATEVHTSS3MCS9: + ret_rate = MGN_VHT3SS_MCS9; + break; + case DESC_RATEVHTSS4MCS0: + ret_rate = MGN_VHT4SS_MCS0; + break; + case DESC_RATEVHTSS4MCS1: + ret_rate = MGN_VHT4SS_MCS1; + break; + case DESC_RATEVHTSS4MCS2: + ret_rate = MGN_VHT4SS_MCS2; + break; + case DESC_RATEVHTSS4MCS3: + ret_rate = MGN_VHT4SS_MCS3; + break; + case DESC_RATEVHTSS4MCS4: + ret_rate = MGN_VHT4SS_MCS4; + break; + case DESC_RATEVHTSS4MCS5: + ret_rate = MGN_VHT4SS_MCS5; + break; + case DESC_RATEVHTSS4MCS6: + ret_rate = MGN_VHT4SS_MCS6; + break; + case DESC_RATEVHTSS4MCS7: + ret_rate = MGN_VHT4SS_MCS7; + break; + case DESC_RATEVHTSS4MCS8: + ret_rate = MGN_VHT4SS_MCS8; + break; + case DESC_RATEVHTSS4MCS9: + ret_rate = MGN_VHT4SS_MCS9; + break; + + default: + RTW_INFO("hw_rate_to_m_rate(): Non supported Rate [%x]!!!\n", rate); + break; + } + + return ret_rate; +} + +void HalSetBrateCfg( + PADAPTER Adapter, + u8 *mBratesOS, + u16 *pBrateCfg) +{ + u8 i, is_brate, brate; + + for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { + is_brate = mBratesOS[i] & IEEE80211_BASIC_RATE_MASK; + brate = mBratesOS[i] & 0x7f; + + if (is_brate) { + switch (brate) { + case IEEE80211_CCK_RATE_1MB: + *pBrateCfg |= RATE_1M; + break; + case IEEE80211_CCK_RATE_2MB: + *pBrateCfg |= RATE_2M; + break; + case IEEE80211_CCK_RATE_5MB: + *pBrateCfg |= RATE_5_5M; + break; + case IEEE80211_CCK_RATE_11MB: + *pBrateCfg |= RATE_11M; + break; + case IEEE80211_OFDM_RATE_6MB: + *pBrateCfg |= RATE_6M; + break; + case IEEE80211_OFDM_RATE_9MB: + *pBrateCfg |= RATE_9M; + break; + case IEEE80211_OFDM_RATE_12MB: + *pBrateCfg |= RATE_12M; + break; + case IEEE80211_OFDM_RATE_18MB: + *pBrateCfg |= RATE_18M; + break; + case IEEE80211_OFDM_RATE_24MB: + *pBrateCfg |= RATE_24M; + break; + case IEEE80211_OFDM_RATE_36MB: + *pBrateCfg |= RATE_36M; + break; + case IEEE80211_OFDM_RATE_48MB: + *pBrateCfg |= RATE_48M; + break; + case IEEE80211_OFDM_RATE_54MB: + *pBrateCfg |= RATE_54M; + break; + } + } + } +} + +static void +_OneOutPipeMapping( + PADAPTER pAdapter +) +{ + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter); + + pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */ + pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */ + pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[0];/* BE */ + pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0];/* BK */ + + pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */ + pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */ + pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */ + pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */ +} + +static void +_TwoOutPipeMapping( + PADAPTER pAdapter, + bool bWIFICfg +) +{ + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter); + + if (bWIFICfg) { /* WMM */ + + /* BK, BE, VI, VO, BCN, CMD,MGT,HIGH,HCCA */ + /* { 0, 1, 0, 1, 0, 0, 0, 0, 0 }; */ + /* 0:ep_0 num, 1:ep_1 num */ + + pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[1];/* VO */ + pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */ + pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1];/* BE */ + pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0];/* BK */ + + pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */ + pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */ + pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */ + pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */ + + } else { /* typical setting */ + + + /* BK, BE, VI, VO, BCN, CMD,MGT,HIGH,HCCA */ + /* { 1, 1, 0, 0, 0, 0, 0, 0, 0 }; */ + /* 0:ep_0 num, 1:ep_1 num */ + + pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */ + pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */ + pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1];/* BE */ + pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1];/* BK */ + + pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */ + pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */ + pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */ + pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */ + + } + +} + +static void _ThreeOutPipeMapping( + PADAPTER pAdapter, + bool bWIFICfg +) +{ + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter); + + if (bWIFICfg) { /* for WMM */ + + /* BK, BE, VI, VO, BCN, CMD,MGT,HIGH,HCCA */ + /* { 1, 2, 1, 0, 0, 0, 0, 0, 0 }; */ + /* 0:H, 1:N, 2:L */ + + pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */ + pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */ + pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */ + pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1];/* BK */ + + pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */ + pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */ + pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */ + pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */ + + } else { /* typical setting */ + + + /* BK, BE, VI, VO, BCN, CMD,MGT,HIGH,HCCA */ + /* { 2, 2, 1, 0, 0, 0, 0, 0, 0 }; */ + /* 0:H, 1:N, 2:L */ + + pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */ + pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */ + pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */ + pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[2];/* BK */ + + pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */ + pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */ + pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */ + pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */ + } + +} +static void _FourOutPipeMapping( + PADAPTER pAdapter, + bool bWIFICfg +) +{ + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter); + + if (bWIFICfg) { /* for WMM */ + + /* BK, BE, VI, VO, BCN, CMD,MGT,HIGH,HCCA */ + /* { 1, 2, 1, 0, 0, 0, 0, 0, 0 }; */ + /* 0:H, 1:N, 2:L ,3:E */ + + pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */ + pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */ + pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */ + pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1];/* BK */ + + pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */ + pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */ + pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[3];/* HIGH */ + pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */ + + } else { /* typical setting */ + + + /* BK, BE, VI, VO, BCN, CMD,MGT,HIGH,HCCA */ + /* { 2, 2, 1, 0, 0, 0, 0, 0, 0 }; */ + /* 0:H, 1:N, 2:L */ + + pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */ + pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */ + pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */ + pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[2];/* BK */ + + pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */ + pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */ + pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[3];/* HIGH */ + pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */ + } + +} +bool +Hal_MappingOutPipe( + PADAPTER pAdapter, + u8 NumOutPipe +) +{ + struct registry_priv *pregistrypriv = &pAdapter->registrypriv; + + bool bWIFICfg = (pregistrypriv->wifi_spec) ? true : false; + + bool result = true; + + switch (NumOutPipe) { + case 2: + _TwoOutPipeMapping(pAdapter, bWIFICfg); + break; + case 3: + case 4: + _ThreeOutPipeMapping(pAdapter, bWIFICfg); + break; + case 1: + _OneOutPipeMapping(pAdapter); + break; + default: + result = false; + break; + } + + return result; + +} + +void rtw_hal_reqtxrpt(_adapter *padapter, u8 macid) +{ + if (padapter->hal_func.reqtxrpt) + padapter->hal_func.reqtxrpt(padapter, macid); +} + +void rtw_hal_dump_macaddr(void *sel, _adapter *adapter) +{ + int i; + _adapter *iface; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + u8 mac_addr[ETH_ALEN]; + +#ifdef CONFIG_MI_WITH_MBSSID_CAM + rtw_mbid_cam_dump(sel, __func__, adapter); +#else + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (iface) { + rtw_hal_get_macaddr_port(iface, mac_addr); + RTW_INFO(ADPT_FMT"- hw port(%d) mac_addr ="MAC_FMT"\n", + ADPT_ARG(iface), iface->hw_port, MAC_ARG(mac_addr)); + } + } +#endif +} + +void rtw_restore_mac_addr(_adapter *adapter) +{ +#ifdef CONFIG_MI_WITH_MBSSID_CAM + _adapter *iface; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + + rtw_mbid_cam_restore(adapter); +#else + int i; + _adapter *iface; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (iface) + rtw_hal_set_macaddr_port(iface, adapter_mac_addr(iface)); + } +#endif + if (1) + rtw_hal_dump_macaddr(RTW_DBGDUMP, adapter); +} + +void rtw_init_hal_com_default_value(PADAPTER Adapter) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter); + struct registry_priv *regsty = adapter_to_regsty(Adapter); + + pHalData->AntDetection = 1; + pHalData->antenna_test = false; + pHalData->u1ForcedIgiLb = regsty->force_igi_lb; +} + +#ifdef CONFIG_FW_C2H_REG +void c2h_evt_clear(_adapter *adapter) +{ + rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE); +} + +s32 c2h_evt_read_88xx(_adapter *adapter, u8 *buf) +{ + s32 ret = _FAIL; + int i; + u8 trigger; + + if (buf == NULL) + goto exit; + + trigger = rtw_read8(adapter, REG_C2HEVT_CLEAR); + + if (trigger == C2H_EVT_HOST_CLOSE) { + goto exit; /* Not ready */ + } else if (trigger != C2H_EVT_FW_CLOSE) { + goto clear_evt; /* Not a valid value */ + } + + memset(buf, 0, C2H_REG_LEN); + + /* Read ID, LEN, SEQ */ + SET_C2H_ID_88XX(buf, rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL)); + SET_C2H_SEQ_88XX(buf, rtw_read8(adapter, REG_C2HEVT_CMD_SEQ_88XX)); + SET_C2H_PLEN_88XX(buf, rtw_read8(adapter, REG_C2HEVT_CMD_LEN_88XX)); + + if (0) { + RTW_INFO("%s id=0x%02x, seq=%u, plen=%u, trigger=0x%02x\n", __func__ + , C2H_ID_88XX(buf), C2H_SEQ_88XX(buf), C2H_PLEN_88XX(buf), trigger); + } + + /* Read the content */ + for (i = 0; i < C2H_PLEN_88XX(buf); i++) + *(C2H_PAYLOAD_88XX(buf) + i) = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 2 + i); + + RTW_DBG_DUMP("payload:\n", C2H_PAYLOAD_88XX(buf), C2H_PLEN_88XX(buf)); + + ret = _SUCCESS; + +clear_evt: + /* + * Clear event to notify FW we have read the command. + * If this field isn't clear, the FW won't update the next command message. + */ + c2h_evt_clear(adapter); + +exit: + return ret; +} +#endif /* CONFIG_FW_C2H_REG */ + +#ifdef CONFIG_FW_C2H_PKT +#ifndef DBG_C2H_PKT_PRE_HDL +#define DBG_C2H_PKT_PRE_HDL 0 +#endif +#ifndef DBG_C2H_PKT_HDL +#define DBG_C2H_PKT_HDL 0 +#endif +void rtw_hal_c2h_pkt_pre_hdl(_adapter *adapter, u8 *buf, u16 len) +{ +#ifdef RTW_HALMAC + /* TODO: extract hal_mac IC's code here*/ +#else + u8 parse_fail = 0; + u8 hdl_here = 0; + s32 ret = _FAIL; + u8 id, seq, plen; + u8 *payload; + + if (rtw_hal_c2h_pkt_hdr_parse(adapter, buf, len, &id, &seq, &plen, &payload) != _SUCCESS) { + parse_fail = 1; + goto exit; + } + + hdl_here = rtw_hal_c2h_id_handle_directly(adapter, id, seq, plen, payload) == true ? 1 : 0; + if (hdl_here) + ret = rtw_hal_c2h_handler(adapter, id, seq, plen, payload); + else + ret = rtw_c2h_packet_wk_cmd(adapter, buf, len); + +exit: + if (parse_fail) + RTW_ERR("%s parse fail, buf=%p, len=:%u\n", __func__, buf, len); + else if (ret != _SUCCESS || DBG_C2H_PKT_PRE_HDL > 0) { + RTW_PRINT("%s: id=0x%02x, seq=%u, plen=%u, %s %s\n", __func__, id, seq, plen + , hdl_here ? "handle" : "enqueue" + , ret == _SUCCESS ? "ok" : "fail" + ); + if (DBG_C2H_PKT_PRE_HDL >= 2) + RTW_PRINT_DUMP("dump: ", buf, len); + } +#endif +} + +void rtw_hal_c2h_pkt_hdl(_adapter *adapter, u8 *buf, u16 len) +{ +#ifdef RTW_HALMAC + adapter->hal_func.hal_mac_c2h_handler(adapter, buf, len); +#else + u8 parse_fail = 0; + u8 bypass = 0; + s32 ret = _FAIL; + u8 id, seq, plen; + u8 *payload; + + if (rtw_hal_c2h_pkt_hdr_parse(adapter, buf, len, &id, &seq, &plen, &payload) != _SUCCESS) { + parse_fail = 1; + goto exit; + } + +#ifdef CONFIG_WOWLAN + if (adapter_to_pwrctl(adapter)->wowlan_mode == true) { + bypass = 1; + ret = _SUCCESS; + goto exit; + } +#endif + + ret = rtw_hal_c2h_handler(adapter, id, seq, plen, payload); + +exit: + if (parse_fail) + RTW_ERR("%s parse fail, buf=%p, len=:%u\n", __func__, buf, len); + else if (ret != _SUCCESS || bypass || DBG_C2H_PKT_HDL > 0) { + RTW_PRINT("%s: id=0x%02x, seq=%u, plen=%u, %s %s\n", __func__, id, seq, plen + , !bypass ? "handle" : "bypass" + , ret == _SUCCESS ? "ok" : "fail" + ); + if (DBG_C2H_PKT_HDL >= 2) + RTW_PRINT_DUMP("dump: ", buf, len); + } +#endif +} +#endif /* CONFIG_FW_C2H_PKT */ + +void c2h_iqk_offload(_adapter *adapter, u8 *data, u8 len) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + struct submit_ctx *iqk_sctx = &hal_data->iqk_sctx; + + RTW_INFO("IQK offload finish in %dms\n", rtw_get_passing_time_ms(iqk_sctx->submit_time)); + if (0) + RTW_INFO_DUMP("C2H_IQK_FINISH: ", data, len); + + rtw_sctx_done(&iqk_sctx); +} + +int c2h_iqk_offload_wait(_adapter *adapter, u32 timeout_ms) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + struct submit_ctx *iqk_sctx = &hal_data->iqk_sctx; + + iqk_sctx->submit_time = jiffies; + iqk_sctx->timeout_ms = timeout_ms; + iqk_sctx->status = RTW_SCTX_SUBMITTED; + + return rtw_sctx_wait(iqk_sctx, __func__); +} + +#define GET_C2H_MAC_HIDDEN_RPT_UUID_X(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 0, 0, 8) +#define GET_C2H_MAC_HIDDEN_RPT_UUID_Y(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 1, 0, 8) +#define GET_C2H_MAC_HIDDEN_RPT_UUID_Z(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 2, 0, 5) +#define GET_C2H_MAC_HIDDEN_RPT_UUID_CRC(_data) LE_BITS_TO_2BYTE(((u8 *)(_data)) + 2, 5, 11) +#define GET_C2H_MAC_HIDDEN_RPT_HCI_TYPE(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 4, 0, 4) +#define GET_C2H_MAC_HIDDEN_RPT_PACKAGE_TYPE(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 4, 4, 3) +#define GET_C2H_MAC_HIDDEN_RPT_TR_SWITCH(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 4, 7, 1) +#define GET_C2H_MAC_HIDDEN_RPT_WL_FUNC(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 5, 0, 4) +#define GET_C2H_MAC_HIDDEN_RPT_HW_STYPE(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 5, 4, 4) +#define GET_C2H_MAC_HIDDEN_RPT_BW(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 6, 0, 3) +#define GET_C2H_MAC_HIDDEN_RPT_FAB(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 6, 3, 2) +#define GET_C2H_MAC_HIDDEN_RPT_ANT_NUM(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 6, 5, 3) +#define GET_C2H_MAC_HIDDEN_RPT_80211_PROTOCOL(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 7, 2, 2) +#define GET_C2H_MAC_HIDDEN_RPT_NIC_ROUTER(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 7, 6, 2) + +#ifndef DBG_C2H_MAC_HIDDEN_RPT_HANDLE +#define DBG_C2H_MAC_HIDDEN_RPT_HANDLE 0 +#endif + +#ifdef CONFIG_RTW_MAC_HIDDEN_RPT +int c2h_mac_hidden_rpt_hdl(_adapter *adapter, u8 *data, u8 len) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + int ret = _FAIL; + + u32 uuid; + u8 uuid_x; + u8 uuid_y; + u8 uuid_z; + u16 uuid_crc; + + u8 hci_type; + u8 package_type; + u8 tr_switch; + u8 wl_func; + u8 hw_stype; + u8 bw; + u8 fab; + u8 ant_num; + u8 protocol; + u8 nic; + + int i; + + if (len < MAC_HIDDEN_RPT_LEN) { + RTW_WARN("%s len(%u) < %d\n", __func__, len, MAC_HIDDEN_RPT_LEN); + goto exit; + } + + uuid_x = GET_C2H_MAC_HIDDEN_RPT_UUID_X(data); + uuid_y = GET_C2H_MAC_HIDDEN_RPT_UUID_Y(data); + uuid_z = GET_C2H_MAC_HIDDEN_RPT_UUID_Z(data); + uuid_crc = GET_C2H_MAC_HIDDEN_RPT_UUID_CRC(data); + + hci_type = GET_C2H_MAC_HIDDEN_RPT_HCI_TYPE(data); + package_type = GET_C2H_MAC_HIDDEN_RPT_PACKAGE_TYPE(data); + + tr_switch = GET_C2H_MAC_HIDDEN_RPT_TR_SWITCH(data); + + wl_func = GET_C2H_MAC_HIDDEN_RPT_WL_FUNC(data); + hw_stype = GET_C2H_MAC_HIDDEN_RPT_HW_STYPE(data); + + bw = GET_C2H_MAC_HIDDEN_RPT_BW(data); + fab = GET_C2H_MAC_HIDDEN_RPT_FAB(data); + ant_num = GET_C2H_MAC_HIDDEN_RPT_ANT_NUM(data); + + protocol = GET_C2H_MAC_HIDDEN_RPT_80211_PROTOCOL(data); + nic = GET_C2H_MAC_HIDDEN_RPT_NIC_ROUTER(data); + + if (DBG_C2H_MAC_HIDDEN_RPT_HANDLE) { + for (i = 0; i < len; i++) + RTW_PRINT("%s: 0x%02X\n", __func__, *(data + i)); + + RTW_PRINT("uuid x:0x%02x y:0x%02x z:0x%x crc:0x%x\n", uuid_x, uuid_y, uuid_z, uuid_crc); + RTW_PRINT("hci_type:0x%x\n", hci_type); + RTW_PRINT("package_type:0x%x\n", package_type); + RTW_PRINT("tr_switch:0x%x\n", tr_switch); + RTW_PRINT("wl_func:0x%x\n", wl_func); + RTW_PRINT("hw_stype:0x%x\n", hw_stype); + RTW_PRINT("bw:0x%x\n", bw); + RTW_PRINT("fab:0x%x\n", fab); + RTW_PRINT("ant_num:0x%x\n", ant_num); + RTW_PRINT("protocol:0x%x\n", protocol); + RTW_PRINT("nic:0x%x\n", nic); + } + + /* + * NOTICE: + * for now, the following is common info/format + * if there is any hal difference need to export + * some IC dependent code will need to be implement + */ + hal_data->PackageType = package_type; + hal_spec->wl_func &= mac_hidden_wl_func_to_hal_wl_func(wl_func); + hal_spec->bw_cap &= mac_hidden_max_bw_to_hal_bw_cap(bw); + hal_spec->tx_nss_num = rtw_min(hal_spec->tx_nss_num, ant_num); + hal_spec->rx_nss_num = rtw_min(hal_spec->rx_nss_num, ant_num); + hal_spec->proto_cap &= mac_hidden_proto_to_hal_proto_cap(protocol); + hal_spec->hci_type = hci_type; + + /* TODO: tr_switch */ + /* TODO: fab */ + + ret = _SUCCESS; + +exit: + return ret; +} + +int c2h_mac_hidden_rpt_2_hdl(_adapter *adapter, u8 *data, u8 len) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + int ret = _FAIL; + + int i; + + if (len < MAC_HIDDEN_RPT_2_LEN) { + RTW_WARN("%s len(%u) < %d\n", __func__, len, MAC_HIDDEN_RPT_2_LEN); + goto exit; + } + + if (DBG_C2H_MAC_HIDDEN_RPT_HANDLE) { + for (i = 0; i < len; i++) + RTW_PRINT("%s: 0x%02X\n", __func__, *(data + i)); + } + + ret = _SUCCESS; + +exit: + return ret; +} + +int hal_read_mac_hidden_rpt(_adapter *adapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter); + int ret = _FAIL; + int ret_fwdl; + u8 mac_hidden_rpt[MAC_HIDDEN_RPT_LEN + MAC_HIDDEN_RPT_2_LEN] = {0}; + u32 start = jiffies; + u32 cnt = 0; + u32 timeout_ms = 800; + u32 min_cnt = 10; + u8 id = C2H_DEFEATURE_RSVD; + int i; + + u8 hci_type = rtw_get_intf_type(adapter); + + if ((hci_type == RTW_USB || hci_type == RTW_PCIE) + && !rtw_is_hw_init_completed(adapter)) + rtw_hal_power_on(adapter); + + /* inform FW mac hidden rpt from reg is needed */ + rtw_write8(adapter, REG_C2HEVT_MSG_NORMAL, C2H_DEFEATURE_RSVD); + + /* download FW */ + pHalData->not_xmitframe_fw_dl = 1; + ret_fwdl = rtw_hal_fw_dl(adapter, false); + pHalData->not_xmitframe_fw_dl = 0; + if (ret_fwdl != _SUCCESS) + goto mac_hidden_rpt_hdl; + + /* polling for data ready */ + start = jiffies; + do { + cnt++; + id = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL); + if (id == C2H_MAC_HIDDEN_RPT || RTW_CANNOT_IO(adapter)) + break; + rtw_msleep_os(10); + } while (rtw_get_passing_time_ms(start) < timeout_ms || cnt < min_cnt); + + if (id == C2H_MAC_HIDDEN_RPT) { + /* read data */ + for (i = 0; i < MAC_HIDDEN_RPT_LEN + MAC_HIDDEN_RPT_2_LEN; i++) + mac_hidden_rpt[i] = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 2 + i); + } + + /* inform FW mac hidden rpt has read */ + rtw_write8(adapter, REG_C2HEVT_MSG_NORMAL, C2H_DBG); + +mac_hidden_rpt_hdl: + c2h_mac_hidden_rpt_hdl(adapter, mac_hidden_rpt, MAC_HIDDEN_RPT_LEN); + c2h_mac_hidden_rpt_2_hdl(adapter, mac_hidden_rpt + MAC_HIDDEN_RPT_LEN, MAC_HIDDEN_RPT_2_LEN); + + if (ret_fwdl == _SUCCESS && id == C2H_MAC_HIDDEN_RPT) + ret = _SUCCESS; + +exit: + + if ((hci_type == RTW_USB || hci_type == RTW_PCIE) + && !rtw_is_hw_init_completed(adapter)) + rtw_hal_power_off(adapter); + + RTW_INFO("%s %s! (%u, %dms), fwdl:%d, id:0x%02x\n", __func__ + , (ret == _SUCCESS) ? "OK" : "Fail", cnt, rtw_get_passing_time_ms(start), ret_fwdl, id); + + return ret; +} +#endif /* CONFIG_RTW_MAC_HIDDEN_RPT */ + +int c2h_defeature_dbg_hdl(_adapter *adapter, u8 *data, u8 len) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + int ret = _FAIL; + + int i; + + if (len < DEFEATURE_DBG_LEN) { + RTW_WARN("%s len(%u) < %d\n", __func__, len, DEFEATURE_DBG_LEN); + goto exit; + } + + for (i = 0; i < len; i++) + RTW_PRINT("%s: 0x%02X\n", __func__, *(data + i)); + + ret = _SUCCESS; + +exit: + return ret; +} + +#ifndef DBG_CUSTOMER_STR_RPT_HANDLE +#define DBG_CUSTOMER_STR_RPT_HANDLE 0 +#endif + +#ifdef CONFIG_RTW_CUSTOMER_STR +s32 rtw_hal_h2c_customer_str_req(_adapter *adapter) +{ + u8 h2c_data[H2C_CUSTOMER_STR_REQ_LEN] = {0}; + + SET_H2CCMD_CUSTOMER_STR_REQ_EN(h2c_data, 1); + return rtw_hal_fill_h2c_cmd(adapter, H2C_CUSTOMER_STR_REQ, H2C_CUSTOMER_STR_REQ_LEN, h2c_data); +} + +#define C2H_CUSTOMER_STR_RPT_BYTE0(_data) ((u8 *)(_data)) +#define C2H_CUSTOMER_STR_RPT_2_BYTE8(_data) ((u8 *)(_data)) + +int c2h_customer_str_rpt_hdl(_adapter *adapter, u8 *data, u8 len) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + int ret = _FAIL; + int i; + + if (len < CUSTOMER_STR_RPT_LEN) { + RTW_WARN("%s len(%u) < %d\n", __func__, len, CUSTOMER_STR_RPT_LEN); + goto exit; + } + + if (DBG_CUSTOMER_STR_RPT_HANDLE) + RTW_PRINT_DUMP("customer_str_rpt: ", data, CUSTOMER_STR_RPT_LEN); + + _enter_critical_mutex(&dvobj->customer_str_mutex, NULL); + + if (dvobj->customer_str_sctx != NULL) { + if (dvobj->customer_str_sctx->status != RTW_SCTX_SUBMITTED) + RTW_WARN("%s invalid sctx.status:%d\n", __func__, dvobj->customer_str_sctx->status); + memcpy(dvobj->customer_str, C2H_CUSTOMER_STR_RPT_BYTE0(data), CUSTOMER_STR_RPT_LEN); + dvobj->customer_str_sctx->status = RTX_SCTX_CSTR_WAIT_RPT2; + } else + RTW_WARN("%s sctx not set\n", __func__); + + _exit_critical_mutex(&dvobj->customer_str_mutex, NULL); + + ret = _SUCCESS; + +exit: + return ret; +} + +int c2h_customer_str_rpt_2_hdl(_adapter *adapter, u8 *data, u8 len) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + int ret = _FAIL; + int i; + + if (len < CUSTOMER_STR_RPT_2_LEN) { + RTW_WARN("%s len(%u) < %d\n", __func__, len, CUSTOMER_STR_RPT_2_LEN); + goto exit; + } + + if (DBG_CUSTOMER_STR_RPT_HANDLE) + RTW_PRINT_DUMP("customer_str_rpt_2: ", data, CUSTOMER_STR_RPT_2_LEN); + + _enter_critical_mutex(&dvobj->customer_str_mutex, NULL); + + if (dvobj->customer_str_sctx != NULL) { + if (dvobj->customer_str_sctx->status != RTX_SCTX_CSTR_WAIT_RPT2) + RTW_WARN("%s rpt not ready\n", __func__); + memcpy(dvobj->customer_str + CUSTOMER_STR_RPT_LEN, C2H_CUSTOMER_STR_RPT_2_BYTE8(data), CUSTOMER_STR_RPT_2_LEN); + rtw_sctx_done(&dvobj->customer_str_sctx); + } else + RTW_WARN("%s sctx not set\n", __func__); + + _exit_critical_mutex(&dvobj->customer_str_mutex, NULL); + + ret = _SUCCESS; + +exit: + return ret; +} + +/* read customer str */ +s32 rtw_hal_customer_str_read(_adapter *adapter, u8 *cs) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct submit_ctx sctx; + s32 ret = _SUCCESS; + + _enter_critical_mutex(&dvobj->customer_str_mutex, NULL); + if (dvobj->customer_str_sctx != NULL) + ret = _FAIL; + else { + rtw_sctx_init(&sctx, 2 * 1000); + dvobj->customer_str_sctx = &sctx; + } + _exit_critical_mutex(&dvobj->customer_str_mutex, NULL); + + if (ret == _FAIL) { + RTW_WARN("%s another handle ongoing\n", __func__); + goto exit; + } + + ret = rtw_customer_str_req_cmd(adapter); + if (ret != _SUCCESS) { + RTW_WARN("%s read cmd fail\n", __func__); + _enter_critical_mutex(&dvobj->customer_str_mutex, NULL); + dvobj->customer_str_sctx = NULL; + _exit_critical_mutex(&dvobj->customer_str_mutex, NULL); + goto exit; + } + + /* wait till rpt done or timeout */ + rtw_sctx_wait(&sctx, __func__); + + _enter_critical_mutex(&dvobj->customer_str_mutex, NULL); + dvobj->customer_str_sctx = NULL; + if (sctx.status == RTW_SCTX_DONE_SUCCESS) + memcpy(cs, dvobj->customer_str, RTW_CUSTOMER_STR_LEN); + else + ret = _FAIL; + _exit_critical_mutex(&dvobj->customer_str_mutex, NULL); + +exit: + return ret; +} + +s32 rtw_hal_h2c_customer_str_write(_adapter *adapter, const u8 *cs) +{ + u8 h2c_data_w1[H2C_CUSTOMER_STR_W1_LEN] = {0}; + u8 h2c_data_w2[H2C_CUSTOMER_STR_W2_LEN] = {0}; + u8 h2c_data_w3[H2C_CUSTOMER_STR_W3_LEN] = {0}; + s32 ret; + + SET_H2CCMD_CUSTOMER_STR_W1_EN(h2c_data_w1, 1); + memcpy(H2CCMD_CUSTOMER_STR_W1_BYTE0(h2c_data_w1), cs, 6); + + SET_H2CCMD_CUSTOMER_STR_W2_EN(h2c_data_w2, 1); + memcpy(H2CCMD_CUSTOMER_STR_W2_BYTE6(h2c_data_w2), cs + 6, 6); + + SET_H2CCMD_CUSTOMER_STR_W3_EN(h2c_data_w3, 1); + memcpy(H2CCMD_CUSTOMER_STR_W3_BYTE12(h2c_data_w3), cs + 6 + 6, 4); + + ret = rtw_hal_fill_h2c_cmd(adapter, H2C_CUSTOMER_STR_W1, H2C_CUSTOMER_STR_W1_LEN, h2c_data_w1); + if (ret != _SUCCESS) { + RTW_WARN("%s w1 fail\n", __func__); + goto exit; + } + + ret = rtw_hal_fill_h2c_cmd(adapter, H2C_CUSTOMER_STR_W2, H2C_CUSTOMER_STR_W2_LEN, h2c_data_w2); + if (ret != _SUCCESS) { + RTW_WARN("%s w2 fail\n", __func__); + goto exit; + } + + ret = rtw_hal_fill_h2c_cmd(adapter, H2C_CUSTOMER_STR_W3, H2C_CUSTOMER_STR_W3_LEN, h2c_data_w3); + if (ret != _SUCCESS) { + RTW_WARN("%s w3 fail\n", __func__); + goto exit; + } + +exit: + return ret; +} + +/* write customer str and check if value reported is the same as requested */ +s32 rtw_hal_customer_str_write(_adapter *adapter, const u8 *cs) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct submit_ctx sctx; + s32 ret = _SUCCESS; + + _enter_critical_mutex(&dvobj->customer_str_mutex, NULL); + if (dvobj->customer_str_sctx != NULL) + ret = _FAIL; + else { + rtw_sctx_init(&sctx, 2 * 1000); + dvobj->customer_str_sctx = &sctx; + } + _exit_critical_mutex(&dvobj->customer_str_mutex, NULL); + + if (ret == _FAIL) { + RTW_WARN("%s another handle ongoing\n", __func__); + goto exit; + } + + ret = rtw_customer_str_write_cmd(adapter, cs); + if (ret != _SUCCESS) { + RTW_WARN("%s write cmd fail\n", __func__); + _enter_critical_mutex(&dvobj->customer_str_mutex, NULL); + dvobj->customer_str_sctx = NULL; + _exit_critical_mutex(&dvobj->customer_str_mutex, NULL); + goto exit; + } + + ret = rtw_customer_str_req_cmd(adapter); + if (ret != _SUCCESS) { + RTW_WARN("%s read cmd fail\n", __func__); + _enter_critical_mutex(&dvobj->customer_str_mutex, NULL); + dvobj->customer_str_sctx = NULL; + _exit_critical_mutex(&dvobj->customer_str_mutex, NULL); + goto exit; + } + + /* wait till rpt done or timeout */ + rtw_sctx_wait(&sctx, __func__); + + _enter_critical_mutex(&dvobj->customer_str_mutex, NULL); + dvobj->customer_str_sctx = NULL; + if (sctx.status == RTW_SCTX_DONE_SUCCESS) { + if (memcmp(cs, dvobj->customer_str, RTW_CUSTOMER_STR_LEN)) { + RTW_WARN("%s read back check fail\n", __func__); + RTW_INFO_DUMP("write req: ", cs, RTW_CUSTOMER_STR_LEN); + RTW_INFO_DUMP("read back: ", dvobj->customer_str, RTW_CUSTOMER_STR_LEN); + ret = _FAIL; + } + } else + ret = _FAIL; + _exit_critical_mutex(&dvobj->customer_str_mutex, NULL); + +exit: + return ret; +} +#endif /* CONFIG_RTW_CUSTOMER_STR */ + +u8 rtw_hal_networktype_to_raid(_adapter *adapter, struct sta_info *psta) +{ +#ifdef CONFIG_GET_RAID_BY_DRV /*Just for 8188E now*/ + if (IS_NEW_GENERATION_IC(adapter)) + return networktype_to_raid_ex(adapter, psta); + else + return networktype_to_raid(adapter, psta); +#else + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter); + u8 bw; + + bw = rtw_get_tx_bw_mode(adapter, psta); + + return phydm_rate_id_mapping(&pHalData->odmpriv, psta->wireless_mode, pHalData->rf_type, bw); +#endif +} +u8 rtw_get_mgntframe_raid(_adapter *adapter, unsigned char network_type) +{ + + u8 raid; + if (IS_NEW_GENERATION_IC(adapter)) { + + raid = (network_type & WIRELESS_11B) ? RATEID_IDX_B + : RATEID_IDX_G; + } else { + raid = (network_type & WIRELESS_11B) ? RATR_INX_WIRELESS_B + : RATR_INX_WIRELESS_G; + } + return raid; +} + +void rtw_hal_update_sta_rate_mask(PADAPTER padapter, struct sta_info *psta) +{ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter); + u8 i, rf_type, tx_nss; + u64 tx_ra_bitmap; + + if (psta == NULL) + return; + + tx_ra_bitmap = 0; + + /* b/g mode ra_bitmap */ + for (i = 0; i < sizeof(psta->bssrateset); i++) { + if (psta->bssrateset[i]) + tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i] & 0x7f); + } + + rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); + tx_nss = rtw_min(rf_type_to_rf_tx_cnt(rf_type), hal_spec->tx_nss_num); + if (psta->htpriv.ht_option) { + /* n mode ra_bitmap */ + + /* Handling SMPS mode for AP MODE only*/ + if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true) { + /*0:static SMPS, 1:dynamic SMPS, 3:SMPS disabled, 2:reserved*/ + if (psta->htpriv.smps_cap == 0 || psta->htpriv.smps_cap == 1) { + /*operate with only one active receive chain // 11n-MCS rate <= MSC7*/ + tx_nss = rtw_min(tx_nss, 1); + } + } + + tx_ra_bitmap |= (rtw_ht_mcs_set_to_bitmap(psta->htpriv.ht_cap.supp_mcs_set, tx_nss) << 12); + } + psta->ra_mask = tx_ra_bitmap; + psta->init_rate = get_highest_rate_idx(tx_ra_bitmap) & 0x3f; +} + +#ifndef SEC_CAM_ACCESS_TIMEOUT_MS + #define SEC_CAM_ACCESS_TIMEOUT_MS 200 +#endif + +#ifndef DBG_SEC_CAM_ACCESS + #define DBG_SEC_CAM_ACCESS 0 +#endif + +u32 rtw_sec_read_cam(_adapter *adapter, u8 addr) +{ + _mutex *mutex = &adapter_to_dvobj(adapter)->cam_ctl.sec_cam_access_mutex; + u32 rdata; + u32 cnt = 0; + u32 start = 0, end = 0; + u8 timeout = 0; + u8 sr = 0; + + _enter_critical_mutex(mutex, NULL); + + rtw_write32(adapter, REG_CAMCMD, CAM_POLLINIG | addr); + + start = jiffies; + while (1) { + if (rtw_is_surprise_removed(adapter)) { + sr = 1; + break; + } + + cnt++; + if (0 == (rtw_read32(adapter, REG_CAMCMD) & CAM_POLLINIG)) + break; + + if (rtw_get_passing_time_ms(start) > SEC_CAM_ACCESS_TIMEOUT_MS) { + timeout = 1; + break; + } + } + end = jiffies; + + rdata = rtw_read32(adapter, REG_CAMREAD); + + _exit_critical_mutex(mutex, NULL); + + if (DBG_SEC_CAM_ACCESS || timeout) { + RTW_INFO(FUNC_ADPT_FMT" addr:0x%02x, rdata:0x%08x, to:%u, polling:%u, %d ms\n" + , FUNC_ADPT_ARG(adapter), addr, rdata, timeout, cnt, rtw_get_time_interval_ms(start, end)); + } + + return rdata; +} + +void rtw_sec_write_cam(_adapter *adapter, u8 addr, u32 wdata) +{ + _mutex *mutex = &adapter_to_dvobj(adapter)->cam_ctl.sec_cam_access_mutex; + u32 cnt = 0; + u32 start = 0, end = 0; + u8 timeout = 0; + u8 sr = 0; + + _enter_critical_mutex(mutex, NULL); + + rtw_write32(adapter, REG_CAMWRITE, wdata); + rtw_write32(adapter, REG_CAMCMD, CAM_POLLINIG | CAM_WRITE | addr); + + start = jiffies; + while (1) { + if (rtw_is_surprise_removed(adapter)) { + sr = 1; + break; + } + + cnt++; + if (0 == (rtw_read32(adapter, REG_CAMCMD) & CAM_POLLINIG)) + break; + + if (rtw_get_passing_time_ms(start) > SEC_CAM_ACCESS_TIMEOUT_MS) { + timeout = 1; + break; + } + } + end = jiffies; + + _exit_critical_mutex(mutex, NULL); + + if (DBG_SEC_CAM_ACCESS || timeout) { + RTW_INFO(FUNC_ADPT_FMT" addr:0x%02x, wdata:0x%08x, to:%u, polling:%u, %d ms\n" + , FUNC_ADPT_ARG(adapter), addr, wdata, timeout, cnt, rtw_get_time_interval_ms(start, end)); + } +} + +void rtw_sec_read_cam_ent(_adapter *adapter, u8 id, u8 *ctrl, u8 *mac, u8 *key) +{ + unsigned int val, addr; + u8 i; + u32 rdata; + u8 begin = 0; + u8 end = 5; /* TODO: consider other key length accordingly */ + + if (!ctrl && !mac && !key) { + rtw_warn_on(1); + goto exit; + } + + /* TODO: check id range */ + + if (!ctrl && !mac) + begin = 2; /* read from key */ + + if (!key && !mac) + end = 0; /* read to ctrl */ + else if (!key) + end = 2; /* read to mac */ + + for (i = begin; i <= end; i++) { + rdata = rtw_sec_read_cam(adapter, (id << 3) | i); + + switch (i) { + case 0: + if (ctrl) + memcpy(ctrl, (u8 *)(&rdata), 2); + if (mac) + memcpy(mac, ((u8 *)(&rdata)) + 2, 2); + break; + case 1: + if (mac) + memcpy(mac + 2, (u8 *)(&rdata), 4); + break; + default: + if (key) + memcpy(key + (i - 2) * 4, (u8 *)(&rdata), 4); + break; + } + } + +exit: + return; +} + + +void rtw_sec_write_cam_ent(_adapter *adapter, u8 id, u16 ctrl, u8 *mac, u8 *key) +{ + unsigned int i; + int j; + u8 addr; + u32 wdata; + + /* TODO: consider other key length accordingly */ + j = 7; + + for (; j >= 0; j--) { + switch (j) { + case 0: + wdata = (ctrl | (mac[0] << 16) | (mac[1] << 24)); + break; + case 1: + wdata = (mac[2] | (mac[3] << 8) | (mac[4] << 16) | (mac[5] << 24)); + break; + case 6: + case 7: + wdata = 0; + break; + default: + i = (j - 2) << 2; + wdata = (key[i] | (key[i + 1] << 8) | (key[i + 2] << 16) | (key[i + 3] << 24)); + break; + } + + addr = (id << 3) + j; + + rtw_sec_write_cam(adapter, addr, wdata); + } +} + +void rtw_sec_clr_cam_ent(_adapter *adapter, u8 id) +{ + u8 addr; + + addr = (id << 3); + rtw_sec_write_cam(adapter, addr, 0); +} + +bool rtw_sec_read_cam_is_gk(_adapter *adapter, u8 id) +{ + bool res; + u16 ctrl; + + rtw_sec_read_cam_ent(adapter, id, (u8 *)&ctrl, NULL, NULL); + + res = (ctrl & BIT6) ? true : false; + return res; +} +#ifdef CONFIG_MBSSID_CAM +void rtw_mbid_cam_init(struct dvobj_priv *dvobj) +{ + struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl; + + spin_lock_init(&mbid_cam_ctl->lock); + mbid_cam_ctl->bitmap = 0; + ATOMIC_SET(&mbid_cam_ctl->mbid_entry_num, 0); + memset(&dvobj->mbid_cam_cache, 0, sizeof(dvobj->mbid_cam_cache)); +} + +void rtw_mbid_cam_deinit(struct dvobj_priv *dvobj) +{ +} + +void rtw_mbid_cam_reset(_adapter *adapter) +{ + unsigned long irqL; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl; + + _enter_critical_bh(&mbid_cam_ctl->lock, &irqL); + mbid_cam_ctl->bitmap = 0; + memset(&dvobj->mbid_cam_cache, 0, sizeof(dvobj->mbid_cam_cache)); + _exit_critical_bh(&mbid_cam_ctl->lock, &irqL); + + ATOMIC_SET(&mbid_cam_ctl->mbid_entry_num, 0); +} +static u8 _rtw_mbid_cam_search_by_macaddr(_adapter *adapter, u8 *mac_addr) +{ + u8 i; + u8 cam_id = INVALID_CAM_ID; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + + for (i = 0; i < TOTAL_MBID_CAM_NUM; i++) { + if (mac_addr && !memcmp(dvobj->mbid_cam_cache[i].mac_addr, mac_addr, ETH_ALEN) == true) { + cam_id = i; + break; + } + } + + RTW_INFO("%s mac:"MAC_FMT" - cam_id:%d\n", __func__, MAC_ARG(mac_addr), cam_id); + return cam_id; +} + +u8 rtw_mbid_cam_search_by_macaddr(_adapter *adapter, u8 *mac_addr) +{ + unsigned long irqL; + + u8 cam_id = INVALID_CAM_ID; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl; + + _enter_critical_bh(&mbid_cam_ctl->lock, &irqL); + cam_id = _rtw_mbid_cam_search_by_macaddr(adapter, mac_addr); + _exit_critical_bh(&mbid_cam_ctl->lock, &irqL); + + return cam_id; +} +static u8 _rtw_mbid_cam_search_by_ifaceid(_adapter *adapter, u8 iface_id) +{ + u8 i; + u8 cam_id = INVALID_CAM_ID; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + + for (i = 0; i < TOTAL_MBID_CAM_NUM; i++) { + if (iface_id == dvobj->mbid_cam_cache[i].iface_id) { + cam_id = i; + break; + } + } + if (cam_id != INVALID_CAM_ID) + RTW_INFO("%s iface_id:%d mac:"MAC_FMT" - cam_id:%d\n", + __func__, iface_id, MAC_ARG(dvobj->mbid_cam_cache[cam_id].mac_addr), cam_id); + + return cam_id; +} + +u8 rtw_mbid_cam_search_by_ifaceid(_adapter *adapter, u8 iface_id) +{ + unsigned long irqL; + u8 cam_id = INVALID_CAM_ID; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl; + + _enter_critical_bh(&mbid_cam_ctl->lock, &irqL); + cam_id = _rtw_mbid_cam_search_by_ifaceid(adapter, iface_id); + _exit_critical_bh(&mbid_cam_ctl->lock, &irqL); + + return cam_id; +} +u8 rtw_get_max_mbid_cam_id(_adapter *adapter) +{ + unsigned long irqL; + s8 i; + u8 cam_id = INVALID_CAM_ID; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl; + + _enter_critical_bh(&mbid_cam_ctl->lock, &irqL); + for (i = (TOTAL_MBID_CAM_NUM - 1); i >= 0; i--) { + if (mbid_cam_ctl->bitmap & BIT(i)) { + cam_id = i; + break; + } + } + _exit_critical_bh(&mbid_cam_ctl->lock, &irqL); + /*RTW_INFO("%s max cam_id:%d\n", __func__, cam_id);*/ + return cam_id; +} + +inline u8 rtw_get_mbid_cam_entry_num(_adapter *adapter) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl; + + return ATOMIC_READ(&mbid_cam_ctl->mbid_entry_num); +} + +static inline void mbid_cam_cache_init(_adapter *adapter, struct mbid_cam_cache *pmbid_cam, u8 *mac_addr) +{ + if (adapter && pmbid_cam && mac_addr) { + memcpy(pmbid_cam->mac_addr, mac_addr, ETH_ALEN); + pmbid_cam->iface_id = adapter->iface_id; + } +} +static inline void mbid_cam_cache_clr(struct mbid_cam_cache *pmbid_cam) +{ + if (pmbid_cam) { + memset(pmbid_cam->mac_addr, 0, ETH_ALEN); + pmbid_cam->iface_id = CONFIG_IFACE_NUMBER; + } +} + +u8 rtw_mbid_camid_alloc(_adapter *adapter, u8 *mac_addr) +{ + unsigned long irqL; + u8 cam_id = INVALID_CAM_ID, i; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl; + u8 entry_num = ATOMIC_READ(&mbid_cam_ctl->mbid_entry_num); + + if (entry_num >= TOTAL_MBID_CAM_NUM) { + RTW_INFO(FUNC_ADPT_FMT" failed !! MBSSID number :%d over TOTAL_CAM_ENTRY(8)\n", FUNC_ADPT_ARG(adapter), entry_num); + rtw_warn_on(1); + } + + if (INVALID_CAM_ID != rtw_mbid_cam_search_by_macaddr(adapter, mac_addr)) + goto exit; + + _enter_critical_bh(&mbid_cam_ctl->lock, &irqL); + for (i = 0; i < TOTAL_MBID_CAM_NUM; i++) { + if (!(mbid_cam_ctl->bitmap & BIT(i))) { + mbid_cam_ctl->bitmap |= BIT(i); + cam_id = i; + break; + } + } + if ((cam_id != INVALID_CAM_ID) && (mac_addr)) + mbid_cam_cache_init(adapter, &dvobj->mbid_cam_cache[cam_id], mac_addr); + _exit_critical_bh(&mbid_cam_ctl->lock, &irqL); + + if (cam_id != INVALID_CAM_ID) { + ATOMIC_INC(&mbid_cam_ctl->mbid_entry_num); + RTW_INFO("%s mac:"MAC_FMT" - cam_id:%d\n", __func__, MAC_ARG(mac_addr), cam_id); +#ifdef DBG_MBID_CAM_DUMP + rtw_mbid_cam_cache_dump(RTW_DBGDUMP, __func__, adapter); +#endif + } else + RTW_INFO("%s [WARN] "MAC_FMT" - invalid cam_id:%d\n", __func__, MAC_ARG(mac_addr), cam_id); +exit: + return cam_id; +} + +u8 rtw_mbid_cam_info_change(_adapter *adapter, u8 *mac_addr) +{ + unsigned long irqL; + u8 entry_id = INVALID_CAM_ID; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl; + + _enter_critical_bh(&mbid_cam_ctl->lock, &irqL); + entry_id = _rtw_mbid_cam_search_by_ifaceid(adapter, adapter->iface_id); + if (entry_id != INVALID_CAM_ID) + mbid_cam_cache_init(adapter, &dvobj->mbid_cam_cache[entry_id], mac_addr); + + _exit_critical_bh(&mbid_cam_ctl->lock, &irqL); + + return entry_id; +} + +u8 rtw_mbid_cam_assign(_adapter *adapter, u8 *mac_addr, u8 camid) +{ + unsigned long irqL; + u8 ret = false; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl; + + if ((camid >= TOTAL_MBID_CAM_NUM) || (camid == INVALID_CAM_ID)) { + RTW_INFO(FUNC_ADPT_FMT" failed !! invlaid mbid_canid :%d\n", FUNC_ADPT_ARG(adapter), camid); + rtw_warn_on(1); + } + if (INVALID_CAM_ID != rtw_mbid_cam_search_by_macaddr(adapter, mac_addr)) + goto exit; + + _enter_critical_bh(&mbid_cam_ctl->lock, &irqL); + if (!(mbid_cam_ctl->bitmap & BIT(camid))) { + if (mac_addr) { + mbid_cam_ctl->bitmap |= BIT(camid); + mbid_cam_cache_init(adapter, &dvobj->mbid_cam_cache[camid], mac_addr); + ret = true; + } + } + _exit_critical_bh(&mbid_cam_ctl->lock, &irqL); + + if (ret == true) { + ATOMIC_INC(&mbid_cam_ctl->mbid_entry_num); + RTW_INFO("%s mac:"MAC_FMT" - cam_id:%d\n", __func__, MAC_ARG(mac_addr), camid); +#ifdef DBG_MBID_CAM_DUMP + rtw_mbid_cam_cache_dump(RTW_DBGDUMP, __func__, adapter); +#endif + } else + RTW_INFO("%s [WARN] mac:"MAC_FMT" - cam_id:%d assigned failed\n", __func__, MAC_ARG(mac_addr), camid); + +exit: + return ret; +} + +void rtw_mbid_camid_clean(_adapter *adapter, u8 mbss_canid) +{ + unsigned long irqL; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl; + + if ((mbss_canid >= TOTAL_MBID_CAM_NUM) || (mbss_canid == INVALID_CAM_ID)) { + RTW_INFO(FUNC_ADPT_FMT" failed !! invlaid mbid_canid :%d\n", FUNC_ADPT_ARG(adapter), mbss_canid); + rtw_warn_on(1); + } + _enter_critical_bh(&mbid_cam_ctl->lock, &irqL); + mbid_cam_cache_clr(&dvobj->mbid_cam_cache[mbss_canid]); + mbid_cam_ctl->bitmap &= (~BIT(mbss_canid)); + _exit_critical_bh(&mbid_cam_ctl->lock, &irqL); + ATOMIC_DEC(&mbid_cam_ctl->mbid_entry_num); + RTW_INFO("%s - cam_id:%d\n", __func__, mbss_canid); +} +int rtw_mbid_cam_cache_dump(void *sel, const char *fun_name, _adapter *adapter) +{ + unsigned long irqL; + u8 i; + _adapter *iface; + u8 iface_id; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl; + u8 entry_num = ATOMIC_READ(&mbid_cam_ctl->mbid_entry_num); + u8 max_cam_id = rtw_get_max_mbid_cam_id(adapter); + + RTW_PRINT_SEL(sel, "== MBSSID CAM DUMP (%s)==\n", fun_name); + + _enter_critical_bh(&mbid_cam_ctl->lock, &irqL); + RTW_PRINT_SEL(sel, "Entry numbers:%d, max_camid:%d, bitmap:0x%08x\n", entry_num, max_cam_id, mbid_cam_ctl->bitmap); + for (i = 0; i < TOTAL_MBID_CAM_NUM; i++) { + RTW_PRINT_SEL(sel, "CAM_ID = %d\t", i); + + if (mbid_cam_ctl->bitmap & BIT(i)) { + iface_id = dvobj->mbid_cam_cache[i].iface_id; + RTW_PRINT_SEL(sel, "IF_ID:%d\t", iface_id); + RTW_PRINT_SEL(sel, "MAC Addr:"MAC_FMT"\t", MAC_ARG(dvobj->mbid_cam_cache[i].mac_addr)); + + iface = dvobj->padapters[iface_id]; + if (iface) { + if (check_fwstate(&iface->mlmepriv, WIFI_STATION_STATE) == true) + RTW_PRINT_SEL(sel, "ROLE:%s\n", "STA"); + else if (check_fwstate(&iface->mlmepriv, WIFI_AP_STATE) == true) + RTW_PRINT_SEL(sel, "ROLE:%s\n", "AP"); + else + RTW_PRINT_SEL(sel, "ROLE:%s\n", "NONE"); + } + + } else + RTW_PRINT_SEL(sel, "N/A\n"); + } + _exit_critical_bh(&mbid_cam_ctl->lock, &irqL); + return 0; +} + +static void read_mbssid_cam(_adapter *padapter, u8 cam_addr, u8 *mac) +{ + u8 poll = 1; + u8 cam_ready = false; + u32 cam_data1 = 0; + u16 cam_data2 = 0; + + if (RTW_CANNOT_RUN(padapter)) + return; + + rtw_write32(padapter, REG_MBIDCAMCFG_2, BIT_MBIDCAM_POLL | ((cam_addr & MBIDCAM_ADDR_MASK) << MBIDCAM_ADDR_SHIFT)); + + do { + if (0 == (rtw_read32(padapter, REG_MBIDCAMCFG_2) & BIT_MBIDCAM_POLL)) { + cam_ready = true; + break; + } + poll++; + } while ((poll % 10) != 0 && !RTW_CANNOT_RUN(padapter)); + + if (cam_ready) { + cam_data1 = rtw_read32(padapter, REG_MBIDCAMCFG_1); + mac[0] = cam_data1 & 0xFF; + mac[1] = (cam_data1 >> 8) & 0xFF; + mac[2] = (cam_data1 >> 16) & 0xFF; + mac[3] = (cam_data1 >> 24) & 0xFF; + + cam_data2 = rtw_read16(padapter, REG_MBIDCAMCFG_2); + mac[4] = cam_data2 & 0xFF; + mac[5] = (cam_data2 >> 8) & 0xFF; + } + +} +int rtw_mbid_cam_dump(void *sel, const char *fun_name, _adapter *adapter) +{ + /*unsigned long irqL;*/ + u8 i; + u8 mac_addr[ETH_ALEN]; + + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl; + + RTW_PRINT_SEL(sel, "\n== MBSSID HW-CAM DUMP (%s)==\n", fun_name); + + /*_enter_critical_bh(&mbid_cam_ctl->lock, &irqL);*/ + for (i = 0; i < TOTAL_MBID_CAM_NUM; i++) { + RTW_PRINT_SEL(sel, "CAM_ID = %d\t", i); + memset(mac_addr, 0, ETH_ALEN); + read_mbssid_cam(adapter, i, mac_addr); + RTW_PRINT_SEL(sel, "MAC Addr:"MAC_FMT"\n", MAC_ARG(mac_addr)); + } + /*_exit_critical_bh(&mbid_cam_ctl->lock, &irqL);*/ + return 0; +} + +static void write_mbssid_cam(_adapter *padapter, u8 cam_addr, u8 *mac) +{ + u32 cam_val[2] = {0}; + + cam_val[0] = (mac[3] << 24) | (mac[2] << 16) | (mac[1] << 8) | mac[0]; + cam_val[1] = ((cam_addr & MBIDCAM_ADDR_MASK) << MBIDCAM_ADDR_SHIFT) | (mac[5] << 8) | mac[4]; + + rtw_hal_set_hwreg(padapter, HW_VAR_MBSSID_CAM_WRITE, (u8 *)cam_val); +} + +static void clear_mbssid_cam(_adapter *padapter, u8 cam_addr) +{ + rtw_hal_set_hwreg(padapter, HW_VAR_MBSSID_CAM_CLEAR, &cam_addr); +} +static void enable_mbssid_cam(_adapter *adapter) +{ + u8 max_cam_id = rtw_get_max_mbid_cam_id(adapter); + /*enable MBSSID*/ + rtw_write32(adapter, REG_RCR, rtw_read32(adapter, REG_RCR) | RCR_ENMBID); + if (max_cam_id != INVALID_CAM_ID) { + rtw_write8(adapter, REG_MBID_NUM, + ((rtw_read8(adapter, REG_MBID_NUM) & 0xF8) | (max_cam_id & 0x07))); + } +} +void rtw_mbid_cam_restore(_adapter *adapter) +{ + u8 i; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl; + +#ifdef DBG_MBID_CAM_DUMP + rtw_mbid_cam_cache_dump(RTW_DBGDUMP, __func__, adapter); +#endif + + for (i = 0; i < TOTAL_MBID_CAM_NUM; i++) { + if (mbid_cam_ctl->bitmap & BIT(i)) { + write_mbssid_cam(adapter, i, dvobj->mbid_cam_cache[i].mac_addr); + RTW_INFO("%s - cam_id:%d => mac:"MAC_FMT"\n", __func__, i, MAC_ARG(dvobj->mbid_cam_cache[i].mac_addr)); + } + } + enable_mbssid_cam(adapter); +} +#endif /*CONFIG_MBSSID_CAM*/ + +#ifdef CONFIG_MI_WITH_MBSSID_CAM +void rtw_hal_set_macaddr_mbid(_adapter *adapter, u8 *mac_addr) +{ + + /* + MBID entry_id = 0~7 ,for IFACE_ID0 ~ IFACE_IDx + */ + u8 entry_id = rtw_mbid_camid_alloc(adapter, mac_addr); + + + if (entry_id != INVALID_CAM_ID) { + write_mbssid_cam(adapter, entry_id, mac_addr); + enable_mbssid_cam(adapter); + } +} + +void rtw_hal_change_macaddr_mbid(_adapter *adapter, u8 *mac_addr) +{ + u8 idx = 0; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + u8 entry_id; + + if (!mac_addr) { + rtw_warn_on(1); + return; + } + + + entry_id = rtw_mbid_cam_info_change(adapter, mac_addr); + + if (entry_id != INVALID_CAM_ID) + write_mbssid_cam(adapter, entry_id, mac_addr); +} + + +#endif/*#ifdef CONFIG_MI_WITH_MBSSID_CAM*/ + +void rtw_hal_set_macaddr_port(_adapter *adapter, u8 *val) +{ + u8 idx = 0; + u32 reg_macid = 0; + + if (val == NULL) + return; + + RTW_INFO("%s "ADPT_FMT"- hw port(%d) mac_addr ="MAC_FMT"\n", __func__, + ADPT_ARG(adapter), adapter->hw_port, MAC_ARG(val)); + + switch (adapter->hw_port) { + case HW_PORT0: + default: + reg_macid = REG_MACID; + break; + case HW_PORT1: + reg_macid = REG_MACID1; + break; + } + + for (idx = 0; idx < 6; idx++) + rtw_write8(GET_PRIMARY_ADAPTER(adapter), (reg_macid + idx), val[idx]); +} + +void rtw_hal_get_macaddr_port(_adapter *adapter, u8 *mac_addr) +{ + u8 idx = 0; + u32 reg_macid = 0; + + if (mac_addr == NULL) + return; + + memset(mac_addr, 0, ETH_ALEN); + switch (adapter->hw_port) { + case HW_PORT0: + default: + reg_macid = REG_MACID; + break; + case HW_PORT1: + reg_macid = REG_MACID1; + break; + } + + for (idx = 0; idx < 6; idx++) + mac_addr[idx] = rtw_read8(GET_PRIMARY_ADAPTER(adapter), (reg_macid + idx)); + + RTW_INFO("%s "ADPT_FMT"- hw port(%d) mac_addr ="MAC_FMT"\n", __func__, + ADPT_ARG(adapter), adapter->hw_port, MAC_ARG(mac_addr)); +} + +void rtw_hal_set_bssid(_adapter *adapter, u8 *val) +{ + u8 idx = 0; + u32 reg_bssid = 0; + + switch (adapter->hw_port) { + case HW_PORT0: + default: + reg_bssid = REG_BSSID; + break; + case HW_PORT1: + reg_bssid = REG_BSSID1; + break; + } + + for (idx = 0 ; idx < 6; idx++) + rtw_write8(adapter, (reg_bssid + idx), val[idx]); + + RTW_INFO("%s "ADPT_FMT"- hw port -%d BSSID: "MAC_FMT"\n", __func__, ADPT_ARG(adapter), adapter->hw_port, MAC_ARG(val)); +} + +static void rtw_hal_get_msr(_adapter *adapter, u8 *net_type) +{ + switch (adapter->hw_port) { + case HW_PORT0: + /*REG_CR - BIT[17:16]-Network Type for port 1*/ + *net_type = rtw_read8(adapter, MSR) & 0x03; + break; + case HW_PORT1: + /*REG_CR - BIT[19:18]-Network Type for port 1*/ + *net_type = (rtw_read8(adapter, MSR) & 0x0C) >> 2; + break; + default: + RTW_INFO("[WARN] "ADPT_FMT"- invalid hw port -%d\n", + ADPT_ARG(adapter), adapter->hw_port); + rtw_warn_on(1); + break; + } +} + +void rtw_hal_set_msr(_adapter *adapter, u8 net_type) +{ + u8 val8 = 0; + + switch (adapter->hw_port) { + case HW_PORT0: +#if defined(CONFIG_MI_WITH_MBSSID_CAM) && defined(CONFIG_MBSSID_CAM) /*For 2 hw ports - 88E/92E/8812/8821/8723B*/ + if (rtw_get_mbid_cam_entry_num(adapter)) { + if (net_type != _HW_STATE_NOLINK_) + net_type = _HW_STATE_AP_; + } +#endif + /*REG_CR - BIT[17:16]-Network Type for port 0*/ + val8 = rtw_read8(adapter, MSR) & 0x0C; + val8 |= net_type; + rtw_write8(adapter, MSR, val8); + break; + case HW_PORT1: + /*REG_CR - BIT[19:18]-Network Type for port 1*/ + val8 = rtw_read8(adapter, MSR) & 0x03; + val8 |= net_type << 2; + rtw_write8(adapter, MSR, val8); + break; + default: + RTW_INFO("[WARN] "ADPT_FMT"- invalid hw port -%d\n", + ADPT_ARG(adapter), adapter->hw_port); + rtw_warn_on(1); + break; + } +} + +void hw_var_port_switch(_adapter *adapter) +{ +#ifdef CONFIG_CONCURRENT_MODE +#ifdef CONFIG_RUNTIME_PORT_SWITCH + /* + 0x102: MSR + 0x550: REG_BCN_CTRL + 0x551: REG_BCN_CTRL_1 + 0x55A: REG_ATIMWND + 0x560: REG_TSFTR + 0x568: REG_TSFTR1 + 0x570: REG_ATIMWND_1 + 0x610: REG_MACID + 0x618: REG_BSSID + 0x700: REG_MACID1 + 0x708: REG_BSSID1 + */ + + int i; + u8 msr; + u8 bcn_ctrl; + u8 bcn_ctrl_1; + u8 atimwnd[2]; + u8 atimwnd_1[2]; + u8 tsftr[8]; + u8 tsftr_1[8]; + u8 macid[6]; + u8 bssid[6]; + u8 macid_1[6]; + u8 bssid_1[6]; + + u8 hw_port; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + _adapter *iface = NULL; + + msr = rtw_read8(adapter, MSR); + bcn_ctrl = rtw_read8(adapter, REG_BCN_CTRL); + bcn_ctrl_1 = rtw_read8(adapter, REG_BCN_CTRL_1); + + for (i = 0; i < 2; i++) + atimwnd[i] = rtw_read8(adapter, REG_ATIMWND + i); + for (i = 0; i < 2; i++) + atimwnd_1[i] = rtw_read8(adapter, REG_ATIMWND_1 + i); + + for (i = 0; i < 8; i++) + tsftr[i] = rtw_read8(adapter, REG_TSFTR + i); + for (i = 0; i < 8; i++) + tsftr_1[i] = rtw_read8(adapter, REG_TSFTR1 + i); + + for (i = 0; i < 6; i++) + macid[i] = rtw_read8(adapter, REG_MACID + i); + + for (i = 0; i < 6; i++) + bssid[i] = rtw_read8(adapter, REG_BSSID + i); + + for (i = 0; i < 6; i++) + macid_1[i] = rtw_read8(adapter, REG_MACID1 + i); + + for (i = 0; i < 6; i++) + bssid_1[i] = rtw_read8(adapter, REG_BSSID1 + i); + +#ifdef DBG_RUNTIME_PORT_SWITCH + RTW_INFO(FUNC_ADPT_FMT" before switch\n" + "msr:0x%02x\n" + "bcn_ctrl:0x%02x\n" + "bcn_ctrl_1:0x%02x\n" + "atimwnd:0x%04x\n" + "atimwnd_1:0x%04x\n" + "tsftr:%llu\n" + "tsftr1:%llu\n" + "macid:"MAC_FMT"\n" + "bssid:"MAC_FMT"\n" + "macid_1:"MAC_FMT"\n" + "bssid_1:"MAC_FMT"\n" + , FUNC_ADPT_ARG(adapter) + , msr + , bcn_ctrl + , bcn_ctrl_1 + , *((u16 *)atimwnd) + , *((u16 *)atimwnd_1) + , *((u64 *)tsftr) + , *((u64 *)tsftr_1) + , MAC_ARG(macid) + , MAC_ARG(bssid) + , MAC_ARG(macid_1) + , MAC_ARG(bssid_1) + ); +#endif /* DBG_RUNTIME_PORT_SWITCH */ + + /* disable bcn function, disable update TSF */ + rtw_write8(adapter, REG_BCN_CTRL, (bcn_ctrl & (~EN_BCN_FUNCTION)) | DIS_TSF_UDT); + rtw_write8(adapter, REG_BCN_CTRL_1, (bcn_ctrl_1 & (~EN_BCN_FUNCTION)) | DIS_TSF_UDT); + + /* switch msr */ + msr = (msr & 0xf0) | ((msr & 0x03) << 2) | ((msr & 0x0c) >> 2); + rtw_write8(adapter, MSR, msr); + + /* write port0 */ + rtw_write8(adapter, REG_BCN_CTRL, bcn_ctrl_1 & ~EN_BCN_FUNCTION); + for (i = 0; i < 2; i++) + rtw_write8(adapter, REG_ATIMWND + i, atimwnd_1[i]); + for (i = 0; i < 8; i++) + rtw_write8(adapter, REG_TSFTR + i, tsftr_1[i]); + for (i = 0; i < 6; i++) + rtw_write8(adapter, REG_MACID + i, macid_1[i]); + for (i = 0; i < 6; i++) + rtw_write8(adapter, REG_BSSID + i, bssid_1[i]); + + /* write port1 */ + rtw_write8(adapter, REG_BCN_CTRL_1, bcn_ctrl & ~EN_BCN_FUNCTION); + for (i = 0; i < 2; i++) + rtw_write8(adapter, REG_ATIMWND_1 + i, atimwnd[i]); + for (i = 0; i < 8; i++) + rtw_write8(adapter, REG_TSFTR1 + i, tsftr[i]); + for (i = 0; i < 6; i++) + rtw_write8(adapter, REG_MACID1 + i, macid[i]); + for (i = 0; i < 6; i++) + rtw_write8(adapter, REG_BSSID1 + i, bssid[i]); + + /* write bcn ctl */ + rtw_write8(adapter, REG_BCN_CTRL, bcn_ctrl_1); + rtw_write8(adapter, REG_BCN_CTRL_1, bcn_ctrl); + + if (adapter->iface_id == IFACE_ID0) + iface = dvobj->padapters[IFACE_ID1]; + else if (adapter->iface_id == IFACE_ID1) + iface = dvobj->padapters[IFACE_ID0]; + + + if (adapter->hw_port == HW_PORT0) { + adapter->hw_port = HW_PORT1; + iface->hw_port = HW_PORT0; + RTW_PRINT("port switch - port0("ADPT_FMT"), port1("ADPT_FMT")\n", + ADPT_ARG(iface), ADPT_ARG(adapter)); + } else { + adapter->hw_port = HW_PORT0; + iface->hw_port = HW_PORT1; + RTW_PRINT("port switch - port0("ADPT_FMT"), port1("ADPT_FMT")\n", + ADPT_ARG(adapter), ADPT_ARG(iface)); + } + +#ifdef DBG_RUNTIME_PORT_SWITCH + msr = rtw_read8(adapter, MSR); + bcn_ctrl = rtw_read8(adapter, REG_BCN_CTRL); + bcn_ctrl_1 = rtw_read8(adapter, REG_BCN_CTRL_1); + + for (i = 0; i < 2; i++) + atimwnd[i] = rtw_read8(adapter, REG_ATIMWND + i); + for (i = 0; i < 2; i++) + atimwnd_1[i] = rtw_read8(adapter, REG_ATIMWND_1 + i); + + for (i = 0; i < 8; i++) + tsftr[i] = rtw_read8(adapter, REG_TSFTR + i); + for (i = 0; i < 8; i++) + tsftr_1[i] = rtw_read8(adapter, REG_TSFTR1 + i); + + for (i = 0; i < 6; i++) + macid[i] = rtw_read8(adapter, REG_MACID + i); + + for (i = 0; i < 6; i++) + bssid[i] = rtw_read8(adapter, REG_BSSID + i); + + for (i = 0; i < 6; i++) + macid_1[i] = rtw_read8(adapter, REG_MACID1 + i); + + for (i = 0; i < 6; i++) + bssid_1[i] = rtw_read8(adapter, REG_BSSID1 + i); + + RTW_INFO(FUNC_ADPT_FMT" after switch\n" + "msr:0x%02x\n" + "bcn_ctrl:0x%02x\n" + "bcn_ctrl_1:0x%02x\n" + "atimwnd:%u\n" + "atimwnd_1:%u\n" + "tsftr:%llu\n" + "tsftr1:%llu\n" + "macid:"MAC_FMT"\n" + "bssid:"MAC_FMT"\n" + "macid_1:"MAC_FMT"\n" + "bssid_1:"MAC_FMT"\n" + , FUNC_ADPT_ARG(adapter) + , msr + , bcn_ctrl + , bcn_ctrl_1 + , *((u16 *)atimwnd) + , *((u16 *)atimwnd_1) + , *((u64 *)tsftr) + , *((u64 *)tsftr_1) + , MAC_ARG(macid) + , MAC_ARG(bssid) + , MAC_ARG(macid_1) + , MAC_ARG(bssid_1) + ); +#endif /* DBG_RUNTIME_PORT_SWITCH */ + +#endif /* CONFIG_RUNTIME_PORT_SWITCH */ +#endif /* CONFIG_CONCURRENT_MODE */ +} + +const char *const _h2c_msr_role_str[] = { + "RSVD", + "STA", + "AP", + "GC", + "GO", + "TDLS", + "ADHOC", + "INVALID", +}; + +#ifdef CONFIG_FW_MULTI_PORT_SUPPORT +s32 rtw_hal_set_default_port_id_cmd(_adapter *adapter, u8 mac_id) +{ + s32 ret = _SUCCESS; + u8 parm[H2C_DEFAULT_PORT_ID_LEN] = {0}; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + + SET_H2CCMD_DFTPID_PORT_ID(parm, adapter->hw_port); + SET_H2CCMD_DFTPID_MAC_ID(parm, mac_id); + + RTW_DBG_DUMP("DFT port id parm:", parm, H2C_DEFAULT_PORT_ID_LEN); + RTW_INFO("%s port_id :%d, mad_id:%d\n", __func__, adapter->hw_port, mac_id); + + ret = rtw_hal_fill_h2c_cmd(adapter, H2C_DEFAULT_PORT_ID, H2C_DEFAULT_PORT_ID_LEN, parm); + dvobj->default_port_id = adapter->hw_port; + + return ret; +} +s32 rtw_set_default_port_id(_adapter *adapter) +{ + s32 ret = _SUCCESS; + struct sta_info *psta; + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + + if (adapter->hw_port == dvobj->default_port_id) + return ret; + + if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) { + psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(pmlmepriv)); + if (psta) + ret = rtw_hal_set_default_port_id_cmd(adapter, psta->mac_id); + } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) { + + } else { + } + + return ret; +} +s32 rtw_set_ps_rsvd_page(_adapter *adapter) +{ + s32 ret = _SUCCESS; + u16 media_status_rpt = RT_MEDIA_CONNECT; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + + if (adapter->hw_port == dvobj->default_port_id) + return ret; + + rtw_hal_set_hwreg(adapter, HW_VAR_H2C_FW_JOINBSSRPT, + (u8 *)&media_status_rpt); + + return ret; +} + +#endif +/* +* rtw_hal_set_FwMediaStatusRpt_cmd - +* +* @adapter: +* @opmode: 0:disconnect, 1:connect +* @miracast: 0:it's not in miracast scenario. 1:it's in miracast scenario +* @miracast_sink: 0:source. 1:sink +* @role: The role of this macid. 0:rsvd. 1:STA. 2:AP. 3:GC. 4:GO. 5:TDLS +* @macid: +* @macid_ind: 0:update Media Status to macid. 1:update Media Status from macid to macid_end +* @macid_end: +*/ +s32 rtw_hal_set_FwMediaStatusRpt_cmd(_adapter *adapter, bool opmode, bool miracast, bool miracast_sink, u8 role, u8 macid, bool macid_ind, u8 macid_end) +{ + struct macid_ctl_t *macid_ctl = &adapter->dvobj->macid_ctl; + u8 parm[H2C_MEDIA_STATUS_RPT_LEN] = {0}; + int i; + s32 ret; + + SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, opmode); + SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, macid_ind); + SET_H2CCMD_MSRRPT_PARM_MIRACAST(parm, miracast); + SET_H2CCMD_MSRRPT_PARM_MIRACAST_SINK(parm, miracast_sink); + SET_H2CCMD_MSRRPT_PARM_ROLE(parm, role); + SET_H2CCMD_MSRRPT_PARM_MACID(parm, macid); + SET_H2CCMD_MSRRPT_PARM_MACID_END(parm, macid_end); +#ifdef CONFIG_FW_MULTI_PORT_SUPPORT + SET_H2CCMD_MSRRPT_PARM_PORT_NUM(parm, adapter->hw_port); +#endif + RTW_DBG_DUMP("MediaStatusRpt parm:", parm, H2C_MEDIA_STATUS_RPT_LEN); + +#ifdef CONFIG_DFS_MASTER + /* workaround for TXPAUSE cleared issue by FW's MediaStatusRpt handling */ + if (macid_ind == 0 && macid == 1 + && !rtw_odm_dfs_domain_unknown(adapter) + ) { + u8 parm0_bak = parm[0]; + + SET_H2CCMD_MSRRPT_PARM_MACID_IND(&parm0_bak, 0); + if (macid_ctl->h2c_msr[macid] == parm0_bak) { + ret = _SUCCESS; + goto post_action; + } + } +#endif + + ret = rtw_hal_fill_h2c_cmd(adapter, H2C_MEDIA_STATUS_RPT, H2C_MEDIA_STATUS_RPT_LEN, parm); + if (ret != _SUCCESS) + goto exit; + +#ifdef CONFIG_DFS_MASTER +post_action: +#endif + if (rtw_get_chip_type(adapter) == RTL8188E) { + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + + /* 8188E FW doesn't set macid no link, driver does it by self */ + if (opmode) + rtw_hal_set_hwreg(adapter, HW_VAR_MACID_LINK, &macid); + else + rtw_hal_set_hwreg(adapter, HW_VAR_MACID_NOLINK, &macid); + + /* for 8188E RA */ +#if (RATE_ADAPTIVE_SUPPORT == 1) + if (hal_data->fw_ractrl == false) { + u8 max_macid; + + max_macid = rtw_search_max_mac_id(adapter); + rtw_hal_set_hwreg(adapter, HW_VAR_TX_RPT_MAX_MACID, &max_macid); + } +#endif + } + + SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0); + if (macid_ind == 0) + macid_end = macid; + + for (i = macid; macid <= macid_end; macid++) { + rtw_macid_ctl_set_h2c_msr(macid_ctl, macid, parm[0]); + if (!opmode) { + rtw_macid_ctl_set_bw(macid_ctl, macid, CHANNEL_WIDTH_20); + rtw_macid_ctl_set_vht_en(macid_ctl, macid, 0); + rtw_macid_ctl_set_rate_bmp0(macid_ctl, macid, 0); + rtw_macid_ctl_set_rate_bmp1(macid_ctl, macid, 0); + } + } + if (!opmode) + rtw_update_tx_rate_bmp(adapter_to_dvobj(adapter)); + +exit: + return ret; +} + +inline s32 rtw_hal_set_FwMediaStatusRpt_single_cmd(_adapter *adapter, bool opmode, bool miracast, bool miracast_sink, u8 role, u8 macid) +{ + return rtw_hal_set_FwMediaStatusRpt_cmd(adapter, opmode, miracast, miracast_sink, role, macid, 0, 0); +} + +inline s32 rtw_hal_set_FwMediaStatusRpt_range_cmd(_adapter *adapter, bool opmode, bool miracast, bool miracast_sink, u8 role, u8 macid, u8 macid_end) +{ + return rtw_hal_set_FwMediaStatusRpt_cmd(adapter, opmode, miracast, miracast_sink, role, macid, 1, macid_end); +} + +static void rtw_hal_set_FwRsvdPage_cmd(PADAPTER padapter, PRSVDPAGE_LOC rsvdpageloc) +{ + struct hal_ops *pHalFunc = &padapter->hal_func; + u8 u1H2CRsvdPageParm[H2C_RSVDPAGE_LOC_LEN] = {0}; + u8 ret = 0; + + RTW_INFO("RsvdPageLoc: ProbeRsp=%d PsPoll=%d Null=%d QoSNull=%d BTNull=%d\n", + rsvdpageloc->LocProbeRsp, rsvdpageloc->LocPsPoll, + rsvdpageloc->LocNullData, rsvdpageloc->LocQosNull, + rsvdpageloc->LocBTQosNull); + + SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1H2CRsvdPageParm, rsvdpageloc->LocProbeRsp); + SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1H2CRsvdPageParm, rsvdpageloc->LocPsPoll); + SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocNullData); + SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocQosNull); + SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocBTQosNull); + + ret = rtw_hal_fill_h2c_cmd(padapter, + H2C_RSVD_PAGE, + H2C_RSVDPAGE_LOC_LEN, + u1H2CRsvdPageParm); + +} + +#ifdef CONFIG_GPIO_WAKEUP +void rtw_hal_switch_gpio_wl_ctrl(_adapter *padapter, u8 index, u8 enable) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + + if (IS_8723D_SERIES(pHalData->version_id) || IS_8822B_SERIES(pHalData->version_id)) + rtw_hal_set_hwreg(padapter, HW_SET_GPIO_WL_CTRL, (u8 *)(&enable)); + /* + * Switch GPIO_13, GPIO_14 to wlan control, or pull GPIO_13,14 MUST fail. + * It happended at 8723B/8192E/8821A. New IC will check multi function GPIO, + * and implement HAL function. + * TODO: GPIO_8 multi function? + */ + + if (index == 13 || index == 14) + rtw_hal_set_hwreg(padapter, HW_SET_GPIO_WL_CTRL, (u8 *)(&enable)); +} + +void rtw_hal_set_output_gpio(_adapter *padapter, u8 index, u8 outputval) +{ + if (index <= 7) { + /* config GPIO mode */ + rtw_write8(padapter, REG_GPIO_PIN_CTRL + 3, + rtw_read8(padapter, REG_GPIO_PIN_CTRL + 3) & ~BIT(index)); + + /* config GPIO Sel */ + /* 0: input */ + /* 1: output */ + rtw_write8(padapter, REG_GPIO_PIN_CTRL + 2, + rtw_read8(padapter, REG_GPIO_PIN_CTRL + 2) | BIT(index)); + + /* set output value */ + if (outputval) { + rtw_write8(padapter, REG_GPIO_PIN_CTRL + 1, + rtw_read8(padapter, REG_GPIO_PIN_CTRL + 1) | BIT(index)); + } else { + rtw_write8(padapter, REG_GPIO_PIN_CTRL + 1, + rtw_read8(padapter, REG_GPIO_PIN_CTRL + 1) & ~BIT(index)); + } + } else if (index <= 15) { + /* 88C Series: */ + /* index: 11~8 transform to 3~0 */ + /* 8723 Series: */ + /* index: 12~8 transform to 4~0 */ + + index -= 8; + + /* config GPIO mode */ + rtw_write8(padapter, REG_GPIO_PIN_CTRL_2 + 3, + rtw_read8(padapter, REG_GPIO_PIN_CTRL_2 + 3) & ~BIT(index)); + + /* config GPIO Sel */ + /* 0: input */ + /* 1: output */ + rtw_write8(padapter, REG_GPIO_PIN_CTRL_2 + 2, + rtw_read8(padapter, REG_GPIO_PIN_CTRL_2 + 2) | BIT(index)); + + /* set output value */ + if (outputval) { + rtw_write8(padapter, REG_GPIO_PIN_CTRL_2 + 1, + rtw_read8(padapter, REG_GPIO_PIN_CTRL_2 + 1) | BIT(index)); + } else { + rtw_write8(padapter, REG_GPIO_PIN_CTRL_2 + 1, + rtw_read8(padapter, REG_GPIO_PIN_CTRL_2 + 1) & ~BIT(index)); + } + } else { + RTW_INFO("%s: invalid GPIO%d=%d\n", + __func__, index, outputval); + } +} +#endif + +static void rtw_hal_set_FwAoacRsvdPage_cmd(PADAPTER padapter, PRSVDPAGE_LOC rsvdpageloc) +{ + struct hal_ops *pHalFunc = &padapter->hal_func; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + u8 res = 0, count = 0, ret = 0; +#ifdef CONFIG_WOWLAN + u8 u1H2CAoacRsvdPageParm[H2C_AOAC_RSVDPAGE_LOC_LEN] = {0}; + + RTW_INFO("AOACRsvdPageLoc: RWC=%d ArpRsp=%d NbrAdv=%d GtkRsp=%d GtkInfo=%d ProbeReq=%d NetworkList=%d\n", + rsvdpageloc->LocRemoteCtrlInfo, rsvdpageloc->LocArpRsp, + rsvdpageloc->LocNbrAdv, rsvdpageloc->LocGTKRsp, + rsvdpageloc->LocGTKInfo, rsvdpageloc->LocProbeReq, + rsvdpageloc->LocNetList); + + if (check_fwstate(pmlmepriv, _FW_LINKED)) { + SET_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1H2CAoacRsvdPageParm, rsvdpageloc->LocRemoteCtrlInfo); + SET_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1H2CAoacRsvdPageParm, rsvdpageloc->LocArpRsp); + /* SET_H2CCMD_AOAC_RSVDPAGE_LOC_NEIGHBOR_ADV(u1H2CAoacRsvdPageParm, rsvdpageloc->LocNbrAdv); */ +#ifdef CONFIG_GTK_OL + SET_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_RSP(u1H2CAoacRsvdPageParm, rsvdpageloc->LocGTKRsp); + SET_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_INFO(u1H2CAoacRsvdPageParm, rsvdpageloc->LocGTKInfo); + SET_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1H2CAoacRsvdPageParm, rsvdpageloc->LocGTKEXTMEM); +#endif /* CONFIG_GTK_OL */ + ret = rtw_hal_fill_h2c_cmd(padapter, + H2C_AOAC_RSVD_PAGE, + H2C_AOAC_RSVDPAGE_LOC_LEN, + u1H2CAoacRsvdPageParm); + + RTW_INFO("AOAC Report=%d\n", rsvdpageloc->LocAOACReport); + memset(&u1H2CAoacRsvdPageParm, 0, sizeof(u1H2CAoacRsvdPageParm)); + SET_H2CCMD_AOAC_RSVDPAGE_LOC_AOAC_REPORT(u1H2CAoacRsvdPageParm, + rsvdpageloc->LocAOACReport); + ret = rtw_hal_fill_h2c_cmd(padapter, + H2C_AOAC_RSVDPAGE3, + H2C_AOAC_RSVDPAGE_LOC_LEN, + u1H2CAoacRsvdPageParm); + pwrpriv->wowlan_aoac_rpt_loc = rsvdpageloc->LocAOACReport; + } +#ifdef CONFIG_PNO_SUPPORT + else { + + if (!pwrpriv->wowlan_in_resume) { + RTW_INFO("NLO_INFO=%d\n", rsvdpageloc->LocPNOInfo); + memset(&u1H2CAoacRsvdPageParm, 0, + sizeof(u1H2CAoacRsvdPageParm)); + SET_H2CCMD_AOAC_RSVDPAGE_LOC_NLO_INFO(u1H2CAoacRsvdPageParm, + rsvdpageloc->LocPNOInfo); + ret = rtw_hal_fill_h2c_cmd(padapter, + H2C_AOAC_RSVDPAGE3, + H2C_AOAC_RSVDPAGE_LOC_LEN, + u1H2CAoacRsvdPageParm); + } + } +#endif /* CONFIG_PNO_SUPPORT */ +#endif /* CONFIG_WOWLAN */ +} + +/*#define DBG_GET_RSVD_PAGE*/ +int rtw_hal_get_rsvd_page(_adapter *adapter, u32 page_offset, + u32 page_num, u8 *buffer, u32 buffer_size) +{ + u32 addr = 0, size = 0, count = 0; + u32 page_size = 0, data_low = 0, data_high = 0; + u16 txbndy = 0, offset = 0; + u8 i = 0; + bool rst = false; + + rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, &page_size); + + addr = page_offset * page_size; + size = page_num * page_size; + + if (buffer_size < size) { + RTW_ERR("%s buffer_size(%d) < get page total size(%d)\n", + __func__, buffer_size, size); + return rst; + } +#ifdef RTW_HALMAC + if (rtw_halmac_dump_fifo(adapter_to_dvobj(adapter), 2, addr, size, buffer) < 0) + rst = false; + else + rst = true; +#else + txbndy = rtw_read8(adapter, REG_TDECTRL + 1); + + offset = (txbndy + page_offset) << 4; + count = (buffer_size / 8) + 1; + + rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, 0x69); + + for (i = 0 ; i < count ; i++) { + rtw_write32(adapter, REG_PKTBUF_DBG_CTRL, offset + i); + data_low = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_L); + data_high = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_H); + memcpy(buffer + (i * 8), + &data_low, sizeof(data_low)); + memcpy(buffer + ((i * 8) + 4), + &data_high, sizeof(data_high)); + } + rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, 0x0); + rst = true; +#endif /*RTW_HALMAC*/ + +#ifdef DBG_GET_RSVD_PAGE + RTW_INFO("%s [page_offset:%d , page_num:%d][start_addr:0x%04x , size:%d]\n", + __func__, page_offset, page_num, addr, size); + RTW_INFO_DUMP("\n", buffer, size); + RTW_INFO(" ==================================================\n"); +#endif + return rst; +} + +void rtw_dump_rsvd_page(void *sel, _adapter *adapter, u8 page_offset, u8 page_num) +{ + u32 page_size = 0; + u8 *buffer = NULL; + u32 buf_size = 0; + + if (page_num == 0) + return; + + RTW_PRINT_SEL(sel, "======= RSVG PAGE DUMP =======\n"); + RTW_PRINT_SEL(sel, "page_offset:%d, page_num:%d\n", page_offset, page_num); + + rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, &page_size); + if (page_size) { + buf_size = page_size * page_num; + buffer = rtw_zvmalloc(buf_size); + + if (buffer) { + rtw_hal_get_rsvd_page(adapter, page_offset, page_num, buffer, buf_size); + _RTW_DUMP_SEL(sel, buffer, buf_size); + rtw_vmfree(buffer, buf_size); + } else + RTW_PRINT_SEL(sel, "ERROR - rsvd_buf mem allocate failed\n"); + } else + RTW_PRINT_SEL(sel, "ERROR - Tx page size is zero ??\n"); + + RTW_PRINT_SEL(sel, "==========================\n"); +} + +#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) +static void rtw_hal_force_enable_rxdma(_adapter *adapter) +{ + RTW_INFO("%s: Set 0x690=0x00\n", __func__); + rtw_write8(adapter, REG_WOW_CTRL, + (rtw_read8(adapter, REG_WOW_CTRL) & 0xf0)); + RTW_PRINT("%s: Release RXDMA\n", __func__); + rtw_write32(adapter, REG_RXPKT_NUM, + (rtw_read32(adapter, REG_RXPKT_NUM) & (~RW_RELEASE_EN))); +} +static void rtw_hal_disable_tx_report(_adapter *adapter) +{ + rtw_write8(adapter, REG_TX_RPT_CTRL, + ((rtw_read8(adapter, REG_TX_RPT_CTRL) & ~BIT(1))) & ~BIT(5)); + RTW_INFO("disable TXRPT:0x%02x\n", rtw_read8(adapter, REG_TX_RPT_CTRL)); +} + +static void rtw_hal_enable_tx_report(_adapter *adapter) +{ + rtw_write8(adapter, REG_TX_RPT_CTRL, + ((rtw_read8(adapter, REG_TX_RPT_CTRL) | BIT(1))) | BIT(5)); + RTW_INFO("enable TX_RPT:0x%02x\n", rtw_read8(adapter, REG_TX_RPT_CTRL)); +} + +static void rtw_hal_release_rx_dma(_adapter *adapter) +{ + u32 val32 = 0; + + val32 = rtw_read32(adapter, REG_RXPKT_NUM); + + rtw_write32(adapter, REG_RXPKT_NUM, (val32 & (~RW_RELEASE_EN))); + + RTW_INFO("%s, [0x%04x]: 0x%08x\n", + __func__, REG_RXPKT_NUM, (val32 & (~RW_RELEASE_EN))); +} + +static u8 rtw_hal_pause_rx_dma(_adapter *adapter) +{ + PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter); + u8 ret = 0; + s8 trycnt = 100; + u32 tmp = 0; + int res = 0; + /* RX DMA stop */ + RTW_PRINT("Pause DMA\n"); + rtw_write32(adapter, REG_RXPKT_NUM, + (rtw_read32(adapter, REG_RXPKT_NUM) | RW_RELEASE_EN)); + do { + if ((rtw_read32(adapter, REG_RXPKT_NUM) & RXDMA_IDLE)) { + /* stop interface before leave */ + if (hal->usb_intf_start) { + rtw_intf_stop(adapter); + RTW_ENABLE_FUNC(adapter, DF_RX_BIT); + RTW_ENABLE_FUNC(adapter, DF_TX_BIT); + } + + RTW_PRINT("RX_DMA_IDLE is true\n"); + ret = _SUCCESS; + break; + } + else { + /* to avoid interface start repeatedly */ + if (false == hal->usb_intf_start) + rtw_intf_start(adapter); + } + } while (trycnt--); + + if (trycnt < 0) { + tmp = rtw_read16(adapter, REG_RXPKT_NUM + 3); + + RTW_PRINT("Stop RX DMA failed......\n"); + RTW_PRINT("%s, RXPKT_NUM: 0x%04x\n", + __func__, tmp); + tmp = rtw_read16(adapter, REG_RXPKT_NUM + 2); + if (tmp & BIT(3)) + RTW_PRINT("%s, RX DMA has req\n", + __func__); + else + RTW_PRINT("%s, RX DMA no req\n", + __func__); + ret = _FAIL; + } + + return ret; +} + +#endif /* CONFIG_WOWLAN || CONFIG_AP_WOWLAN */ + +#ifdef CONFIG_WOWLAN +/* + * rtw_hal_check_wow_ctrl + * chk_type: true means to check enable, if 0x690 & bit1, WOW enable successful + * false means to check disable, if 0x690 & bit1, WOW disable fail + */ +static u8 rtw_hal_check_wow_ctrl(_adapter *adapter, u8 chk_type) +{ + u8 mstatus = 0; + u8 trycnt = 25; + u8 res = false; + + mstatus = rtw_read8(adapter, REG_WOW_CTRL); + RTW_INFO("%s mstatus:0x%02x\n", __func__, mstatus); + + if (chk_type) { + while (!(mstatus & BIT1) && trycnt > 1) { + mstatus = rtw_read8(adapter, REG_WOW_CTRL); + RTW_PRINT("Loop index: %d :0x%02x\n", + trycnt, mstatus); + trycnt--; + rtw_msleep_os(20); + } + if (mstatus & BIT1) + res = true; + else + res = false; + } else { + while (mstatus & BIT1 && trycnt > 1) { + mstatus = rtw_read8(adapter, REG_WOW_CTRL); + RTW_PRINT("Loop index: %d :0x%02x\n", + trycnt, mstatus); + trycnt--; + rtw_msleep_os(20); + } + + if (mstatus & BIT1) + res = false; + else + res = true; + } + RTW_PRINT("%s check_type: %d res: %d trycnt: %d\n", + __func__, chk_type, res, (25 - trycnt)); + return res; +} + +#ifdef CONFIG_PNO_SUPPORT +static u8 rtw_hal_check_pno_enabled(_adapter *adapter) +{ + struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(adapter); + u8 res = 0, count = 0; + u8 ret = false; + + if (ppwrpriv->wowlan_pno_enable && ppwrpriv->wowlan_in_resume == false) { + res = rtw_read8(adapter, REG_PNO_STATUS); + while (!(res & BIT(7)) && count < 25) { + RTW_INFO("[%d] cmd: 0x81 REG_PNO_STATUS: 0x%02x\n", + count, res); + res = rtw_read8(adapter, REG_PNO_STATUS); + count++; + rtw_msleep_os(2); + } + if (res & BIT(7)) + ret = true; + else + ret = false; + RTW_INFO("cmd: 0x81 REG_PNO_STATUS: ret(%d)\n", ret); + } + return ret; +} +#endif + +static void rtw_hal_backup_rate(_adapter *adapter) +{ + RTW_INFO("%s\n", __func__); + /* backup data rate to register 0x8b for wowlan FW */ + rtw_write8(adapter, 0x8d, 1); + rtw_write8(adapter, 0x8c, 0); + rtw_write8(adapter, 0x8f, 0x40); + rtw_write8(adapter, 0x8b, rtw_read8(adapter, 0x2f0)); +} + +#ifdef CONFIG_GTK_OL +static void rtw_hal_fw_sync_cam_id(_adapter *adapter) +{ + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + int cam_id, index = 0; + u8 *addr = NULL; + + if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) + return; + + addr = get_bssid(pmlmepriv); + + if (addr == NULL) { + RTW_INFO("%s: get bssid MAC addr fail!!\n", __func__); + return; + } + + rtw_clean_dk_section(adapter); + + do { + cam_id = rtw_camid_search(adapter, addr, index, 1); + + if (cam_id == -1) + RTW_INFO("%s: cam_id: %d, key_id:%d\n", __func__, cam_id, index); + else + rtw_sec_cam_swap(adapter, cam_id, index); + + index++; + } while (index < 4); + + rtw_write8(adapter, REG_SECCFG, 0xcc); +} + +static void rtw_dump_aoac_rpt(_adapter *adapter) +{ + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter); + struct aoac_report *paoac_rpt = &pwrctl->wowlan_aoac_rpt; + + RTW_INFO_DUMP("[AOAC-RPT] IV -", paoac_rpt->iv, 8); + RTW_INFO_DUMP("[AOAC-RPT] Replay counter of EAPOL key - ", + paoac_rpt->replay_counter_eapol_key, 8); + RTW_INFO_DUMP("[AOAC-RPT] Group key - ", paoac_rpt->group_key, 32); + RTW_INFO("[AOAC-RPT] Key Index - %d\n", paoac_rpt->key_index); + RTW_INFO("[AOAC-RPT] Security Type - %d\n", paoac_rpt->security_type); +} + +static void rtw_hal_get_aoac_rpt(_adapter *adapter) +{ + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter); + struct aoac_report *paoac_rpt = &pwrctl->wowlan_aoac_rpt; + u32 page_offset = 0, page_number = 0; + u32 page_size = 0, buf_size = 0; + u8 *buffer = NULL; + u8 i = 0, tmp = 0; + int ret = -1; + + /* read aoac report from rsvd page */ + page_offset = pwrctl->wowlan_aoac_rpt_loc; + page_number = 1; + + rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, &page_size); + buf_size = page_size * page_number; + + buffer = rtw_zvmalloc(buf_size); + + if (NULL == buffer) { + RTW_ERR("%s buffer allocate failed size(%d)\n", + __func__, buf_size); + return; + } + + RTW_INFO("Get AOAC Report from rsvd page_offset:%d\n", page_offset); + + ret = rtw_hal_get_rsvd_page(adapter, page_offset, + page_number, buffer, buf_size); + + if (ret == false) { + RTW_ERR("%s get aoac report failed\n", __func__); + rtw_warn_on(1); + goto _exit; + } + + memset(paoac_rpt, 0, sizeof(struct aoac_report)); + memcpy(paoac_rpt, buffer, sizeof(struct aoac_report)); + + for (i = 0 ; i < 4 ; i++) { + tmp = paoac_rpt->replay_counter_eapol_key[i]; + paoac_rpt->replay_counter_eapol_key[i] = + paoac_rpt->replay_counter_eapol_key[7 - i]; + paoac_rpt->replay_counter_eapol_key[7 - i] = tmp; + } + + /* rtw_dump_aoac_rpt(adapter); */ + +_exit: + if (buffer) + rtw_vmfree(buffer, buf_size); +} + +static void rtw_hal_update_gtk_offload_info(_adapter *adapter) +{ + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter); + struct aoac_report *paoac_rpt = &pwrctl->wowlan_aoac_rpt; + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct security_priv *psecuritypriv = &adapter->securitypriv; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl; + unsigned long irqL; + u8 get_key[16]; + u8 gtk_id = 0, offset = 0, i = 0, sz = 0; + u64 replay_count = 0; + + if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) + return; + + memset(get_key, 0, sizeof(get_key)); + memcpy(&replay_count, + paoac_rpt->replay_counter_eapol_key, 8); + + /*read gtk key index*/ + gtk_id = paoac_rpt->key_index; + + if (gtk_id == 5 || gtk_id == 0) { + RTW_INFO("%s no rekey event happened.\n", __func__); + } else if (gtk_id > 0 && gtk_id < 4) { + RTW_INFO("%s update security key.\n", __func__); + /*read key from sec-cam,for DK ,keyindex is equal to cam-id*/ + rtw_sec_read_cam_ent(adapter, gtk_id, + NULL, NULL, get_key); + rtw_clean_hw_dk_cam(adapter); + + if (_rtw_camid_is_gk(adapter, gtk_id)) { + _enter_critical_bh(&cam_ctl->lock, &irqL); + memcpy(&dvobj->cam_cache[gtk_id].key, + get_key, 16); + _exit_critical_bh(&cam_ctl->lock, &irqL); + } else { + struct setkey_parm parm_gtk; + + parm_gtk.algorithm = paoac_rpt->security_type; + parm_gtk.keyid = gtk_id; + memcpy(parm_gtk.key, get_key, 16); + setkey_hdl(adapter, (u8 *)&parm_gtk); + } + + /*update key into related sw variable and sec-cam cache*/ + psecuritypriv->dot118021XGrpKeyid = gtk_id; + memcpy(&psecuritypriv->dot118021XGrpKey[gtk_id], + get_key, 16); + /* update SW TKIP TX/RX MIC value */ + if (psecuritypriv->dot118021XGrpPrivacy == _TKIP_) { + offset = RTW_KEK_LEN + RTW_TKIP_MIC_LEN; + memcpy( + &psecuritypriv->dot118021XGrptxmickey[gtk_id], + &(paoac_rpt->group_key[offset]), + RTW_TKIP_MIC_LEN); + + offset = RTW_KEK_LEN; + memcpy( + &psecuritypriv->dot118021XGrprxmickey[gtk_id], + &(paoac_rpt->group_key[offset]), + RTW_TKIP_MIC_LEN); + } + /* Update broadcast RX IV */ + if (psecuritypriv->dot118021XGrpPrivacy == _AES_) { + sz = sizeof(psecuritypriv->iv_seq[0]); + for (i = 0 ; i < 4 ; i++) + memset(psecuritypriv->iv_seq[i], 0, sz); + } + + RTW_PRINT("GTK (%d) "KEY_FMT"\n", gtk_id, + KEY_ARG(psecuritypriv->dot118021XGrpKey[gtk_id].skey)); + } + + rtw_clean_dk_section(adapter); + + rtw_write8(adapter, REG_SECCFG, 0x0c); + + #ifdef CONFIG_GTK_OL_DBG + /* if (gtk_keyindex != 5) */ + dump_sec_cam(RTW_DBGDUMP, adapter); + dump_sec_cam_cache(RTW_DBGDUMP, adapter); + #endif +} + +static void rtw_hal_update_tx_iv(_adapter *adapter) +{ + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter); + struct aoac_report *paoac_rpt = &pwrctl->wowlan_aoac_rpt; + struct sta_info *psta; + struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct security_priv *psecpriv = &adapter->securitypriv; + + u16 val16 = 0; + u32 val32 = 0; + u64 txiv = 0; + u8 *pval = NULL; + + psta = rtw_get_stainfo(&adapter->stapriv, + get_my_bssid(&pmlmeinfo->network)); + + /* Update TX iv data. */ + pval = (u8 *)&paoac_rpt->iv; + + if (psecpriv->dot11PrivacyAlgrthm == _TKIP_) { + val16 = ((u16)(paoac_rpt->iv[2]) << 0) + + ((u16)(paoac_rpt->iv[0]) << 8); + val32 = ((u32)(paoac_rpt->iv[4]) << 0) + + ((u32)(paoac_rpt->iv[5]) << 8) + + ((u32)(paoac_rpt->iv[6]) << 16) + + ((u32)(paoac_rpt->iv[7]) << 24); + } else if (psecpriv->dot11PrivacyAlgrthm == _AES_) { + val16 = ((u16)(paoac_rpt->iv[0]) << 0) + + ((u16)(paoac_rpt->iv[1]) << 8); + val32 = ((u32)(paoac_rpt->iv[4]) << 0) + + ((u32)(paoac_rpt->iv[5]) << 8) + + ((u32)(paoac_rpt->iv[6]) << 16) + + ((u32)(paoac_rpt->iv[7]) << 24); + } + + if (psta) { + txiv = val16 + ((u64)val32 << 16); + if (txiv != 0) + psta->dot11txpn.val = txiv; + } +} + +static void rtw_hal_update_sw_security_info(_adapter *adapter) +{ + rtw_hal_update_tx_iv(adapter); + rtw_hal_update_gtk_offload_info(adapter); +} +#endif /*CONFIG_GTK_OL*/ + +static u8 rtw_hal_set_keep_alive_cmd(_adapter *adapter, u8 enable, u8 pkt_type) +{ + struct hal_ops *pHalFunc = &adapter->hal_func; + + u8 u1H2CKeepAliveParm[H2C_KEEP_ALIVE_CTRL_LEN] = {0}; + u8 adopt = 1, check_period = 5; + u8 ret = _FAIL; + + SET_H2CCMD_KEEPALIVE_PARM_ENABLE(u1H2CKeepAliveParm, enable); + SET_H2CCMD_KEEPALIVE_PARM_ADOPT(u1H2CKeepAliveParm, adopt); + SET_H2CCMD_KEEPALIVE_PARM_PKT_TYPE(u1H2CKeepAliveParm, pkt_type); + SET_H2CCMD_KEEPALIVE_PARM_CHECK_PERIOD(u1H2CKeepAliveParm, check_period); +#ifdef CONFIG_FW_MULTI_PORT_SUPPORT + SET_H2CCMD_KEEPALIVE_PARM_PORT_NUM(u1H2CKeepAliveParm, adapter->hw_port); + RTW_INFO("%s(): enable = %d, port = %d\n", __func__, enable, adapter->hw_port); +#else + RTW_INFO("%s(): enable = %d\n", __func__, enable); +#endif + ret = rtw_hal_fill_h2c_cmd(adapter, + H2C_KEEP_ALIVE, + H2C_KEEP_ALIVE_CTRL_LEN, + u1H2CKeepAliveParm); + + return ret; +} + +static u8 rtw_hal_set_disconnect_decision_cmd(_adapter *adapter, u8 enable) +{ + struct hal_ops *pHalFunc = &adapter->hal_func; + u8 u1H2CDisconDecisionParm[H2C_DISCON_DECISION_LEN] = {0}; + u8 adopt = 1, check_period = 10, trypkt_num = 0; + u8 ret = _FAIL; + + SET_H2CCMD_DISCONDECISION_PARM_ENABLE(u1H2CDisconDecisionParm, enable); + SET_H2CCMD_DISCONDECISION_PARM_ADOPT(u1H2CDisconDecisionParm, adopt); + SET_H2CCMD_DISCONDECISION_PARM_CHECK_PERIOD(u1H2CDisconDecisionParm, check_period); + SET_H2CCMD_DISCONDECISION_PARM_TRY_PKT_NUM(u1H2CDisconDecisionParm, trypkt_num); +#ifdef CONFIG_FW_MULTI_PORT_SUPPORT + SET_H2CCMD_DISCONDECISION_PORT_NUM(u1H2CDisconDecisionParm, adapter->hw_port); + RTW_INFO("%s(): enable = %d, port = %d\n", __func__, enable, adapter->hw_port); +#else + RTW_INFO("%s(): enable = %d\n", __func__, enable); +#endif + + ret = rtw_hal_fill_h2c_cmd(adapter, + H2C_DISCON_DECISION, + H2C_DISCON_DECISION_LEN, + u1H2CDisconDecisionParm); + return ret; +} + +static u8 rtw_hal_set_wowlan_ctrl_cmd(_adapter *adapter, u8 enable, u8 change_unit) +{ + struct security_priv *psecpriv = &adapter->securitypriv; + struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(adapter); + struct hal_ops *pHalFunc = &adapter->hal_func; + + u8 u1H2CWoWlanCtrlParm[H2C_WOWLAN_LEN] = {0}; + u8 discont_wake = 1, gpionum = 0, gpio_dur = 0; + u8 hw_unicast = 0, gpio_pulse_cnt = 0, gpio_pulse_en = 0; + u8 sdio_wakeup_enable = 1; + u8 gpio_high_active = 0; + u8 magic_pkt = 0; + u8 gpio_unit = 0; /*0: 64ns, 1: 8ms*/ + u8 ret = _FAIL; + +#ifdef CONFIG_GPIO_WAKEUP + gpio_high_active = ppwrpriv->is_high_active; + gpionum = WAKEUP_GPIO_IDX; + sdio_wakeup_enable = 0; +#endif /* CONFIG_GPIO_WAKEUP */ + + if (!ppwrpriv->wowlan_pno_enable) + magic_pkt = enable; + + if (psecpriv->dot11PrivacyAlgrthm == _WEP40_ || psecpriv->dot11PrivacyAlgrthm == _WEP104_) + hw_unicast = 1; + else + hw_unicast = 0; + + RTW_INFO("%s(): enable=%d change_unit=%d\n", __func__, + enable, change_unit); + + /* time = (gpio_dur/2) * gpio_unit, default:256 ms */ + if (enable && change_unit) { + gpio_dur = 0x40; + gpio_unit = 1; + gpio_pulse_en = 1; + } + +#ifdef CONFIG_PLATFORM_ARM_RK3188 + if (enable) { + gpio_pulse_en = 1; + gpio_pulse_cnt = 0x04; + } +#endif + + SET_H2CCMD_WOWLAN_FUNC_ENABLE(u1H2CWoWlanCtrlParm, enable); + SET_H2CCMD_WOWLAN_PATTERN_MATCH_ENABLE(u1H2CWoWlanCtrlParm, enable); + SET_H2CCMD_WOWLAN_MAGIC_PKT_ENABLE(u1H2CWoWlanCtrlParm, magic_pkt); + SET_H2CCMD_WOWLAN_UNICAST_PKT_ENABLE(u1H2CWoWlanCtrlParm, hw_unicast); + SET_H2CCMD_WOWLAN_ALL_PKT_DROP(u1H2CWoWlanCtrlParm, 0); + SET_H2CCMD_WOWLAN_GPIO_ACTIVE(u1H2CWoWlanCtrlParm, gpio_high_active); + +#ifdef CONFIG_GTK_OL + /* GTK rekey only for AES, if GTK rekey is TKIP, then wake up*/ + if (psecpriv->binstallKCK_KEK == true) + SET_H2CCMD_WOWLAN_REKEY_WAKE_UP(u1H2CWoWlanCtrlParm, 0); + else + SET_H2CCMD_WOWLAN_REKEY_WAKE_UP(u1H2CWoWlanCtrlParm, 1); +#else + SET_H2CCMD_WOWLAN_REKEY_WAKE_UP(u1H2CWoWlanCtrlParm, enable); +#endif + SET_H2CCMD_WOWLAN_DISCONNECT_WAKE_UP(u1H2CWoWlanCtrlParm, discont_wake); + SET_H2CCMD_WOWLAN_GPIONUM(u1H2CWoWlanCtrlParm, gpionum); + SET_H2CCMD_WOWLAN_DATAPIN_WAKE_UP(u1H2CWoWlanCtrlParm, sdio_wakeup_enable); + + SET_H2CCMD_WOWLAN_GPIO_DURATION(u1H2CWoWlanCtrlParm, gpio_dur); + SET_H2CCMD_WOWLAN_CHANGE_UNIT(u1H2CWoWlanCtrlParm, gpio_unit); + + SET_H2CCMD_WOWLAN_GPIO_PULSE_EN(u1H2CWoWlanCtrlParm, gpio_pulse_en); + SET_H2CCMD_WOWLAN_GPIO_PULSE_COUNT(u1H2CWoWlanCtrlParm, gpio_pulse_cnt); + + ret = rtw_hal_fill_h2c_cmd(adapter, + H2C_WOWLAN, + H2C_WOWLAN_LEN, + u1H2CWoWlanCtrlParm); + return ret; +} + +static u8 rtw_hal_set_remote_wake_ctrl_cmd(_adapter *adapter, u8 enable) +{ + struct hal_ops *pHalFunc = &adapter->hal_func; + struct security_priv *psecuritypriv = &(adapter->securitypriv); + struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(adapter); + struct registry_priv *pregistrypriv = &adapter->registrypriv; + u8 u1H2CRemoteWakeCtrlParm[H2C_REMOTE_WAKE_CTRL_LEN] = {0}; + u8 ret = _FAIL, count = 0; + + RTW_INFO("%s(): enable=%d\n", __func__, enable); + + if (!ppwrpriv->wowlan_pno_enable) { + SET_H2CCMD_REMOTE_WAKECTRL_ENABLE( + u1H2CRemoteWakeCtrlParm, enable); + SET_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN( + u1H2CRemoteWakeCtrlParm, 1); +#ifdef CONFIG_GTK_OL + if (psecuritypriv->binstallKCK_KEK == true) { + SET_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN( + u1H2CRemoteWakeCtrlParm, 1); + } else { + RTW_INFO("no kck kek\n"); + SET_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN( + u1H2CRemoteWakeCtrlParm, 0); + } +#endif /* CONFIG_GTK_OL */ + + if (pregistrypriv->default_patterns_en == false) { + SET_H2CCMD_REMOTE_WAKE_CTRL_FW_UNICAST_EN( + u1H2CRemoteWakeCtrlParm, enable); + /* + * filter NetBios name service pkt to avoid being waked-up + * by this kind of unicast pkt this exceptional modification + * is used for match competitor's behavior + */ + SET_H2CCMD_REMOTE_WAKE_CTRL_NBNS_FILTER_EN( + u1H2CRemoteWakeCtrlParm, enable); + } + + if ((psecuritypriv->dot11PrivacyAlgrthm == _AES_) || + (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_) || + (psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_)) { + SET_H2CCMD_REMOTE_WAKE_CTRL_ARP_ACTION( + u1H2CRemoteWakeCtrlParm, 0); + } else { + SET_H2CCMD_REMOTE_WAKE_CTRL_ARP_ACTION( + u1H2CRemoteWakeCtrlParm, 1); + } + + if (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_) { + SET_H2CCMD_REMOTE_WAKE_CTRL_TKIP_OFFLOAD_EN( + u1H2CRemoteWakeCtrlParm, enable); + + if (IS_HARDWARE_TYPE_8188E(adapter)) { + SET_H2CCMD_REMOTE_WAKE_CTRL_TKIP_OFFLOAD_EN( + u1H2CRemoteWakeCtrlParm, 0); + SET_H2CCMD_REMOTE_WAKE_CTRL_ARP_ACTION( + u1H2CRemoteWakeCtrlParm, 1); + } + } + + SET_H2CCMD_REMOTE_WAKE_CTRL_FW_PARSING_UNTIL_WAKEUP( + u1H2CRemoteWakeCtrlParm, 1); + } +#ifdef CONFIG_PNO_SUPPORT + else { + SET_H2CCMD_REMOTE_WAKECTRL_ENABLE( + u1H2CRemoteWakeCtrlParm, enable); + SET_H2CCMD_REMOTE_WAKE_CTRL_NLO_OFFLOAD_EN( + u1H2CRemoteWakeCtrlParm, enable); + } +#endif + +#ifdef CONFIG_P2P_WOWLAN + if (ppwrpriv->wowlan_p2p_mode) { + RTW_INFO("P2P OFFLOAD ENABLE\n"); + SET_H2CCMD_REMOTE_WAKE_CTRL_P2P_OFFLAD_EN(u1H2CRemoteWakeCtrlParm, 1); + } else { + RTW_INFO("P2P OFFLOAD DISABLE\n"); + SET_H2CCMD_REMOTE_WAKE_CTRL_P2P_OFFLAD_EN(u1H2CRemoteWakeCtrlParm, 0); + } +#endif /* CONFIG_P2P_WOWLAN */ + + + ret = rtw_hal_fill_h2c_cmd(adapter, + H2C_REMOTE_WAKE_CTRL, + H2C_REMOTE_WAKE_CTRL_LEN, + u1H2CRemoteWakeCtrlParm); + return ret; +} + +static u8 rtw_hal_set_global_info_cmd(_adapter *adapter, u8 group_alg, u8 pairwise_alg) +{ + struct hal_ops *pHalFunc = &adapter->hal_func; + u8 ret = _FAIL; + u8 u1H2CAOACGlobalInfoParm[H2C_AOAC_GLOBAL_INFO_LEN] = {0}; + + RTW_INFO("%s(): group_alg=%d pairwise_alg=%d\n", + __func__, group_alg, pairwise_alg); + SET_H2CCMD_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(u1H2CAOACGlobalInfoParm, + pairwise_alg); + SET_H2CCMD_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(u1H2CAOACGlobalInfoParm, + group_alg); + + ret = rtw_hal_fill_h2c_cmd(adapter, + H2C_AOAC_GLOBAL_INFO, + H2C_AOAC_GLOBAL_INFO_LEN, + u1H2CAOACGlobalInfoParm); + + return ret; +} + +#ifdef CONFIG_PNO_SUPPORT +static u8 rtw_hal_set_scan_offload_info_cmd(_adapter *adapter, + PRSVDPAGE_LOC rsvdpageloc, u8 enable) +{ + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter); + struct hal_ops *pHalFunc = &adapter->hal_func; + + u8 u1H2CScanOffloadInfoParm[H2C_SCAN_OFFLOAD_CTRL_LEN] = {0}; + u8 res = 0, count = 0, ret = _FAIL; + + RTW_INFO("%s: loc_probe_packet:%d, loc_scan_info: %d loc_ssid_info:%d\n", + __func__, rsvdpageloc->LocProbePacket, + rsvdpageloc->LocScanInfo, rsvdpageloc->LocSSIDInfo); + + SET_H2CCMD_AOAC_NLO_FUN_EN(u1H2CScanOffloadInfoParm, enable); + SET_H2CCMD_AOAC_NLO_IPS_EN(u1H2CScanOffloadInfoParm, enable); + SET_H2CCMD_AOAC_RSVDPAGE_LOC_SCAN_INFO(u1H2CScanOffloadInfoParm, + rsvdpageloc->LocScanInfo); + SET_H2CCMD_AOAC_RSVDPAGE_LOC_PROBE_PACKET(u1H2CScanOffloadInfoParm, + rsvdpageloc->LocProbePacket); + /* + SET_H2CCMD_AOAC_RSVDPAGE_LOC_SSID_INFO(u1H2CScanOffloadInfoParm, + rsvdpageloc->LocSSIDInfo); + */ + ret = rtw_hal_fill_h2c_cmd(adapter, + H2C_D0_SCAN_OFFLOAD_INFO, + H2C_SCAN_OFFLOAD_CTRL_LEN, + u1H2CScanOffloadInfoParm); + return ret; +} +#endif /* CONFIG_PNO_SUPPORT */ + +void rtw_hal_set_fw_wow_related_cmd(_adapter *padapter, u8 enable) +{ + struct security_priv *psecpriv = &padapter->securitypriv; + struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(padapter); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct sta_info *psta = NULL; + u16 media_status_rpt; + u8 pkt_type = 0; + u8 ret = _SUCCESS; + + RTW_PRINT("+%s()+: enable=%d\n", __func__, enable); + + rtw_hal_set_wowlan_ctrl_cmd(padapter, enable, false); + + if (enable) { + rtw_hal_set_global_info_cmd(padapter, + psecpriv->dot118021XGrpPrivacy, + psecpriv->dot11PrivacyAlgrthm); + + if (!(ppwrpriv->wowlan_pno_enable)) { + rtw_hal_set_disconnect_decision_cmd(padapter, enable); +#ifdef CONFIG_ARP_KEEP_ALIVE + if ((psecpriv->dot11PrivacyAlgrthm == _WEP40_) || + (psecpriv->dot11PrivacyAlgrthm == _WEP104_)) + pkt_type = 0; + else + pkt_type = 1; +#else + pkt_type = 0; +#endif /* CONFIG_ARP_KEEP_ALIVE */ + rtw_hal_set_keep_alive_cmd(padapter, enable, pkt_type); + } + rtw_hal_set_remote_wake_ctrl_cmd(padapter, enable); +#ifdef CONFIG_PNO_SUPPORT + rtw_hal_check_pno_enabled(padapter); +#endif /* CONFIG_PNO_SUPPORT */ + } else { + rtw_hal_set_remote_wake_ctrl_cmd(padapter, enable); + } + RTW_PRINT("-%s()-\n", __func__); +} +#endif /* CONFIG_WOWLAN */ + +#ifdef CONFIG_AP_WOWLAN +static u8 rtw_hal_set_ap_wowlan_ctrl_cmd(_adapter *adapter, u8 enable) +{ + struct security_priv *psecpriv = &adapter->securitypriv; + struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(adapter); + struct hal_ops *pHalFunc = &adapter->hal_func; + + u8 u1H2CAPWoWlanCtrlParm[H2C_AP_WOW_GPIO_CTRL_LEN] = {0}; + u8 gpionum = 0, gpio_dur = 0; + u8 gpio_pulse = enable; + u8 sdio_wakeup_enable = 1; + u8 gpio_high_active = 0; + u8 ret = _FAIL; + +#ifdef CONFIG_GPIO_WAKEUP + gpio_high_active = ppwrpriv->is_high_active; + gpionum = WAKEUP_GPIO_IDX; + sdio_wakeup_enable = 0; +#endif /*CONFIG_GPIO_WAKEUP*/ + + RTW_INFO("%s(): enable=%d\n", __func__, enable); + + SET_H2CCMD_AP_WOW_GPIO_CTRL_INDEX(u1H2CAPWoWlanCtrlParm, + gpionum); + SET_H2CCMD_AP_WOW_GPIO_CTRL_PLUS(u1H2CAPWoWlanCtrlParm, + gpio_pulse); + SET_H2CCMD_AP_WOW_GPIO_CTRL_HIGH_ACTIVE(u1H2CAPWoWlanCtrlParm, + gpio_high_active); + SET_H2CCMD_AP_WOW_GPIO_CTRL_EN(u1H2CAPWoWlanCtrlParm, + enable); + SET_H2CCMD_AP_WOW_GPIO_CTRL_DURATION(u1H2CAPWoWlanCtrlParm, + gpio_dur); + + ret = rtw_hal_fill_h2c_cmd(adapter, + H2C_AP_WOW_GPIO_CTRL, + H2C_AP_WOW_GPIO_CTRL_LEN, + u1H2CAPWoWlanCtrlParm); + + return ret; +} + +static u8 rtw_hal_set_ap_offload_ctrl_cmd(_adapter *adapter, u8 enable) +{ + struct hal_ops *pHalFunc = &adapter->hal_func; + u8 u1H2CAPOffloadCtrlParm[H2C_WOWLAN_LEN] = {0}; + u8 ret = _FAIL; + + RTW_INFO("%s(): bFuncEn=%d\n", __func__, enable); + + SET_H2CCMD_AP_WOWLAN_EN(u1H2CAPOffloadCtrlParm, enable); + + ret = rtw_hal_fill_h2c_cmd(adapter, + H2C_AP_OFFLOAD, + H2C_AP_OFFLOAD_LEN, + u1H2CAPOffloadCtrlParm); + + return ret; +} + +static u8 rtw_hal_set_ap_ps_cmd(_adapter *adapter, u8 enable) +{ + struct hal_ops *pHalFunc = &adapter->hal_func; + u8 ap_ps_parm[H2C_AP_PS_LEN] = {0}; + u8 ret = _FAIL; + + RTW_INFO("%s(): enable=%d\n" , __func__ , enable); + + SET_H2CCMD_AP_WOW_PS_EN(ap_ps_parm, enable); + SET_H2CCMD_AP_WOW_PS_32K_EN(ap_ps_parm, enable); + SET_H2CCMD_AP_WOW_PS_RF(ap_ps_parm, enable); + + if (enable) + SET_H2CCMD_AP_WOW_PS_DURATION(ap_ps_parm, 0x32); + else + SET_H2CCMD_AP_WOW_PS_DURATION(ap_ps_parm, 0x0); + + ret = rtw_hal_fill_h2c_cmd(adapter, H2C_SAP_PS_, + H2C_AP_PS_LEN, ap_ps_parm); + + return ret; +} + +static void rtw_hal_set_ap_rsvdpage_loc_cmd(PADAPTER padapter, + PRSVDPAGE_LOC rsvdpageloc) +{ + struct hal_ops *pHalFunc = &padapter->hal_func; + u8 rsvdparm[H2C_AOAC_RSVDPAGE_LOC_LEN] = {0}; + u8 ret = _FAIL, header = 0; + + if (pHalFunc->fill_h2c_cmd == NULL) { + RTW_INFO("%s: Please hook fill_h2c_cmd first!\n", __func__); + return; + } + + header = rtw_read8(padapter, REG_BCNQ_BDNY); + + RTW_INFO("%s: beacon: %d, probeRsp: %d, header:0x%02x\n", __func__, + rsvdpageloc->LocApOffloadBCN, + rsvdpageloc->LocProbeRsp, + header); + + SET_H2CCMD_AP_WOWLAN_RSVDPAGE_LOC_BCN(rsvdparm, + rsvdpageloc->LocApOffloadBCN + header); + + ret = rtw_hal_fill_h2c_cmd(padapter, H2C_BCN_RSVDPAGE, + H2C_BCN_RSVDPAGE_LEN, rsvdparm); + + if (ret == _FAIL) + RTW_INFO("%s: H2C_BCN_RSVDPAGE cmd fail\n", __func__); + + rtw_msleep_os(10); + + memset(&rsvdparm, 0, sizeof(rsvdparm)); + + SET_H2CCMD_AP_WOWLAN_RSVDPAGE_LOC_ProbeRsp(rsvdparm, + rsvdpageloc->LocProbeRsp + header); + + ret = rtw_hal_fill_h2c_cmd(padapter, H2C_PROBERSP_RSVDPAGE, + H2C_PROBERSP_RSVDPAGE_LEN, rsvdparm); + + if (ret == _FAIL) + RTW_INFO("%s: H2C_PROBERSP_RSVDPAGE cmd fail\n", __func__); + + rtw_msleep_os(10); +} + +static void rtw_hal_set_fw_ap_wow_related_cmd(_adapter *padapter, u8 enable) +{ + rtw_hal_set_ap_offload_ctrl_cmd(padapter, enable); + rtw_hal_set_ap_wowlan_ctrl_cmd(padapter, enable); + rtw_hal_set_ap_ps_cmd(padapter, enable); +} + +static void rtw_hal_ap_wow_enable(_adapter *padapter) +{ + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter); + struct security_priv *psecuritypriv = &padapter->securitypriv; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct hal_ops *pHalFunc = &padapter->hal_func; + struct sta_info *psta = NULL; + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); +#ifdef DBG_CHECK_FW_PS_STATE + struct dvobj_priv *psdpriv = padapter->dvobj; + struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; +#endif /*DBG_CHECK_FW_PS_STATE*/ + int res; + u16 media_status_rpt; + + RTW_INFO("%s, WOWLAN_AP_ENABLE\n", __func__); +#ifdef DBG_CHECK_FW_PS_STATE + if (rtw_fw_ps_state(padapter) == _FAIL) { + pdbgpriv->dbg_enwow_dload_fw_fail_cnt++; + RTW_PRINT("wowlan enable no leave 32k\n"); + } +#endif /*DBG_CHECK_FW_PS_STATE*/ + + /* 1. Download WOWLAN FW*/ + rtw_hal_fw_dl(padapter, true); + + media_status_rpt = RT_MEDIA_CONNECT; + rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, + (u8 *)&media_status_rpt); + + issue_beacon(padapter, 0); + + rtw_msleep_os(2); + if (IS_HARDWARE_TYPE_8188E(padapter)) + rtw_hal_disable_tx_report(padapter); + /* RX DMA stop */ + res = rtw_hal_pause_rx_dma(padapter); + if (res == _FAIL) + RTW_PRINT("[WARNING] pause RX DMA fail\n"); + + /* 5. Set Enable WOWLAN H2C command. */ + RTW_PRINT("Set Enable AP WOWLan cmd\n"); + rtw_hal_set_fw_ap_wow_related_cmd(padapter, 1); + + rtw_write8(padapter, REG_MCUTST_WOWLAN, 0); + rtw_mi_intf_stop(padapter); + /* Invoid SE0 reset signal during suspending*/ + rtw_write8(padapter, REG_RSV_CTRL, 0x20); + if (IS_8188F(pHalData->version_id) == false) + rtw_write8(padapter, REG_RSV_CTRL, 0x60); +} + +static void rtw_hal_ap_wow_disable(_adapter *padapter) +{ + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter); + struct hal_ops *pHalFunc = &padapter->hal_func; +#ifdef DBG_CHECK_FW_PS_STATE + struct dvobj_priv *psdpriv = padapter->dvobj; + struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; +#endif /*DBG_CHECK_FW_PS_STATE*/ + u16 media_status_rpt; + u8 val8; + + RTW_INFO("%s, WOWLAN_AP_DISABLE\n", __func__); + /* 1. Read wakeup reason*/ + pwrctl->wowlan_wake_reason = rtw_read8(padapter, REG_MCUTST_WOWLAN); + + RTW_PRINT("wakeup_reason: 0x%02x\n", + pwrctl->wowlan_wake_reason); + + rtw_hal_set_fw_ap_wow_related_cmd(padapter, 0); + + rtw_msleep_os(2); +#ifdef DBG_CHECK_FW_PS_STATE + if (rtw_fw_ps_state(padapter) == _FAIL) { + pdbgpriv->dbg_diswow_dload_fw_fail_cnt++; + RTW_PRINT("wowlan enable no leave 32k\n"); + } +#endif /*DBG_CHECK_FW_PS_STATE*/ + + if (IS_HARDWARE_TYPE_8188E(padapter)) + rtw_hal_enable_tx_report(padapter); + + rtw_hal_force_enable_rxdma(padapter); + + rtw_hal_fw_dl(padapter, false); + +#ifdef CONFIG_GPIO_WAKEUP + val8 = (pwrctl->is_high_active == 0) ? 1 : 0; + RTW_PRINT("Set Wake GPIO to default(%d).\n", val8); + rtw_hal_set_output_gpio(padapter, WAKEUP_GPIO_IDX, val8); + + rtw_hal_switch_gpio_wl_ctrl(padapter, WAKEUP_GPIO_IDX, false); +#endif + media_status_rpt = RT_MEDIA_CONNECT; + + rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, + (u8 *)&media_status_rpt); + + issue_beacon(padapter, 0); +} +#endif /*CONFIG_AP_WOWLAN*/ + +#ifdef CONFIG_P2P_WOWLAN +static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode) +{ + u8 *ssid_ie; + sint ssid_len_ori; + int len_diff = 0; + + ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len); + + /* RTW_INFO("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */ + + if (ssid_ie && ssid_len_ori > 0) { + switch (hidden_ssid_mode) { + case 1: { + u8 *next_ie = ssid_ie + 2 + ssid_len_ori; + u32 remain_len = 0; + + remain_len = ies_len - (next_ie - ies); + + ssid_ie[1] = 0; + memcpy(ssid_ie + 2, next_ie, remain_len); + len_diff -= ssid_len_ori; + + break; + } + case 2: + memset(&ssid_ie[2], 0, ssid_len_ori); + break; + default: + break; + } + } + + return len_diff; +} + +static void rtw_hal_construct_P2PBeacon(_adapter *padapter, u8 *pframe, u32 *pLength) +{ + /* struct xmit_frame *pmgntframe; */ + /* struct pkt_attrib *pattrib; */ + /* unsigned char *pframe; */ + struct rtw_ieee80211_hdr *pwlanhdr; + __le16 *fctrl; + unsigned int rate_len; + struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); + u32 pktlen; + /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */ + /* unsigned long irqL; + * struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + * #endif */ /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */ + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); + u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +#ifdef CONFIG_P2P + struct wifidirect_info *pwdinfo = &(padapter->wdinfo); +#endif /* CONFIG_P2P */ + + /* for debug */ + u8 *dbgbuf = pframe; + u8 dbgbufLen = 0, index = 0; + + RTW_INFO("%s\n", __func__); + /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */ + /* _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL); + * #endif */ /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */ + + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + + fctrl = &(pwlanhdr->frame_ctl); + *(fctrl) = 0; + + memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); + memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); + memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); + + SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); + /* pmlmeext->mgnt_seq++; */ + set_frame_sub_type(pframe, WIFI_BEACON); + + pframe += sizeof(struct rtw_ieee80211_hdr_3addr); + pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + + if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { + /* RTW_INFO("ie len=%d\n", cur_network->IELength); */ +#ifdef CONFIG_P2P + /* for P2P : Primary Device Type & Device Name */ + u32 wpsielen = 0, insert_len = 0; + u8 *wpsie = NULL; + wpsie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_, cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wpsielen); + + if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wpsie && wpsielen > 0) { + uint wps_offset, remainder_ielen; + u8 *premainder_ie, *pframe_wscie; + + wps_offset = (uint)(wpsie - cur_network->IEs); + + premainder_ie = wpsie + wpsielen; + + remainder_ielen = cur_network->IELength - wps_offset - wpsielen; + +#ifdef CONFIG_IOCTL_CFG80211 + if (pwdinfo->driver_interface == DRIVER_CFG80211) { + if (pmlmepriv->wps_beacon_ie && pmlmepriv->wps_beacon_ie_len > 0) { + memcpy(pframe, cur_network->IEs, wps_offset); + pframe += wps_offset; + pktlen += wps_offset; + + memcpy(pframe, pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len); + pframe += pmlmepriv->wps_beacon_ie_len; + pktlen += pmlmepriv->wps_beacon_ie_len; + + /* copy remainder_ie to pframe */ + memcpy(pframe, premainder_ie, remainder_ielen); + pframe += remainder_ielen; + pktlen += remainder_ielen; + } else { + memcpy(pframe, cur_network->IEs, cur_network->IELength); + pframe += cur_network->IELength; + pktlen += cur_network->IELength; + } + } else +#endif /* CONFIG_IOCTL_CFG80211 */ + { + pframe_wscie = pframe + wps_offset; + memcpy(pframe, cur_network->IEs, wps_offset + wpsielen); + pframe += (wps_offset + wpsielen); + pktlen += (wps_offset + wpsielen); + + /* now pframe is end of wsc ie, insert Primary Device Type & Device Name */ + /* Primary Device Type */ + /* Type: */ + *(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE); + insert_len += 2; + + /* Length: */ + *(u16 *)(pframe + insert_len) = cpu_to_be16(0x0008); + insert_len += 2; + + /* Value: */ + /* Category ID */ + *(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); + insert_len += 2; + + /* OUI */ + *(u32 *)(pframe + insert_len) = cpu_to_be32(WPSOUI); + insert_len += 4; + + /* Sub Category ID */ + *(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); + insert_len += 2; + + + /* Device Name */ + /* Type: */ + *(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); + insert_len += 2; + + /* Length: */ + *(u16 *)(pframe + insert_len) = cpu_to_be16(pwdinfo->device_name_len); + insert_len += 2; + + /* Value: */ + memcpy(pframe + insert_len, pwdinfo->device_name, pwdinfo->device_name_len); + insert_len += pwdinfo->device_name_len; + + + /* update wsc ie length */ + *(pframe_wscie + 1) = (wpsielen - 2) + insert_len; + + /* pframe move to end */ + pframe += insert_len; + pktlen += insert_len; + + /* copy remainder_ie to pframe */ + memcpy(pframe, premainder_ie, remainder_ielen); + pframe += remainder_ielen; + pktlen += remainder_ielen; + } + } else +#endif /* CONFIG_P2P */ + { + int len_diff; + memcpy(pframe, cur_network->IEs, cur_network->IELength); + len_diff = update_hidden_ssid( + pframe + _BEACON_IE_OFFSET_ + , cur_network->IELength - _BEACON_IE_OFFSET_ + , pmlmeinfo->hidden_ssid_mode + ); + pframe += (cur_network->IELength + len_diff); + pktlen += (cur_network->IELength + len_diff); + } +#ifdef CONFIG_P2P + if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { + u32 len; +#ifdef CONFIG_IOCTL_CFG80211 + if (pwdinfo->driver_interface == DRIVER_CFG80211) { + len = pmlmepriv->p2p_beacon_ie_len; + if (pmlmepriv->p2p_beacon_ie && len > 0) + memcpy(pframe, pmlmepriv->p2p_beacon_ie, len); + } else +#endif /* CONFIG_IOCTL_CFG80211 */ + { + len = build_beacon_p2p_ie(pwdinfo, pframe); + } + + pframe += len; + pktlen += len; + + #ifdef CONFIG_WFD + len = rtw_append_beacon_wfd_ie(padapter, pframe); + pframe += len; + pktlen += len; + #endif + + } +#endif /* CONFIG_P2P */ + + goto _issue_bcn; + + } + + /* below for ad-hoc mode */ + + /* timestamp will be inserted by hardware */ + pframe += 8; + pktlen += 8; + + /* beacon interval: 2 bytes */ + + memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); + + pframe += 2; + pktlen += 2; + + /* capability info: 2 bytes */ + + memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); + + pframe += 2; + pktlen += 2; + + /* SSID */ + pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen); + + /* supported rates... */ + rate_len = rtw_get_rateset_len(cur_network->SupportedRates); + pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pktlen); + + /* DS parameter set */ + pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen); + + /* if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */ + { + u8 erpinfo = 0; + u32 ATIMWindow; + /* IBSS Parameter Set... */ + /* ATIMWindow = cur->Configuration.ATIMWindow; */ + ATIMWindow = 0; + pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen); + + /* ERP IE */ + pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pktlen); + } + + + /* EXTERNDED SUPPORTED RATE */ + if (rate_len > 8) + pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen); + + + /* todo:HT for adhoc */ + +_issue_bcn: + + /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */ + /* pmlmepriv->update_bcn = false; + * + * _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL); + * #endif */ /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */ + + *pLength = pktlen; +} + +static int get_reg_classes_full_count(struct p2p_channels channel_list) +{ + int cnt = 0; + int i; + + for (i = 0; i < channel_list.reg_classes; i++) + cnt += channel_list.reg_class[i].channels; + + return cnt; +} + +static void rtw_hal_construct_P2PProbeRsp(_adapter *padapter, u8 *pframe, u32 *pLength) +{ + /* struct xmit_frame *pmgntframe; */ + /* struct pkt_attrib *pattrib; */ + /* unsigned char *pframe; */ + struct rtw_ieee80211_hdr *pwlanhdr; + __le16 *fctrl; + unsigned char *mac; + struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + /* WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); */ + u16 beacon_interval = 100; + u16 capInfo = 0; + struct wifidirect_info *pwdinfo = &(padapter->wdinfo); + u8 wpsie[255] = { 0x00 }; + u32 wpsielen = 0, p2pielen = 0; + u32 pktlen; +#ifdef CONFIG_WFD + u32 wfdielen = 0; +#endif +#ifdef CONFIG_INTEL_WIDI + u8 zero_array_check[L2SDTA_SERVICE_VE_LEN] = { 0x00 }; +#endif /* CONFIG_INTEL_WIDI */ + + /* for debug */ + u8 *dbgbuf = pframe; + u8 dbgbufLen = 0, index = 0; + + RTW_INFO("%s\n", __func__); + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + mac = adapter_mac_addr(padapter); + + fctrl = &(pwlanhdr->frame_ctl); + *(fctrl) = 0; + + /* DA filled by FW */ + memset(pwlanhdr->addr1, 0, ETH_ALEN); + memcpy(pwlanhdr->addr2, mac, ETH_ALEN); + + /* Use the device address for BSSID field. */ + memcpy(pwlanhdr->addr3, mac, ETH_ALEN); + + SetSeqNum(pwlanhdr, 0); + set_frame_sub_type(fctrl, WIFI_PROBERSP); + + pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += pktlen; + + + /* timestamp will be inserted by hardware */ + pframe += 8; + pktlen += 8; + + /* beacon interval: 2 bytes */ + memcpy(pframe, (unsigned char *) &beacon_interval, 2); + pframe += 2; + pktlen += 2; + + /* capability info: 2 bytes */ + /* ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of WiFi Direct Spec) */ + capInfo |= cap_ShortPremble; + capInfo |= cap_ShortSlot; + + memcpy(pframe, (unsigned char *) &capInfo, 2); + pframe += 2; + pktlen += 2; + + + /* SSID */ + pframe = rtw_set_ie(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid, &pktlen); + + /* supported rates... */ + /* Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 ) */ + pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pktlen); + + /* DS parameter set */ + pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pktlen); + +#ifdef CONFIG_IOCTL_CFG80211 + if (pwdinfo->driver_interface == DRIVER_CFG80211) { + if (pmlmepriv->wps_probe_resp_ie != NULL && pmlmepriv->p2p_probe_resp_ie != NULL) { + /* WPS IE */ + memcpy(pframe, pmlmepriv->wps_probe_resp_ie, pmlmepriv->wps_probe_resp_ie_len); + pktlen += pmlmepriv->wps_probe_resp_ie_len; + pframe += pmlmepriv->wps_probe_resp_ie_len; + + /* P2P IE */ + memcpy(pframe, pmlmepriv->p2p_probe_resp_ie, pmlmepriv->p2p_probe_resp_ie_len); + pktlen += pmlmepriv->p2p_probe_resp_ie_len; + pframe += pmlmepriv->p2p_probe_resp_ie_len; + } + } else +#endif /* CONFIG_IOCTL_CFG80211 */ + { + + /* Todo: WPS IE */ + /* Noted by Albert 20100907 */ + /* According to the WPS specification, all the WPS attribute is presented by Big Endian. */ + + wpsielen = 0; + /* WPS OUI */ + *(u32 *)(wpsie) = cpu_to_be32(WPSOUI); + wpsielen += 4; + + /* WPS version */ + /* Type: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1); + wpsielen += 2; + + /* Length: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); + wpsielen += 2; + + /* Value: */ + wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */ + +#ifdef CONFIG_INTEL_WIDI + /* Commented by Kurt */ + /* Appended WiDi info. only if we did issued_probereq_widi(), and then we saved ven. ext. in pmlmepriv->sa_ext. */ + if (!memcmp(pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN) == false + || pmlmepriv->num_p2p_sdt != 0) { + /* Sec dev type */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SEC_DEV_TYPE_LIST); + wpsielen += 2; + + /* Length: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008); + wpsielen += 2; + + /* Value: */ + /* Category ID */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_DISPLAYS); + wpsielen += 2; + + /* OUI */ + *(u32 *)(wpsie + wpsielen) = cpu_to_be32(INTEL_DEV_TYPE_OUI); + wpsielen += 4; + + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_WIDI_CONSUMER_SINK); + wpsielen += 2; + + if (!memcmp(pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN) == false) { + /* Vendor Extension */ + memcpy(wpsie + wpsielen, pmlmepriv->sa_ext, L2SDTA_SERVICE_VE_LEN); + wpsielen += L2SDTA_SERVICE_VE_LEN; + } + } +#endif /* CONFIG_INTEL_WIDI */ + + /* WiFi Simple Config State */ + /* Type: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SIMPLE_CONF_STATE); + wpsielen += 2; + + /* Length: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); + wpsielen += 2; + + /* Value: */ + wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG; /* Not Configured. */ + + /* Response Type */ + /* Type: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_RESP_TYPE); + wpsielen += 2; + + /* Length: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); + wpsielen += 2; + + /* Value: */ + wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X; + + /* UUID-E */ + /* Type: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E); + wpsielen += 2; + + /* Length: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010); + wpsielen += 2; + + /* Value: */ + if (pwdinfo->external_uuid == 0) { + memset(wpsie + wpsielen, 0x0, 16); + memcpy(wpsie + wpsielen, mac, ETH_ALEN); + } else + memcpy(wpsie + wpsielen, pwdinfo->uuid, 0x10); + wpsielen += 0x10; + + /* Manufacturer */ + /* Type: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MANUFACTURER); + wpsielen += 2; + + /* Length: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0007); + wpsielen += 2; + + /* Value: */ + memcpy(wpsie + wpsielen, "Realtek", 7); + wpsielen += 7; + + /* Model Name */ + /* Type: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NAME); + wpsielen += 2; + + /* Length: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0006); + wpsielen += 2; + + /* Value: */ + memcpy(wpsie + wpsielen, "8192CU", 6); + wpsielen += 6; + + /* Model Number */ + /* Type: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NUMBER); + wpsielen += 2; + + /* Length: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); + wpsielen += 2; + + /* Value: */ + wpsie[wpsielen++] = 0x31; /* character 1 */ + + /* Serial Number */ + /* Type: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SERIAL_NUMBER); + wpsielen += 2; + + /* Length: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(ETH_ALEN); + wpsielen += 2; + + /* Value: */ + memcpy(wpsie + wpsielen, "123456" , ETH_ALEN); + wpsielen += ETH_ALEN; + + /* Primary Device Type */ + /* Type: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE); + wpsielen += 2; + + /* Length: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008); + wpsielen += 2; + + /* Value: */ + /* Category ID */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); + wpsielen += 2; + + /* OUI */ + *(u32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI); + wpsielen += 4; + + /* Sub Category ID */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); + wpsielen += 2; + + /* Device Name */ + /* Type: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); + wpsielen += 2; + + /* Length: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len); + wpsielen += 2; + + /* Value: */ + memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len); + wpsielen += pwdinfo->device_name_len; + + /* Config Method */ + /* Type: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD); + wpsielen += 2; + + /* Length: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002); + wpsielen += 2; + + /* Value: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm); + wpsielen += 2; + + + pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pktlen); + + + p2pielen = build_probe_resp_p2p_ie(pwdinfo, pframe); + pframe += p2pielen; + pktlen += p2pielen; + } + +#ifdef CONFIG_WFD + wfdielen = rtw_append_probe_resp_wfd_ie(padapter, pframe); + pframe += wfdielen; + pktlen += wfdielen; +#endif + + *pLength = pktlen; +} + +static void rtw_hal_construct_P2PNegoRsp(_adapter *padapter, u8 *pframe, u32 *pLength) +{ + unsigned char category = RTW_WLAN_CATEGORY_PUBLIC; + u8 action = P2P_PUB_ACTION_ACTION; + u32 p2poui = cpu_to_be32(P2POUI); + u8 oui_subtype = P2P_GO_NEGO_RESP; + u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 }; + u8 p2pielen = 0, i; + uint wpsielen = 0; + u16 wps_devicepassword_id = 0x0000; + uint wps_devicepassword_id_len = 0; + u8 channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh; + u16 len_channellist_attr = 0; + u32 pktlen; + u8 dialogToken = 0; + + /* struct xmit_frame *pmgntframe; */ + /* struct pkt_attrib *pattrib; */ + /* unsigned char *pframe; */ + struct rtw_ieee80211_hdr *pwlanhdr; + __le16 *fctrl; + struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wifidirect_info *pwdinfo = &(padapter->wdinfo); + /* WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); */ + +#ifdef CONFIG_WFD + u32 wfdielen = 0; +#endif + + /* for debug */ + u8 *dbgbuf = pframe; + u8 dbgbufLen = 0, index = 0; + + RTW_INFO("%s\n", __func__); + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + fctrl = &(pwlanhdr->frame_ctl); + *(fctrl) = 0; + + /* RA, filled by FW */ + memset(pwlanhdr->addr1, 0, ETH_ALEN); + memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); + memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN); + + SetSeqNum(pwlanhdr, 0); + set_frame_sub_type(pframe, WIFI_ACTION); + + pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += pktlen; + + pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pktlen)); + pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pktlen)); + pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pktlen)); + pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pktlen)); + + /* dialog token, filled by FW */ + pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pktlen)); + + memset(wpsie, 0x00, 255); + wpsielen = 0; + + /* WPS Section */ + wpsielen = 0; + /* WPS OUI */ + *(u32 *)(wpsie) = cpu_to_be32(WPSOUI); + wpsielen += 4; + + /* WPS version */ + /* Type: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1); + wpsielen += 2; + + /* Length: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); + wpsielen += 2; + + /* Value: */ + wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */ + + /* Device Password ID */ + /* Type: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID); + wpsielen += 2; + + /* Length: */ + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002); + wpsielen += 2; + + /* Value: */ + if (wps_devicepassword_id == WPS_DPID_USER_SPEC) + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC); + else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC) + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC); + else + *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC); + wpsielen += 2; + + pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pktlen); + + + /* P2P IE Section. */ + + /* P2P OUI */ + p2pielen = 0; + p2pie[p2pielen++] = 0x50; + p2pie[p2pielen++] = 0x6F; + p2pie[p2pielen++] = 0x9A; + p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ + + /* Commented by Albert 20100908 */ + /* According to the P2P Specification, the group negoitation response frame should contain 9 P2P attributes */ + /* 1. Status */ + /* 2. P2P Capability */ + /* 3. Group Owner Intent */ + /* 4. Configuration Timeout */ + /* 5. Operating Channel */ + /* 6. Intended P2P Interface Address */ + /* 7. Channel List */ + /* 8. Device Info */ + /* 9. Group ID ( Only GO ) */ + + + /* ToDo: */ + + /* P2P Status */ + /* Type: */ + p2pie[p2pielen++] = P2P_ATTR_STATUS; + + /* Length: */ + *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001); + p2pielen += 2; + + /* Value, filled by FW */ + p2pie[p2pielen++] = 1; + + /* P2P Capability */ + /* Type: */ + p2pie[p2pielen++] = P2P_ATTR_CAPABILITY; + + /* Length: */ + *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); + p2pielen += 2; + + /* Value: */ + /* Device Capability Bitmap, 1 byte */ + + if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) { + /* Commented by Albert 2011/03/08 */ + /* According to the P2P specification */ + /* if the sending device will be client, the P2P Capability should be reserved of group negotation response frame */ + p2pie[p2pielen++] = 0; + } else { + /* Be group owner or meet the error case */ + p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT; + } + + /* Group Capability Bitmap, 1 byte */ + if (pwdinfo->persistent_supported) + p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP; + else + p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN; + + /* Group Owner Intent */ + /* Type: */ + p2pie[p2pielen++] = P2P_ATTR_GO_INTENT; + + /* Length: */ + *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001); + p2pielen += 2; + + /* Value: */ + if (pwdinfo->peer_intent & 0x01) { + /* Peer's tie breaker bit is 1, our tie breaker bit should be 0 */ + p2pie[p2pielen++] = (pwdinfo->intent << 1); + } else { + /* Peer's tie breaker bit is 0, our tie breaker bit should be 1 */ + p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0)); + } + + + /* Configuration Timeout */ + /* Type: */ + p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT; + + /* Length: */ + *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); + p2pielen += 2; + + /* Value: */ + p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */ + p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */ + + /* Operating Channel */ + /* Type: */ + p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH; + + /* Length: */ + *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); + p2pielen += 2; + + /* Value: */ + /* Country String */ + p2pie[p2pielen++] = 'X'; + p2pie[p2pielen++] = 'X'; + + /* The third byte should be set to 0x04. */ + /* Described in the "Operating Channel Attribute" section. */ + p2pie[p2pielen++] = 0x04; + + /* Operating Class */ + if (pwdinfo->operating_channel <= 14) { + /* Operating Class */ + p2pie[p2pielen++] = 0x51; + } else if ((pwdinfo->operating_channel >= 36) && (pwdinfo->operating_channel <= 48)) { + /* Operating Class */ + p2pie[p2pielen++] = 0x73; + } else { + /* Operating Class */ + p2pie[p2pielen++] = 0x7c; + } + + /* Channel Number */ + p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */ + + /* Intended P2P Interface Address */ + /* Type: */ + p2pie[p2pielen++] = P2P_ATTR_INTENDED_IF_ADDR; + + /* Length: */ + *(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN); + p2pielen += 2; + + /* Value: */ + memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN); + p2pielen += ETH_ALEN; + + /* Channel List */ + /* Type: */ + p2pie[p2pielen++] = P2P_ATTR_CH_LIST; + + /* Country String(3) */ + /* + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */ + /* + number of channels in all classes */ + len_channellist_attr = 3 + + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes + + get_reg_classes_full_count(pmlmeext->channel_list); + +#ifdef CONFIG_CONCURRENT_MODE + if (rtw_mi_buddy_check_fwstate(padapter, _FW_LINKED)) + *(u16 *)(p2pie + p2pielen) = cpu_to_le16(5 + 1); + else + *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); + +#else + + *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); + +#endif + p2pielen += 2; + + /* Value: */ + /* Country String */ + p2pie[p2pielen++] = 'X'; + p2pie[p2pielen++] = 'X'; + + /* The third byte should be set to 0x04. */ + /* Described in the "Operating Channel Attribute" section. */ + p2pie[p2pielen++] = 0x04; + + /* Channel Entry List */ + +#ifdef CONFIG_CONCURRENT_MODE + if (rtw_mi_check_status(padapter, MI_LINKED)) { + u8 union_ch = rtw_mi_get_union_chan(padapter); + + /* Operating Class */ + if (union_ch > 14) { + if (union_ch >= 149) + p2pie[p2pielen++] = 0x7c; + else + p2pie[p2pielen++] = 0x73; + } else + p2pie[p2pielen++] = 0x51; + + + /* Number of Channels */ + /* Just support 1 channel and this channel is AP's channel */ + p2pie[p2pielen++] = 1; + + /* Channel List */ + p2pie[p2pielen++] = union_ch; + } else { + int i, j; + for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) { + /* Operating Class */ + p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class; + + /* Number of Channels */ + p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels; + + /* Channel List */ + for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) + p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i]; + } + } +#else /* CONFIG_CONCURRENT_MODE */ + { + int i, j; + for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) { + /* Operating Class */ + p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class; + + /* Number of Channels */ + p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels; + + /* Channel List */ + for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) + p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i]; + } + } +#endif /* CONFIG_CONCURRENT_MODE */ + + + /* Device Info */ + /* Type: */ + p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO; + + /* Length: */ + /* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */ + /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */ + *(u16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); + p2pielen += 2; + + /* Value: */ + /* P2P Device Address */ + memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN); + p2pielen += ETH_ALEN; + + /* Config Method */ + /* This field should be big endian. Noted by P2P specification. */ + + *(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm); + + p2pielen += 2; + + /* Primary Device Type */ + /* Category ID */ + *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); + p2pielen += 2; + + /* OUI */ + *(u32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI); + p2pielen += 4; + + /* Sub Category ID */ + *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); + p2pielen += 2; + + /* Number of Secondary Device Types */ + p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */ + + /* Device Name */ + /* Type: */ + *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); + p2pielen += 2; + + /* Length: */ + *(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); + p2pielen += 2; + + /* Value: */ + memcpy(p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len); + p2pielen += pwdinfo->device_name_len; + + if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { + /* Group ID Attribute */ + /* Type: */ + p2pie[p2pielen++] = P2P_ATTR_GROUP_ID; + + /* Length: */ + *(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen); + p2pielen += 2; + + /* Value: */ + /* p2P Device Address */ + memcpy(p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN); + p2pielen += ETH_ALEN; + + /* SSID */ + memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen); + p2pielen += pwdinfo->nego_ssidlen; + + } + + pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pktlen); + +#ifdef CONFIG_WFD + wfdielen = build_nego_resp_wfd_ie(pwdinfo, pframe); + pframe += wfdielen; + pktlen += wfdielen; +#endif + *pLength = pktlen; +} + +static void rtw_hal_construct_P2PInviteRsp(_adapter *padapter, u8 *pframe, u32 *pLength) +{ + unsigned char category = RTW_WLAN_CATEGORY_PUBLIC; + u8 action = P2P_PUB_ACTION_ACTION; + u32 p2poui = cpu_to_be32(P2POUI); + u8 oui_subtype = P2P_INVIT_RESP; + u8 p2pie[255] = { 0x00 }; + u8 p2pielen = 0, i; + u8 channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh = 0; + u16 len_channellist_attr = 0; + u32 pktlen; + u8 dialogToken = 0; +#ifdef CONFIG_WFD + u32 wfdielen = 0; +#endif + + /* struct xmit_frame *pmgntframe; */ + /* struct pkt_attrib *pattrib; */ + /* unsigned char *pframe; */ + struct rtw_ieee80211_hdr *pwlanhdr; + __le16 *fctrl; + struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wifidirect_info *pwdinfo = &(padapter->wdinfo); + + /* for debug */ + u8 *dbgbuf = pframe; + u8 dbgbufLen = 0, index = 0; + + + RTW_INFO("%s\n", __func__); + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + fctrl = &(pwlanhdr->frame_ctl); + *(fctrl) = 0; + + /* RA fill by FW */ + memset(pwlanhdr->addr1, 0, ETH_ALEN); + memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); + + /* BSSID fill by FW */ + memset(pwlanhdr->addr3, 0, ETH_ALEN); + + SetSeqNum(pwlanhdr, 0); + set_frame_sub_type(pframe, WIFI_ACTION); + + pframe += sizeof(struct rtw_ieee80211_hdr_3addr); + pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + + pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pktlen)); + pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pktlen)); + pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pktlen)); + pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pktlen)); + + /* dialog token, filled by FW */ + pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pktlen)); + + /* P2P IE Section. */ + + /* P2P OUI */ + p2pielen = 0; + p2pie[p2pielen++] = 0x50; + p2pie[p2pielen++] = 0x6F; + p2pie[p2pielen++] = 0x9A; + p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ + + /* Commented by Albert 20101005 */ + /* According to the P2P Specification, the P2P Invitation response frame should contain 5 P2P attributes */ + /* 1. Status */ + /* 2. Configuration Timeout */ + /* 3. Operating Channel ( Only GO ) */ + /* 4. P2P Group BSSID ( Only GO ) */ + /* 5. Channel List */ + + /* P2P Status */ + /* Type: */ + p2pie[p2pielen++] = P2P_ATTR_STATUS; + + /* Length: */ + *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001); + p2pielen += 2; + + /* Value: filled by FW, defult value is FAIL INFO UNAVAILABLE */ + p2pie[p2pielen++] = P2P_STATUS_FAIL_INFO_UNAVAILABLE; + + /* Configuration Timeout */ + /* Type: */ + p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT; + + /* Length: */ + *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); + p2pielen += 2; + + /* Value: */ + p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */ + p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */ + + /* due to defult value is FAIL INFO UNAVAILABLE, so the following IE is not needed */ + pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pktlen); + +#ifdef CONFIG_WFD + wfdielen = build_invitation_resp_wfd_ie(pwdinfo, pframe); + pframe += wfdielen; + pktlen += wfdielen; +#endif + + *pLength = pktlen; +} + +static void rtw_hal_construct_P2PProvisionDisRsp(_adapter *padapter, u8 *pframe, u32 *pLength) +{ + unsigned char category = RTW_WLAN_CATEGORY_PUBLIC; + u8 action = P2P_PUB_ACTION_ACTION; + u8 dialogToken = 0; + u32 p2poui = cpu_to_be32(P2POUI); + u8 oui_subtype = P2P_PROVISION_DISC_RESP; + u8 wpsie[100] = { 0x00 }; + u8 wpsielen = 0; + u32 pktlen; +#ifdef CONFIG_WFD + u32 wfdielen = 0; +#endif + + /* struct xmit_frame *pmgntframe; */ + /* struct pkt_attrib *pattrib; */ + /* unsigned char *pframe; */ + struct rtw_ieee80211_hdr *pwlanhdr; + __le16 *fctrl; + struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wifidirect_info *pwdinfo = &(padapter->wdinfo); + + /* for debug */ + u8 *dbgbuf = pframe; + u8 dbgbufLen = 0, index = 0; + + RTW_INFO("%s\n", __func__); + + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + fctrl = &(pwlanhdr->frame_ctl); + *(fctrl) = 0; + + /* RA filled by FW */ + memset(pwlanhdr->addr1, 0, ETH_ALEN); + memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); + memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN); + + SetSeqNum(pwlanhdr, 0); + set_frame_sub_type(pframe, WIFI_ACTION); + + pframe += sizeof(struct rtw_ieee80211_hdr_3addr); + pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + + pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pktlen)); + pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pktlen)); + pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pktlen)); + pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pktlen)); + /* dialog token, filled by FW */ + pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pktlen)); + + wpsielen = 0; + /* WPS OUI */ + /* *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI ); */ + RTW_PUT_BE32(wpsie, WPSOUI); + wpsielen += 4; + + /* Config Method */ + /* Type: */ + /* *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD ); */ + RTW_PUT_BE16(wpsie + wpsielen, WPS_ATTR_CONF_METHOD); + wpsielen += 2; + + /* Length: */ + /* *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 ); */ + RTW_PUT_BE16(wpsie + wpsielen, 0x0002); + wpsielen += 2; + + /* Value: filled by FW, default value is PBC */ + /* *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( config_method ); */ + RTW_PUT_BE16(wpsie + wpsielen, WPS_CM_PUSH_BUTTON); + wpsielen += 2; + + pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pktlen); + +#ifdef CONFIG_WFD + wfdielen = build_provdisc_resp_wfd_ie(pwdinfo, pframe); + pframe += wfdielen; + pktlen += wfdielen; +#endif + + *pLength = pktlen; +} + +u8 rtw_hal_set_FwP2PRsvdPage_cmd(_adapter *adapter, PRSVDPAGE_LOC rsvdpageloc) +{ + u8 u1H2CP2PRsvdPageParm[H2C_P2PRSVDPAGE_LOC_LEN] = {0}; + struct hal_ops *pHalFunc = &adapter->hal_func; + u8 ret = _FAIL; + + RTW_INFO("P2PRsvdPageLoc: P2PBeacon=%d P2PProbeRsp=%d NegoRsp=%d InviteRsp=%d PDRsp=%d\n", + rsvdpageloc->LocP2PBeacon, rsvdpageloc->LocP2PProbeRsp, + rsvdpageloc->LocNegoRsp, rsvdpageloc->LocInviteRsp, + rsvdpageloc->LocPDRsp); + + SET_H2CCMD_RSVDPAGE_LOC_P2P_BCN(u1H2CP2PRsvdPageParm, rsvdpageloc->LocProbeRsp); + SET_H2CCMD_RSVDPAGE_LOC_P2P_PROBE_RSP(u1H2CP2PRsvdPageParm, rsvdpageloc->LocPsPoll); + SET_H2CCMD_RSVDPAGE_LOC_P2P_NEGO_RSP(u1H2CP2PRsvdPageParm, rsvdpageloc->LocNullData); + SET_H2CCMD_RSVDPAGE_LOC_P2P_INVITE_RSP(u1H2CP2PRsvdPageParm, rsvdpageloc->LocQosNull); + SET_H2CCMD_RSVDPAGE_LOC_P2P_PD_RSP(u1H2CP2PRsvdPageParm, rsvdpageloc->LocBTQosNull); + + /* FillH2CCmd8723B(padapter, H2C_8723B_P2P_OFFLOAD_RSVD_PAGE, H2C_P2PRSVDPAGE_LOC_LEN, u1H2CP2PRsvdPageParm); */ + ret = rtw_hal_fill_h2c_cmd(adapter, + H2C_P2P_OFFLOAD_RSVD_PAGE, + H2C_P2PRSVDPAGE_LOC_LEN, + u1H2CP2PRsvdPageParm); + + return ret; +} + +u8 rtw_hal_set_p2p_wowlan_offload_cmd(_adapter *adapter) +{ + + u8 offload_cmd[H2C_P2P_OFFLOAD_LEN] = {0}; + struct wifidirect_info *pwdinfo = &(adapter->wdinfo); + struct P2P_WoWlan_Offload_t *p2p_wowlan_offload = (struct P2P_WoWlan_Offload_t *)offload_cmd; + struct hal_ops *pHalFunc = &adapter->hal_func; + u8 ret = _FAIL; + + memset(p2p_wowlan_offload, 0 , sizeof(struct P2P_WoWlan_Offload_t)); + RTW_INFO("%s\n", __func__); + switch (pwdinfo->role) { + case P2P_ROLE_DEVICE: + RTW_INFO("P2P_ROLE_DEVICE\n"); + p2p_wowlan_offload->role = 0; + break; + case P2P_ROLE_CLIENT: + RTW_INFO("P2P_ROLE_CLIENT\n"); + p2p_wowlan_offload->role = 1; + break; + case P2P_ROLE_GO: + RTW_INFO("P2P_ROLE_GO\n"); + p2p_wowlan_offload->role = 2; + break; + default: + RTW_INFO("P2P_ROLE_DISABLE\n"); + break; + } + p2p_wowlan_offload->Wps_Config[0] = pwdinfo->supported_wps_cm >> 8; + p2p_wowlan_offload->Wps_Config[1] = pwdinfo->supported_wps_cm; + offload_cmd = (u8 *)p2p_wowlan_offload; + RTW_INFO("p2p_wowlan_offload: %x:%x:%x\n", offload_cmd[0], offload_cmd[1], offload_cmd[2]); + + ret = rtw_hal_fill_h2c_cmd(adapter, + H2C_P2P_OFFLOAD, + H2C_P2P_OFFLOAD_LEN, + offload_cmd); + return ret; + + /* FillH2CCmd8723B(adapter, H2C_8723B_P2P_OFFLOAD, sizeof(struct P2P_WoWlan_Offload_t), (u8 *)p2p_wowlan_offload); */ +} +#endif /* CONFIG_P2P_WOWLAN */ + +static void rtw_hal_construct_beacon(_adapter *padapter, + u8 *pframe, u32 *pLength) +{ + struct rtw_ieee80211_hdr *pwlanhdr; + __le16 *fctrl; + u32 rate_len, pktlen; + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); + u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + + /* RTW_INFO("%s\n", __func__); */ + + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + fctrl = &(pwlanhdr->frame_ctl); + *(fctrl) = 0; + + memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); + memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); + memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); + + SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); + /* pmlmeext->mgnt_seq++; */ + set_frame_sub_type(pframe, WIFI_BEACON); + + pframe += sizeof(struct rtw_ieee80211_hdr_3addr); + pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + + /* timestamp will be inserted by hardware */ + pframe += 8; + pktlen += 8; + + /* beacon interval: 2 bytes */ + memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); + + pframe += 2; + pktlen += 2; + + /* capability info: 2 bytes */ + memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); + + pframe += 2; + pktlen += 2; + + if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { + /* RTW_INFO("ie len=%d\n", cur_network->IELength); */ + pktlen += cur_network->IELength - sizeof(NDIS_802_11_FIXED_IEs); + memcpy(pframe, cur_network->IEs + sizeof(NDIS_802_11_FIXED_IEs), pktlen); + + goto _ConstructBeacon; + } + + /* below for ad-hoc mode */ + + /* SSID */ + pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen); + + /* supported rates... */ + rate_len = rtw_get_rateset_len(cur_network->SupportedRates); + pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pktlen); + + /* DS parameter set */ + pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen); + + if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) { + u32 ATIMWindow; + /* IBSS Parameter Set... */ + /* ATIMWindow = cur->Configuration.ATIMWindow; */ + ATIMWindow = 0; + pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen); + } + + + /* todo: ERP IE */ + + + /* EXTERNDED SUPPORTED RATE */ + if (rate_len > 8) + pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen); + + + /* todo:HT for adhoc */ + +_ConstructBeacon: + + if ((pktlen + TXDESC_SIZE) > 512) { + RTW_INFO("beacon frame too large\n"); + return; + } + + *pLength = pktlen; + + /* RTW_INFO("%s bcn_sz=%d\n", __func__, pktlen); */ + +} + +static void rtw_hal_construct_PSPoll(_adapter *padapter, + u8 *pframe, u32 *pLength) +{ + struct rtw_ieee80211_hdr *pwlanhdr; + __le16 *fctrl; + u32 pktlen; + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + /* RTW_INFO("%s\n", __func__); */ + + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + /* Frame control. */ + fctrl = &(pwlanhdr->frame_ctl); + *(fctrl) = 0; + SetPwrMgt(fctrl); + set_frame_sub_type(pframe, WIFI_PSPOLL); + + /* AID. */ + set_duration(pframe, (pmlmeinfo->aid | 0xc000)); + + /* BSSID. */ + memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + + /* TA. */ + memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); + + *pLength = 16; +} + +void rtw_hal_construct_NullFunctionData( + PADAPTER padapter, + u8 *pframe, + u32 *pLength, + u8 *StaAddr, + u8 bQoS, + u8 AC, + u8 bEosp, + u8 bForcePowerSave) +{ + struct rtw_ieee80211_hdr *pwlanhdr; + __le16 *fctrl; + u32 pktlen; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct wlan_network *cur_network = &pmlmepriv->cur_network; + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + + /* RTW_INFO("%s:%d\n", __func__, bForcePowerSave); */ + + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + fctrl = &pwlanhdr->frame_ctl; + *(fctrl) = 0; + if (bForcePowerSave) + SetPwrMgt(fctrl); + + switch (cur_network->network.InfrastructureMode) { + case Ndis802_11Infrastructure: + SetToDs(fctrl); + memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); + memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN); + break; + case Ndis802_11APMode: + SetFrDs(fctrl); + memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); + memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN); + break; + case Ndis802_11IBSS: + default: + memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); + memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); + memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + break; + } + + SetSeqNum(pwlanhdr, 0); + + if (bQoS == true) { + struct rtw_ieee80211_hdr_3addr_qos *pwlanqoshdr; + + set_frame_sub_type(pframe, WIFI_QOS_DATA_NULL); + + pwlanqoshdr = (struct rtw_ieee80211_hdr_3addr_qos *)pframe; + SetPriority(&pwlanqoshdr->qc, AC); + SetEOSP(&pwlanqoshdr->qc, bEosp); + + pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos); + } else { + set_frame_sub_type(pframe, WIFI_DATA_NULL); + + pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + } + + *pLength = pktlen; +} + +static void rtw_hal_construct_ProbeRsp(_adapter *padapter, u8 *pframe, u32 *pLength, + u8 *StaAddr, bool bHideSSID) +{ + struct rtw_ieee80211_hdr *pwlanhdr; + __le16 *fctrl; + u8 *mac, *bssid; + u32 pktlen; + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); + + /*RTW_INFO("%s\n", __func__);*/ + + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + mac = adapter_mac_addr(padapter); + bssid = cur_network->MacAddress; + + fctrl = &(pwlanhdr->frame_ctl); + *(fctrl) = 0; + memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); + memcpy(pwlanhdr->addr2, mac, ETH_ALEN); + memcpy(pwlanhdr->addr3, bssid, ETH_ALEN); + + SetSeqNum(pwlanhdr, 0); + set_frame_sub_type(fctrl, WIFI_PROBERSP); + + pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += pktlen; + + if (cur_network->IELength > MAX_IE_SZ) + return; + + memcpy(pframe, cur_network->IEs, cur_network->IELength); + pframe += cur_network->IELength; + pktlen += cur_network->IELength; + + *pLength = pktlen; +} + +#ifdef CONFIG_WOWLAN +static void rtw_hal_append_tkip_mic(PADAPTER padapter, + u8 *pframe, u32 offset) +{ + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct rtw_ieee80211_hdr *pwlanhdr; + struct mic_data micdata; + struct sta_info *psta = NULL; + int res = 0; + + u8 *payload = (u8 *)(pframe + offset); + + u8 mic[8]; + u8 priority[4] = {0x0}; + u8 null_key[16] = {0x0}; + + RTW_INFO("%s(): Add MIC, offset: %d\n", __func__, offset); + + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + psta = rtw_get_stainfo(&padapter->stapriv, + get_my_bssid(&(pmlmeinfo->network))); + if (psta != NULL) { + res = !memcmp(&psta->dot11tkiptxmickey.skey[0], + null_key, 16); + if (res) + RTW_INFO("%s(): STA dot11tkiptxmickey==0\n", __func__); + rtw_secmicsetkey(&micdata, &psta->dot11tkiptxmickey.skey[0]); + } + + rtw_secmicappend(&micdata, pwlanhdr->addr3, 6); /* DA */ + + rtw_secmicappend(&micdata, pwlanhdr->addr2, 6); /* SA */ + + priority[0] = 0; + + rtw_secmicappend(&micdata, &priority[0], 4); + + rtw_secmicappend(&micdata, payload, 36); /* payload length = 8 + 28 */ + + rtw_secgetmic(&micdata, &(mic[0])); + + payload += 36; + + memcpy(payload, &(mic[0]), 8); +} +/* + * Description: + * Construct the ARP response packet to support ARP offload. + * */ +static void rtw_hal_construct_ARPRsp( + PADAPTER padapter, + u8 *pframe, + u32 *pLength, + u8 *pIPAddress +) +{ + struct rtw_ieee80211_hdr *pwlanhdr; + __le16 *fctrl; + u32 pktlen; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct wlan_network *cur_network = &pmlmepriv->cur_network; + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct security_priv *psecuritypriv = &padapter->securitypriv; + static u8 ARPLLCHeader[8] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06}; + u8 *pARPRspPkt = pframe; + /* for TKIP Cal MIC */ + u8 *payload = pframe; + u8 EncryptionHeadOverhead = 0, arp_offset = 0; + /* RTW_INFO("%s:%d\n", __func__, bForcePowerSave); */ + + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + fctrl = &pwlanhdr->frame_ctl; + *(fctrl) = 0; + + /* ------------------------------------------------------------------------- */ + /* MAC Header. */ + /* ------------------------------------------------------------------------- */ + SetFrameType(fctrl, WIFI_DATA); + /* set_frame_sub_type(fctrl, 0); */ + SetToDs(fctrl); + memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); + memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + + SetSeqNum(pwlanhdr, 0); + set_duration(pwlanhdr, 0); + /* SET_80211_HDR_FRAME_CONTROL(pARPRspPkt, 0); */ + /* SET_80211_HDR_TYPE_AND_SUBTYPE(pARPRspPkt, Type_Data); */ + /* SET_80211_HDR_TO_DS(pARPRspPkt, 1); */ + /* SET_80211_HDR_ADDRESS1(pARPRspPkt, pMgntInfo->Bssid); */ + /* SET_80211_HDR_ADDRESS2(pARPRspPkt, Adapter->CurrentAddress); */ + /* SET_80211_HDR_ADDRESS3(pARPRspPkt, pMgntInfo->Bssid); */ + + /* SET_80211_HDR_DURATION(pARPRspPkt, 0); */ + /* SET_80211_HDR_FRAGMENT_SEQUENCE(pARPRspPkt, 0); */ +#ifdef CONFIG_WAPI_SUPPORT + *pLength = sMacHdrLng; +#else + *pLength = 24; +#endif + switch (psecuritypriv->dot11PrivacyAlgrthm) { + case _WEP40_: + case _WEP104_: + EncryptionHeadOverhead = 4; + break; + case _TKIP_: + EncryptionHeadOverhead = 8; + break; + case _AES_: + EncryptionHeadOverhead = 8; + break; +#ifdef CONFIG_WAPI_SUPPORT + case _SMS4_: + EncryptionHeadOverhead = 18; + break; +#endif + default: + EncryptionHeadOverhead = 0; + } + + if (EncryptionHeadOverhead > 0) { + memset(&(pframe[*pLength]), 0, EncryptionHeadOverhead); + *pLength += EncryptionHeadOverhead; + /* SET_80211_HDR_WEP(pARPRspPkt, 1); */ /* Suggested by CCW. */ + SetPrivacy(fctrl); + } + + /* ------------------------------------------------------------------------- */ + /* Frame Body. */ + /* ------------------------------------------------------------------------- */ + arp_offset = *pLength; + pARPRspPkt = (u8 *)(pframe + arp_offset); + payload = pARPRspPkt; /* Get Payload pointer */ + /* LLC header */ + memcpy(pARPRspPkt, ARPLLCHeader, 8); + *pLength += 8; + + /* ARP element */ + pARPRspPkt += 8; + SET_ARP_PKT_HW(pARPRspPkt, 0x0100); + SET_ARP_PKT_PROTOCOL(pARPRspPkt, 0x0008); /* IP protocol */ + SET_ARP_PKT_HW_ADDR_LEN(pARPRspPkt, 6); + SET_ARP_PKT_PROTOCOL_ADDR_LEN(pARPRspPkt, 4); + SET_ARP_PKT_OPERATION(pARPRspPkt, 0x0200); /* ARP response */ + SET_ARP_PKT_SENDER_MAC_ADDR(pARPRspPkt, adapter_mac_addr(padapter)); + SET_ARP_PKT_SENDER_IP_ADDR(pARPRspPkt, pIPAddress); +#ifdef CONFIG_ARP_KEEP_ALIVE + if (!is_zero_mac_addr(pmlmepriv->gw_mac_addr)) { + SET_ARP_PKT_TARGET_MAC_ADDR(pARPRspPkt, pmlmepriv->gw_mac_addr); + SET_ARP_PKT_TARGET_IP_ADDR(pARPRspPkt, pmlmepriv->gw_ip); + } else +#endif + { + SET_ARP_PKT_TARGET_MAC_ADDR(pARPRspPkt, + get_my_bssid(&(pmlmeinfo->network))); + SET_ARP_PKT_TARGET_IP_ADDR(pARPRspPkt, + pIPAddress); + RTW_INFO("%s Target Mac Addr:" MAC_FMT "\n", __func__, + MAC_ARG(get_my_bssid(&(pmlmeinfo->network)))); + RTW_INFO("%s Target IP Addr" IP_FMT "\n", __func__, + IP_ARG(pIPAddress)); + } + + *pLength += 28; + + if (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_) { + if (IS_HARDWARE_TYPE_8188E(padapter)) + rtw_hal_append_tkip_mic(padapter, pframe, arp_offset); + *pLength += 8; + } +} + +#ifdef CONFIG_PNO_SUPPORT +static void rtw_hal_construct_ProbeReq(_adapter *padapter, u8 *pframe, + u32 *pLength, pno_ssid_t *ssid) +{ + struct rtw_ieee80211_hdr *pwlanhdr; + __le16 *fctrl; + u32 pktlen; + unsigned char *mac; + unsigned char bssrate[NumRates]; + struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + int bssrate_len = 0; + u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + mac = adapter_mac_addr(padapter); + + fctrl = &(pwlanhdr->frame_ctl); + *(fctrl) = 0; + + memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); + memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN); + + memcpy(pwlanhdr->addr2, mac, ETH_ALEN); + + SetSeqNum(pwlanhdr, 0); + set_frame_sub_type(pframe, WIFI_PROBEREQ); + + pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += pktlen; + + if (ssid == NULL) + pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &pktlen); + else { + /* RTW_INFO("%s len:%d\n", ssid->SSID, ssid->SSID_len); */ + pframe = rtw_set_ie(pframe, _SSID_IE_, ssid->SSID_len, ssid->SSID, &pktlen); + } + + get_rate_set(padapter, bssrate, &bssrate_len); + + if (bssrate_len > 8) { + pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &pktlen); + pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &pktlen); + } else + pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &pktlen); + + *pLength = pktlen; +} + +static void rtw_hal_construct_PNO_info(_adapter *padapter, + u8 *pframe, u32 *pLength) +{ + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter); + int i; + + u8 *pPnoInfoPkt = pframe; + pPnoInfoPkt = (u8 *)(pframe + *pLength); + memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->ssid_num, 1); + + pPnoInfoPkt += 1; + memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->hidden_ssid_num, 1); + + pPnoInfoPkt += 3; + memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->fast_scan_period, 1); + + pPnoInfoPkt += 4; + memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->fast_scan_iterations, 4); + + pPnoInfoPkt += 4; + memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->slow_scan_period, 4); + + pPnoInfoPkt += 4; + memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->ssid_length, MAX_PNO_LIST_COUNT); + + pPnoInfoPkt += MAX_PNO_LIST_COUNT; + memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->ssid_cipher_info, MAX_PNO_LIST_COUNT); + + pPnoInfoPkt += MAX_PNO_LIST_COUNT; + memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->ssid_channel_info, MAX_PNO_LIST_COUNT); + + pPnoInfoPkt += MAX_PNO_LIST_COUNT; + memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->loc_probe_req, MAX_HIDDEN_AP); + + pPnoInfoPkt += MAX_HIDDEN_AP; + + /* + SSID is located at 128th Byte in NLO info Page + */ + + *pLength += 128; + pPnoInfoPkt = pframe + 128; + + for (i = 0; i < pwrctl->pnlo_info->ssid_num ; i++) { + memcpy(pPnoInfoPkt, &pwrctl->pno_ssid_list->node[i].SSID, + pwrctl->pnlo_info->ssid_length[i]); + *pLength += WLAN_SSID_MAXLEN; + pPnoInfoPkt += WLAN_SSID_MAXLEN; + } +} + +static void rtw_hal_construct_ssid_list(_adapter *padapter, + u8 *pframe, u32 *pLength) +{ + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter); + u8 *pSSIDListPkt = pframe; + int i; + + pSSIDListPkt = (u8 *)(pframe + *pLength); + + for (i = 0; i < pwrctl->pnlo_info->ssid_num ; i++) { + memcpy(pSSIDListPkt, &pwrctl->pno_ssid_list->node[i].SSID, + pwrctl->pnlo_info->ssid_length[i]); + + *pLength += WLAN_SSID_MAXLEN; + pSSIDListPkt += WLAN_SSID_MAXLEN; + } +} + +static void rtw_hal_construct_scan_info(_adapter *padapter, + u8 *pframe, u32 *pLength) +{ + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter); + u8 *pScanInfoPkt = pframe; + int i; + + pScanInfoPkt = (u8 *)(pframe + *pLength); + + memcpy(pScanInfoPkt, &pwrctl->pscan_info->channel_num, 1); + + *pLength += 1; + pScanInfoPkt += 1; + memcpy(pScanInfoPkt, &pwrctl->pscan_info->orig_ch, 1); + + + *pLength += 1; + pScanInfoPkt += 1; + memcpy(pScanInfoPkt, &pwrctl->pscan_info->orig_bw, 1); + + + *pLength += 1; + pScanInfoPkt += 1; + memcpy(pScanInfoPkt, &pwrctl->pscan_info->orig_40_offset, 1); + + *pLength += 1; + pScanInfoPkt += 1; + memcpy(pScanInfoPkt, &pwrctl->pscan_info->orig_80_offset, 1); + + *pLength += 1; + pScanInfoPkt += 1; + memcpy(pScanInfoPkt, &pwrctl->pscan_info->periodScan, 1); + + *pLength += 1; + pScanInfoPkt += 1; + memcpy(pScanInfoPkt, &pwrctl->pscan_info->period_scan_time, 1); + + *pLength += 1; + pScanInfoPkt += 1; + memcpy(pScanInfoPkt, &pwrctl->pscan_info->enableRFE, 1); + + *pLength += 1; + pScanInfoPkt += 1; + memcpy(pScanInfoPkt, &pwrctl->pscan_info->rfe_type, 8); + + *pLength += 8; + pScanInfoPkt += 8; + + for (i = 0 ; i < MAX_SCAN_LIST_COUNT ; i++) { + memcpy(pScanInfoPkt, + &pwrctl->pscan_info->ssid_channel_info[i], 4); + *pLength += 4; + pScanInfoPkt += 4; + } +} +#endif /* CONFIG_PNO_SUPPORT */ + +#ifdef CONFIG_GTK_OL +static void rtw_hal_construct_GTKRsp( + PADAPTER padapter, + u8 *pframe, + u32 *pLength +) +{ + struct rtw_ieee80211_hdr *pwlanhdr; + __le16 *fctrl; + u32 pktlen; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct wlan_network *cur_network = &pmlmepriv->cur_network; + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct security_priv *psecuritypriv = &padapter->securitypriv; + static u8 LLCHeader[8] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8E}; + static u8 GTKbody_a[11] = {0x01, 0x03, 0x00, 0x5F, 0x02, 0x03, 0x12, 0x00, 0x10, 0x42, 0x0B}; + u8 *pGTKRspPkt = pframe; + u8 EncryptionHeadOverhead = 0; + /* RTW_INFO("%s:%d\n", __func__, bForcePowerSave); */ + + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + fctrl = &pwlanhdr->frame_ctl; + *(fctrl) = 0; + + /* ------------------------------------------------------------------------- */ + /* MAC Header. */ + /* ------------------------------------------------------------------------- */ + SetFrameType(fctrl, WIFI_DATA); + /* set_frame_sub_type(fctrl, 0); */ + SetToDs(fctrl); + + memcpy(pwlanhdr->addr1, + get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + + memcpy(pwlanhdr->addr2, + adapter_mac_addr(padapter), ETH_ALEN); + + memcpy(pwlanhdr->addr3, + get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + + SetSeqNum(pwlanhdr, 0); + set_duration(pwlanhdr, 0); + +#ifdef CONFIG_WAPI_SUPPORT + *pLength = sMacHdrLng; +#else + *pLength = 24; +#endif /* CONFIG_WAPI_SUPPORT */ + + /* ------------------------------------------------------------------------- */ + /* Security Header: leave space for it if necessary. */ + /* ------------------------------------------------------------------------- */ + switch (psecuritypriv->dot11PrivacyAlgrthm) { + case _WEP40_: + case _WEP104_: + EncryptionHeadOverhead = 4; + break; + case _TKIP_: + EncryptionHeadOverhead = 8; + break; + case _AES_: + EncryptionHeadOverhead = 8; + break; +#ifdef CONFIG_WAPI_SUPPORT + case _SMS4_: + EncryptionHeadOverhead = 18; + break; +#endif /* CONFIG_WAPI_SUPPORT */ + default: + EncryptionHeadOverhead = 0; + } + + if (EncryptionHeadOverhead > 0) { + memset(&(pframe[*pLength]), 0, EncryptionHeadOverhead); + *pLength += EncryptionHeadOverhead; + /* SET_80211_HDR_WEP(pGTKRspPkt, 1); */ /* Suggested by CCW. */ + /* GTK's privacy bit is done by FW */ + /* SetPrivacy(fctrl); */ + } + /* ------------------------------------------------------------------------- */ + /* Frame Body. */ + /* ------------------------------------------------------------------------- */ + pGTKRspPkt = (u8 *)(pframe + *pLength); + /* LLC header */ + memcpy(pGTKRspPkt, LLCHeader, 8); + *pLength += 8; + + /* GTK element */ + pGTKRspPkt += 8; + + /* GTK frame body after LLC, part 1 */ + /* TKIP key_length = 32, AES key_length = 16 */ + if (psecuritypriv->dot118021XGrpPrivacy == _TKIP_) + GTKbody_a[8] = 0x20; + + /* GTK frame body after LLC, part 1 */ + memcpy(pGTKRspPkt, GTKbody_a, 11); + *pLength += 11; + pGTKRspPkt += 11; + /* GTK frame body after LLC, part 2 */ + memset(&(pframe[*pLength]), 0, 88); + *pLength += 88; + pGTKRspPkt += 88; + + if (psecuritypriv->dot118021XGrpPrivacy == _TKIP_) + *pLength += 8; +} +#endif /* CONFIG_GTK_OL */ + +void rtw_hal_set_wow_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 index, + u8 tx_desc, u32 page_size, u8 *page_num, u32 *total_pkt_len, + RSVDPAGE_LOC *rsvd_page_loc) +{ + struct security_priv *psecuritypriv = &adapter->securitypriv; + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter); + struct mlme_ext_priv *pmlmeext; + struct mlme_ext_info *pmlmeinfo; + u32 ARPLength = 0, GTKLength = 0, PNOLength = 0, ScanInfoLength = 0; + u32 SSIDLegnth = 0, ProbeReqLength = 0; + u8 CurtPktPageNum = 0; + u8 currentip[4]; + u8 cur_dot11txpn[8]; + +#ifdef CONFIG_GTK_OL + struct sta_priv *pstapriv = &adapter->stapriv; + struct sta_info *psta; + struct security_priv *psecpriv = &adapter->securitypriv; + u8 kek[RTW_KEK_LEN]; + u8 kck[RTW_KCK_LEN]; +#endif /* CONFIG_GTK_OL */ +#ifdef CONFIG_PNO_SUPPORT + int pno_index; + u8 ssid_num; +#endif /* CONFIG_PNO_SUPPORT */ + + pmlmeext = &adapter->mlmeextpriv; + pmlmeinfo = &pmlmeext->mlmext_info; + + if (pwrctl->wowlan_pno_enable == false) { + /* ARP RSP * 1 page */ + rtw_get_current_ip_address(adapter, currentip); + + rsvd_page_loc->LocArpRsp = *page_num; + + RTW_INFO("LocArpRsp: %d\n", rsvd_page_loc->LocArpRsp); + + rtw_hal_construct_ARPRsp(adapter, &pframe[index], + &ARPLength, currentip); + + rtw_hal_fill_fake_txdesc(adapter, + &pframe[index - tx_desc], + ARPLength, false, false, true); + + CurtPktPageNum = (u8)PageNum(tx_desc + ARPLength, page_size); + + *page_num += CurtPktPageNum; + + index += (CurtPktPageNum * page_size); + + /* 3 SEC IV * 1 page */ + rtw_get_sec_iv(adapter, cur_dot11txpn, + get_my_bssid(&pmlmeinfo->network)); + + rsvd_page_loc->LocRemoteCtrlInfo = *page_num; + + RTW_INFO("LocRemoteCtrlInfo: %d\n", rsvd_page_loc->LocRemoteCtrlInfo); + + memcpy(pframe + index - tx_desc, cur_dot11txpn, _AES_IV_LEN_); + + CurtPktPageNum = (u8)PageNum(_AES_IV_LEN_, page_size); + + *page_num += CurtPktPageNum; + + *total_pkt_len = index + _AES_IV_LEN_; +#ifdef CONFIG_GTK_OL + index += (CurtPktPageNum * page_size); + + /* if the ap staion info. exists, get the kek, kck from staion info. */ + psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv)); + if (psta == NULL) { + memset(kek, 0, RTW_KEK_LEN); + memset(kck, 0, RTW_KCK_LEN); + RTW_INFO("%s, KEK, KCK download rsvd page all zero\n", + __func__); + } else { + memcpy(kek, psta->kek, RTW_KEK_LEN); + memcpy(kck, psta->kck, RTW_KCK_LEN); + } + + /* 3 KEK, KCK */ + rsvd_page_loc->LocGTKInfo = *page_num; + RTW_INFO("LocGTKInfo: %d\n", rsvd_page_loc->LocGTKInfo); + + if (IS_HARDWARE_TYPE_8188E(adapter)) { + struct security_priv *psecpriv = NULL; + + psecpriv = &adapter->securitypriv; + memcpy(pframe + index - tx_desc, + &psecpriv->dot11PrivacyAlgrthm, 1); + memcpy(pframe + index - tx_desc + 1, + &psecpriv->dot118021XGrpPrivacy, 1); + memcpy(pframe + index - tx_desc + 2, + kck, RTW_KCK_LEN); + memcpy(pframe + index - tx_desc + 2 + RTW_KCK_LEN, + kek, RTW_KEK_LEN); + CurtPktPageNum = (u8)PageNum(tx_desc + 2 + RTW_KCK_LEN + RTW_KEK_LEN, page_size); + } else { + + memcpy(pframe + index - tx_desc, kck, RTW_KCK_LEN); + memcpy(pframe + index - tx_desc + RTW_KCK_LEN, + kek, RTW_KEK_LEN); + GTKLength = tx_desc + RTW_KCK_LEN + RTW_KEK_LEN; + + if (psta != NULL && + psecuritypriv->dot118021XGrpPrivacy == _TKIP_) { + memcpy(pframe + index - tx_desc + 56, + &psta->dot11tkiptxmickey, RTW_TKIP_MIC_LEN); + GTKLength += RTW_TKIP_MIC_LEN; + } + CurtPktPageNum = (u8)PageNum(GTKLength, page_size); + } + *page_num += CurtPktPageNum; + + index += (CurtPktPageNum * page_size); + + /* 3 GTK Response */ + rsvd_page_loc->LocGTKRsp = *page_num; + RTW_INFO("LocGTKRsp: %d\n", rsvd_page_loc->LocGTKRsp); + rtw_hal_construct_GTKRsp(adapter, &pframe[index], >KLength); + + rtw_hal_fill_fake_txdesc(adapter, &pframe[index - tx_desc], + GTKLength, false, false, true); + + CurtPktPageNum = (u8)PageNum(tx_desc + GTKLength, page_size); + + *page_num += CurtPktPageNum; + + index += (CurtPktPageNum * page_size); + + /* below page is empty for GTK extension memory */ + /* 3(11) GTK EXT MEM */ + rsvd_page_loc->LocGTKEXTMEM = *page_num; + RTW_INFO("LocGTKEXTMEM: %d\n", rsvd_page_loc->LocGTKEXTMEM); + CurtPktPageNum = 2; + + if (page_size >= 256) + CurtPktPageNum = 1; + + *page_num += CurtPktPageNum; + /* extension memory for FW */ + *total_pkt_len = index + (page_size * CurtPktPageNum); +#endif /* CONFIG_GTK_OL */ + + index += (CurtPktPageNum * page_size); + + /*Reserve 1 page for AOAC report*/ + rsvd_page_loc->LocAOACReport = *page_num; + RTW_INFO("LocAOACReport: %d\n", rsvd_page_loc->LocAOACReport); + *page_num += 1; + *total_pkt_len = index + (page_size * 1); + } else { +#ifdef CONFIG_PNO_SUPPORT + if (pwrctl->wowlan_in_resume == false && + pwrctl->pno_inited == true) { + + /* Broadcast Probe Request */ + rsvd_page_loc->LocProbePacket = *page_num; + + RTW_INFO("loc_probe_req: %d\n", + rsvd_page_loc->LocProbePacket); + + rtw_hal_construct_ProbeReq( + adapter, + &pframe[index], + &ProbeReqLength, + NULL); + + rtw_hal_fill_fake_txdesc(adapter, + &pframe[index - tx_desc], + ProbeReqLength, false, false, false); + + CurtPktPageNum = + (u8)PageNum(tx_desc + ProbeReqLength, page_size); + + *page_num += CurtPktPageNum; + + index += (CurtPktPageNum * page_size); + + /* Hidden SSID Probe Request */ + ssid_num = pwrctl->pnlo_info->hidden_ssid_num; + + for (pno_index = 0 ; pno_index < ssid_num ; pno_index++) { + pwrctl->pnlo_info->loc_probe_req[pno_index] = + *page_num; + + rtw_hal_construct_ProbeReq( + adapter, + &pframe[index], + &ProbeReqLength, + &pwrctl->pno_ssid_list->node[pno_index]); + + rtw_hal_fill_fake_txdesc(adapter, + &pframe[index - tx_desc], + ProbeReqLength, false, false, false); + + CurtPktPageNum = + (u8)PageNum(tx_desc + ProbeReqLength, page_size); + + *page_num += CurtPktPageNum; + + index += (CurtPktPageNum * page_size); + } + + /* PNO INFO Page */ + rsvd_page_loc->LocPNOInfo = *page_num; + RTW_INFO("LocPNOInfo: %d\n", rsvd_page_loc->LocPNOInfo); + rtw_hal_construct_PNO_info(adapter, + &pframe[index - tx_desc], + &PNOLength); + + CurtPktPageNum = (u8)PageNum(PNOLength, page_size); + *page_num += CurtPktPageNum; + index += (CurtPktPageNum * page_size); + + /* Scan Info Page */ + rsvd_page_loc->LocScanInfo = *page_num; + RTW_INFO("LocScanInfo: %d\n", rsvd_page_loc->LocScanInfo); + rtw_hal_construct_scan_info(adapter, + &pframe[index - tx_desc], + &ScanInfoLength); + + CurtPktPageNum = (u8)PageNum(ScanInfoLength, page_size); + *page_num += CurtPktPageNum; + *total_pkt_len = index + ScanInfoLength; + index += (CurtPktPageNum * page_size); + } +#endif /* CONFIG_PNO_SUPPORT */ + } +} + +static void rtw_hal_gate_bb(_adapter *adapter, bool stop) +{ + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter); + u8 val8 = 0; + u16 val16 = 0; + + if (stop) { + /* Pause TX*/ + pwrpriv->wowlan_txpause_status = rtw_read8(adapter, REG_TXPAUSE); + rtw_write8(adapter, REG_TXPAUSE, 0xff); + val8 = rtw_read8(adapter, REG_SYS_FUNC_EN); + val8 &= ~BIT(0); + rtw_write8(adapter, REG_SYS_FUNC_EN, val8); + RTW_INFO("%s: BB gated: 0x%02x, store TXPAUSE: %02x\n", + __func__, + rtw_read8(adapter, REG_SYS_FUNC_EN), + pwrpriv->wowlan_txpause_status); + } else { + val8 = rtw_read8(adapter, REG_SYS_FUNC_EN); + val8 |= BIT(0); + rtw_write8(adapter, REG_SYS_FUNC_EN, val8); + RTW_INFO("%s: BB release: 0x%02x, recover TXPAUSE:%02x\n", + __func__, rtw_read8(adapter, REG_SYS_FUNC_EN), + pwrpriv->wowlan_txpause_status); + /* release TX*/ + rtw_write8(adapter, REG_TXPAUSE, pwrpriv->wowlan_txpause_status); + } +} + +static void rtw_hal_reset_mac_rx(_adapter *adapter) +{ + u8 val8 = 0; + /* Set REG_CR bit1, bit3, bit7 to 0*/ + val8 = rtw_read8(adapter, REG_CR); + val8 &= 0x75; + rtw_write8(adapter, REG_CR, val8); + val8 = rtw_read8(adapter, REG_CR); + /* Set REG_CR bit1, bit3, bit7 to 1*/ + val8 |= 0x8a; + rtw_write8(adapter, REG_CR, val8); + RTW_INFO("0x%04x: %02x\n", REG_CR, rtw_read8(adapter, REG_CR)); +} + +static u8 rtw_hal_wow_pattern_generate(_adapter *adapter, u8 idx, struct rtl_wow_pattern *pwow_pattern) +{ + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter); + u8 *pattern; + u8 len = 0; + u8 *mask; + + u8 mask_hw[MAX_WKFM_SIZE] = {0}; + u8 content[MAX_WKFM_PATTERN_SIZE] = {0}; + u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u8 multicast_addr1[2] = {0x33, 0x33}; + u8 multicast_addr2[3] = {0x01, 0x00, 0x5e}; + u8 mask_len = 0; + u8 mac_addr[ETH_ALEN] = {0}; + u16 count = 0; + int i, j; + + if (pwrctl->wowlan_pattern_idx > MAX_WKFM_CAM_NUM) { + RTW_INFO("%s pattern_idx is more than MAX_FMC_NUM: %d\n", + __func__, MAX_WKFM_CAM_NUM); + return _FAIL; + } + + pattern = pwrctl->patterns[idx].content; + len = pwrctl->patterns[idx].len; + mask = pwrctl->patterns[idx].mask; + + memcpy(mac_addr, adapter_mac_addr(adapter), ETH_ALEN); + memset(pwow_pattern, 0, sizeof(struct rtl_wow_pattern)); + + mask_len = DIV_ROUND_UP(len, 8); + + /* 1. setup A1 table */ + if (memcmp(pattern, broadcast_addr, ETH_ALEN) == 0) + pwow_pattern->type = PATTERN_BROADCAST; + else if (memcmp(pattern, multicast_addr1, 2) == 0) + pwow_pattern->type = PATTERN_MULTICAST; + else if (memcmp(pattern, multicast_addr2, 3) == 0) + pwow_pattern->type = PATTERN_MULTICAST; + else if (memcmp(pattern, mac_addr, ETH_ALEN) == 0) + pwow_pattern->type = PATTERN_UNICAST; + else + pwow_pattern->type = PATTERN_INVALID; + + /* translate mask from os to mask for hw */ + + /****************************************************************************** + * pattern from OS uses 'ethenet frame', like this: + + | 6 | 6 | 2 | 20 | Variable | 4 | + |--------+--------+------+-----------+------------+-----| + | 802.3 Mac Header | IP Header | TCP Packet | FCS | + | DA | SA | Type | + + * BUT, packet catched by our HW is in '802.11 frame', begin from LLC, + + | 24 or 30 | 6 | 2 | 20 | Variable | 4 | + |-------------------+--------+------+-----------+------------+-----| + | 802.11 MAC Header | LLC | IP Header | TCP Packet | FCS | + | Others | Tpye | + + * Therefore, we need translate mask_from_OS to mask_to_hw. + * We should left-shift mask by 6 bits, then set the new bit[0~5] = 0, + * because new mask[0~5] means 'SA', but our HW packet begins from LLC, + * bit[0~5] corresponds to first 6 Bytes in LLC, they just don't match. + ******************************************************************************/ + /* Shift 6 bits */ + for (i = 0; i < mask_len - 1; i++) { + mask_hw[i] = mask[i] >> 6; + mask_hw[i] |= (mask[i + 1] & 0x3F) << 2; + } + + mask_hw[i] = (mask[i] >> 6) & 0x3F; + /* Set bit 0-5 to zero */ + mask_hw[0] &= 0xC0; + + for (i = 0; i < (MAX_WKFM_SIZE / 4); i++) { + pwow_pattern->mask[i] = mask_hw[i * 4]; + pwow_pattern->mask[i] |= (mask_hw[i * 4 + 1] << 8); + pwow_pattern->mask[i] |= (mask_hw[i * 4 + 2] << 16); + pwow_pattern->mask[i] |= (mask_hw[i * 4 + 3] << 24); + } + + /* To get the wake up pattern from the mask. + * We do not count first 12 bits which means + * DA[6] and SA[6] in the pattern to match HW design. */ + count = 0; + for (i = 12; i < len; i++) { + if ((mask[i / 8] >> (i % 8)) & 0x01) { + content[count] = pattern[i]; + count++; + } + } + + pwow_pattern->crc = rtw_calc_crc(content, count); + + if (pwow_pattern->crc != 0) { + if (pwow_pattern->type == PATTERN_INVALID) + pwow_pattern->type = PATTERN_VALID; + } + + return _SUCCESS; +} + +#ifndef CONFIG_WOW_PATTERN_HW_CAM +static void rtw_hal_set_wow_rxff_boundary(_adapter *adapter, bool wow_mode) +{ + u8 val8 = 0; + u16 rxff_bndy = 0; + u32 rx_dma_buff_sz = 0; + + val8 = rtw_read8(adapter, REG_FIFOPAGE + 3); + if (val8 != 0) + RTW_INFO("%s:[%04x]some PKTs in TXPKTBUF\n", + __func__, (REG_FIFOPAGE + 3)); + + rtw_hal_reset_mac_rx(adapter); + + if (wow_mode) { + rtw_hal_get_def_var(adapter, HAL_DEF_RX_DMA_SZ_WOW, + (u8 *)&rx_dma_buff_sz); + rxff_bndy = rx_dma_buff_sz - 1; + + rtw_write16(adapter, (REG_TRXFF_BNDY + 2), rxff_bndy); + RTW_INFO("%s: wow mode, 0x%04x: 0x%04x\n", __func__, + REG_TRXFF_BNDY + 2, + rtw_read16(adapter, (REG_TRXFF_BNDY + 2))); + } else { + rtw_hal_get_def_var(adapter, HAL_DEF_RX_DMA_SZ, + (u8 *)&rx_dma_buff_sz); + rxff_bndy = rx_dma_buff_sz - 1; + rtw_write16(adapter, (REG_TRXFF_BNDY + 2), rxff_bndy); + RTW_INFO("%s: normal mode, 0x%04x: 0x%04x\n", __func__, + REG_TRXFF_BNDY + 2, + rtw_read16(adapter, (REG_TRXFF_BNDY + 2))); + } +} + +bool rtw_read_from_frame_mask(_adapter *adapter, u8 idx) +{ + u32 data_l = 0, data_h = 0, rx_dma_buff_sz = 0, page_sz = 0; + u16 offset, rx_buf_ptr = 0; + u16 cam_start_offset = 0; + u16 ctrl_l = 0, ctrl_h = 0; + u8 count = 0, tmp = 0; + int i = 0; + bool res = true; + + if (idx > MAX_WKFM_CAM_NUM) { + RTW_INFO("[Error]: %s, pattern index is out of range\n", + __func__); + return false; + } + + rtw_hal_get_def_var(adapter, HAL_DEF_RX_DMA_SZ_WOW, + (u8 *)&rx_dma_buff_sz); + + if (rx_dma_buff_sz == 0) { + RTW_INFO("[Error]: %s, rx_dma_buff_sz is 0!!\n", __func__); + return false; + } + + rtw_hal_get_def_var(adapter, HAL_DEF_RX_PAGE_SIZE, (u8 *)&page_sz); + + if (page_sz == 0) { + RTW_INFO("[Error]: %s, page_sz is 0!!\n", __func__); + return false; + } + + offset = (u16)PageNum(rx_dma_buff_sz, page_sz); + cam_start_offset = offset * page_sz; + + ctrl_l = 0x0; + ctrl_h = 0x0; + + /* Enable RX packet buffer access */ + rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, RXPKT_BUF_SELECT); + + /* Read the WKFM CAM */ + for (i = 0; i < (WKFMCAM_ADDR_NUM / 2); i++) { + /* + * Set Rx packet buffer offset. + * RxBufer pointer increases 1, we can access 8 bytes in Rx packet buffer. + * CAM start offset (unit: 1 byte) = Index*WKFMCAM_SIZE + * RxBufer pointer addr = (CAM start offset + per entry offset of a WKFMCAM)/8 + * * Index: The index of the wake up frame mask + * * WKFMCAM_SIZE: the total size of one WKFM CAM + * * per entry offset of a WKFM CAM: Addr i * 4 bytes + */ + rx_buf_ptr = + (cam_start_offset + idx * WKFMCAM_SIZE + i * 8) >> 3; + rtw_write16(adapter, REG_PKTBUF_DBG_CTRL, rx_buf_ptr); + + rtw_write16(adapter, REG_RXPKTBUF_CTRL, ctrl_l); + data_l = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_L); + data_h = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_H); + + RTW_INFO("[%d]: %08x %08x\n", i, data_h, data_l); + + count = 0; + + do { + tmp = rtw_read8(adapter, REG_RXPKTBUF_CTRL); + rtw_udelay_os(2); + count++; + } while (!tmp && count < 100); + + if (count >= 100) { + RTW_INFO("%s count:%d\n", __func__, count); + res = false; + } + } + + /* Disable RX packet buffer access */ + rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, + DISABLE_TRXPKT_BUF_ACCESS); + return res; +} + +bool rtw_write_to_frame_mask(_adapter *adapter, u8 idx, + struct rtl_wow_pattern *context) +{ + u32 data = 0, rx_dma_buff_sz = 0, page_sz = 0; + u16 offset, rx_buf_ptr = 0; + u16 cam_start_offset = 0; + u16 ctrl_l = 0, ctrl_h = 0; + u8 count = 0, tmp = 0; + int res = 0, i = 0; + + if (idx > MAX_WKFM_CAM_NUM) { + RTW_INFO("[Error]: %s, pattern index is out of range\n", + __func__); + return false; + } + + rtw_hal_get_def_var(adapter, HAL_DEF_RX_DMA_SZ_WOW, + (u8 *)&rx_dma_buff_sz); + + if (rx_dma_buff_sz == 0) { + RTW_INFO("[Error]: %s, rx_dma_buff_sz is 0!!\n", __func__); + return false; + } + + rtw_hal_get_def_var(adapter, HAL_DEF_RX_PAGE_SIZE, (u8 *)&page_sz); + + if (page_sz == 0) { + RTW_INFO("[Error]: %s, page_sz is 0!!\n", __func__); + return false; + } + + offset = (u16)PageNum(rx_dma_buff_sz, page_sz); + + cam_start_offset = offset * page_sz; + + if (IS_HARDWARE_TYPE_8188E(adapter)) { + ctrl_l = 0x0001; + ctrl_h = 0x0001; + } else { + ctrl_l = 0x0f01; + ctrl_h = 0xf001; + } + + /* Enable RX packet buffer access */ + rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, RXPKT_BUF_SELECT); + + /* Write the WKFM CAM */ + for (i = 0; i < WKFMCAM_ADDR_NUM; i++) { + /* + * Set Rx packet buffer offset. + * RxBufer pointer increases 1, we can access 8 bytes in Rx packet buffer. + * CAM start offset (unit: 1 byte) = Index*WKFMCAM_SIZE + * RxBufer pointer addr = (CAM start offset + per entry offset of a WKFMCAM)/8 + * * Index: The index of the wake up frame mask + * * WKFMCAM_SIZE: the total size of one WKFM CAM + * * per entry offset of a WKFM CAM: Addr i * 4 bytes + */ + rx_buf_ptr = + (cam_start_offset + idx * WKFMCAM_SIZE + i * 4) >> 3; + rtw_write16(adapter, REG_PKTBUF_DBG_CTRL, rx_buf_ptr); + + if (i == 0) { + if (context->type == PATTERN_VALID) + data = BIT(31); + else if (context->type == PATTERN_BROADCAST) + data = BIT(31) | BIT(26); + else if (context->type == PATTERN_MULTICAST) + data = BIT(31) | BIT(25); + else if (context->type == PATTERN_UNICAST) + data = BIT(31) | BIT(24); + + if (context->crc != 0) + data |= context->crc; + + rtw_write32(adapter, REG_PKTBUF_DBG_DATA_L, data); + rtw_write16(adapter, REG_RXPKTBUF_CTRL, ctrl_l); + } else if (i == 1) { + data = 0; + rtw_write32(adapter, REG_PKTBUF_DBG_DATA_H, data); + rtw_write16(adapter, REG_RXPKTBUF_CTRL, ctrl_h); + } else if (i == 2 || i == 4) { + data = context->mask[i - 2]; + rtw_write32(adapter, REG_PKTBUF_DBG_DATA_L, data); + /* write to RX packet buffer*/ + rtw_write16(adapter, REG_RXPKTBUF_CTRL, ctrl_l); + } else if (i == 3 || i == 5) { + data = context->mask[i - 2]; + rtw_write32(adapter, REG_PKTBUF_DBG_DATA_H, data); + /* write to RX packet buffer*/ + rtw_write16(adapter, REG_RXPKTBUF_CTRL, ctrl_h); + } + + count = 0; + do { + tmp = rtw_read8(adapter, REG_RXPKTBUF_CTRL); + rtw_udelay_os(2); + count++; + } while (tmp && count < 100); + + if (count >= 100) + res = false; + else + res = true; + } + + /* Disable RX packet buffer access */ + rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, + DISABLE_TRXPKT_BUF_ACCESS); + + return res; +} +void rtw_clean_pattern(_adapter *adapter) +{ + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter); + struct rtl_wow_pattern zero_pattern; + int i = 0; + + memset(&zero_pattern, 0, sizeof(struct rtl_wow_pattern)); + + zero_pattern.type = PATTERN_INVALID; + + for (i = 0; i < MAX_WKFM_CAM_NUM; i++) + rtw_write_to_frame_mask(adapter, i, &zero_pattern); + + rtw_write8(adapter, REG_WKFMCAM_NUM, 0); +} +static int rtw_hal_set_pattern(_adapter *adapter, u8 *pattern, + u8 len, u8 *mask, u8 idx) +{ + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter); + struct mlme_ext_priv *pmlmeext = NULL; + struct mlme_ext_info *pmlmeinfo = NULL; + struct rtl_wow_pattern wow_pattern; + u8 mask_hw[MAX_WKFM_SIZE] = {0}; + u8 content[MAX_WKFM_PATTERN_SIZE] = {0}; + u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u8 multicast_addr1[2] = {0x33, 0x33}; + u8 multicast_addr2[3] = {0x01, 0x00, 0x5e}; + u8 res = false, index = 0, mask_len = 0; + u8 mac_addr[ETH_ALEN] = {0}; + u16 count = 0; + int i, j; + + if (pwrctl->wowlan_pattern_idx > MAX_WKFM_CAM_NUM) { + RTW_INFO("%s pattern_idx is more than MAX_FMC_NUM: %d\n", + __func__, MAX_WKFM_CAM_NUM); + return false; + } + + pmlmeext = &adapter->mlmeextpriv; + pmlmeinfo = &pmlmeext->mlmext_info; + memcpy(mac_addr, adapter_mac_addr(adapter), ETH_ALEN); + memset(&wow_pattern, 0, sizeof(struct rtl_wow_pattern)); + + mask_len = DIV_ROUND_UP(len, 8); + + /* 1. setup A1 table */ + if (memcmp(pattern, broadcast_addr, ETH_ALEN) == 0) + wow_pattern.type = PATTERN_BROADCAST; + else if (memcmp(pattern, multicast_addr1, 2) == 0) + wow_pattern.type = PATTERN_MULTICAST; + else if (memcmp(pattern, multicast_addr2, 3) == 0) + wow_pattern.type = PATTERN_MULTICAST; + else if (memcmp(pattern, mac_addr, ETH_ALEN) == 0) + wow_pattern.type = PATTERN_UNICAST; + else + wow_pattern.type = PATTERN_INVALID; + + /* translate mask from os to mask for hw */ + +/****************************************************************************** + * pattern from OS uses 'ethenet frame', like this: + + | 6 | 6 | 2 | 20 | Variable | 4 | + |--------+--------+------+-----------+------------+-----| + | 802.3 Mac Header | IP Header | TCP Packet | FCS | + | DA | SA | Type | + + * BUT, packet catched by our HW is in '802.11 frame', begin from LLC, + + | 24 or 30 | 6 | 2 | 20 | Variable | 4 | + |-------------------+--------+------+-----------+------------+-----| + | 802.11 MAC Header | LLC | IP Header | TCP Packet | FCS | + | Others | Tpye | + + * Therefore, we need translate mask_from_OS to mask_to_hw. + * We should left-shift mask by 6 bits, then set the new bit[0~5] = 0, + * because new mask[0~5] means 'SA', but our HW packet begins from LLC, + * bit[0~5] corresponds to first 6 Bytes in LLC, they just don't match. + ******************************************************************************/ + /* Shift 6 bits */ + for (i = 0; i < mask_len - 1; i++) { + mask_hw[i] = mask[i] >> 6; + mask_hw[i] |= (mask[i + 1] & 0x3F) << 2; + } + + mask_hw[i] = (mask[i] >> 6) & 0x3F; + /* Set bit 0-5 to zero */ + mask_hw[0] &= 0xC0; + + for (i = 0; i < (MAX_WKFM_SIZE / 4); i++) { + wow_pattern.mask[i] = mask_hw[i * 4]; + wow_pattern.mask[i] |= (mask_hw[i * 4 + 1] << 8); + wow_pattern.mask[i] |= (mask_hw[i * 4 + 2] << 16); + wow_pattern.mask[i] |= (mask_hw[i * 4 + 3] << 24); + } + + /* To get the wake up pattern from the mask. + * We do not count first 12 bits which means + * DA[6] and SA[6] in the pattern to match HW design. */ + count = 0; + for (i = 12; i < len; i++) { + if ((mask[i / 8] >> (i % 8)) & 0x01) { + content[count] = pattern[i]; + count++; + } + } + + wow_pattern.crc = rtw_calc_crc(content, count); + + if (wow_pattern.crc != 0) { + if (wow_pattern.type == PATTERN_INVALID) + wow_pattern.type = PATTERN_VALID; + } + + index = idx; + + if (!pwrctl->bInSuspend) + index += 2; + + /* write pattern */ + res = rtw_write_to_frame_mask(adapter, index, &wow_pattern); + + if (res == false) + RTW_INFO("%s: ERROR!! idx: %d write_to_frame_mask_cam fail\n", + __func__, idx); + + return res; +} +void rtw_fill_pattern(_adapter *adapter) +{ + int i = 0, total = 0, index; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter); + struct rtl_wow_pattern wow_pattern; + + total = pwrpriv->wowlan_pattern_idx; + + if (total > MAX_WKFM_CAM_NUM) + total = MAX_WKFM_CAM_NUM; + + for (i = 0 ; i < total ; i++) { + if (_SUCCESS == rtw_hal_wow_pattern_generate(adapter, i, &wow_pattern)) { + + index = i; + if (!pwrpriv->bInSuspend) + index += 2; + + if (rtw_write_to_frame_mask(adapter, index, &wow_pattern) == false) + RTW_INFO("%s: ERROR!! idx: %d write_to_frame_mask_cam fail\n", __func__, i); + } + + } + rtw_write8(adapter, REG_WKFMCAM_NUM, total); + +} + +#else /*CONFIG_WOW_PATTERN_HW_CAM*/ + +#define WOW_CAM_ACCESS_TIMEOUT_MS 200 +#define WOW_VALID_BIT BIT31 +#define WOW_BC_BIT BIT26 +#define WOW_MC_BIT BIT25 +#define WOW_UC_BIT BIT24 + +static u32 _rtw_wow_pattern_read_cam(_adapter *adapter, u8 addr) +{ + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter); + _mutex *mutex = &pwrpriv->wowlan_pattern_cam_mutex; + + u32 rdata = 0; + u32 cnt = 0; + u32 start = 0; + u8 timeout = 0; + u8 rst = false; + + _enter_critical_mutex(mutex, NULL); + + rtw_write32(adapter, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1 | BIT_WKFCAM_ADDR_V2(addr)); + + start = jiffies; + while (1) { + if (rtw_is_surprise_removed(adapter)) + break; + + cnt++; + if (0 == (rtw_read32(adapter, REG_WKFMCAM_CMD) & BIT_WKFCAM_POLLING_V1)) { + rst = _SUCCESS; + break; + } + if (rtw_get_passing_time_ms(start) > WOW_CAM_ACCESS_TIMEOUT_MS) { + timeout = 1; + break; + } + } + + rdata = rtw_read32(adapter, REG_WKFMCAM_RWD); + + _exit_critical_mutex(mutex, NULL); + + /*RTW_INFO("%s ==> addr:0x%02x , rdata:0x%08x\n", __func__, addr, rdata);*/ + + if (timeout) + RTW_ERR(FUNC_ADPT_FMT" failed due to polling timeout\n", FUNC_ADPT_ARG(adapter)); + + return rdata; +} +void rtw_wow_pattern_read_cam_ent(_adapter *adapter, u8 id, struct rtl_wow_pattern *context) +{ + int i; + u32 rdata; + + memset(context, 0, sizeof(struct rtl_wow_pattern)); + + for (i = 4; i >= 0; i--) { + rdata = _rtw_wow_pattern_read_cam(adapter, (id << 3) | i); + + switch (i) { + case 4: + if (rdata & WOW_BC_BIT) + context->type = PATTERN_BROADCAST; + else if (rdata & WOW_MC_BIT) + context->type = PATTERN_MULTICAST; + else if (rdata & WOW_UC_BIT) + context->type = PATTERN_UNICAST; + else + context->type = PATTERN_INVALID; + + context->crc = rdata & 0xFFFF; + break; + default: + memcpy(&context->mask[i], (u8 *)(&rdata), 4); + break; + } + } +} + +static void _rtw_wow_pattern_write_cam(_adapter *adapter, u8 addr, u32 wdata) +{ + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter); + _mutex *mutex = &pwrpriv->wowlan_pattern_cam_mutex; + u32 cnt = 0; + u32 start = 0, end = 0; + u8 timeout = 0; + + /*RTW_INFO("%s ==> addr:0x%02x , wdata:0x%08x\n", __func__, addr, wdata);*/ + _enter_critical_mutex(mutex, NULL); + + rtw_write32(adapter, REG_WKFMCAM_RWD, wdata); + rtw_write32(adapter, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1 | BIT_WKFCAM_WE | BIT_WKFCAM_ADDR_V2(addr)); + + start = jiffies; + while (1) { + if (rtw_is_surprise_removed(adapter)) + break; + + cnt++; + if (0 == (rtw_read32(adapter, REG_WKFMCAM_CMD) & BIT_WKFCAM_POLLING_V1)) + break; + + if (rtw_get_passing_time_ms(start) > WOW_CAM_ACCESS_TIMEOUT_MS) { + timeout = 1; + break; + } + } + end = jiffies; + + _exit_critical_mutex(mutex, NULL); + + if (timeout) { + RTW_ERR(FUNC_ADPT_FMT" addr:0x%02x, wdata:0x%08x, to:%u, polling:%u, %d ms\n" + , FUNC_ADPT_ARG(adapter), addr, wdata, timeout, cnt, rtw_get_time_interval_ms(start, end)); + } +} + +void rtw_wow_pattern_write_cam_ent(_adapter *adapter, u8 id, struct rtl_wow_pattern *context) +{ + int j; + u8 addr; + u32 wdata = 0; + + for (j = 4; j >= 0; j--) { + switch (j) { + case 4: + wdata = context->crc; + + if (PATTERN_BROADCAST == context->type) + wdata |= WOW_BC_BIT; + if (PATTERN_MULTICAST == context->type) + wdata |= WOW_MC_BIT; + if (PATTERN_UNICAST == context->type) + wdata |= WOW_UC_BIT; + if (PATTERN_INVALID != context->type) + wdata |= WOW_VALID_BIT; + break; + default: + wdata = context->mask[j]; + break; + } + + addr = (id << 3) + j; + + _rtw_wow_pattern_write_cam(adapter, addr, wdata); + } +} + +static u8 _rtw_wow_pattern_clean_cam(_adapter *adapter) +{ + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter); + _mutex *mutex = &pwrpriv->wowlan_pattern_cam_mutex; + u32 cnt = 0; + u32 start = 0; + u8 timeout = 0; + u8 rst = _FAIL; + + _enter_critical_mutex(mutex, NULL); + rtw_write32(adapter, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1 | BIT_WKFCAM_CLR_V1); + + start = jiffies; + while (1) { + if (rtw_is_surprise_removed(adapter)) + break; + + cnt++; + if (0 == (rtw_read32(adapter, REG_WKFMCAM_CMD) & BIT_WKFCAM_POLLING_V1)) { + rst = _SUCCESS; + break; + } + if (rtw_get_passing_time_ms(start) > WOW_CAM_ACCESS_TIMEOUT_MS) { + timeout = 1; + break; + } + } + _exit_critical_mutex(mutex, NULL); + + if (timeout) + RTW_ERR(FUNC_ADPT_FMT" falied ,polling timeout\n", FUNC_ADPT_ARG(adapter)); + + return rst; +} + +void rtw_clean_pattern(_adapter *adapter) +{ + if (_FAIL == _rtw_wow_pattern_clean_cam(adapter)) + RTW_ERR("rtw_clean_pattern failed\n"); +} + +void rtw_dump_wow_pattern(void *sel, struct rtl_wow_pattern *pwow_pattern, u8 idx) +{ + int j; + + RTW_PRINT_SEL(sel, "=======WOW CAM-ID[%d]=======\n", idx); + RTW_PRINT_SEL(sel, "[WOW CAM] type:%d\n", pwow_pattern->type); + RTW_PRINT_SEL(sel, "[WOW CAM] crc:0x%04x\n", pwow_pattern->crc); + for (j = 0; j < 4; j++) + RTW_PRINT_SEL(sel, "[WOW CAM] Mask:0x%08x\n", pwow_pattern->mask[j]); +} + +void rtw_fill_pattern(_adapter *adapter) +{ + int i = 0, total = 0; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter); + struct rtl_wow_pattern wow_pattern; + + total = pwrpriv->wowlan_pattern_idx; + + if (total > MAX_WKFM_CAM_NUM) + total = MAX_WKFM_CAM_NUM; + + for (i = 0 ; i < total ; i++) { + if (_SUCCESS == rtw_hal_wow_pattern_generate(adapter, i, &wow_pattern)) { + rtw_dump_wow_pattern(RTW_DBGDUMP, &wow_pattern, i); + rtw_wow_pattern_write_cam_ent(adapter, i, &wow_pattern); + } + } +} + +#endif +void rtw_wow_pattern_cam_dump(_adapter *adapter) +{ + +#ifndef CONFIG_WOW_PATTERN_HW_CAM + int i; + + for (i = 0 ; i < MAX_WKFM_CAM_NUM; i++) { + RTW_INFO("=======[%d]=======\n", i); + rtw_read_from_frame_mask(adapter, i); + } +#else + struct rtl_wow_pattern context; + int i; + + for (i = 0 ; i < MAX_WKFM_CAM_NUM; i++) { + rtw_wow_pattern_read_cam_ent(adapter, i, &context); + rtw_dump_wow_pattern(RTW_DBGDUMP, &context, i); + } + +#endif +} + + +static void rtw_hal_dl_pattern(_adapter *adapter, u8 mode) +{ + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter); + + switch (mode) { + case 0: + rtw_clean_pattern(adapter); + RTW_INFO("%s: total patterns: %d\n", __func__, pwrpriv->wowlan_pattern_idx); + break; + case 1: + rtw_set_default_pattern(adapter); + rtw_fill_pattern(adapter); + RTW_INFO("%s: pattern total: %d downloaded\n", __func__, pwrpriv->wowlan_pattern_idx); + break; + case 2: + rtw_clean_pattern(adapter); + rtw_wow_pattern_sw_reset(adapter); + RTW_INFO("%s: clean patterns\n", __func__); + break; + default: + RTW_INFO("%s: unknown mode\n", __func__); + break; + } +} + +static void rtw_hal_wow_enable(_adapter *adapter) +{ + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter); + struct security_priv *psecuritypriv = &adapter->securitypriv; + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct hal_ops *pHalFunc = &adapter->hal_func; + struct sta_info *psta = NULL; + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(adapter); + int res; + u16 media_status_rpt; + + + RTW_PRINT("%s, WOWLAN_ENABLE\n", __func__); + rtw_hal_gate_bb(adapter, true); +#ifdef CONFIG_GTK_OL + if (psecuritypriv->binstallKCK_KEK == true) + rtw_hal_fw_sync_cam_id(adapter); +#endif + /* RX DMA stop */ + if (IS_HARDWARE_TYPE_8188E(adapter)) + rtw_hal_disable_tx_report(adapter); + + res = rtw_hal_pause_rx_dma(adapter); + if (res == _FAIL) + RTW_PRINT("[WARNING] pause RX DMA fail\n"); + + #ifndef CONFIG_WOW_PATTERN_HW_CAM + /* Reconfig RX_FF Boundary */ + rtw_hal_set_wow_rxff_boundary(adapter, true); + #endif + + /* redownload wow pattern */ + rtw_hal_dl_pattern(adapter, 1); + + rtw_hal_fw_dl(adapter, true); + media_status_rpt = RT_MEDIA_CONNECT; + rtw_hal_set_hwreg(adapter, HW_VAR_H2C_FW_JOINBSSRPT, + (u8 *)&media_status_rpt); + + if (!pwrctl->wowlan_pno_enable) { + psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(pmlmepriv)); + + if (psta != NULL) { + #ifdef CONFIG_FW_MULTI_PORT_SUPPORT + rtw_hal_set_default_port_id_cmd(adapter, psta->mac_id); + #endif + + rtw_sta_media_status_rpt(adapter, psta, 1); + } + } + + /* Set WOWLAN H2C command. */ + RTW_PRINT("Set WOWLan cmd\n"); + rtw_hal_set_fw_wow_related_cmd(adapter, 1); + + res = rtw_hal_check_wow_ctrl(adapter, true); + + if (res == false) + RTW_INFO("[Error]%s: set wowlan CMD fail!!\n", __func__); + + pwrctl->wowlan_wake_reason = + rtw_read8(adapter, REG_WOWLAN_WAKE_REASON); + + RTW_PRINT("wowlan_wake_reason: 0x%02x\n", + pwrctl->wowlan_wake_reason); +#ifdef CONFIG_GTK_OL_DBG + dump_sec_cam(RTW_DBGDUMP, adapter); + dump_sec_cam_cache(RTW_DBGDUMP, adapter); +#endif + /* free adapter's resource */ + rtw_mi_intf_stop(adapter); + + /* Invoid SE0 reset signal during suspending*/ + rtw_write8(adapter, REG_RSV_CTRL, 0x20); + if (IS_8188F(pHalData->version_id) == false) + rtw_write8(adapter, REG_RSV_CTRL, 0x60); + + rtw_hal_gate_bb(adapter, false); +} + +#define DBG_WAKEUP_REASON +#ifdef DBG_WAKEUP_REASON +void _dbg_wake_up_reason_string(_adapter *adapter, const char *srt_res) +{ + RTW_INFO(ADPT_FMT "- wake up reason - %s\n", ADPT_ARG(adapter), srt_res); +} +void _dbg_rtw_wake_up_reason(_adapter *adapter, u8 reason) +{ + if (RX_PAIRWISEKEY == reason) + _dbg_wake_up_reason_string(adapter, "Rx pairwise key"); + else if (RX_GTK == reason) + _dbg_wake_up_reason_string(adapter, "Rx GTK"); + else if (RX_FOURWAY_HANDSHAKE == reason) + _dbg_wake_up_reason_string(adapter, "Rx four way handshake"); + else if (RX_DISASSOC == reason) + _dbg_wake_up_reason_string(adapter, "Rx disassoc"); + else if (RX_DEAUTH == reason) + _dbg_wake_up_reason_string(adapter, "Rx deauth"); + else if (RX_ARP_REQUEST == reason) + _dbg_wake_up_reason_string(adapter, "Rx ARP request"); + else if (FW_DECISION_DISCONNECT == reason) + _dbg_wake_up_reason_string(adapter, "FW detect disconnect"); + else if (RX_MAGIC_PKT == reason) + _dbg_wake_up_reason_string(adapter, "Rx magic packet"); + else if (RX_UNICAST_PKT == reason) + _dbg_wake_up_reason_string(adapter, "Rx unicast packet"); + else if (RX_PATTERN_PKT == reason) + _dbg_wake_up_reason_string(adapter, "Rx pattern packet"); + else if (RTD3_SSID_MATCH == reason) + _dbg_wake_up_reason_string(adapter, "RTD3 SSID match"); + else if (RX_REALWOW_V2_WAKEUP_PKT == reason) + _dbg_wake_up_reason_string(adapter, "Rx real WOW V2 wakeup packet"); + else if (RX_REALWOW_V2_ACK_LOST == reason) + _dbg_wake_up_reason_string(adapter, "Rx real WOW V2 ack lost"); + else if (ENABLE_FAIL_DMA_IDLE == reason) + _dbg_wake_up_reason_string(adapter, "enable fail DMA idle"); + else if (ENABLE_FAIL_DMA_PAUSE == reason) + _dbg_wake_up_reason_string(adapter, "enable fail DMA pause"); + else if (AP_OFFLOAD_WAKEUP == reason) + _dbg_wake_up_reason_string(adapter, "AP offload wakeup"); + else if (CLK_32K_UNLOCK == reason) + _dbg_wake_up_reason_string(adapter, "clk 32k unlock"); + else if (RTIME_FAIL_DMA_IDLE == reason) + _dbg_wake_up_reason_string(adapter, "RTIME fail DMA idle"); + else if (CLK_32K_LOCK == reason) + _dbg_wake_up_reason_string(adapter, "clk 32k lock"); + else + _dbg_wake_up_reason_string(adapter, "unknown reasoen"); +} +#endif + +static void rtw_hal_wow_disable(_adapter *adapter) +{ + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter); + struct security_priv *psecuritypriv = &adapter->securitypriv; + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct hal_ops *pHalFunc = &adapter->hal_func; + struct sta_info *psta = NULL; + int res; + u16 media_status_rpt; + u8 val8; + + RTW_PRINT("%s, WOWLAN_DISABLE\n", __func__); + + if (!pwrctl->wowlan_pno_enable) { + psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(pmlmepriv)); + if (psta != NULL) + rtw_sta_media_status_rpt(adapter, psta, 0); + else + RTW_INFO("%s: psta is null\n", __func__); + } + + if (0) { + RTW_INFO("0x630:0x%02x\n", rtw_read8(adapter, 0x630)); + RTW_INFO("0x631:0x%02x\n", rtw_read8(adapter, 0x631)); + RTW_INFO("0x634:0x%02x\n", rtw_read8(adapter, 0x634)); + RTW_INFO("0x1c7:0x%02x\n", rtw_read8(adapter, 0x1c7)); + } + + pwrctl->wowlan_wake_reason = rtw_read8(adapter, REG_WOWLAN_WAKE_REASON); + + RTW_PRINT("wakeup_reason: 0x%02x\n", + pwrctl->wowlan_wake_reason); + #ifdef DBG_WAKEUP_REASON + _dbg_rtw_wake_up_reason(adapter, pwrctl->wowlan_wake_reason); + #endif + + rtw_hal_set_fw_wow_related_cmd(adapter, 0); + + res = rtw_hal_check_wow_ctrl(adapter, false); + + if (res == false) { + RTW_INFO("[Error]%s: disable WOW cmd fail\n!!", __func__); + rtw_hal_force_enable_rxdma(adapter); + } + + rtw_hal_gate_bb(adapter, true); + + res = rtw_hal_pause_rx_dma(adapter); + if (res == _FAIL) + RTW_PRINT("[WARNING] pause RX DMA fail\n"); + + /* clean HW pattern match */ + rtw_hal_dl_pattern(adapter, 0); + + #ifndef CONFIG_WOW_PATTERN_HW_CAM + /* config RXFF boundary to original */ + rtw_hal_set_wow_rxff_boundary(adapter, false); + #endif + rtw_hal_release_rx_dma(adapter); + + if (IS_HARDWARE_TYPE_8188E(adapter)) + rtw_hal_enable_tx_report(adapter); + +#ifdef CONFIG_GTK_OL + if (((pwrctl->wowlan_wake_reason != RX_DISASSOC) || + (pwrctl->wowlan_wake_reason != RX_DEAUTH) || + (pwrctl->wowlan_wake_reason != FW_DECISION_DISCONNECT)) && + psecuritypriv->binstallKCK_KEK == true) { + rtw_hal_get_aoac_rpt(adapter); + rtw_hal_update_sw_security_info(adapter); + } +#endif /*CONFIG_GTK_OL*/ + + rtw_hal_fw_dl(adapter, false); + +#ifdef CONFIG_GPIO_WAKEUP + val8 = (pwrctl->is_high_active == 0) ? 1 : 0; + RTW_PRINT("Set Wake GPIO to default(%d).\n", val8); + rtw_hal_set_output_gpio(adapter, WAKEUP_GPIO_IDX, val8); + + rtw_hal_switch_gpio_wl_ctrl(adapter, WAKEUP_GPIO_IDX, false); +#endif + + if ((pwrctl->wowlan_wake_reason != FW_DECISION_DISCONNECT) && + (pwrctl->wowlan_wake_reason != RX_PAIRWISEKEY) && + (pwrctl->wowlan_wake_reason != RX_DISASSOC) && + (pwrctl->wowlan_wake_reason != RX_DEAUTH)) { + + media_status_rpt = RT_MEDIA_CONNECT; + rtw_hal_set_hwreg(adapter, HW_VAR_H2C_FW_JOINBSSRPT, + (u8 *)&media_status_rpt); + + if (psta != NULL) { + #ifdef CONFIG_FW_MULTI_PORT_SUPPORT + rtw_hal_set_default_port_id_cmd(adapter, psta->mac_id); + #endif + rtw_sta_media_status_rpt(adapter, psta, 1); + } + } + rtw_hal_gate_bb(adapter, false); +} +#endif /*CONFIG_WOWLAN*/ + +#ifdef CONFIG_P2P_WOWLAN +void rtw_hal_set_p2p_wow_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 index, + u8 tx_desc, u32 page_size, u8 *page_num, u32 *total_pkt_len, + RSVDPAGE_LOC *rsvd_page_loc) +{ + u32 P2PNegoRspLength = 0, P2PInviteRspLength = 0; + u32 P2PPDRspLength = 0, P2PProbeRspLength = 0, P2PBCNLength = 0; + u8 CurtPktPageNum = 0; + + /* P2P Beacon */ + rsvd_page_loc->LocP2PBeacon = *page_num; + rtw_hal_construct_P2PBeacon(adapter, &pframe[index], &P2PBCNLength); + rtw_hal_fill_fake_txdesc(adapter, &pframe[index - tx_desc], + P2PBCNLength, false, false, false); + + CurtPktPageNum = (u8)PageNum(tx_desc + P2PBCNLength, page_size); + + *page_num += CurtPktPageNum; + + index += (CurtPktPageNum * page_size); + + /* P2P Probe rsp */ + rsvd_page_loc->LocP2PProbeRsp = *page_num; + rtw_hal_construct_P2PProbeRsp(adapter, &pframe[index], + &P2PProbeRspLength); + rtw_hal_fill_fake_txdesc(adapter, &pframe[index - tx_desc], + P2PProbeRspLength, false, false, false); + + CurtPktPageNum = (u8)PageNum(tx_desc + P2PProbeRspLength, page_size); + + *page_num += CurtPktPageNum; + + index += (CurtPktPageNum * page_size); + + /* P2P nego rsp */ + rsvd_page_loc->LocNegoRsp = *page_num; + rtw_hal_construct_P2PNegoRsp(adapter, &pframe[index], + &P2PNegoRspLength); + rtw_hal_fill_fake_txdesc(adapter, &pframe[index - tx_desc], + P2PNegoRspLength, false, false, false); + + /* RTW_INFO("%s(): HW_VAR_SET_TX_CMD: QOS NULL DATA %p %d\n", */ + /* __func__, &pframe[index-tx_desc], (NegoRspLength+tx_desc)); */ + + CurtPktPageNum = (u8)PageNum(tx_desc + P2PNegoRspLength, page_size); + + *page_num += CurtPktPageNum; + + index += (CurtPktPageNum * page_size); + + /* P2P invite rsp */ + rsvd_page_loc->LocInviteRsp = *page_num; + rtw_hal_construct_P2PInviteRsp(adapter, &pframe[index], + &P2PInviteRspLength); + rtw_hal_fill_fake_txdesc(adapter, &pframe[index - tx_desc], + P2PInviteRspLength, false, false, false); + + /* RTW_INFO("%s(): HW_VAR_SET_TX_CMD: QOS NULL DATA %p %d\n", */ + /* __func__, &pframe[index-tx_desc], (InviteRspLength+tx_desc)); */ + + CurtPktPageNum = (u8)PageNum(tx_desc + P2PInviteRspLength, page_size); + + *page_num += CurtPktPageNum; + + index += (CurtPktPageNum * page_size); + + /* P2P provision discovery rsp */ + rsvd_page_loc->LocPDRsp = *page_num; + rtw_hal_construct_P2PProvisionDisRsp(adapter, + &pframe[index], &P2PPDRspLength); + + rtw_hal_fill_fake_txdesc(adapter, &pframe[index - tx_desc], + P2PPDRspLength, false, false, false); + + /* RTW_INFO("%s(): HW_VAR_SET_TX_CMD: QOS NULL DATA %p %d\n", */ + /* __func__, &pframe[index-tx_desc], (PDRspLength+tx_desc)); */ + + CurtPktPageNum = (u8)PageNum(tx_desc + P2PPDRspLength, page_size); + + *page_num += CurtPktPageNum; + + *total_pkt_len = index + P2PPDRspLength; + + index += (CurtPktPageNum * page_size); + + +} +#endif /* CONFIG_P2P_WOWLAN */ + +#ifdef CONFIG_LPS_PG +#include "hal_halmac.h" + +#define DBG_LPSPG_SEC_DUMP +#define LPS_PG_INFO_RSVD_LEN 16 +#define LPS_PG_INFO_RSVD_PAGE_NUM 1 + +#define DBG_LPSPG_INFO_DUMP +static void rtw_hal_set_lps_pg_info_rsvd_page(_adapter *adapter) +{ + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter); + struct sta_info *psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(&adapter->mlmepriv)); + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + PHAL_DATA_TYPE phal_data = GET_HAL_DATA(adapter); + u8 lps_pg_info[LPS_PG_INFO_RSVD_LEN] = {0}; +#ifdef CONFIG_MBSSID_CAM + u8 cam_id = INVALID_CAM_ID; +#endif + u8 *psec_cam_id = lps_pg_info + 8; + u8 sec_cam_num = 0; + + if (!psta) { + RTW_ERR("%s [ERROR] sta is NULL\n", __func__); + rtw_warn_on(1); + return; + } + + /*Byte 0 - used macid*/ + LPSPG_RSVD_PAGE_SET_MACID(lps_pg_info, psta->mac_id); + RTW_INFO("[LPSPG-INFO] mac_id:%d\n", psta->mac_id); + +#ifdef CONFIG_MBSSID_CAM + /*Byte 1 - used BSSID CAM entry*/ + cam_id = rtw_mbid_cam_search_by_ifaceid(adapter, adapter->iface_id); + if (cam_id != INVALID_CAM_ID) + LPSPG_RSVD_PAGE_SET_MBSSCAMID(lps_pg_info, cam_id); + RTW_INFO("[LPSPG-INFO] mbss_cam_id:%d\n", cam_id); +#endif + +#ifdef CONFIG_WOWLAN /*&& pattern match cam used*/ + /*Btye 2 - Max used Pattern Match CAM entry*/ + if (pwrpriv->wowlan_mode == true && + check_fwstate(&adapter->mlmepriv, _FW_LINKED) == true) { + LPSPG_RSVD_PAGE_SET_PMC_NUM(lps_pg_info, pwrpriv->wowlan_pattern_idx); + RTW_INFO("[LPSPG-INFO] Max Pattern Match CAM entry :%d\n", pwrpriv->wowlan_pattern_idx); + } +#endif +#ifdef CONFIG_BEAMFORMING /*&& MU BF*/ + /*Btye 3 - Max MU rate table Group ID*/ + LPSPG_RSVD_PAGE_SET_MU_RAID_GID(lps_pg_info, _value); + RTW_INFO("[LPSPG-INFO] Max MU rate table Group ID :%d\n", _value); +#endif + + /*Btye 8 ~15 - used Security CAM entry */ + sec_cam_num = rtw_get_sec_camid(adapter, 8, psec_cam_id); + + /*Btye 4 - used Security CAM entry number*/ + if (sec_cam_num < 8) + LPSPG_RSVD_PAGE_SET_SEC_CAM_NUM(lps_pg_info, sec_cam_num); + RTW_INFO("[LPSPG-INFO] Security CAM entry number :%d\n", sec_cam_num); + + /*Btye 5 - Txbuf used page number for fw offload*/ + LPSPG_RSVD_PAGE_SET_DRV_RSVDPAGE_NUM(lps_pg_info, phal_data->drv_rsvd_page_number); + RTW_INFO("[LPSPG-INFO] DRV's rsvd page numbers :%d\n", phal_data->drv_rsvd_page_number); + +#ifdef DBG_LPSPG_SEC_DUMP + { + int i; + + for (i = 0; i < sec_cam_num; i++) + RTW_INFO("%d = sec_cam_id:%d\n", i, psec_cam_id[i]); + } +#endif + +#ifdef DBG_LPSPG_INFO_DUMP + RTW_INFO("==== DBG_LPSPG_INFO_RSVD_PAGE_DUMP====\n"); + RTW_INFO(" %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", + *(lps_pg_info), *(lps_pg_info + 1), *(lps_pg_info + 2), *(lps_pg_info + 3), + *(lps_pg_info + 4), *(lps_pg_info + 5), *(lps_pg_info + 6), *(lps_pg_info + 7)); + RTW_INFO(" %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", + *(lps_pg_info + 8), *(lps_pg_info + 9), *(lps_pg_info + 10), *(lps_pg_info + 11), + *(lps_pg_info + 12), *(lps_pg_info + 13), *(lps_pg_info + 14), *(lps_pg_info + 15)); + RTW_INFO("==== DBG_LPSPG_INFO_RSVD_PAGE_DUMP====\n"); +#endif + + rtw_halmac_download_rsvd_page(dvobj, pwrpriv->lpspg_rsvd_page_locate, lps_pg_info, LPS_PG_INFO_RSVD_LEN); + +#ifdef DBG_LPSPG_INFO_DUMP + RTW_INFO("Get LPS-PG INFO from rsvd page_offset:%d\n", pwrpriv->lpspg_rsvd_page_locate); + rtw_dump_rsvd_page(RTW_DBGDUMP, adapter, pwrpriv->lpspg_rsvd_page_locate, 1); +#endif +} + + +static u8 rtw_hal_set_lps_pg_info_cmd(_adapter *adapter) +{ + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter); + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + + u8 lpspg_info[H2C_LPS_PG_INFO_LEN] = {0}; + u8 ret = _FAIL; + + RTW_INFO("%s: loc_lpspg_info:%d\n", __func__, pwrpriv->lpspg_rsvd_page_locate); + + if (_NO_PRIVACY_ != adapter->securitypriv.dot11PrivacyAlgrthm) + SET_H2CCMD_LPSPG_SEC_CAM_EN(lpspg_info, 1); /*SecurityCAM_En*/ +#ifdef CONFIG_MBSSID_CAM + SET_H2CCMD_LPSPG_MBID_CAM_EN(lpspg_info, 1); /*BSSIDCAM_En*/ +#endif + +#if defined(CONFIG_WOWLAN) && defined(CONFIG_WOW_PATTERN_HW_CAM) + if (pwrpriv->wowlan_mode == true && + check_fwstate(pmlmepriv, _FW_LINKED) == true) { + + SET_H2CCMD_LPSPG_PMC_CAM_EN(lpspg_info, 1); /*PatternMatchCAM_En*/ + } +#endif + +#ifdef CONFIG_MACID_SEARCH + SET_H2CCMD_LPSPG_MACID_SEARCH_EN(lpspg_info, 1); /*MACIDSearch_En*/ +#endif + +#ifdef CONFIG_TX_SC + SET_H2CCMD_LPSPG_TXSC_EN(lpspg_info, 1); /*TXSC_En*/ +#endif + +#ifdef CONFIG_BEAMFORMING /*&& MU BF*/ + SET_H2CCMD_LPSPG_MU_RATE_TB_EN(lpspg_info, 1); /*MURateTable_En*/ +#endif + + SET_H2CCMD_LPSPG_LOC(lpspg_info, pwrpriv->lpspg_rsvd_page_locate); + +#ifdef DBG_LPSPG_INFO_DUMP + RTW_INFO("==== DBG_LPSPG_INFO_CMD_DUMP====\n"); + RTW_INFO(" H2C_CMD: 0x%02x, H2C_LEN: %d\n", H2C_LPS_PG_INFO, H2C_LPS_PG_INFO_LEN); + RTW_INFO(" %02X:%02X\n", *(lpspg_info), *(lpspg_info + 1)); + RTW_INFO("==== DBG_LPSPG_INFO_CMD_DUMP====\n"); +#endif + + ret = rtw_hal_fill_h2c_cmd(adapter, + H2C_LPS_PG_INFO, + H2C_LPS_PG_INFO_LEN, + lpspg_info); + return ret; +} +u8 rtw_hal_set_lps_pg_info(_adapter *adapter) +{ + u8 ret = _FAIL; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter); + + if (pwrpriv->lpspg_rsvd_page_locate == 0) { + RTW_ERR("%s [ERROR] lpspg_rsvd_page_locate = 0\n", __func__); + rtw_warn_on(1); + return ret; + } + + rtw_hal_set_lps_pg_info_rsvd_page(adapter); + ret = rtw_hal_set_lps_pg_info_cmd(adapter); + if (_SUCCESS == ret) + pwrpriv->blpspg_info_up = false; + + return ret; +} + +void rtw_hal_lps_pg_handler(_adapter *adapter, enum lps_pg_hdl_id hdl_id) +{ + switch (hdl_id) { + case LPS_PG_INFO_CFG: + rtw_hal_set_lps_pg_info(adapter); + break; + case LPS_PG_REDLEMEM: + /*rtw_halmac_redl_fw();*/ + break; + + case LPS_PG_RESEND_H2C: + { + struct macid_ctl_t *macid_ctl = &adapter->dvobj->macid_ctl; + struct sta_info *sta; + PHAL_DATA_TYPE hal_data = GET_HAL_DATA(adapter); + int i; + + for (i = 0; i < MACID_NUM_SW_LIMIT; i++) { + sta = macid_ctl->sta[i]; + if (sta && !is_broadcast_mac_addr(sta->hwaddr)) { + /*rtw_dm_ra_mask_hdl(adapter, sta);*/ + /*phydm_rssi_report(hal_data->odmpriv, sta->mac_id);*/ + } + } + } + break; + + default: + break; + } +} + +#endif /*CONFIG_LPS_PG*/ + +/* + * Description: Fill the reserved packets that FW will use to RSVD page. + * Now we just send 4 types packet to rsvd page. + * (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. + * Input: + * finished - false:At the first time we will send all the packets as a large packet to Hw, + * so we need to set the packet length to total lengh. + * true: At the second time, we should send the first packet (default:beacon) + * to Hw again and set the lengh in descriptor to the real beacon lengh. + * 2009.10.15 by tynli. + * + * Page Size = 128: 8188e, 8723a/b, 8192c/d, + * Page Size = 256: 8192e, 8821a + * Page Size = 512: 8812a + */ + +/*#define DBG_DUMP_SET_RSVD_PAGE*/ +void rtw_hal_set_fw_rsvd_page(_adapter *adapter, bool finished) +{ + PHAL_DATA_TYPE pHalData; + struct xmit_frame *pcmdframe; + struct pkt_attrib *pattrib; + struct xmit_priv *pxmitpriv; + struct mlme_ext_priv *pmlmeext; + struct mlme_ext_info *pmlmeinfo; + struct pwrctrl_priv *pwrctl; + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct hal_ops *pHalFunc = &adapter->hal_func; + u32 BeaconLength = 0, ProbeRspLength = 0, PSPollLength = 0; + u32 NullDataLength = 0, QosNullLength = 0, BTQosNullLength = 0; + u32 ProbeReqLength = 0, NullFunctionDataLength = 0; + u8 TxDescLen = TXDESC_SIZE, TxDescOffset = TXDESC_OFFSET; + u8 TotalPageNum = 0 , CurtPktPageNum = 0 , RsvdPageNum = 0; + u8 *ReservedPagePacket; + u16 BufIndex = 0; + u32 TotalPacketLen = 0, MaxRsvdPageBufSize = 0, PageSize = 0; + RSVDPAGE_LOC RsvdPageLoc; + +#ifdef DBG_CONFIG_ERROR_DETECT + struct sreset_priv *psrtpriv; +#endif /* DBG_CONFIG_ERROR_DETECT */ + +#ifdef CONFIG_MCC_MODE + u8 dl_mcc_page = _FAIL; +#endif /* CONFIG_MCC_MODE */ + + pHalData = GET_HAL_DATA(adapter); +#ifdef DBG_CONFIG_ERROR_DETECT + psrtpriv = &pHalData->srestpriv; +#endif + pxmitpriv = &adapter->xmitpriv; + pmlmeext = &adapter->mlmeextpriv; + pmlmeinfo = &pmlmeext->mlmext_info; + pwrctl = adapter_to_pwrctl(adapter); + + rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, (u8 *)&PageSize); + + if (PageSize == 0) { + RTW_INFO("[Error]: %s, PageSize is zero!!\n", __func__); + return; + } + + if (pwrctl->wowlan_mode == true || pwrctl->wowlan_ap_mode == true) + RsvdPageNum = rtw_hal_get_txbuff_rsvd_page_num(adapter, true); + else + RsvdPageNum = rtw_hal_get_txbuff_rsvd_page_num(adapter, false); + + RTW_INFO("%s PageSize: %d, RsvdPageNUm: %d\n", __func__, PageSize, RsvdPageNum); + + MaxRsvdPageBufSize = RsvdPageNum * PageSize; + + if (MaxRsvdPageBufSize > MAX_CMDBUF_SZ) { + RTW_INFO("%s MaxRsvdPageBufSize(%d) is larger than MAX_CMDBUF_SZ(%d)", + __func__, MaxRsvdPageBufSize, MAX_CMDBUF_SZ); + rtw_warn_on(1); + return; + } + + pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv); + + if (pcmdframe == NULL) { + RTW_INFO("%s: alloc ReservedPagePacket fail!\n", __func__); + return; + } + + ReservedPagePacket = pcmdframe->buf_addr; + memset(&RsvdPageLoc, 0, sizeof(RSVDPAGE_LOC)); + + /* beacon * 2 pages */ + BufIndex = TxDescOffset; + rtw_hal_construct_beacon(adapter, + &ReservedPagePacket[BufIndex], &BeaconLength); + + /* + * When we count the first page size, we need to reserve description size for the RSVD + * packet, it will be filled in front of the packet in TXPKTBUF. + */ + CurtPktPageNum = (u8)PageNum((TxDescLen + BeaconLength), PageSize); + /* If we don't add 1 more page, ARP offload function will fail at 8723bs.*/ + if (CurtPktPageNum == 1) + CurtPktPageNum += 1; + + TotalPageNum += CurtPktPageNum; + + BufIndex += (CurtPktPageNum * PageSize); + + if (pwrctl->wowlan_ap_mode == true) { + /* (4) probe response*/ + RsvdPageLoc.LocProbeRsp = TotalPageNum; + rtw_hal_construct_ProbeRsp( + adapter, &ReservedPagePacket[BufIndex], + &ProbeRspLength, + get_my_bssid(&pmlmeinfo->network), false); + rtw_hal_fill_fake_txdesc(adapter, + &ReservedPagePacket[BufIndex - TxDescLen], + ProbeRspLength, false, false, false); + + CurtPktPageNum = (u8)PageNum(TxDescLen + ProbeRspLength, PageSize); + TotalPageNum += CurtPktPageNum; + TotalPacketLen = BufIndex + ProbeRspLength; + BufIndex += (CurtPktPageNum * PageSize); + goto download_page; + } + + /* ps-poll * 1 page */ + RsvdPageLoc.LocPsPoll = TotalPageNum; + RTW_INFO("LocPsPoll: %d\n", RsvdPageLoc.LocPsPoll); + rtw_hal_construct_PSPoll(adapter, + &ReservedPagePacket[BufIndex], &PSPollLength); + rtw_hal_fill_fake_txdesc(adapter, + &ReservedPagePacket[BufIndex - TxDescLen], + PSPollLength, true, false, false); + + CurtPktPageNum = (u8)PageNum((TxDescLen + PSPollLength), PageSize); + + TotalPageNum += CurtPktPageNum; + + BufIndex += (CurtPktPageNum * PageSize); + +#ifdef CONFIG_BT_COEXIST + /* BT Qos null data * 1 page */ + RsvdPageLoc.LocBTQosNull = TotalPageNum; + RTW_INFO("LocBTQosNull: %d\n", RsvdPageLoc.LocBTQosNull); + rtw_hal_construct_NullFunctionData( + adapter, + &ReservedPagePacket[BufIndex], + &BTQosNullLength, + get_my_bssid(&pmlmeinfo->network), + true, 0, 0, false); + rtw_hal_fill_fake_txdesc(adapter, + &ReservedPagePacket[BufIndex - TxDescLen], + BTQosNullLength, false, true, false); + + CurtPktPageNum = (u8)PageNum(TxDescLen + BTQosNullLength, PageSize); + + TotalPageNum += CurtPktPageNum; + + BufIndex += (CurtPktPageNum * PageSize); +#endif /* CONFIG_BT_COEXIT */ + +#ifdef CONFIG_MCC_MODE + if (MCC_EN(adapter)) { + dl_mcc_page = rtw_hal_dl_mcc_fw_rsvd_page(adapter, ReservedPagePacket, + &BufIndex, TxDescLen, PageSize, + &TotalPageNum, &TotalPacketLen, &RsvdPageLoc); + } else + dl_mcc_page = _FAIL; + + if (dl_mcc_page == _FAIL) { +#endif /* CONFIG_MCC_MODE */ + + /* null data * 1 page */ + RsvdPageLoc.LocNullData = TotalPageNum; + RTW_INFO("LocNullData: %d\n", RsvdPageLoc.LocNullData); + rtw_hal_construct_NullFunctionData( + adapter, + &ReservedPagePacket[BufIndex], + &NullDataLength, + get_my_bssid(&pmlmeinfo->network), + false, 0, 0, false); + rtw_hal_fill_fake_txdesc(adapter, + &ReservedPagePacket[BufIndex - TxDescLen], + NullDataLength, false, false, false); + + CurtPktPageNum = (u8)PageNum(TxDescLen + NullDataLength, PageSize); + + TotalPageNum += CurtPktPageNum; + + BufIndex += (CurtPktPageNum * PageSize); +#ifdef CONFIG_MCC_MODE + } +#endif /* CONFIG_MCC_MODE */ + + /* Qos null data * 1 page */ + RsvdPageLoc.LocQosNull = TotalPageNum; + RTW_INFO("LocQosNull: %d\n", RsvdPageLoc.LocQosNull); + rtw_hal_construct_NullFunctionData( + adapter, + &ReservedPagePacket[BufIndex], + &QosNullLength, + get_my_bssid(&pmlmeinfo->network), + true, 0, 0, false); + rtw_hal_fill_fake_txdesc(adapter, + &ReservedPagePacket[BufIndex - TxDescLen], + QosNullLength, false, false, false); + + CurtPktPageNum = (u8)PageNum(TxDescLen + QosNullLength, PageSize); + + TotalPageNum += CurtPktPageNum; + + TotalPacketLen = BufIndex + QosNullLength; + + BufIndex += (CurtPktPageNum * PageSize); + +#ifdef CONFIG_WOWLAN + if (pwrctl->wowlan_mode == true && + pwrctl->wowlan_in_resume == false) { + rtw_hal_set_wow_fw_rsvd_page(adapter, ReservedPagePacket, + BufIndex, TxDescLen, PageSize, + &TotalPageNum, &TotalPacketLen, &RsvdPageLoc); + } +#endif /* CONFIG_WOWLAN */ + +#ifdef CONFIG_P2P_WOWLAN + if (pwrctl->wowlan_p2p_mode) { + rtw_hal_set_p2p_wow_fw_rsvd_page(adapter, ReservedPagePacket, + BufIndex, TxDescLen, PageSize, + &TotalPageNum, &TotalPacketLen, &RsvdPageLoc); + } +#endif /* CONFIG_P2P_WOWLAN */ + +#ifdef CONFIG_LPS_PG + /* must reserved last 1 x page for LPS PG Info*/ + pwrctl->lpspg_rsvd_page_locate = TotalPageNum; + pwrctl->blpspg_info_up = true; +#endif + +download_page: + /* RTW_INFO("%s BufIndex(%d), TxDescLen(%d), PageSize(%d)\n",__func__, BufIndex, TxDescLen, PageSize);*/ + RTW_INFO("%s PageNum(%d), pktlen(%d)\n", + __func__, TotalPageNum, TotalPacketLen); + +#ifdef CONFIG_LPS_PG + if ((TotalPacketLen + (LPS_PG_INFO_RSVD_PAGE_NUM * PageSize)) > MaxRsvdPageBufSize) { + pwrctl->lpspg_rsvd_page_locate = 0; + pwrctl->blpspg_info_up = false; + + RTW_ERR("%s rsvd page size is not enough!!TotalPacketLen+LPS_PG_INFO_LEN %d, MaxRsvdPageBufSize %d\n", + __func__, (TotalPacketLen + (LPS_PG_INFO_RSVD_PAGE_NUM * PageSize)), MaxRsvdPageBufSize); + rtw_warn_on(1); + } +#endif + + if (TotalPacketLen > MaxRsvdPageBufSize) { + RTW_ERR("%s(ERROR): rsvd page size is not enough!!TotalPacketLen %d, MaxRsvdPageBufSize %d\n", + __func__, TotalPacketLen, MaxRsvdPageBufSize); + rtw_warn_on(1); + goto error; + } else { + /* update attribute */ + pattrib = &pcmdframe->attrib; + update_mgntframe_attrib(adapter, pattrib); + pattrib->qsel = QSLT_BEACON; + pattrib->pktlen = TotalPacketLen - TxDescOffset; + pattrib->last_txcmdsz = TotalPacketLen - TxDescOffset; + dump_mgntframe_and_wait(adapter, pcmdframe, 100); + } + + RTW_INFO("%s: Set RSVD page location to Fw ,TotalPacketLen(%d), TotalPageNum(%d)\n", + __func__, TotalPacketLen, TotalPageNum); +#ifdef DBG_DUMP_SET_RSVD_PAGE + RTW_INFO(" ==================================================\n"); + RTW_INFO_DUMP("\n", ReservedPagePacket, TotalPacketLen); + RTW_INFO(" ==================================================\n"); +#endif + if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { + rtw_hal_set_FwRsvdPage_cmd(adapter, &RsvdPageLoc); +#ifdef CONFIG_WOWLAN + if (pwrctl->wowlan_mode == true && + pwrctl->wowlan_in_resume == false) + rtw_hal_set_FwAoacRsvdPage_cmd(adapter, &RsvdPageLoc); +#endif /* CONFIG_WOWLAN */ +#ifdef CONFIG_AP_WOWLAN + if (pwrctl->wowlan_ap_mode == true) + rtw_hal_set_ap_rsvdpage_loc_cmd(adapter, &RsvdPageLoc); +#endif /* CONFIG_AP_WOWLAN */ + } else if (pwrctl->wowlan_pno_enable) { +#ifdef CONFIG_PNO_SUPPORT + rtw_hal_set_FwAoacRsvdPage_cmd(adapter, &RsvdPageLoc); + if (pwrctl->wowlan_in_resume) + rtw_hal_set_scan_offload_info_cmd(adapter, + &RsvdPageLoc, 0); + else + rtw_hal_set_scan_offload_info_cmd(adapter, + &RsvdPageLoc, 1); +#endif /* CONFIG_PNO_SUPPORT */ + } +#ifdef CONFIG_P2P_WOWLAN + if (pwrctl->wowlan_p2p_mode) + rtw_hal_set_FwP2PRsvdPage_cmd(adapter, &RsvdPageLoc); +#endif /* CONFIG_P2P_WOWLAN */ + return; +error: + rtw_free_xmitframe(pxmitpriv, pcmdframe); +} +static void rtw_hal_set_hw_update_tsf(PADAPTER padapter) +{ + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + +#if defined(CONFIG_MI_WITH_MBSSID_CAM) + RTW_INFO("[Warn] %s "ADPT_FMT" enter func\n", __func__, ADPT_ARG(padapter)); + rtw_warn_on(1); + return; +#endif + + if (!pmlmeext->en_hw_update_tsf) + return; + + /* check REG_RCR bit is set */ + if (!(rtw_read32(padapter, REG_RCR) & RCR_CBSSID_BCN)) + return; + + /* enable hw update tsf function for non-AP */ + if (rtw_linked_check(padapter) && + check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) { +#ifdef CONFIG_CONCURRENT_MODE + if (padapter->hw_port == HW_PORT1) + rtw_write8(padapter, REG_BCN_CTRL_1, rtw_read8(padapter, REG_BCN_CTRL_1) & (~DIS_TSF_UDT)); + else +#endif + rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL) & (~DIS_TSF_UDT)); + } + pmlmeext->en_hw_update_tsf = false; +} + +#ifdef CONFIG_TDLS +#ifdef CONFIG_TDLS_CH_SW +s32 rtw_hal_ch_sw_oper_offload(_adapter *padapter, u8 channel, u8 channel_offset, u16 bwmode) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + u8 ch_sw_h2c_buf[4] = {0x00, 0x00, 0x00, 0x00}; + + + SET_H2CCMD_CH_SW_OPER_OFFLOAD_CH_NUM(ch_sw_h2c_buf, channel); + SET_H2CCMD_CH_SW_OPER_OFFLOAD_BW_MODE(ch_sw_h2c_buf, bwmode); + switch (bwmode) { + case CHANNEL_WIDTH_40: + SET_H2CCMD_CH_SW_OPER_OFFLOAD_BW_40M_SC(ch_sw_h2c_buf, channel_offset); + break; + case CHANNEL_WIDTH_80: + SET_H2CCMD_CH_SW_OPER_OFFLOAD_BW_80M_SC(ch_sw_h2c_buf, channel_offset); + break; + case CHANNEL_WIDTH_20: + default: + break; + } + SET_H2CCMD_CH_SW_OPER_OFFLOAD_RFE_TYPE(ch_sw_h2c_buf, pHalData->rfe_type); + + return rtw_hal_fill_h2c_cmd(padapter, H2C_CHNL_SWITCH_OPER_OFFLOAD, sizeof(ch_sw_h2c_buf), ch_sw_h2c_buf); +} +#endif +#endif + +#ifdef CONFIG_WMMPS +void rtw_hal_update_uapsd_tid(_adapter *adapter) +{ + rtw_write8(adapter, REG_WMMPS_UAPSD_TID, 0xFF); +} +#endif + +#if defined(CONFIG_BT_COEXIST) && defined(CONFIG_FW_MULTI_PORT_SUPPORT) +/* For multi-port support, driver needs to inform the port ID to FW for btc operations */ +s32 rtw_hal_set_wifi_port_id_cmd(_adapter *adapter) +{ + u8 port_id = 0; + u8 h2c_buf[H2C_BTC_WL_PORT_ID_LEN] = {0}; + + SET_H2CCMD_BTC_WL_PORT_ID(h2c_buf, adapter->hw_port); + return rtw_hal_fill_h2c_cmd(adapter, H2C_BTC_WL_PORT_ID, H2C_BTC_WL_PORT_ID_LEN, h2c_buf); +} +#endif + +void SetHwReg(_adapter *adapter, u8 variable, u8 *val) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + + switch (variable) { + case HW_VAR_MEDIA_STATUS: { + u8 net_type = *((u8 *)val); + + rtw_hal_set_msr(adapter, net_type); + } + break; + case HW_VAR_MAC_ADDR: +#ifdef CONFIG_MI_WITH_MBSSID_CAM + rtw_hal_set_macaddr_mbid(adapter, val); +#else + rtw_hal_set_macaddr_port(adapter, val); +#endif + break; + case HW_VAR_BSSID: + rtw_hal_set_bssid(adapter, val); + break; +#ifdef CONFIG_MBSSID_CAM + case HW_VAR_MBSSID_CAM_WRITE: { + u32 cmd = 0; + u32 *cam_val = (u32 *)val; + + rtw_write32(adapter, REG_MBIDCAMCFG_1, cam_val[0]); + cmd = BIT_MBIDCAM_POLL | BIT_MBIDCAM_WT_EN | BIT_MBIDCAM_VALID | cam_val[1]; + rtw_write32(adapter, REG_MBIDCAMCFG_2, cmd); + } + break; + case HW_VAR_MBSSID_CAM_CLEAR: { + u32 cmd; + u8 entry_id = *(u8 *)val; + + rtw_write32(adapter, REG_MBIDCAMCFG_1, 0); + + cmd = BIT_MBIDCAM_POLL | BIT_MBIDCAM_WT_EN | ((entry_id & MBIDCAM_ADDR_MASK) << MBIDCAM_ADDR_SHIFT); + rtw_write32(adapter, REG_MBIDCAMCFG_2, cmd); + } + break; + case HW_VAR_RCR_MBSSID_EN: + if (*((u8 *)val)) + rtw_write32(adapter, REG_RCR, rtw_read32(adapter, REG_RCR) | RCR_ENMBID); + else { + u32 val32; + + val32 = rtw_read32(adapter, REG_RCR); + val32 &= ~(RCR_ENMBID); + rtw_write32(adapter, REG_RCR, val32); + } + break; +#endif + case HW_VAR_PORT_SWITCH: + hw_var_port_switch(adapter); + break; + case HW_VAR_INIT_RTS_RATE: { + u16 brate_cfg = *((u16 *)val); + u8 rate_index = 0; + HAL_VERSION *hal_ver = &hal_data->version_id; + + if (IS_8188E(*hal_ver)) { + + while (brate_cfg > 0x1) { + brate_cfg = (brate_cfg >> 1); + rate_index++; + } + rtw_write8(adapter, REG_INIRTS_RATE_SEL, rate_index); + } else + rtw_warn_on(1); + } + break; + case HW_VAR_SEC_CFG: { + u16 reg_scr_ori; + u16 reg_scr; + + reg_scr = reg_scr_ori = rtw_read16(adapter, REG_SECCFG); + reg_scr |= (SCR_CHK_KEYID | SCR_RxDecEnable | SCR_TxEncEnable); + + if (_rtw_camctl_chk_cap(adapter, SEC_CAP_CHK_BMC)) + reg_scr |= SCR_CHK_BMC; + + if (_rtw_camctl_chk_flags(adapter, SEC_STATUS_STA_PK_GK_CONFLICT_DIS_BMC_SEARCH)) + reg_scr |= SCR_NoSKMC; + + if (reg_scr != reg_scr_ori) + rtw_write16(adapter, REG_SECCFG, reg_scr); + } + break; + case HW_VAR_SEC_DK_CFG: { + struct security_priv *sec = &adapter->securitypriv; + u8 reg_scr = rtw_read8(adapter, REG_SECCFG); + + if (val) { /* Enable default key related setting */ + reg_scr |= SCR_TXBCUSEDK; + if (sec->dot11AuthAlgrthm != dot11AuthAlgrthm_8021X) + reg_scr |= (SCR_RxUseDK | SCR_TxUseDK); + } else /* Disable default key related setting */ + reg_scr &= ~(SCR_RXBCUSEDK | SCR_TXBCUSEDK | SCR_RxUseDK | SCR_TxUseDK); + + rtw_write8(adapter, REG_SECCFG, reg_scr); + } + break; + + case HW_VAR_ASIX_IOT: + /* enable ASIX IOT function */ + if (*((u8 *)val) == true) { + /* 0xa2e[0]=0 (disable rake receiver) */ + rtw_write8(adapter, rCCK0_FalseAlarmReport + 2, + rtw_read8(adapter, rCCK0_FalseAlarmReport + 2) & ~(BIT0)); + /* 0xa1c=0xa0 (reset channel estimation if signal quality is bad) */ + rtw_write8(adapter, rCCK0_DSPParameter2, 0xa0); + } else { + /* restore reg:0xa2e, reg:0xa1c */ + rtw_write8(adapter, rCCK0_FalseAlarmReport + 2, + rtw_read8(adapter, rCCK0_FalseAlarmReport + 2) | (BIT0)); + rtw_write8(adapter, rCCK0_DSPParameter2, 0x00); + } + break; +#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) + case HW_VAR_WOWLAN: { + struct wowlan_ioctl_param *poidparam; + + poidparam = (struct wowlan_ioctl_param *)val; + switch (poidparam->subcode) { +#ifdef CONFIG_WOWLAN + case WOWLAN_PATTERN_CLEAN: + rtw_hal_dl_pattern(adapter, 2); + break; + case WOWLAN_ENABLE: + rtw_hal_wow_enable(adapter); + break; + case WOWLAN_DISABLE: + rtw_hal_wow_disable(adapter); + break; +#endif /*CONFIG_WOWLAN*/ +#ifdef CONFIG_AP_WOWLAN + case WOWLAN_AP_ENABLE: + rtw_hal_ap_wow_enable(adapter); + break; + case WOWLAN_AP_DISABLE: + rtw_hal_ap_wow_disable(adapter); + break; +#endif /*CONFIG_AP_WOWLAN*/ + default: + break; + } + } + break; +#endif /*defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)*/ + + case HW_VAR_EN_HW_UPDATE_TSF: + rtw_hal_set_hw_update_tsf(adapter); + break; + + case HW_VAR_APFM_ON_MAC: + hal_data->bMacPwrCtrlOn = *val; + RTW_INFO("%s: bMacPwrCtrlOn=%d\n", __func__, hal_data->bMacPwrCtrlOn); + break; +#ifdef CONFIG_WMMPS + case HW_VAR_UAPSD_TID: + rtw_hal_update_uapsd_tid(adapter); + break; +#endif +#ifdef CONFIG_LPS_PG + case HW_VAR_LPS_PG_HANDLE: + rtw_hal_lps_pg_handler(adapter, *val); + break; +#endif + + default: + if (0) + RTW_PRINT(FUNC_ADPT_FMT" variable(%d) not defined!\n", + FUNC_ADPT_ARG(adapter), variable); + break; + } + +} + +void GetHwReg(_adapter *adapter, u8 variable, u8 *val) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + + + switch (variable) { + case HW_VAR_BASIC_RATE: + *((u16 *)val) = hal_data->BasicRateSet; + break; + case HW_VAR_RF_TYPE: + *((u8 *)val) = hal_data->rf_type; + break; + case HW_VAR_MEDIA_STATUS: + rtw_hal_get_msr(adapter, val); + break; + case HW_VAR_DO_IQK: + *val = hal_data->bNeedIQK; + break; + case HW_VAR_CH_SW_NEED_TO_TAKE_CARE_IQK_INFO: + if (hal_is_band_support(adapter, BAND_ON_5G)) + *val = true; + else + *val = false; + break; + case HW_VAR_APFM_ON_MAC: + *val = hal_data->bMacPwrCtrlOn; + break; + default: + if (0) + RTW_PRINT(FUNC_ADPT_FMT" variable(%d) not defined!\n", + FUNC_ADPT_ARG(adapter), variable); + break; + } + +} + +u8 +SetHalDefVar(_adapter *adapter, HAL_DEF_VARIABLE variable, void *value) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + u8 bResult = _SUCCESS; + + switch (variable) { + + case HAL_DEF_DBG_DUMP_RXPKT: + hal_data->bDumpRxPkt = *((u8 *)value); + break; + case HAL_DEF_DBG_DUMP_TXPKT: + hal_data->bDumpTxPkt = *((u8 *)value); + break; + case HAL_DEF_ANT_DETECT: + hal_data->AntDetection = *((u8 *)value); + break; + case HAL_DEF_DBG_DIS_PWT: + hal_data->bDisableTXPowerTraining = *((u8 *)value); + break; + default: + RTW_PRINT("%s: [WARNING] HAL_DEF_VARIABLE(%d) not defined!\n", __func__, variable); + bResult = _FAIL; + break; + } + + return bResult; +} + +#ifdef CONFIG_BEAMFORMING +u8 rtw_hal_query_txbfer_rf_num(_adapter *adapter) +{ + struct registry_priv *pregistrypriv = &adapter->registrypriv; + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + + return 1; + +} +u8 rtw_hal_query_txbfee_rf_num(_adapter *adapter) +{ + struct registry_priv *pregistrypriv = &adapter->registrypriv; + struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + + return 1; +} +#endif + +u8 +GetHalDefVar(_adapter *adapter, HAL_DEF_VARIABLE variable, void *value) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + u8 bResult = _SUCCESS; + + switch (variable) { + case HAL_DEF_UNDERCORATEDSMOOTHEDPWDB: { + struct mlme_priv *pmlmepriv; + struct sta_priv *pstapriv; + struct sta_info *psta; + + pmlmepriv = &adapter->mlmepriv; + pstapriv = &adapter->stapriv; + psta = rtw_get_stainfo(pstapriv, pmlmepriv->cur_network.network.MacAddress); + if (psta) + *((int *)value) = psta->rssi_stat.undecorated_smoothed_pwdb; + } + break; + case HAL_DEF_DBG_DUMP_RXPKT: + *((u8 *)value) = hal_data->bDumpRxPkt; + break; + case HAL_DEF_DBG_DUMP_TXPKT: + *((u8 *)value) = hal_data->bDumpTxPkt; + break; + case HAL_DEF_ANT_DETECT: + *((u8 *)value) = hal_data->AntDetection; + break; + case HAL_DEF_MACID_SLEEP: + *(u8 *)value = false; + break; + case HAL_DEF_TX_PAGE_SIZE: + *((u32 *)value) = PAGE_SIZE_128; + break; + case HAL_DEF_DBG_DIS_PWT: + *(u8 *)value = hal_data->bDisableTXPowerTraining; + break; + case HAL_DEF_EXPLICIT_BEAMFORMER: + case HAL_DEF_EXPLICIT_BEAMFORMEE: + case HAL_DEF_VHT_MU_BEAMFORMER: + case HAL_DEF_VHT_MU_BEAMFORMEE: + *(u8 *)value = false; + break; +#ifdef CONFIG_BEAMFORMING + case HAL_DEF_BEAMFORMER_CAP: + *(u8 *)value = rtw_hal_query_txbfer_rf_num(adapter); + break; + case HAL_DEF_BEAMFORMEE_CAP: + *(u8 *)value = rtw_hal_query_txbfee_rf_num(adapter); + break; +#endif + default: + RTW_PRINT("%s: [WARNING] HAL_DEF_VARIABLE(%d) not defined!\n", __func__, variable); + bResult = _FAIL; + break; + } + + return bResult; +} + +void SetHalODMVar( + PADAPTER Adapter, + HAL_ODM_VARIABLE eVariable, + void * pValue1, + bool bSet) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + struct PHY_DM_STRUCT *podmpriv = &pHalData->odmpriv; + /* unsigned long irqL; */ + switch (eVariable) { + case HAL_ODM_STA_INFO: { + struct sta_info *psta = (struct sta_info *)pValue1; + if (bSet) { + RTW_INFO("### Set STA_(%d) info ###\n", psta->mac_id); + odm_cmn_info_ptr_array_hook(podmpriv, ODM_CMNINFO_STA_STATUS, psta->mac_id, psta); + } else { + RTW_INFO("### Clean STA_(%d) info ###\n", psta->mac_id); + /* _enter_critical_bh(&pHalData->odm_stainfo_lock, &irqL); */ + psta->rssi_level = 0; + odm_cmn_info_ptr_array_hook(podmpriv, ODM_CMNINFO_STA_STATUS, psta->mac_id, NULL); + + /* _exit_critical_bh(&pHalData->odm_stainfo_lock, &irqL); */ + } + } + break; + case HAL_ODM_P2P_STATE: + odm_cmn_info_update(podmpriv, ODM_CMNINFO_WIFI_DIRECT, bSet); + break; + case HAL_ODM_WIFI_DISPLAY_STATE: + odm_cmn_info_update(podmpriv, ODM_CMNINFO_WIFI_DISPLAY, bSet); + break; + case HAL_ODM_REGULATION: + odm_cmn_info_init(podmpriv, ODM_CMNINFO_DOMAIN_CODE_2G, pHalData->Regulation2_4G); + odm_cmn_info_init(podmpriv, ODM_CMNINFO_DOMAIN_CODE_5G, pHalData->Regulation5G); + break; +#if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR) + case HAL_ODM_NOISE_MONITOR: { + struct noise_info *pinfo = (struct noise_info *)pValue1; + +#ifdef DBG_NOISE_MONITOR + RTW_INFO("### Noise monitor chan(%d)-bPauseDIG:%d,IGIValue:0x%02x,max_time:%d (ms) ###\n", + pinfo->chan, pinfo->bPauseDIG, pinfo->IGIValue, pinfo->max_time); +#endif + + pHalData->noise[pinfo->chan] = odm_inband_noise_monitor(podmpriv, pinfo->is_pause_dig, pinfo->igi_value, pinfo->max_time); + RTW_INFO("chan_%d, noise = %d (dBm)\n", pinfo->chan, pHalData->noise[pinfo->chan]); +#ifdef DBG_NOISE_MONITOR + RTW_INFO("noise_a = %d, noise_b = %d noise_all:%d\n", + podmpriv->noise_level.noise[ODM_RF_PATH_A], + podmpriv->noise_level.noise[ODM_RF_PATH_B], + podmpriv->noise_level.noise_all); +#endif + } + break; +#endif/*#ifdef CONFIG_BACKGROUND_NOISE_MONITOR*/ + + case HAL_ODM_INITIAL_GAIN: { + u8 rx_gain = *((u8 *)(pValue1)); + /*printk("rx_gain:%x\n",rx_gain);*/ + if (rx_gain == 0xff) {/*restore rx gain*/ + /*odm_write_dig(podmpriv,pDigTable->backup_ig_value);*/ + odm_pause_dig(podmpriv, PHYDM_RESUME, PHYDM_PAUSE_LEVEL_0, rx_gain); + } else { + /*pDigTable->backup_ig_value = pDigTable->cur_ig_value;*/ + /*odm_write_dig(podmpriv,rx_gain);*/ + odm_pause_dig(podmpriv, PHYDM_PAUSE, PHYDM_PAUSE_LEVEL_0, rx_gain); + } + } + break; + case HAL_ODM_FA_CNT_DUMP: + if (*((u8 *)pValue1)) + podmpriv->debug_components |= (ODM_COMP_DIG | ODM_COMP_FA_CNT); + else + podmpriv->debug_components &= ~(ODM_COMP_DIG | ODM_COMP_FA_CNT); + break; + case HAL_ODM_DBG_FLAG: + odm_cmn_info_update(podmpriv, ODM_CMNINFO_DBG_COMP, *((u64 *)pValue1)); + break; + case HAL_ODM_DBG_LEVEL: + odm_cmn_info_update(podmpriv, ODM_CMNINFO_DBG_LEVEL, *((u32 *)pValue1)); + break; + case HAL_ODM_RX_INFO_DUMP: { + struct false_ALARM_STATISTICS *false_alm_cnt = (struct false_ALARM_STATISTICS *)phydm_get_structure(podmpriv , PHYDMfalseALMCNT); + struct _dynamic_initial_gain_threshold_ *pDM_DigTable = &podmpriv->dm_dig_table; + void *sel; + + sel = pValue1; + + _RTW_PRINT_SEL(sel , "============ Rx Info dump ===================\n"); + _RTW_PRINT_SEL(sel , "is_linked = %d, rssi_min = %d(%%), current_igi = 0x%x\n", podmpriv->is_linked, podmpriv->rssi_min, pDM_DigTable->cur_ig_value); + _RTW_PRINT_SEL(sel , "cnt_cck_fail = %d, cnt_ofdm_fail = %d, Total False Alarm = %d\n", false_alm_cnt->cnt_cck_fail, false_alm_cnt->cnt_ofdm_fail, false_alm_cnt->cnt_all); + + if (podmpriv->is_linked) { + _RTW_PRINT_SEL(sel , "rx_rate = %s", HDATA_RATE(podmpriv->rx_rate)); + _RTW_PRINT_SEL(sel , " RSSI_A = %d(%%), RSSI_B = %d(%%)\n", podmpriv->RSSI_A, podmpriv->RSSI_B); +#ifdef DBG_RX_SIGNAL_DISPLAY_RAW_DATA + rtw_dump_raw_rssi_info(Adapter, sel); +#endif + } + } + break; + case HAL_ODM_RX_Dframe_INFO: { + void *sel; + + sel = pValue1; + + /*_RTW_PRINT_SEL(sel , "HAL_ODM_RX_Dframe_INFO\n");*/ +#ifdef DBG_RX_DFRAME_RAW_DATA + rtw_dump_rx_dframe_info(Adapter, sel); +#endif + } + break; + +#ifdef CONFIG_AUTO_CHNL_SEL_NHM + case HAL_ODM_AUTO_CHNL_SEL: { + ACS_OP acs_op = *(ACS_OP *)pValue1; + + rtw_phydm_func_set(Adapter, ODM_BB_NHM_CNT); + + if (ACS_INIT == acs_op) { +#ifdef DBG_AUTO_CHNL_SEL_NHM + RTW_INFO("[ACS-"ADPT_FMT"] HAL_ODM_AUTO_CHNL_SEL: ACS_INIT\n", ADPT_ARG(Adapter)); +#endif + odm_AutoChannelSelectInit(podmpriv); + } else if (ACS_RESET == acs_op) { + /* Reset statistics for auto channel selection mechanism.*/ +#ifdef DBG_AUTO_CHNL_SEL_NHM + RTW_INFO("[ACS-"ADPT_FMT"] HAL_ODM_AUTO_CHNL_SEL: ACS_RESET\n", ADPT_ARG(Adapter)); +#endif + odm_auto_channel_select_reset(podmpriv); + + } else if (ACS_SELECT == acs_op) { + /* Collect NHM measurement result after current channel */ +#ifdef DBG_AUTO_CHNL_SEL_NHM + RTW_INFO("[ACS-"ADPT_FMT"] HAL_ODM_AUTO_CHNL_SEL: ACS_SELECT, CH(%d)\n", ADPT_ARG(Adapter), rtw_get_acs_channel(Adapter)); +#endif + odm_AutoChannelSelect(podmpriv, rtw_get_acs_channel(Adapter)); + } else + RTW_INFO("[ACS-"ADPT_FMT"] HAL_ODM_AUTO_CHNL_SEL: Unexpected OP\n", ADPT_ARG(Adapter)); + + } + break; +#endif +#ifdef CONFIG_ANTENNA_DIVERSITY + case HAL_ODM_ANTDIV_SELECT: { + u8 antenna = (*(u8 *)pValue1); + + /*switch antenna*/ + odm_update_rx_idle_ant(&pHalData->odmpriv, antenna); + /*RTW_INFO("==> HAL_ODM_ANTDIV_SELECT, Ant_(%s)\n", (antenna == MAIN_ANT) ? "MAIN_ANT" : "AUX_ANT");*/ + + } + break; +#endif + + default: + break; + } +} + +void GetHalODMVar( + PADAPTER Adapter, + HAL_ODM_VARIABLE eVariable, + void * pValue1, + void * pValue2) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + struct PHY_DM_STRUCT *podmpriv = &pHalData->odmpriv; + + switch (eVariable) { +#if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR) + case HAL_ODM_NOISE_MONITOR: { + u8 chan = *(u8 *)pValue1; + *(s16 *)pValue2 = pHalData->noise[chan]; +#ifdef DBG_NOISE_MONITOR + RTW_INFO("### Noise monitor chan(%d)-noise:%d (dBm) ###\n", + chan, pHalData->noise[chan]); +#endif + } + break; +#endif/*#ifdef CONFIG_BACKGROUND_NOISE_MONITOR*/ + case HAL_ODM_DBG_FLAG: + *((u64 *)pValue1) = podmpriv->debug_components; + break; + case HAL_ODM_DBG_LEVEL: + *((u32 *)pValue1) = podmpriv->debug_level; + break; + +#ifdef CONFIG_AUTO_CHNL_SEL_NHM + case HAL_ODM_AUTO_CHNL_SEL: { +#ifdef DBG_AUTO_CHNL_SEL_NHM + RTW_INFO("[ACS-"ADPT_FMT"] HAL_ODM_AUTO_CHNL_SEL: GET_BEST_CHAN\n", ADPT_ARG(Adapter)); +#endif + /* Retrieve better channel from NHM mechanism */ + if (IsSupported24G(Adapter->registrypriv.wireless_mode)) + *((u8 *)(pValue1)) = odm_get_auto_channel_select_result(podmpriv, BAND_ON_2_4G); + if (is_supported_5g(Adapter->registrypriv.wireless_mode)) + *((u8 *)(pValue2)) = odm_get_auto_channel_select_result(podmpriv, BAND_ON_5G); + } + break; +#endif +#ifdef CONFIG_ANTENNA_DIVERSITY + case HAL_ODM_ANTDIV_SELECT: { + struct _FAST_ANTENNA_TRAINNING_ *pDM_FatTable = &podmpriv->dm_fat_table; + *((u8 *)pValue1) = pDM_FatTable->rx_idle_ant; + } + break; +#endif + case HAL_ODM_INITIAL_GAIN: { + struct _dynamic_initial_gain_threshold_ *pDM_DigTable = &podmpriv->dm_dig_table; + *((u8 *)pValue1) = pDM_DigTable->cur_ig_value; + } + break; + default: + break; + } +} + + +u32 rtw_phydm_ability_ops(_adapter *adapter, HAL_PHYDM_OPS ops, u32 ability) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter); + struct PHY_DM_STRUCT *podmpriv = &pHalData->odmpriv; + u32 result = 0; + + switch (ops) { + case HAL_PHYDM_DIS_ALL_FUNC: + podmpriv->support_ability = DYNAMIC_FUNC_DISABLE; + break; + case HAL_PHYDM_FUNC_SET: + podmpriv->support_ability |= ability; + break; + case HAL_PHYDM_FUNC_CLR: + podmpriv->support_ability &= ~(ability); + break; + case HAL_PHYDM_ABILITY_BK: + /* dm flag backup*/ + podmpriv->bk_support_ability = podmpriv->support_ability; + break; + case HAL_PHYDM_ABILITY_RESTORE: + /* restore dm flag */ + podmpriv->support_ability = podmpriv->bk_support_ability; + break; + case HAL_PHYDM_ABILITY_SET: + podmpriv->support_ability = ability; + break; + case HAL_PHYDM_ABILITY_GET: + result = podmpriv->support_ability; + break; + } + return result; +} + + +bool +eqNByte( + u8 *str1, + u8 *str2, + u32 num +) +{ + if (num == 0) + return false; + while (num > 0) { + num--; + if (str1[num] != str2[num]) + return false; + } + return true; +} + +/* + * Description: + * Translate a character to hex digit. + * */ +u32 +MapCharToHexDigit( + char chTmp +) +{ + if (chTmp >= '0' && chTmp <= '9') + return chTmp - '0'; + else if (chTmp >= 'a' && chTmp <= 'f') + return 10 + (chTmp - 'a'); + else if (chTmp >= 'A' && chTmp <= 'F') + return 10 + (chTmp - 'A'); + else + return 0; +} + + + +/* + * Description: + * Parse hex number from the string pucStr. + * */ +bool +GetHexValueFromString( + char *szStr, + u32 *pu4bVal, + u32 *pu4bMove +) +{ + char *szScan = szStr; + + /* Check input parameter. */ + if (szStr == NULL || pu4bVal == NULL || pu4bMove == NULL) { + RTW_INFO("GetHexValueFromString(): Invalid inpur argumetns! szStr: %p, pu4bVal: %p, pu4bMove: %p\n", szStr, pu4bVal, pu4bMove); + return false; + } + + /* Initialize output. */ + *pu4bMove = 0; + *pu4bVal = 0; + + /* Skip leading space. */ + while (*szScan != '\0' && + (*szScan == ' ' || *szScan == '\t')) { + szScan++; + (*pu4bMove)++; + } + + /* Skip leading '0x' or '0X'. */ + if (*szScan == '0' && (*(szScan + 1) == 'x' || *(szScan + 1) == 'X')) { + szScan += 2; + (*pu4bMove) += 2; + } + + /* Check if szScan is now pointer to a character for hex digit, */ + /* if not, it means this is not a valid hex number. */ + if (!IsHexDigit(*szScan)) + return false; + + /* Parse each digit. */ + do { + (*pu4bVal) <<= 4; + *pu4bVal += MapCharToHexDigit(*szScan); + + szScan++; + (*pu4bMove)++; + } while (IsHexDigit(*szScan)); + + return true; +} + +bool +GetFractionValueFromString( + char *szStr, + u8 *pInteger, + u8 *pFraction, + u32 *pu4bMove +) +{ + char *szScan = szStr; + + /* Initialize output. */ + *pu4bMove = 0; + *pInteger = 0; + *pFraction = 0; + + /* Skip leading space. */ + while (*szScan != '\0' && (*szScan == ' ' || *szScan == '\t')) { + ++szScan; + ++(*pu4bMove); + } + + /* Parse each digit. */ + do { + (*pInteger) *= 10; + *pInteger += (*szScan - '0'); + + ++szScan; + ++(*pu4bMove); + + if (*szScan == '.') { + ++szScan; + ++(*pu4bMove); + + if (*szScan < '0' || *szScan > '9') + return false; + else { + *pFraction = *szScan - '0'; + ++szScan; + ++(*pu4bMove); + return true; + } + } + } while (*szScan >= '0' && *szScan <= '9'); + + return true; +} + +/* + * Description: + * Return true if szStr is comment out with leading " */ /* ". + * */ +bool +IsCommentString( + char *szStr +) +{ + if (*szStr == '/' && *(szStr + 1) == '/') + return true; + else + return false; +} + +bool +GetU1ByteIntegerFromStringInDecimal( + char *Str, + u8 *pInt +) +{ + u16 i = 0; + *pInt = 0; + + while (Str[i] != '\0') { + if (Str[i] >= '0' && Str[i] <= '9') { + *pInt *= 10; + *pInt += (Str[i] - '0'); + } else + return false; + ++i; + } + + return true; +} + +/* <20121004, Kordan> For example, + * ParseQualifiedString(inString, 0, outString, '[', ']') gets "Kordan" from a string "Hello [Kordan]". + * If RightQualifier does not exist, it will hang on in the while loop */ +bool +ParseQualifiedString( + char *In, + u32 *Start, + char *Out, + char LeftQualifier, + char RightQualifier +) +{ + u32 i = 0, j = 0; + char c = In[(*Start)++]; + + if (c != LeftQualifier) + return false; + + i = (*Start); + while ((c = In[(*Start)++]) != RightQualifier) + ; /* find ']' */ + j = (*Start) - 2; + strncpy((char *)Out, (const char *)(In + i), j - i + 1); + + return true; +} + +bool +isAllSpaceOrTab( + u8 *data, + u8 size +) +{ + u8 cnt = 0, NumOfSpaceAndTab = 0; + + while (size > cnt) { + if (data[cnt] == ' ' || data[cnt] == '\t' || data[cnt] == '\0') + ++NumOfSpaceAndTab; + + ++cnt; + } + + return size == NumOfSpaceAndTab; +} + + +void rtw_hal_check_rxfifo_full(_adapter *adapter) +{ + struct dvobj_priv *psdpriv = adapter->dvobj; + struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter); + struct registry_priv *regsty = &adapter->registrypriv; + int save_cnt = false; + + if (regsty->check_hw_status == 1) { + /* switch counter to RX fifo */ + if (IS_8188E(pHalData->version_id) || + IS_8188F(pHalData->version_id) || + IS_8812_SERIES(pHalData->version_id) || + IS_8821_SERIES(pHalData->version_id) || + IS_8723B_SERIES(pHalData->version_id) || + IS_8192E(pHalData->version_id) || + IS_8703B_SERIES(pHalData->version_id) || + IS_8723D_SERIES(pHalData->version_id)) { + rtw_write8(adapter, REG_RXERR_RPT + 3, rtw_read8(adapter, REG_RXERR_RPT + 3) | 0xa0); + save_cnt = true; + } else { + /* todo: other chips */ + } + + + if (save_cnt) { + pdbgpriv->dbg_rx_fifo_last_overflow = pdbgpriv->dbg_rx_fifo_curr_overflow; + pdbgpriv->dbg_rx_fifo_curr_overflow = rtw_read16(adapter, REG_RXERR_RPT); + pdbgpriv->dbg_rx_fifo_diff_overflow = pdbgpriv->dbg_rx_fifo_curr_overflow - pdbgpriv->dbg_rx_fifo_last_overflow; + } else { + /* special value to indicate no implementation */ + pdbgpriv->dbg_rx_fifo_last_overflow = 1; + pdbgpriv->dbg_rx_fifo_curr_overflow = 1; + pdbgpriv->dbg_rx_fifo_diff_overflow = 1; + } + } +} + +void linked_info_dump(_adapter *padapter, u8 benable) +{ + struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); + + if (padapter->bLinkInfoDump == benable) + return; + + RTW_INFO("%s %s\n", __func__, (benable) ? "enable" : "disable"); + + if (benable) { +#ifdef CONFIG_LPS + pwrctrlpriv->org_power_mgnt = pwrctrlpriv->power_mgnt;/* keep org value */ + rtw_pm_set_lps(padapter, PS_MODE_ACTIVE); +#endif + +#ifdef CONFIG_IPS + pwrctrlpriv->ips_org_mode = pwrctrlpriv->ips_mode;/* keep org value */ + rtw_pm_set_ips(padapter, IPS_NONE); +#endif + } else { +#ifdef CONFIG_IPS + rtw_pm_set_ips(padapter, pwrctrlpriv->ips_org_mode); +#endif /* CONFIG_IPS */ + +#ifdef CONFIG_LPS + rtw_pm_set_lps(padapter, pwrctrlpriv->org_power_mgnt); +#endif /* CONFIG_LPS */ + } + padapter->bLinkInfoDump = benable ; +} + +#ifdef DBG_RX_SIGNAL_DISPLAY_RAW_DATA +void rtw_get_raw_rssi_info(void *sel, _adapter *padapter) +{ + u8 isCCKrate, rf_path; + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + struct rx_raw_rssi *psample_pkt_rssi = &padapter->recvpriv.raw_rssi_info; + RTW_PRINT_SEL(sel, "RxRate = %s, PWDBALL = %d(%%), rx_pwr_all = %d(dBm)\n", + HDATA_RATE(psample_pkt_rssi->data_rate), psample_pkt_rssi->pwdball, psample_pkt_rssi->pwr_all); + isCCKrate = (psample_pkt_rssi->data_rate <= DESC_RATE11M) ? true : false; + + if (isCCKrate) + psample_pkt_rssi->mimo_signal_strength[0] = psample_pkt_rssi->pwdball; + + for (rf_path = 0; rf_path < pHalData->NumTotalRFPath; rf_path++) { + RTW_PRINT_SEL(sel, "RF_PATH_%d=>signal_strength:%d(%%),signal_quality:%d(%%)\n" + , rf_path, psample_pkt_rssi->mimo_signal_strength[rf_path], psample_pkt_rssi->mimo_signal_quality[rf_path]); + + if (!isCCKrate) { + RTW_PRINT_SEL(sel, "\trx_ofdm_pwr:%d(dBm),rx_ofdm_snr:%d(dB)\n", + psample_pkt_rssi->ofdm_pwr[rf_path], psample_pkt_rssi->ofdm_snr[rf_path]); + } + } +} + +void rtw_dump_raw_rssi_info(_adapter *padapter, void *sel) +{ + u8 isCCKrate, rf_path; + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + struct rx_raw_rssi *psample_pkt_rssi = &padapter->recvpriv.raw_rssi_info; + _RTW_PRINT_SEL(sel, "============ RAW Rx Info dump ===================\n"); + _RTW_PRINT_SEL(sel, "RxRate = %s, PWDBALL = %d(%%), rx_pwr_all = %d(dBm)\n", HDATA_RATE(psample_pkt_rssi->data_rate), psample_pkt_rssi->pwdball, psample_pkt_rssi->pwr_all); + + isCCKrate = (psample_pkt_rssi->data_rate <= DESC_RATE11M) ? true : false; + + if (isCCKrate) + psample_pkt_rssi->mimo_signal_strength[0] = psample_pkt_rssi->pwdball; + + for (rf_path = 0; rf_path < pHalData->NumTotalRFPath; rf_path++) { + _RTW_PRINT_SEL(sel , "RF_PATH_%d=>signal_strength:%d(%%),signal_quality:%d(%%)" + , rf_path, psample_pkt_rssi->mimo_signal_strength[rf_path], psample_pkt_rssi->mimo_signal_quality[rf_path]); + + if (!isCCKrate) + _RTW_PRINT_SEL(sel , ",rx_ofdm_pwr:%d(dBm),rx_ofdm_snr:%d(dB)\n", psample_pkt_rssi->ofdm_pwr[rf_path], psample_pkt_rssi->ofdm_snr[rf_path]); + else + _RTW_PRINT_SEL(sel , "\n"); + + } +} +#endif + +#ifdef DBG_RX_DFRAME_RAW_DATA +void rtw_dump_rx_dframe_info(_adapter *padapter, void *sel) +{ + unsigned long irqL; + u8 isCCKrate, rf_path; + struct recv_priv *precvpriv = &(padapter->recvpriv); + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + struct sta_priv *pstapriv = &padapter->stapriv; + struct sta_info *psta; + struct sta_recv_dframe_info *psta_dframe_info; + int i; + _list *plist, *phead; + char *BW; + u8 bc_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u8 null_addr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + if (precvpriv->store_law_data_flag) { + + _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL); + + for (i = 0; i < NUM_STA; i++) { + phead = &(pstapriv->sta_hash[i]); + plist = get_next(phead); + + while ((rtw_end_of_queue_search(phead, plist)) == false) { + + psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); + plist = get_next(plist); + + if (psta) { + psta_dframe_info = &psta->sta_dframe_info; + if ((memcmp(psta->hwaddr, bc_addr, 6)) + && (memcmp(psta->hwaddr, null_addr, 6)) + && (memcmp(psta->hwaddr, adapter_mac_addr(padapter), 6))) { + + + isCCKrate = (psta_dframe_info->sta_data_rate <= DESC_RATE11M) ? true : false; + + switch (psta_dframe_info->sta_bw_mode) { + + case CHANNEL_WIDTH_20: + BW = "20M"; + break; + + case CHANNEL_WIDTH_40: + BW = "40M"; + break; + + case CHANNEL_WIDTH_80: + BW = "80M"; + break; + + case CHANNEL_WIDTH_160: + BW = "160M"; + break; + + default: + BW = ""; + break; + } + + RTW_PRINT_SEL(sel, "==============================\n"); + _RTW_PRINT_SEL(sel, "macaddr =" MAC_FMT "\n", MAC_ARG(psta->hwaddr)); + _RTW_PRINT_SEL(sel, "BW=%s, sgi =%d\n", BW, psta_dframe_info->sta_sgi); + _RTW_PRINT_SEL(sel, "Rx_Data_Rate = %s\n", HDATA_RATE(psta_dframe_info->sta_data_rate)); + + for (rf_path = 0; rf_path < pHalData->NumTotalRFPath; rf_path++) { + + if (!isCCKrate) { + + _RTW_PRINT_SEL(sel , "RF_PATH_%d RSSI:%d(dBm)", rf_path, psta_dframe_info->sta_RxPwr[rf_path]); + _RTW_PRINT_SEL(sel , ",rx_ofdm_snr:%d(dB)\n", psta_dframe_info->sta_ofdm_snr[rf_path]); + + } else + + _RTW_PRINT_SEL(sel , "RF_PATH_%d RSSI:%d(dBm)\n", rf_path, (psta_dframe_info->sta_mimo_signal_strength[rf_path]) - 100); + } + } + } + } + } + _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL); + } +} +#endif +void rtw_store_phy_info(_adapter *padapter, union recv_frame *prframe) +{ + u8 isCCKrate, rf_path , dframe_type; + u8 *ptr; + u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +#ifdef DBG_RX_DFRAME_RAW_DATA + struct sta_recv_dframe_info *psta_dframe_info; +#endif + struct recv_priv *precvpriv = &(padapter->recvpriv); + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; + struct sta_info *psta = prframe->u.hdr.psta; + struct _odm_phy_status_info_ *p_phy_info = (struct _odm_phy_status_info_ *)(&pattrib->phy_info); + struct rx_raw_rssi *psample_pkt_rssi = &padapter->recvpriv.raw_rssi_info; + psample_pkt_rssi->data_rate = pattrib->data_rate; + ptr = prframe->u.hdr.rx_data; + dframe_type = GetFrameType(ptr); + /*RTW_INFO("=>%s\n", __func__);*/ + + + if (precvpriv->store_law_data_flag) { + isCCKrate = (pattrib->data_rate <= DESC_RATE11M) ? true : false; + + psample_pkt_rssi->pwdball = p_phy_info->rx_pwdb_all; + psample_pkt_rssi->pwr_all = p_phy_info->recv_signal_power; + + for (rf_path = 0; rf_path < pHalData->NumTotalRFPath; rf_path++) { + psample_pkt_rssi->mimo_signal_strength[rf_path] = p_phy_info->rx_mimo_signal_strength[rf_path]; + psample_pkt_rssi->mimo_signal_quality[rf_path] = p_phy_info->rx_mimo_signal_quality[rf_path]; + if (!isCCKrate) { + psample_pkt_rssi->ofdm_pwr[rf_path] = p_phy_info->rx_pwr[rf_path]; + psample_pkt_rssi->ofdm_snr[rf_path] = p_phy_info->rx_snr[rf_path]; + } + } +#ifdef DBG_RX_DFRAME_RAW_DATA + if ((dframe_type == WIFI_DATA_TYPE) || (dframe_type == WIFI_QOS_DATA_TYPE) || (padapter->registrypriv.mp_mode == 1)) { + + /*RTW_INFO("=>%s WIFI_DATA_TYPE or WIFI_QOS_DATA_TYPE\n", __func__);*/ + if (psta) { + psta_dframe_info = &psta->sta_dframe_info; + /*RTW_INFO("=>%s psta->hwaddr="MAC_FMT" !\n", __func__, MAC_ARG(psta->hwaddr));*/ + if ((memcmp(psta->hwaddr, bc_addr, ETH_ALEN)) || (padapter->registrypriv.mp_mode == 1)) { + psta_dframe_info->sta_data_rate = pattrib->data_rate; + psta_dframe_info->sta_sgi = pattrib->sgi; + psta_dframe_info->sta_bw_mode = pattrib->bw; + for (rf_path = 0; rf_path < pHalData->NumTotalRFPath; rf_path++) { + + psta_dframe_info->sta_mimo_signal_strength[rf_path] = (p_phy_info->rx_mimo_signal_strength[rf_path]);/*Percentage to dbm*/ + + if (!isCCKrate) { + psta_dframe_info->sta_ofdm_snr[rf_path] = p_phy_info->rx_snr[rf_path]; + psta_dframe_info->sta_RxPwr[rf_path] = p_phy_info->rx_pwr[rf_path]; + } + } + } + } + } +#endif + } + +} + + +int check_phy_efuse_tx_power_info_valid(PADAPTER padapter) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + u8 *pContent = pHalData->efuse_eeprom_data; + int index = 0; + u16 tx_index_offset = 0x0000; + + switch (rtw_get_chip_type(padapter)) { + case RTL8723B: + tx_index_offset = EEPROM_TX_PWR_INX_8723B; + break; + case RTL8703B: + tx_index_offset = EEPROM_TX_PWR_INX_8703B; + break; + case RTL8723D: + tx_index_offset = EEPROM_TX_PWR_INX_8723D; + break; + case RTL8188E: + tx_index_offset = EEPROM_TX_PWR_INX_88E; + break; + case RTL8188F: + tx_index_offset = EEPROM_TX_PWR_INX_8188F; + break; + case RTL8192E: + tx_index_offset = EEPROM_TX_PWR_INX_8192E; + break; + case RTL8821: + tx_index_offset = EEPROM_TX_PWR_INX_8821; + break; + case RTL8812: + tx_index_offset = EEPROM_TX_PWR_INX_8812; + break; + case RTL8814A: + tx_index_offset = EEPROM_TX_PWR_INX_8814; + break; + case RTL8822B: + tx_index_offset = EEPROM_TX_PWR_INX_8822B; + break; + case RTL8821C: + tx_index_offset = EEPROM_TX_PWR_INX_8821C; + break; + default: + tx_index_offset = 0x0010; + break; + } + + /* TODO: chacking length by ICs */ + for (index = 0 ; index < 11 ; index++) { + if (pContent[tx_index_offset + index] == 0xFF) + return false; + } + return true; +} + +int hal_efuse_macaddr_offset(_adapter *adapter) +{ + u8 interface_type = 0; + int addr_offset = -1; + + interface_type = rtw_get_intf_type(adapter); + + switch (rtw_get_chip_type(adapter)) { + case RTL8188E: + if (interface_type == RTW_USB) + addr_offset = EEPROM_MAC_ADDR_88EU; + else if (interface_type == RTW_SDIO) + addr_offset = EEPROM_MAC_ADDR_88ES; + else if (interface_type == RTW_PCIE) + addr_offset = EEPROM_MAC_ADDR_88EE; + break; + } + + if (addr_offset == -1) { + RTW_ERR("%s: unknown combination - chip_type:%u, interface:%u\n" + , __func__, rtw_get_chip_type(adapter), rtw_get_intf_type(adapter)); + } + + return addr_offset; +} + +int Hal_GetPhyEfuseMACAddr(PADAPTER padapter, u8 *mac_addr) +{ + int ret = _FAIL; + int addr_offset; + + addr_offset = hal_efuse_macaddr_offset(padapter); + if (addr_offset == -1) + goto exit; + + ret = rtw_efuse_map_read(padapter, addr_offset, ETH_ALEN, mac_addr); + +exit: + return ret; +} + +void rtw_dump_cur_efuse(PADAPTER padapter) +{ + int i =0; + u16 mapsize =0; + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter); + + EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (void *)&mapsize, false); + + if (mapsize <= 0 || mapsize > EEPROM_MAX_SIZE) { + RTW_ERR("wrong map size %d\n", mapsize); + return; + } + + if (hal_data->efuse_file_status == EFUSE_FILE_LOADED) + RTW_INFO("EFUSE FILE\n"); + else + RTW_INFO("HW EFUSE\n"); +} + +#ifdef CONFIG_EFUSE_CONFIG_FILE +u32 Hal_readPGDataFromConfigFile(PADAPTER padapter) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter); + u32 ret = false; + u16 maplen = 0; + + EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (void *)&maplen, false); + + if (maplen < 256 || maplen > EEPROM_MAX_SIZE) { + RTW_ERR("eFuse length error :%d\n", maplen); + return false; + } + + ret = rtw_read_efuse_from_file(EFUSE_MAP_PATH, hal_data->efuse_eeprom_data, maplen); + + hal_data->efuse_file_status = ((ret == _FAIL) ? EFUSE_FILE_FAILED : EFUSE_FILE_LOADED); + + if (hal_data->efuse_file_status == EFUSE_FILE_LOADED) + rtw_dump_cur_efuse(padapter); + + return ret; +} + +u32 Hal_ReadMACAddrFromFile(PADAPTER padapter, u8 *mac_addr) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter); + u32 ret = _FAIL; + + if (rtw_read_macaddr_from_file(WIFIMAC_PATH, mac_addr) == _SUCCESS + && rtw_check_invalid_mac_address(mac_addr, true) == false + ) { + hal_data->macaddr_file_status = MACADDR_FILE_LOADED; + ret = _SUCCESS; + } else + hal_data->macaddr_file_status = MACADDR_FILE_FAILED; + + return ret; +} +#endif /* CONFIG_EFUSE_CONFIG_FILE */ + +int hal_config_macaddr(_adapter *adapter, bool autoload_fail) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + u8 addr[ETH_ALEN]; + int addr_offset = hal_efuse_macaddr_offset(adapter); + u8 *hw_addr = NULL; + int ret = _SUCCESS; + + if (autoload_fail) + goto bypass_hw_pg; + + if (addr_offset != -1) + hw_addr = &hal_data->efuse_eeprom_data[addr_offset]; + +#ifdef CONFIG_EFUSE_CONFIG_FILE + /* if the hw_addr is written by efuse file, set to NULL */ + if (hal_data->efuse_file_status == EFUSE_FILE_LOADED) + hw_addr = NULL; +#endif + + if (!hw_addr) { + /* try getting hw pg data */ + if (Hal_GetPhyEfuseMACAddr(adapter, addr) == _SUCCESS) + hw_addr = addr; + } + + /* check hw pg data */ + if (hw_addr && rtw_check_invalid_mac_address(hw_addr, true) == false) { + memcpy(hal_data->EEPROMMACAddr, hw_addr, ETH_ALEN); + goto exit; + } + +bypass_hw_pg: + +#ifdef CONFIG_EFUSE_CONFIG_FILE + /* check wifi mac file */ + if (Hal_ReadMACAddrFromFile(adapter, addr) == _SUCCESS) { + memcpy(hal_data->EEPROMMACAddr, addr, ETH_ALEN); + goto exit; + } +#endif + + memset(hal_data->EEPROMMACAddr, 0, ETH_ALEN); + ret = _FAIL; + +exit: + return ret; +} + +#ifdef CONFIG_RF_POWER_TRIM +u32 Array_kfreemap[] = { + 0x08, 0xe, + 0x06, 0xc, + 0x04, 0xa, + 0x02, 0x8, + 0x00, 0x6, + 0x03, 0x4, + 0x05, 0x2, + 0x07, 0x0, + 0x09, 0x0, + 0x0c, 0x0, +}; + +void rtw_bb_rf_gain_offset(_adapter *padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct registry_priv *registry_par = &padapter->registrypriv; + struct kfree_data_t *kfree_data = &pHalData->kfree_data; + u8 value = pHalData->EEPROMRFGainOffset; + u8 tmp = 0x3e; + u32 res, i = 0; + u32 ArrayLen = sizeof(Array_kfreemap) / sizeof(u32); + u32 * Array = Array_kfreemap; + u32 v1 = 0, v2 = 0, GainValue = 0, target = 0; + + if (registry_par->RegPwrTrimEnable == 2) { + RTW_INFO("Registry kfree default force disable.\n"); + return; + } + + if (value & BIT4 || (registry_par->RegPwrTrimEnable == 1)) { + RTW_INFO("8188ES Offset RF Gain.\n"); + RTW_INFO("8188ES Offset RF Gain. EEPROMRFGainVal=0x%x\n", + pHalData->EEPROMRFGainVal); + + if (pHalData->EEPROMRFGainVal != 0xff) { + res = rtw_hal_read_rfreg(padapter, RF_PATH_A, + REG_RF_BB_GAIN_OFFSET, 0xffffffff); + + RTW_INFO("Offset RF Gain. reg 0x55=0x%x\n", res); + res &= 0xfff87fff; + + res |= (pHalData->EEPROMRFGainVal & 0x0f) << 15; + RTW_INFO("Offset RF Gain. res=0x%x\n", res); + + rtw_hal_write_rfreg(padapter, RF_PATH_A, + REG_RF_BB_GAIN_OFFSET, + RF_GAIN_OFFSET_MASK, res); + } else { + RTW_INFO("Offset RF Gain. EEPROMRFGainVal=0x%x == 0xff, didn't run Kfree\n", + pHalData->EEPROMRFGainVal); + } + } else + RTW_INFO("Using the default RF gain.\n"); +} +#endif /*CONFIG_RF_POWER_TRIM */ + +bool kfree_data_is_bb_gain_empty(struct kfree_data_t *data) +{ +#ifdef CONFIG_RF_POWER_TRIM + int i, j; + + for (i = 0; i < BB_GAIN_NUM; i++) + for (j = 0; j < RF_PATH_MAX; j++) + if (data->bb_gain[i][j] != 0) + return 0; +#endif + return 1; +} + +#ifdef CONFIG_USB_RX_AGGREGATION +static void rtw_set_usb_agg_by_mode_normal(_adapter *padapter, u8 cur_wireless_mode) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + if (cur_wireless_mode < WIRELESS_11_24N + && cur_wireless_mode > 0) { /* ABG mode */ +#ifdef CONFIG_PREALLOC_RX_SKB_BUFFER + u32 remainder = 0; + u8 quotient = 0; + + remainder = MAX_RECVBUF_SZ % (4 * 1024); + quotient = (u8)(MAX_RECVBUF_SZ >> 12); + + if (quotient > 5) { + pHalData->rxagg_usb_size = 0x6; + pHalData->rxagg_usb_timeout = 0x10; + } else { + if (remainder >= 2048) { + pHalData->rxagg_usb_size = quotient; + pHalData->rxagg_usb_timeout = 0x10; + } else { + pHalData->rxagg_usb_size = (quotient - 1); + pHalData->rxagg_usb_timeout = 0x10; + } + } +#else /* !CONFIG_PREALLOC_RX_SKB_BUFFER */ + if (0x6 != pHalData->rxagg_usb_size || 0x10 != pHalData->rxagg_usb_timeout) { + pHalData->rxagg_usb_size = 0x6; + pHalData->rxagg_usb_timeout = 0x10; + rtw_write16(padapter, REG_RXDMA_AGG_PG_TH, + pHalData->rxagg_usb_size | (pHalData->rxagg_usb_timeout << 8)); + } +#endif /* CONFIG_PREALLOC_RX_SKB_BUFFER */ + + } else if (cur_wireless_mode >= WIRELESS_11_24N + && cur_wireless_mode <= WIRELESS_MODE_MAX) { /* N AC mode */ +#ifdef CONFIG_PREALLOC_RX_SKB_BUFFER + u32 remainder = 0; + u8 quotient = 0; + + remainder = MAX_RECVBUF_SZ % (4 * 1024); + quotient = (u8)(MAX_RECVBUF_SZ >> 12); + + if (quotient > 5) { + pHalData->rxagg_usb_size = 0x5; + pHalData->rxagg_usb_timeout = 0x20; + } else { + if (remainder >= 2048) { + pHalData->rxagg_usb_size = quotient; + pHalData->rxagg_usb_timeout = 0x10; + } else { + pHalData->rxagg_usb_size = (quotient - 1); + pHalData->rxagg_usb_timeout = 0x10; + } + } +#else /* !CONFIG_PREALLOC_RX_SKB_BUFFER */ + if ((0x5 != pHalData->rxagg_usb_size) || (0x20 != pHalData->rxagg_usb_timeout)) { + pHalData->rxagg_usb_size = 0x5; + pHalData->rxagg_usb_timeout = 0x20; + rtw_write16(padapter, REG_RXDMA_AGG_PG_TH, + pHalData->rxagg_usb_size | (pHalData->rxagg_usb_timeout << 8)); + } +#endif /* CONFIG_PREALLOC_RX_SKB_BUFFER */ + + } else { + /* RTW_INFO("%s: Unknow wireless mode(0x%x)\n",__func__,padapter->mlmeextpriv.cur_wireless_mode); */ + } +} + +static void rtw_set_usb_agg_by_mode_customer(_adapter *padapter, u8 cur_wireless_mode, u8 UsbDmaSize, u8 Legacy_UsbDmaSize) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + if (cur_wireless_mode < WIRELESS_11_24N + && cur_wireless_mode > 0) { /* ABG mode */ + if (Legacy_UsbDmaSize != pHalData->rxagg_usb_size + || 0x10 != pHalData->rxagg_usb_timeout) { + pHalData->rxagg_usb_size = Legacy_UsbDmaSize; + pHalData->rxagg_usb_timeout = 0x10; + rtw_write16(padapter, REG_RXDMA_AGG_PG_TH, + pHalData->rxagg_usb_size | (pHalData->rxagg_usb_timeout << 8)); + } + } else if (cur_wireless_mode >= WIRELESS_11_24N + && cur_wireless_mode <= WIRELESS_MODE_MAX) { /* N AC mode */ + if (UsbDmaSize != pHalData->rxagg_usb_size + || 0x20 != pHalData->rxagg_usb_timeout) { + pHalData->rxagg_usb_size = UsbDmaSize; + pHalData->rxagg_usb_timeout = 0x20; + rtw_write16(padapter, REG_RXDMA_AGG_PG_TH, + pHalData->rxagg_usb_size | (pHalData->rxagg_usb_timeout << 8)); + } + } else { + /* RTW_INFO("%s: Unknown wireless mode(0x%x)\n",__func__,padapter->mlmeextpriv.cur_wireless_mode); */ + } +} + +static void rtw_set_usb_agg_by_mode(_adapter *padapter, u8 cur_wireless_mode) +{ +#ifdef CONFIG_PLATFORM_NOVATEK_NT72668 + rtw_set_usb_agg_by_mode_customer(padapter, cur_wireless_mode, 0x3, 0x3); + return; +#endif /* CONFIG_PLATFORM_NOVATEK_NT72668 */ + + rtw_set_usb_agg_by_mode_normal(padapter, cur_wireless_mode); +} +#endif /* CONFIG_USB_RX_AGGREGATION */ + +/* To avoid RX affect TX throughput */ +void dm_DynamicUsbTxAgg(_adapter *padapter, u8 from_timer) +{ + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + u8 cur_wireless_mode = WIRELESS_INVALID; + +#ifdef CONFIG_USB_RX_AGGREGATION +#ifdef CONFIG_PLATFORM_NOVATEK_NT72668 + rtw_set_usb_agg_by_mode(padapter, cur_wireless_mode); +#endif /* CONFIG_PLATFORM_NOVATEK_NT72668 */ +#endif +} + +/* bus-agg check for SoftAP mode */ +inline u8 rtw_hal_busagg_qsel_check(_adapter *padapter, u8 pre_qsel, u8 next_qsel) +{ + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + u8 chk_rst = _SUCCESS; + + if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) + return chk_rst; + + /* if((pre_qsel == 0xFF)||(next_qsel== 0xFF)) */ + /* return chk_rst; */ + + if (((pre_qsel == QSLT_HIGH) || ((next_qsel == QSLT_HIGH))) + && (pre_qsel != next_qsel)) { + /* RTW_INFO("### bus-agg break cause of qsel misatch, pre_qsel=0x%02x,next_qsel=0x%02x ###\n", */ + /* pre_qsel,next_qsel); */ + chk_rst = _FAIL; + } + return chk_rst; +} + +/* + * Description: + * dump_TX_FIFO: This is only used to dump TX_FIFO for debug WoW mode offload + * contant. + * + * Input: + * adapter: adapter pointer. + * page_num: The max. page number that user want to dump. + * page_size: page size of each page. eg. 128 bytes, 256 bytes, 512byte. + */ +void dump_TX_FIFO(_adapter *padapter, u8 page_num, u16 page_size) +{ + + int i; + u8 val = 0; + u8 base = 0; + u32 addr = 0; + u32 count = (page_size / 8); + + if (page_num <= 0) { + RTW_INFO("!!%s: incorrect input page_num paramter!\n", __func__); + return; + } + + if (page_size < 128 || page_size > 512) { + RTW_INFO("!!%s: incorrect input page_size paramter!\n", __func__); + return; + } + + RTW_INFO("+%s+\n", __func__); + val = rtw_read8(padapter, 0x106); + rtw_write8(padapter, 0x106, 0x69); + RTW_INFO("0x106: 0x%02x\n", val); + base = rtw_read8(padapter, 0x209); + RTW_INFO("0x209: 0x%02x\n", base); + + addr = ((base)*page_size) / 8; + for (i = 0 ; i < page_num * count ; i += 2) { + rtw_write32(padapter, 0x140, addr + i); + printk(" %08x %08x ", rtw_read32(padapter, 0x144), rtw_read32(padapter, 0x148)); + rtw_write32(padapter, 0x140, addr + i + 1); + printk(" %08x %08x\n", rtw_read32(padapter, 0x144), rtw_read32(padapter, 0x148)); + } +} + +#ifdef CONFIG_GPIO_API +u8 rtw_hal_get_gpio(_adapter *adapter, u8 gpio_num) +{ + u8 value = 0; + u8 direction = 0; + u32 gpio_ctrl_reg_to_set = REG_GPIO_PIN_CTRL + 2; + u8 gpio_num_to_set = gpio_num; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter); + + if (rtw_hal_gpio_func_check(adapter, gpio_num) == _FAIL) + return value; + + rtw_ps_deny(adapter, PS_DENY_IOCTL); + + RTW_INFO("rf_pwrstate=0x%02x\n", pwrpriv->rf_pwrstate); + LeaveAllPowerSaveModeDirect(adapter); + + if (gpio_num > 7) { + gpio_ctrl_reg_to_set = REG_GPIO_PIN_CTRL_2 + 2; + gpio_num_to_set = gpio_num - 8; + } + + /* Read GPIO Direction */ + direction = (rtw_read8(adapter, gpio_ctrl_reg_to_set) & BIT(gpio_num_to_set)) >> gpio_num; + + /* According the direction to read register value */ + if (direction) + value = (rtw_read8(adapter, gpio_ctrl_reg_to_set) & BIT(gpio_num_to_set)) >> gpio_num; + else + value = (rtw_read8(adapter, gpio_ctrl_reg_to_set) & BIT(gpio_num_to_set)) >> gpio_num; + + rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL); + RTW_INFO("%s direction=%d value=%d\n", __func__, direction, value); + + return value; +} + +int rtw_hal_set_gpio_output_value(_adapter *adapter, u8 gpio_num, bool isHigh) +{ + u8 direction = 0; + u8 res = -1; + u32 gpio_ctrl_reg_to_set = REG_GPIO_PIN_CTRL + 2; + u8 gpio_num_to_set = gpio_num; + + if (rtw_hal_gpio_func_check(adapter, gpio_num) == _FAIL) + return -1; + + rtw_ps_deny(adapter, PS_DENY_IOCTL); + + LeaveAllPowerSaveModeDirect(adapter); + + if (gpio_num > 7) { + gpio_ctrl_reg_to_set = REG_GPIO_PIN_CTRL_2 + 2; + gpio_num_to_set = gpio_num - 8; + } + + /* Read GPIO direction */ + direction = (rtw_read8(adapter, REG_GPIO_PIN_CTRL + 2) & BIT(gpio_num)) >> gpio_num; + + /* If GPIO is output direction, setting value. */ + if (direction) { + if (isHigh) + rtw_write8(adapter, gpio_ctrl_reg_to_set, rtw_read8(adapter, gpio_ctrl_reg_to_set) | BIT(gpio_num_to_set)); + else + rtw_write8(adapter, gpio_ctrl_reg_to_set, rtw_read8(adapter, gpio_ctrl_reg_to_set) & ~BIT(gpio_num_to_set)); + + RTW_INFO("%s Set gpio %x[%d]=%d\n", __func__, REG_GPIO_PIN_CTRL + 1, gpio_num, isHigh); + res = 0; + } else { + RTW_INFO("%s The gpio is input,not be set!\n", __func__); + res = -1; + } + + rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL); + return res; +} + +int rtw_hal_config_gpio(_adapter *adapter, u8 gpio_num, bool isOutput) +{ + u32 gpio_ctrl_reg_to_set = REG_GPIO_PIN_CTRL + 2; + u8 gpio_num_to_set = gpio_num; + + if (rtw_hal_gpio_func_check(adapter, gpio_num) == _FAIL) + return -1; + + RTW_INFO("%s gpio_num =%d direction=%d\n", __func__, gpio_num, isOutput); + + rtw_ps_deny(adapter, PS_DENY_IOCTL); + + LeaveAllPowerSaveModeDirect(adapter); + + rtw_hal_gpio_multi_func_reset(adapter, gpio_num); + + if (gpio_num > 7) { + gpio_ctrl_reg_to_set = REG_GPIO_PIN_CTRL_2 + 2; + gpio_num_to_set = gpio_num - 8; + } + + if (isOutput) + rtw_write8(adapter, gpio_ctrl_reg_to_set, rtw_read8(adapter, gpio_ctrl_reg_to_set) | BIT(gpio_num_to_set)); + else + rtw_write8(adapter, gpio_ctrl_reg_to_set, rtw_read8(adapter, gpio_ctrl_reg_to_set) & ~BIT(gpio_num_to_set)); + + rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL); + + return 0; +} +int rtw_hal_register_gpio_interrupt(_adapter *adapter, int gpio_num, void(*callback)(u8 level)) +{ + u8 value; + u8 direction; + PHAL_DATA_TYPE phal = GET_HAL_DATA(adapter); + + if (IS_HARDWARE_TYPE_8188E(adapter)) { + if (gpio_num > 7 || gpio_num < 4) { + RTW_PRINT("%s The gpio number does not included 4~7.\n", __func__); + return -1; + } + } + + rtw_ps_deny(adapter, PS_DENY_IOCTL); + + LeaveAllPowerSaveModeDirect(adapter); + + /* Read GPIO direction */ + direction = (rtw_read8(adapter, REG_GPIO_PIN_CTRL + 2) & BIT(gpio_num)) >> gpio_num; + if (direction) { + RTW_PRINT("%s Can't register output gpio as interrupt.\n", __func__); + return -1; + } + + /* Config GPIO Mode */ + rtw_write8(adapter, REG_GPIO_PIN_CTRL + 3, rtw_read8(adapter, REG_GPIO_PIN_CTRL + 3) | BIT(gpio_num)); + + /* Register GPIO interrupt handler*/ + adapter->gpiointpriv.callback[gpio_num] = callback; + + /* Set GPIO interrupt mode, 0:positive edge, 1:negative edge */ + value = rtw_read8(adapter, REG_GPIO_PIN_CTRL) & BIT(gpio_num); + adapter->gpiointpriv.interrupt_mode = rtw_read8(adapter, REG_HSIMR + 2) ^ value; + rtw_write8(adapter, REG_GPIO_INTM, adapter->gpiointpriv.interrupt_mode); + + /* Enable GPIO interrupt */ + adapter->gpiointpriv.interrupt_enable_mask = rtw_read8(adapter, REG_HSIMR + 2) | BIT(gpio_num); + rtw_write8(adapter, REG_HSIMR + 2, adapter->gpiointpriv.interrupt_enable_mask); + + rtw_hal_update_hisr_hsisr_ind(adapter, 1); + + rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL); + + return 0; +} +int rtw_hal_disable_gpio_interrupt(_adapter *adapter, int gpio_num) +{ + u8 value; + u8 direction; + PHAL_DATA_TYPE phal = GET_HAL_DATA(adapter); + + if (IS_HARDWARE_TYPE_8188E(adapter)) { + if (gpio_num > 7 || gpio_num < 4) { + RTW_INFO("%s The gpio number does not included 4~7.\n", __func__); + return -1; + } + } + + rtw_ps_deny(adapter, PS_DENY_IOCTL); + + LeaveAllPowerSaveModeDirect(adapter); + + /* Config GPIO Mode */ + rtw_write8(adapter, REG_GPIO_PIN_CTRL + 3, rtw_read8(adapter, REG_GPIO_PIN_CTRL + 3) & ~BIT(gpio_num)); + + /* Unregister GPIO interrupt handler*/ + adapter->gpiointpriv.callback[gpio_num] = NULL; + + /* Reset GPIO interrupt mode, 0:positive edge, 1:negative edge */ + adapter->gpiointpriv.interrupt_mode = rtw_read8(adapter, REG_GPIO_INTM) & ~BIT(gpio_num); + rtw_write8(adapter, REG_GPIO_INTM, 0x00); + + /* Disable GPIO interrupt */ + adapter->gpiointpriv.interrupt_enable_mask = rtw_read8(adapter, REG_HSIMR + 2) & ~BIT(gpio_num); + rtw_write8(adapter, REG_HSIMR + 2, adapter->gpiointpriv.interrupt_enable_mask); + + if (!adapter->gpiointpriv.interrupt_enable_mask) + rtw_hal_update_hisr_hsisr_ind(adapter, 0); + + rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL); + + return 0; +} +#endif + +s8 rtw_hal_ch_sw_iqk_info_search(_adapter *padapter, u8 central_chnl, u8 bw_mode) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + u8 i; + + for (i = 0; i < MAX_IQK_INFO_BACKUP_CHNL_NUM; i++) { + if ((pHalData->iqk_reg_backup[i].central_chnl != 0)) { + if ((pHalData->iqk_reg_backup[i].central_chnl == central_chnl) + && (pHalData->iqk_reg_backup[i].bw_mode == bw_mode)) + return i; + } + } + + return -1; +} + +void rtw_hal_ch_sw_iqk_info_backup(_adapter *padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + s8 res; + u8 i; + + /* If it's an existed record, overwrite it */ + res = rtw_hal_ch_sw_iqk_info_search(padapter, pHalData->current_channel, pHalData->current_channel_bw); + if ((res >= 0) && (res < MAX_IQK_INFO_BACKUP_CHNL_NUM)) { + rtw_hal_set_hwreg(padapter, HW_VAR_CH_SW_IQK_INFO_BACKUP, (u8 *)&(pHalData->iqk_reg_backup[res])); + return; + } + + /* Search for the empty record to use */ + for (i = 0; i < MAX_IQK_INFO_BACKUP_CHNL_NUM; i++) { + if (pHalData->iqk_reg_backup[i].central_chnl == 0) { + rtw_hal_set_hwreg(padapter, HW_VAR_CH_SW_IQK_INFO_BACKUP, (u8 *)&(pHalData->iqk_reg_backup[i])); + return; + } + } + + /* Else, overwrite the oldest record */ + for (i = 1; i < MAX_IQK_INFO_BACKUP_CHNL_NUM; i++) + memcpy(&(pHalData->iqk_reg_backup[i - 1]), &(pHalData->iqk_reg_backup[i]), sizeof(struct hal_iqk_reg_backup)); + + rtw_hal_set_hwreg(padapter, HW_VAR_CH_SW_IQK_INFO_BACKUP, (u8 *)&(pHalData->iqk_reg_backup[MAX_IQK_INFO_BACKUP_CHNL_NUM - 1])); +} + +void rtw_hal_ch_sw_iqk_info_restore(_adapter *padapter, u8 ch_sw_use_case) +{ + rtw_hal_set_hwreg(padapter, HW_VAR_CH_SW_IQK_INFO_RESTORE, &ch_sw_use_case); +} + +void rtw_dump_mac_rx_counters(_adapter *padapter, struct dbg_rx_counter *rx_counter) +{ + u32 mac_cck_ok = 0, mac_ofdm_ok = 0, mac_ht_ok = 0, mac_vht_ok = 0; + u32 mac_cck_err = 0, mac_ofdm_err = 0, mac_ht_err = 0, mac_vht_err = 0; + u32 mac_cck_fa = 0, mac_ofdm_fa = 0, mac_ht_fa = 0; + u32 DropPacket = 0; + + if (!rx_counter) { + rtw_warn_on(1); + return; + } + phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x3); + mac_cck_ok = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */ + phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x0); + mac_ofdm_ok = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */ + phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x6); + mac_ht_ok = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */ + mac_vht_ok = 0; + + phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x4); + mac_cck_err = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */ + phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x1); + mac_ofdm_err = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */ + phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x7); + mac_ht_err = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */ + mac_vht_err = 0; + + phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x5); + mac_cck_fa = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */ + phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x2); + mac_ofdm_fa = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */ + phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x9); + mac_ht_fa = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */ + + /* Mac_DropPacket */ + rtw_write32(padapter, REG_RXERR_RPT, (rtw_read32(padapter, REG_RXERR_RPT) & 0x0FFFFFFF) | Mac_DropPacket); + DropPacket = rtw_read32(padapter, REG_RXERR_RPT) & 0x0000FFFF; + + rx_counter->rx_pkt_ok = mac_cck_ok + mac_ofdm_ok + mac_ht_ok + mac_vht_ok; + rx_counter->rx_pkt_crc_error = mac_cck_err + mac_ofdm_err + mac_ht_err + mac_vht_err; + rx_counter->rx_cck_fa = mac_cck_fa; + rx_counter->rx_ofdm_fa = mac_ofdm_fa; + rx_counter->rx_ht_fa = mac_ht_fa; + rx_counter->rx_pkt_drop = DropPacket; +} +void rtw_reset_mac_rx_counters(_adapter *padapter) +{ + /* reset mac counter */ + phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT27, 0x1); + phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT27, 0x0); +} + +void rtw_dump_phy_rx_counters(_adapter *padapter, struct dbg_rx_counter *rx_counter) +{ + u32 cckok = 0, cckcrc = 0, ofdmok = 0, ofdmcrc = 0, htok = 0, htcrc = 0, OFDM_FA = 0, CCK_FA = 0, vht_ok = 0, vht_err = 0; + if (!rx_counter) { + rtw_warn_on(1); + return; + } + cckok = phy_query_bb_reg(padapter, 0xF88, bMaskDWord); + ofdmok = phy_query_bb_reg(padapter, 0xF94, bMaskLWord); + htok = phy_query_bb_reg(padapter, 0xF90, bMaskLWord); + vht_ok = 0; + cckcrc = phy_query_bb_reg(padapter, 0xF84, bMaskDWord); + ofdmcrc = phy_query_bb_reg(padapter, 0xF94, bMaskHWord); + htcrc = phy_query_bb_reg(padapter, 0xF90, bMaskHWord); + vht_err = 0; + OFDM_FA = phy_query_bb_reg(padapter, 0xCF0, bMaskLWord) + phy_query_bb_reg(padapter, 0xCF2, bMaskLWord) + + phy_query_bb_reg(padapter, 0xDA2, bMaskLWord) + phy_query_bb_reg(padapter, 0xDA4, bMaskLWord) + + phy_query_bb_reg(padapter, 0xDA6, bMaskLWord) + phy_query_bb_reg(padapter, 0xDA8, bMaskLWord); + + CCK_FA = (rtw_read8(padapter, 0xA5B) << 8) | (rtw_read8(padapter, 0xA5C)); + + rx_counter->rx_pkt_ok = cckok + ofdmok + htok + vht_ok; + rx_counter->rx_pkt_crc_error = cckcrc + ofdmcrc + htcrc + vht_err; + rx_counter->rx_ofdm_fa = OFDM_FA; + rx_counter->rx_cck_fa = CCK_FA; + +} + +void rtw_reset_phy_trx_ok_counters(_adapter *padapter) +{ +} + +void rtw_reset_phy_rx_counters(_adapter *padapter) +{ + /* reset phy counter */ + phy_set_bb_reg(padapter, 0xF14, BIT16, 0x1); + rtw_msleep_os(10); + phy_set_bb_reg(padapter, 0xF14, BIT16, 0x0); + + phy_set_bb_reg(padapter, 0xD00, BIT27, 0x1);/* reset OFDA FA counter */ + phy_set_bb_reg(padapter, 0xC0C, BIT31, 0x1);/* reset OFDA FA counter */ + phy_set_bb_reg(padapter, 0xD00, BIT27, 0x0); + phy_set_bb_reg(padapter, 0xC0C, BIT31, 0x0); + + phy_set_bb_reg(padapter, 0xA2C, BIT15, 0x0);/* reset CCK FA counter */ + phy_set_bb_reg(padapter, 0xA2C, BIT15, 0x1); +} + +#ifdef DBG_RX_COUNTER_DUMP +void rtw_dump_drv_rx_counters(_adapter *padapter, struct dbg_rx_counter *rx_counter) +{ + struct recv_priv *precvpriv = &padapter->recvpriv; + if (!rx_counter) { + rtw_warn_on(1); + return; + } + rx_counter->rx_pkt_ok = padapter->drv_rx_cnt_ok; + rx_counter->rx_pkt_crc_error = padapter->drv_rx_cnt_crcerror; + rx_counter->rx_pkt_drop = precvpriv->rx_drop - padapter->drv_rx_cnt_drop; +} +void rtw_reset_drv_rx_counters(_adapter *padapter) +{ + struct recv_priv *precvpriv = &padapter->recvpriv; + padapter->drv_rx_cnt_ok = 0; + padapter->drv_rx_cnt_crcerror = 0; + padapter->drv_rx_cnt_drop = precvpriv->rx_drop; +} +void rtw_dump_phy_rxcnts_preprocess(_adapter *padapter, u8 rx_cnt_mode) +{ + u8 initialgain; + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter); + + if ((!(padapter->dump_rx_cnt_mode & DUMP_PHY_RX_COUNTER)) && (rx_cnt_mode & DUMP_PHY_RX_COUNTER)) { + rtw_hal_get_odm_var(padapter, HAL_ODM_INITIAL_GAIN, &initialgain, NULL); + RTW_INFO("%s CurIGValue:0x%02x\n", __func__, initialgain); + rtw_hal_set_odm_var(padapter, HAL_ODM_INITIAL_GAIN, &initialgain, false); + /*disable dynamic functions, such as high power, DIG*/ + rtw_phydm_ability_backup(padapter); + rtw_phydm_func_clr(padapter, (ODM_BB_DIG | ODM_BB_FA_CNT)); + } else if ((padapter->dump_rx_cnt_mode & DUMP_PHY_RX_COUNTER) && (!(rx_cnt_mode & DUMP_PHY_RX_COUNTER))) { + /* turn on phy-dynamic functions */ + rtw_phydm_ability_restore(padapter); + initialgain = 0xff; /* restore RX GAIN */ + rtw_hal_set_odm_var(padapter, HAL_ODM_INITIAL_GAIN, &initialgain, false); + + } +} + +void rtw_dump_rx_counters(_adapter *padapter) +{ + struct dbg_rx_counter rx_counter; + + if (padapter->dump_rx_cnt_mode & DUMP_DRV_RX_COUNTER) { + memset(&rx_counter, 0, sizeof(struct dbg_rx_counter)); + rtw_dump_drv_rx_counters(padapter, &rx_counter); + RTW_INFO("Drv Received packet OK:%d CRC error:%d Drop Packets: %d\n", + rx_counter.rx_pkt_ok, rx_counter.rx_pkt_crc_error, rx_counter.rx_pkt_drop); + rtw_reset_drv_rx_counters(padapter); + } + + if (padapter->dump_rx_cnt_mode & DUMP_MAC_RX_COUNTER) { + memset(&rx_counter, 0, sizeof(struct dbg_rx_counter)); + rtw_dump_mac_rx_counters(padapter, &rx_counter); + RTW_INFO("Mac Received packet OK:%d CRC error:%d FA Counter: %d Drop Packets: %d\n", + rx_counter.rx_pkt_ok, rx_counter.rx_pkt_crc_error, + rx_counter.rx_cck_fa + rx_counter.rx_ofdm_fa + rx_counter.rx_ht_fa, + rx_counter.rx_pkt_drop); + rtw_reset_mac_rx_counters(padapter); + } + + if (padapter->dump_rx_cnt_mode & DUMP_PHY_RX_COUNTER) { + memset(&rx_counter, 0, sizeof(struct dbg_rx_counter)); + rtw_dump_phy_rx_counters(padapter, &rx_counter); + /* RTW_INFO("%s: OFDM_FA =%d\n", __func__, rx_counter.rx_ofdm_fa); */ + /* RTW_INFO("%s: CCK_FA =%d\n", __func__, rx_counter.rx_cck_fa); */ + RTW_INFO("Phy Received packet OK:%d CRC error:%d FA Counter: %d\n", rx_counter.rx_pkt_ok, rx_counter.rx_pkt_crc_error, + rx_counter.rx_ofdm_fa + rx_counter.rx_cck_fa); + rtw_reset_phy_rx_counters(padapter); + } +} +#endif +void rtw_get_noise(_adapter *padapter) +{ +#if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR) + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct noise_info info; + if (rtw_linked_check(padapter)) { + info.bPauseDIG = true; + info.IGIValue = 0x1e; + info.max_time = 100;/* ms */ + info.chan = pmlmeext->cur_channel ;/* rtw_get_oper_ch(padapter); */ + rtw_ps_deny(padapter, PS_DENY_IOCTL); + LeaveAllPowerSaveModeDirect(padapter); + + rtw_hal_set_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &info, false); + /* odm_inband_noise_monitor(podmpriv,true,0x20,100); */ + rtw_ps_deny_cancel(padapter, PS_DENY_IOCTL); + rtw_hal_get_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &(info.chan), &(padapter->recvpriv.noise)); +#ifdef DBG_NOISE_MONITOR + RTW_INFO("chan:%d,noise_level:%d\n", info.chan, padapter->recvpriv.noise); +#endif + } +#endif + +} +u8 rtw_get_current_tx_sgi(_adapter *padapter, u8 macid) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct PHY_DM_STRUCT *pDM_Odm = &pHalData->odmpriv; + struct _rate_adaptive_table_ *pRA_Table = &pDM_Odm->dm_ra_table; + u8 curr_tx_sgi = 0; + + curr_tx_sgi = odm_ra_get_decision_rate_8188e(pDM_Odm, macid); + + return curr_tx_sgi; +} + +u8 rtw_get_current_tx_rate(_adapter *padapter, u8 macid) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct PHY_DM_STRUCT *pDM_Odm = &pHalData->odmpriv; + struct _rate_adaptive_table_ *pRA_Table = &pDM_Odm->dm_ra_table; + u8 rate_id = 0; + +#if (RATE_ADAPTIVE_SUPPORT == 1) + rate_id = odm_ra_get_decision_rate_8188e(pDM_Odm, macid); +#else + rate_id = (pRA_Table->link_tx_rate[macid]) & 0x7f; +#endif + + return rate_id; + +} + +void update_IOT_info(_adapter *padapter) +{ + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + switch (pmlmeinfo->assoc_AP_vendor) { + case HT_IOT_PEER_MARVELL: + pmlmeinfo->turboMode_cts2self = 1; + pmlmeinfo->turboMode_rtsen = 0; + break; + + case HT_IOT_PEER_RALINK: + pmlmeinfo->turboMode_cts2self = 0; + pmlmeinfo->turboMode_rtsen = 1; + /* disable high power */ + rtw_phydm_func_clr(padapter, ODM_BB_DYNAMIC_TXPWR); + break; + case HT_IOT_PEER_REALTEK: + /* rtw_write16(padapter, 0x4cc, 0xffff); */ + /* rtw_write16(padapter, 0x546, 0x01c0); */ + /* disable high power */ + rtw_phydm_func_clr(padapter, ODM_BB_DYNAMIC_TXPWR); + break; + default: + pmlmeinfo->turboMode_cts2self = 0; + pmlmeinfo->turboMode_rtsen = 1; + break; + } + +} +#ifdef CONFIG_AUTO_CHNL_SEL_NHM +void rtw_acs_start(_adapter *padapter, bool bStart) +{ + if (bStart) { + ACS_OP acs_op = ACS_INIT; + + rtw_hal_set_odm_var(padapter, HAL_ODM_AUTO_CHNL_SEL, &acs_op, true); + rtw_set_acs_channel(padapter, 0); + SET_ACS_STATE(padapter, ACS_ENABLE); + } else { + SET_ACS_STATE(padapter, ACS_DISABLE); +#ifdef DBG_AUTO_CHNL_SEL_NHM + if (1) { + u8 best_24g_ch = 0; + u8 best_5g_ch = 0; + + rtw_hal_get_odm_var(padapter, HAL_ODM_AUTO_CHNL_SEL, &(best_24g_ch), &(best_5g_ch)); + RTW_INFO("[ACS-"ADPT_FMT"] Best 2.4G CH:%u\n", ADPT_ARG(padapter), best_24g_ch); + RTW_INFO("[ACS-"ADPT_FMT"] Best 5G CH:%u\n", ADPT_ARG(padapter), best_5g_ch); + } +#endif + } +} +#endif + +/* TODO: merge with phydm, see odm_SetCrystalCap() */ +void hal_set_crystal_cap(_adapter *adapter, u8 crystal_cap) +{ + crystal_cap = crystal_cap & 0x3F; + + switch (rtw_get_chip_type(adapter)) { + case RTL8188E: + case RTL8188F: + /* write 0x24[16:11] = 0x24[22:17] = CrystalCap */ + phy_set_bb_reg(adapter, REG_AFE_XTAL_CTRL, 0x007FF800, (crystal_cap | (crystal_cap << 6))); + break; + default: + rtw_warn_on(1); + } +} + +int hal_spec_init(_adapter *adapter) +{ + u8 interface_type = 0; + int ret = _SUCCESS; + + interface_type = rtw_get_intf_type(adapter); + + switch (rtw_get_chip_type(adapter)) { + case RTL8188E: + init_hal_spec_8188e(adapter); + break; + default: + RTW_ERR("%s: unknown chip_type:%u\n" + , __func__, rtw_get_chip_type(adapter)); + ret = _FAIL; + break; + } + return ret; +} + +static const char *const _band_cap_str[] = { + /* BIT0 */"2G", + /* BIT1 */"5G", +}; + +static const char *const _bw_cap_str[] = { + /* BIT0 */"5M", + /* BIT1 */"10M", + /* BIT2 */"20M", + /* BIT3 */"40M", + /* BIT4 */"80M", + /* BIT5 */"160M", + /* BIT6 */"80_80M", +}; + +static const char *const _proto_cap_str[] = { + /* BIT0 */"b", + /* BIT1 */"g", + /* BIT2 */"n", + /* BIT3 */"ac", +}; + +static const char *const _wl_func_str[] = { + /* BIT0 */"P2P", + /* BIT1 */"MIRACAST", + /* BIT2 */"TDLS", + /* BIT3 */"FTM", +}; + +void dump_hal_spec(void *sel, _adapter *adapter) +{ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + int i; + + RTW_PRINT_SEL(sel, "macid_num:%u\n", hal_spec->macid_num); + RTW_PRINT_SEL(sel, "sec_cap:0x%02x\n", hal_spec->sec_cap); + RTW_PRINT_SEL(sel, "sec_cam_ent_num:%u\n", hal_spec->sec_cam_ent_num); + RTW_PRINT_SEL(sel, "rfpath_num_2g:%u\n", hal_spec->rfpath_num_2g); + RTW_PRINT_SEL(sel, "rfpath_num_5g:%u\n", hal_spec->rfpath_num_5g); + RTW_PRINT_SEL(sel, "max_tx_cnt:%u\n", hal_spec->max_tx_cnt); + RTW_PRINT_SEL(sel, "tx_nss_num:%u\n", hal_spec->tx_nss_num); + RTW_PRINT_SEL(sel, "rx_nss_num:%u\n", hal_spec->rx_nss_num); + + RTW_PRINT_SEL(sel, "band_cap:"); + for (i = 0; i < BAND_CAP_BIT_NUM; i++) { + if (((hal_spec->band_cap) >> i) & BIT0 && _band_cap_str[i]) + _RTW_PRINT_SEL(sel, "%s ", _band_cap_str[i]); + } + _RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "bw_cap:"); + for (i = 0; i < BW_CAP_BIT_NUM; i++) { + if (((hal_spec->bw_cap) >> i) & BIT0 && _bw_cap_str[i]) + _RTW_PRINT_SEL(sel, "%s ", _bw_cap_str[i]); + } + _RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "proto_cap:"); + for (i = 0; i < PROTO_CAP_BIT_NUM; i++) { + if (((hal_spec->proto_cap) >> i) & BIT0 && _proto_cap_str[i]) + _RTW_PRINT_SEL(sel, "%s ", _proto_cap_str[i]); + } + _RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "wl_func:"); + for (i = 0; i < WL_FUNC_BIT_NUM; i++) { + if (((hal_spec->wl_func) >> i) & BIT0 && _wl_func_str[i]) + _RTW_PRINT_SEL(sel, "%s ", _wl_func_str[i]); + } + _RTW_PRINT_SEL(sel, "\n"); +} + +inline bool hal_chk_band_cap(_adapter *adapter, u8 cap) +{ + return GET_HAL_SPEC(adapter)->band_cap & cap; +} + +inline bool hal_chk_bw_cap(_adapter *adapter, u8 cap) +{ + return GET_HAL_SPEC(adapter)->bw_cap & cap; +} + +inline bool hal_chk_proto_cap(_adapter *adapter, u8 cap) +{ + return GET_HAL_SPEC(adapter)->proto_cap & cap; +} + +inline bool hal_chk_wl_func(_adapter *adapter, u8 func) +{ + return GET_HAL_SPEC(adapter)->wl_func & func; +} + +inline bool hal_is_band_support(_adapter *adapter, u8 band) +{ + return GET_HAL_SPEC(adapter)->band_cap & band_to_band_cap(band); +} + +inline bool hal_is_bw_support(_adapter *adapter, u8 bw) +{ + return GET_HAL_SPEC(adapter)->bw_cap & ch_width_to_bw_cap(bw); +} + +inline bool hal_is_wireless_mode_support(_adapter *adapter, u8 mode) +{ + u8 proto_cap = GET_HAL_SPEC(adapter)->proto_cap; + + if (mode == WIRELESS_11B) + if ((proto_cap & PROTO_CAP_11B) && hal_chk_band_cap(adapter, BAND_CAP_2G)) + return 1; + + if (mode == WIRELESS_11G) + if ((proto_cap & PROTO_CAP_11G) && hal_chk_band_cap(adapter, BAND_CAP_2G)) + return 1; + + if (mode == WIRELESS_11A) + if ((proto_cap & PROTO_CAP_11G) && hal_chk_band_cap(adapter, BAND_CAP_5G)) + return 1; + + if (mode == WIRELESS_11_24N) + if ((proto_cap & PROTO_CAP_11N) && hal_chk_band_cap(adapter, BAND_CAP_2G)) + return 1; + + if (mode == WIRELESS_11_5N) + if ((proto_cap & PROTO_CAP_11N) && hal_chk_band_cap(adapter, BAND_CAP_5G)) + return 1; + + if (mode == WIRELESS_11AC) + if ((proto_cap & PROTO_CAP_11AC) && hal_chk_band_cap(adapter, BAND_CAP_5G)) + return 1; + + return 0; +} + +/* +* hal_largest_bw - starting from in_bw, get largest bw supported by HAL +* @adapter: +* @in_bw: starting bw, value of CHANNEL_WIDTH +* +* Returns: value of CHANNEL_WIDTH +*/ +u8 hal_largest_bw(_adapter *adapter, u8 in_bw) +{ + for (; in_bw > CHANNEL_WIDTH_20; in_bw--) { + if (hal_is_bw_support(adapter, in_bw)) + break; + } + + if (!hal_is_bw_support(adapter, in_bw)) + rtw_warn_on(1); + + return in_bw; +} + +void rtw_hal_correct_tsf(_adapter *padapter, u8 hw_port, u64 tsf) +{ + if (hw_port == HW_PORT0) { + /*disable related TSF function*/ + rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL) & (~EN_BCN_FUNCTION)); + + rtw_write32(padapter, REG_TSFTR, tsf); + rtw_write32(padapter, REG_TSFTR + 4, tsf >> 32); + + /*enable related TSF function*/ + rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL) | EN_BCN_FUNCTION); + } else if (hw_port == HW_PORT1) { + /*disable related TSF function*/ + rtw_write8(padapter, REG_BCN_CTRL_1, rtw_read8(padapter, REG_BCN_CTRL_1) & (~EN_BCN_FUNCTION)); + + rtw_write32(padapter, REG_TSFTR1, tsf); + rtw_write32(padapter, REG_TSFTR1 + 4, tsf >> 32); + + /*enable related TSF function*/ + rtw_write8(padapter, REG_BCN_CTRL_1, rtw_read8(padapter, REG_BCN_CTRL_1) | EN_BCN_FUNCTION); + } else + RTW_INFO("%s-[WARN] "ADPT_FMT" invalid hw_port:%d\n", __func__, ADPT_ARG(padapter), hw_port); +} + +void ResumeTxBeacon(_adapter *padapter) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + + + /* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */ + /* which should be read from register to a global variable. */ + + + pHalData->RegFwHwTxQCtrl |= BIT(6); + rtw_write8(padapter, REG_FWHW_TXQ_CTRL + 2, pHalData->RegFwHwTxQCtrl); + /*TBTT hold time :4ms 0x540[19:8]*/ + rtw_write8(padapter, REG_TBTT_PROHIBIT + 1, + TBTT_PROBIHIT_HOLD_TIME & 0xFF); + rtw_write8(padapter, REG_TBTT_PROHIBIT + 2, + (rtw_read8(padapter, REG_TBTT_PROHIBIT + 2) & 0xF0) | (TBTT_PROBIHIT_HOLD_TIME >> 8)); +} + +void StopTxBeacon(_adapter *padapter) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + + + /* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */ + /* which should be read from register to a global variable. */ + + + pHalData->RegFwHwTxQCtrl &= ~BIT(6); + rtw_write8(padapter, REG_FWHW_TXQ_CTRL + 2, pHalData->RegFwHwTxQCtrl); + rtw_write8(padapter, REG_TBTT_PROHIBIT + 1, 0x64); + rtw_write8(padapter, REG_TBTT_PROHIBIT + 2, + (rtw_read8(padapter, REG_TBTT_PROHIBIT + 2) & 0xF0)); + + /*CheckFwRsvdPageContent(padapter);*/ /* 2010.06.23. Added by tynli. */ +} + +#ifdef CONFIG_MI_WITH_MBSSID_CAM /*HW port0 - MBSS*/ +void hw_var_set_opmode_mbid(_adapter *Adapter, u8 mode) +{ + RTW_INFO("%s()-"ADPT_FMT" mode = %d\n", __func__, ADPT_ARG(Adapter), mode); + + rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR) & (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN))); + + /* disable Port0 TSF update*/ + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL) | DIS_TSF_UDT); + + /* set net_type */ + Set_MSR(Adapter, mode); + + if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) { + if (!rtw_mi_check_status(Adapter, MI_AP_MODE)) + StopTxBeacon(Adapter); + + rtw_write8(Adapter, REG_BCN_CTRL, DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_ATIM);/*disable atim wnd*/ + } else if (mode == _HW_STATE_ADHOC_) { + ResumeTxBeacon(Adapter); + rtw_write8(Adapter, REG_BCN_CTRL, DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB); + + } else if (mode == _HW_STATE_AP_) { + ResumeTxBeacon(Adapter); + + rtw_write8(Adapter, REG_BCN_CTRL, DIS_TSF_UDT | DIS_BCNQ_SUB); + + /*enable to rx data frame*/ + rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); + + /*Beacon Control related register for first time*/ + rtw_write8(Adapter, REG_BCNDMATIM, 0x02); /* 2ms */ + + /*rtw_write8(Adapter, REG_BCN_MAX_ERR, 0xFF);*/ + rtw_write8(Adapter, REG_ATIMWND, 0x0a); /* 10ms */ + rtw_write16(Adapter, REG_BCNTCFG, 0x00); + rtw_write16(Adapter, REG_TBTT_PROHIBIT, 0xff04); + rtw_write16(Adapter, REG_TSFTR_SYN_OFFSET, 0x7fff);/* +32767 (~32ms) */ + + /*reset TSF*/ + rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(0)); + + /*enable BCN0 Function for if1*/ + /*don't enable update TSF0 for if1 (due to TSF update when beacon,probe rsp are received)*/ + rtw_write8(Adapter, REG_BCN_CTRL, (DIS_TSF_UDT | EN_BCN_FUNCTION | EN_TXBCN_RPT | DIS_BCNQ_SUB)); + } +} +#endif + +#ifdef CONFIG_ANTENNA_DIVERSITY +u8 rtw_hal_antdiv_before_linked(_adapter *padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + u8 cur_ant, change_ant; + + if (!pHalData->AntDivCfg) + return false; + + if (pHalData->sw_antdiv_bl_state == 0) { + pHalData->sw_antdiv_bl_state = 1; + + rtw_hal_get_odm_var(padapter, HAL_ODM_ANTDIV_SELECT, &cur_ant, NULL); + change_ant = (cur_ant == MAIN_ANT) ? AUX_ANT : MAIN_ANT; + + return rtw_antenna_select_cmd(padapter, change_ant, false); + } + + pHalData->sw_antdiv_bl_state = 0; + return false; +} + +void rtw_hal_antdiv_rssi_compared(_adapter *padapter, WLAN_BSSID_EX *dst, WLAN_BSSID_EX *src) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + if (pHalData->AntDivCfg) { + /*RTW_INFO("update_network=> org-RSSI(%d), new-RSSI(%d)\n", dst->Rssi, src->Rssi);*/ + /*select optimum_antenna for before linked =>For antenna diversity*/ + if (dst->Rssi >= src->Rssi) {/*keep org parameter*/ + src->Rssi = dst->Rssi; + src->PhyInfo.Optimum_antenna = dst->PhyInfo.Optimum_antenna; + } + } +} +#endif + +#ifdef CONFIG_PHY_CAPABILITY_QUERY +static void rtw_dump_phy_cap_by_phydmapi(void *sel, _adapter *adapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter); + struct phy_spec_t *phy_spec = &pHalData->phy_spec; + + RTW_PRINT_SEL(sel, "[PHY SPEC] TRx Capability : 0x%08x\n", phy_spec->trx_cap); + RTW_PRINT_SEL(sel, "[PHY SPEC] Tx Stream Num Index : %d\n", (phy_spec->trx_cap >> 24) & 0xFF); /*Tx Stream Num Index [31:24]*/ + RTW_PRINT_SEL(sel, "[PHY SPEC] Rx Stream Num Index : %d\n", (phy_spec->trx_cap >> 16) & 0xFF); /*Rx Stream Num Index [23:16]*/ + RTW_PRINT_SEL(sel, "[PHY SPEC] Tx Path Num Index : %d\n", (phy_spec->trx_cap >> 8) & 0xFF);/*Tx Path Num Index [15:8]*/ + RTW_PRINT_SEL(sel, "[PHY SPEC] Rx Path Num Index : %d\n\n", (phy_spec->trx_cap & 0xFF));/*Rx Path Num Index [7:0]*/ + + RTW_PRINT_SEL(sel, "[PHY SPEC] STBC Capability : 0x%08x\n", phy_spec->stbc_cap); + RTW_PRINT_SEL(sel, "[PHY SPEC] VHT STBC Tx : %s\n", ((phy_spec->stbc_cap >> 24) & 0xFF) ? "Supported" : "N/A"); /*VHT STBC Tx [31:24]*/ + /*VHT STBC Rx [23:16] + 0 = not support + 1 = support for 1 spatial stream + 2 = support for 1 or 2 spatial streams + 3 = support for 1 or 2 or 3 spatial streams + 4 = support for 1 or 2 or 3 or 4 spatial streams*/ + RTW_PRINT_SEL(sel, "[PHY SPEC] VHT STBC Rx :%d\n", ((phy_spec->stbc_cap >> 16) & 0xFF)); + RTW_PRINT_SEL(sel, "[PHY SPEC] HT STBC Tx : %s\n", ((phy_spec->stbc_cap >> 8) & 0xFF) ? "Supported" : "N/A"); /*HT STBC Tx [15:8]*/ + /*HT STBC Rx [7:0] + 0 = not support + 1 = support for 1 spatial stream + 2 = support for 1 or 2 spatial streams + 3 = support for 1 or 2 or 3 spatial streams*/ + RTW_PRINT_SEL(sel, "[PHY SPEC] HT STBC Rx : %d\n\n", (phy_spec->stbc_cap & 0xFF)); + + RTW_PRINT_SEL(sel, "[PHY SPEC] LDPC Capability : 0x%08x\n", phy_spec->ldpc_cap); + RTW_PRINT_SEL(sel, "[PHY SPEC] VHT LDPC Tx : %s\n", ((phy_spec->ldpc_cap >> 24) & 0xFF) ? "Supported" : "N/A"); /*VHT LDPC Tx [31:24]*/ + RTW_PRINT_SEL(sel, "[PHY SPEC] VHT LDPC Rx : %s\n", ((phy_spec->ldpc_cap >> 16) & 0xFF) ? "Supported" : "N/A"); /*VHT LDPC Rx [23:16]*/ + RTW_PRINT_SEL(sel, "[PHY SPEC] HT LDPC Tx : %s\n", ((phy_spec->ldpc_cap >> 8) & 0xFF) ? "Supported" : "N/A"); /*HT LDPC Tx [15:8]*/ + RTW_PRINT_SEL(sel, "[PHY SPEC] HT LDPC Rx : %s\n\n", (phy_spec->ldpc_cap & 0xFF) ? "Supported" : "N/A"); /*HT LDPC Rx [7:0]*/ + #ifdef CONFIG_BEAMFORMING + RTW_PRINT_SEL(sel, "[PHY SPEC] TxBF Capability : 0x%08x\n", phy_spec->txbf_cap); + RTW_PRINT_SEL(sel, "[PHY SPEC] VHT MU Bfer : %s\n", ((phy_spec->txbf_cap >> 28) & 0xF) ? "Supported" : "N/A"); /*VHT MU Bfer [31:28]*/ + RTW_PRINT_SEL(sel, "[PHY SPEC] VHT MU Bfee : %s\n", ((phy_spec->txbf_cap >> 24) & 0xF) ? "Supported" : "N/A"); /*VHT MU Bfee [27:24]*/ + RTW_PRINT_SEL(sel, "[PHY SPEC] VHT SU Bfer : %s\n", ((phy_spec->txbf_cap >> 20) & 0xF) ? "Supported" : "N/A"); /*VHT SU Bfer [23:20]*/ + RTW_PRINT_SEL(sel, "[PHY SPEC] VHT SU Bfee : %s\n", ((phy_spec->txbf_cap >> 16) & 0xF) ? "Supported" : "N/A"); /*VHT SU Bfee [19:16]*/ + RTW_PRINT_SEL(sel, "[PHY SPEC] HT Bfer : %s\n", ((phy_spec->txbf_cap >> 4) & 0xF) ? "Supported" : "N/A"); /*HT Bfer [7:4]*/ + RTW_PRINT_SEL(sel, "[PHY SPEC] HT Bfee : %s\n\n", (phy_spec->txbf_cap & 0xF) ? "Supported" : "N/A"); /*HT Bfee [3:0]*/ + + RTW_PRINT_SEL(sel, "[PHY SPEC] TxBF parameter : 0x%08x\n", phy_spec->txbf_param); + RTW_PRINT_SEL(sel, "[PHY SPEC] VHT Sounding Dim : %d\n", (phy_spec->txbf_param >> 24) & 0xFF); /*VHT Sounding Dim [31:24]*/ + RTW_PRINT_SEL(sel, "[PHY SPEC] VHT Steering Ant : %d\n", (phy_spec->txbf_param >> 16) & 0xFF); /*VHT Steering Ant [23:16]*/ + RTW_PRINT_SEL(sel, "[PHY SPEC] HT Sounding Dim : %d\n", (phy_spec->txbf_param >> 8) & 0xFF); /*HT Sounding Dim [15:8]*/ + RTW_PRINT_SEL(sel, "[PHY SPEC] HT Steering Ant : %d\n", phy_spec->txbf_param & 0xFF); /*HT Steering Ant [7:0]*/ + #endif +} +#else +static void rtw_dump_phy_cap_by_hal(void *sel, _adapter *adapter) +{ + u8 phy_cap = false; + + /* STBC */ + rtw_hal_get_def_var(adapter, HAL_DEF_TX_STBC, (u8 *)&phy_cap); + RTW_PRINT_SEL(sel, "[HAL] STBC Tx : %s\n", (phy_cap) ? "Supported" : "N/A"); + + phy_cap = false; + rtw_hal_get_def_var(adapter, HAL_DEF_RX_STBC, (u8 *)&phy_cap); + RTW_PRINT_SEL(sel, "[HAL] STBC Rx : %s\n\n", (phy_cap) ? "Supported" : "N/A"); + + /* LDPC support */ + phy_cap = false; + rtw_hal_get_def_var(adapter, HAL_DEF_TX_LDPC, (u8 *)&phy_cap); + RTW_PRINT_SEL(sel, "[HAL] LDPC Tx : %s\n", (phy_cap) ? "Supported" : "N/A"); + + phy_cap = false; + rtw_hal_get_def_var(adapter, HAL_DEF_RX_LDPC, (u8 *)&phy_cap); + RTW_PRINT_SEL(sel, "[HAL] LDPC Rx : %s\n\n", (phy_cap) ? "Supported" : "N/A"); + + #ifdef CONFIG_BEAMFORMING + phy_cap = false; + rtw_hal_get_def_var(adapter, HAL_DEF_EXPLICIT_BEAMFORMER, (u8 *)&phy_cap); + RTW_PRINT_SEL(sel, "[HAL] Beamformer: %s\n", (phy_cap) ? "Supported" : "N/A"); + + phy_cap = false; + rtw_hal_get_def_var(adapter, HAL_DEF_EXPLICIT_BEAMFORMEE, (u8 *)&phy_cap); + RTW_PRINT_SEL(sel, "[HAL] Beamformee: %s\n", (phy_cap) ? "Supported" : "N/A"); + + phy_cap = false; + rtw_hal_get_def_var(adapter, HAL_DEF_VHT_MU_BEAMFORMER, &phy_cap); + RTW_PRINT_SEL(sel, "[HAL] VHT MU Beamformer: %s\n", (phy_cap) ? "Supported" : "N/A"); + + phy_cap = false; + rtw_hal_get_def_var(adapter, HAL_DEF_VHT_MU_BEAMFORMEE, &phy_cap); + RTW_PRINT_SEL(sel, "[HAL] VHT MU Beamformee: %s\n", (phy_cap) ? "Supported" : "N/A"); + #endif +} +#endif +void rtw_dump_phy_cap(void *sel, _adapter *adapter) +{ + RTW_PRINT_SEL(sel, "\n ======== PHY Capability ========\n"); +#ifdef CONFIG_PHY_CAPABILITY_QUERY + rtw_dump_phy_cap_by_phydmapi(sel, adapter); +#else + rtw_dump_phy_cap_by_hal(sel, adapter); +#endif +} + diff --git a/drivers/staging/rtl8188eu/hal/hal_com_c2h.h b/drivers/staging/rtl8188eu/hal/hal_com_c2h.h new file mode 100644 index 000000000000..172c15258e13 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal_com_c2h.h @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#ifndef __COMMON_C2H_H__ +#define __COMMON_C2H_H__ + +#define C2H_TYPE_REG 0 +#define C2H_TYPE_PKT 1 + +/* +* C2H event format: +* Fields TRIGGER PAYLOAD SEQ PLEN ID +* BITS [127:120] [119:16] [15:8] [7:4] [3:0] +*/ +#define C2H_ID(_c2h) LE_BITS_TO_1BYTE(((u8*)(_c2h)), 0, 4) +#define C2H_PLEN(_c2h) LE_BITS_TO_1BYTE(((u8*)(_c2h)), 4, 4) +#define C2H_SEQ(_c2h) LE_BITS_TO_1BYTE(((u8*)(_c2h)) + 1, 0, 8) +#define C2H_PAYLOAD(_c2h) (((u8*)(_c2h)) + 2) + +#define SET_C2H_ID(_c2h, _val) SET_BITS_TO_LE_1BYTE(((u8*)(_c2h)), 0, 4, _val) +#define SET_C2H_PLEN(_c2h, _val) SET_BITS_TO_LE_1BYTE(((u8*)(_c2h)), 4, 4, _val) +#define SET_C2H_SEQ(_c2h, _val) SET_BITS_TO_LE_1BYTE(((u8*)(_c2h)) + 1 , 0, 8, _val) + +/* +* C2H event format: +* Fields TRIGGER PLEN PAYLOAD SEQ ID +* BITS [127:120] [119:112] [111:16] [15:8] [7:0] +*/ +#define C2H_ID_88XX(_c2h) LE_BITS_TO_1BYTE(((u8*)(_c2h)), 0, 8) +#define C2H_SEQ_88XX(_c2h) LE_BITS_TO_1BYTE(((u8*)(_c2h)) + 1, 0, 8) +#define C2H_PAYLOAD_88XX(_c2h) (((u8*)(_c2h)) + 2) +#define C2H_PLEN_88XX(_c2h) LE_BITS_TO_1BYTE(((u8*)(_c2h)) + 14, 0, 8) +#define C2H_TRIGGER_88XX(_c2h) LE_BITS_TO_1BYTE(((u8*)(_c2h)) + 15, 0, 8) + +#define SET_C2H_ID_88XX(_c2h, _val) SET_BITS_TO_LE_1BYTE(((u8*)(_c2h)), 0, 8, _val) +#define SET_C2H_SEQ_88XX(_c2h, _val) SET_BITS_TO_LE_1BYTE(((u8*)(_c2h)) + 1, 0, 8, _val) +#define SET_C2H_PLEN_88XX(_c2h, _val) SET_BITS_TO_LE_1BYTE(((u8*)(_c2h)) + 14, 0, 8, _val) + +typedef enum _C2H_EVT { + C2H_DBG = 0x00, + C2H_LB = 0x01, + C2H_TXBF = 0x02, + C2H_CCX_TX_RPT = 0x03, + C2H_AP_REQ_TXRPT = 0x04, + C2H_FW_SCAN_COMPLETE = 0x7, + C2H_BT_INFO = 0x09, + C2H_BT_MP_INFO = 0x0B, + C2H_RA_RPT = 0x0C, + C2H_SPC_STAT = 0x0D, + C2H_RA_PARA_RPT = 0x0E, + C2H_FW_CHNL_SWITCH_COMPLETE = 0x10, + C2H_IQK_FINISH = 0x11, + C2H_MAILBOX_STATUS = 0x15, + C2H_P2P_RPORT = 0x16, + C2H_MCC = 0x17, + C2H_MAC_HIDDEN_RPT = 0x19, + C2H_MAC_HIDDEN_RPT_2 = 0x1A, + C2H_BCN_EARLY_RPT = 0x1E, + C2H_DEFEATURE_DBG = 0x22, + C2H_CUSTOMER_STR_RPT = 0x24, + C2H_CUSTOMER_STR_RPT_2 = 0x25, + C2H_DEFEATURE_RSVD = 0xFD, + C2H_EXTEND = 0xff, +} C2H_EVT; + +typedef enum _EXTEND_C2H_EVT { + EXTEND_C2H_DBG_PRINT = 0 +} EXTEND_C2H_EVT; + +#define C2H_REG_LEN 16 + +/* C2H_IQK_FINISH, 0x11 */ +#define IQK_OFFLOAD_LEN 1 +void c2h_iqk_offload(_adapter *adapter, u8 *data, u8 len); +int c2h_iqk_offload_wait(_adapter *adapter, u32 timeout_ms); +#define rtl8812_iqk_wait c2h_iqk_offload_wait /* TODO: remove this after phydm call c2h_iqk_offload_wait instead */ + +#ifdef CONFIG_RTW_MAC_HIDDEN_RPT +/* C2H_MAC_HIDDEN_RPT, 0x19 */ +#define MAC_HIDDEN_RPT_LEN 8 +int c2h_mac_hidden_rpt_hdl(_adapter *adapter, u8 *data, u8 len); + +/* C2H_MAC_HIDDEN_RPT_2, 0x1A */ +#define MAC_HIDDEN_RPT_2_LEN 5 +int c2h_mac_hidden_rpt_2_hdl(_adapter *adapter, u8 *data, u8 len); +int hal_read_mac_hidden_rpt(_adapter *adapter); +#endif /* CONFIG_RTW_MAC_HIDDEN_RPT */ + +/* C2H_DEFEATURE_DBG, 0x22 */ +#define DEFEATURE_DBG_LEN 1 +int c2h_defeature_dbg_hdl(_adapter *adapter, u8 *data, u8 len); + +#ifdef CONFIG_RTW_CUSTOMER_STR +/* C2H_CUSTOMER_STR_RPT, 0x24 */ +#define CUSTOMER_STR_RPT_LEN 8 +int c2h_customer_str_rpt_hdl(_adapter *adapter, u8 *data, u8 len); + +/* C2H_CUSTOMER_STR_RPT_2, 0x25 */ +#define CUSTOMER_STR_RPT_2_LEN 8 +int c2h_customer_str_rpt_2_hdl(_adapter *adapter, u8 *data, u8 len); +#endif /* CONFIG_RTW_CUSTOMER_STR */ + +#endif /* __COMMON_C2H_H__ */ diff --git a/drivers/staging/rtl8188eu/hal/hal_com_phycfg.c b/drivers/staging/rtl8188eu/hal/hal_com_phycfg.c new file mode 100644 index 000000000000..5ad88c012c73 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal_com_phycfg.c @@ -0,0 +1,5150 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#define _HAL_COM_PHYCFG_C_ + +#include +#include + +#define PG_TXPWR_MSB_DIFF_S4BIT(_pg_v) (((_pg_v) & 0xf0) >> 4) +#define PG_TXPWR_LSB_DIFF_S4BIT(_pg_v) ((_pg_v) & 0x0f) +#define PG_TXPWR_MSB_DIFF_TO_S8BIT(_pg_v) ((PG_TXPWR_MSB_DIFF_S4BIT(_pg_v) & BIT3) ? (PG_TXPWR_MSB_DIFF_S4BIT(_pg_v) | 0xF0) : PG_TXPWR_MSB_DIFF_S4BIT(_pg_v)) +#define PG_TXPWR_LSB_DIFF_TO_S8BIT(_pg_v) ((PG_TXPWR_LSB_DIFF_S4BIT(_pg_v) & BIT3) ? (PG_TXPWR_LSB_DIFF_S4BIT(_pg_v) | 0xF0) : PG_TXPWR_LSB_DIFF_S4BIT(_pg_v)) +#define IS_PG_TXPWR_BASE_INVALID(_base) ((_base) > 63) +#define IS_PG_TXPWR_DIFF_INVALID(_diff) ((_diff) > 7 || (_diff) < -8) +#define PG_TXPWR_INVALID_BASE 255 +#define PG_TXPWR_INVALID_DIFF 8 + +#if !IS_PG_TXPWR_BASE_INVALID(PG_TXPWR_INVALID_BASE) +#error "PG_TXPWR_BASE definition has problem" +#endif + +#if !IS_PG_TXPWR_DIFF_INVALID(PG_TXPWR_INVALID_DIFF) +#error "PG_TXPWR_DIFF definition has problem" +#endif + +#define PG_TXPWR_SRC_PG_DATA 0 +#define PG_TXPWR_SRC_IC_DEF 1 +#define PG_TXPWR_SRC_DEF 2 +#define PG_TXPWR_SRC_NUM 3 + +static const char *const _pg_txpwr_src_str[] = { + "PG_DATA", + "IC_DEF", + "DEF", + "UNKNOWN" +}; + +#define pg_txpwr_src_str(src) (((src) >= PG_TXPWR_SRC_NUM) ? _pg_txpwr_src_str[PG_TXPWR_SRC_NUM] : _pg_txpwr_src_str[(src)]) + +#ifndef DBG_PG_TXPWR_READ +#define DBG_PG_TXPWR_READ 0 +#endif + +void dump_pg_txpwr_info_2g(void *sel, TxPowerInfo24G *txpwr_info, u8 rfpath_num, u8 max_tx_cnt) +{ + int path, group, tx_idx; + + RTW_PRINT_SEL(sel, "2.4G\n"); + RTW_PRINT_SEL(sel, "CCK-1T base:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (group = 0; group < MAX_CHNL_GROUP_24G; group++) + _RTW_PRINT_SEL(sel, "G%02d ", group); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (group = 0; group < MAX_CHNL_GROUP_24G; group++) + _RTW_PRINT_SEL(sel, "%3u ", txpwr_info->IndexCCK_Base[path][group]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "CCK diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) + _RTW_PRINT_SEL(sel, "%dT ", path + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->CCK_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "BW40-1S base:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (group = 0; group < MAX_CHNL_GROUP_24G - 1; group++) + _RTW_PRINT_SEL(sel, "G%02d ", group); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (group = 0; group < MAX_CHNL_GROUP_24G - 1; group++) + _RTW_PRINT_SEL(sel, "%3u ", txpwr_info->IndexBW40_Base[path][group]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "OFDM diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) + _RTW_PRINT_SEL(sel, "%dT ", path + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->OFDM_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "BW20 diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) + _RTW_PRINT_SEL(sel, "%dS ", path + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->BW20_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "BW40 diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) + _RTW_PRINT_SEL(sel, "%dS ", path + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->BW40_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); +} + +void dump_pg_txpwr_info_5g(void *sel, TxPowerInfo5G *txpwr_info, u8 rfpath_num, u8 max_tx_cnt) +{ + int path, group, tx_idx; + + RTW_PRINT_SEL(sel, "5G\n"); + RTW_PRINT_SEL(sel, "BW40-1S base:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (group = 0; group < MAX_CHNL_GROUP_5G; group++) + _RTW_PRINT_SEL(sel, "G%02d ", group); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (group = 0; group < MAX_CHNL_GROUP_5G; group++) + _RTW_PRINT_SEL(sel, "%3u ", txpwr_info->IndexBW40_Base[path][group]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "OFDM diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) + _RTW_PRINT_SEL(sel, "%dT ", path + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->OFDM_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "BW20 diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) + _RTW_PRINT_SEL(sel, "%dS ", path + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->BW20_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "BW40 diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) + _RTW_PRINT_SEL(sel, "%dS ", path + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->BW40_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "BW80 diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) + _RTW_PRINT_SEL(sel, "%dS ", path + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->BW80_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "BW160 diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) + _RTW_PRINT_SEL(sel, "%dS ", path + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", txpwr_info->BW160_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); +} + +static const struct map_t pg_txpwr_def_info = + MAP_ENT(0xB8, 1, 0xFF + , MAPSEG_ARRAY_ENT(0x10, 168, + 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x24, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, + 0x04, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, + 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x24, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x2A, 0x2A, 0x2A, 0x2A, + 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x04, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x24, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, + 0x2A, 0x2A, 0x2A, 0x2A, 0x04, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x2D, 0x2D, + 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x24, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x04, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE) + ); + +static const struct map_t rtl8188e_pg_txpwr_def_info = + MAP_ENT(0xB8, 1, 0xFF + , MAPSEG_ARRAY_ENT(0x10, 12, + 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x24) + ); + +const struct map_t *hal_pg_txpwr_def_info(_adapter *adapter) +{ + u8 interface_type = 0; + const struct map_t *map = NULL; + + interface_type = rtw_get_intf_type(adapter); + + switch (rtw_get_chip_type(adapter)) { + case RTL8188E: + map = &rtl8188e_pg_txpwr_def_info; + break; + } + + if (map == NULL) { + RTW_ERR("%s: unknown chip_type:%u\n" + , __func__, rtw_get_chip_type(adapter)); + rtw_warn_on(1); + } + + return map; +} + +static u8 hal_chk_pg_txpwr_info_2g(_adapter *adapter, TxPowerInfo24G *pwr_info) +{ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + u8 path, group, tx_idx; + + if (pwr_info == NULL || !hal_chk_band_cap(adapter, BAND_CAP_2G)) + return _SUCCESS; + + for (path = 0; path < MAX_RF_PATH; path++) { + if (!HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path)) + continue; + for (group = 0; group < MAX_CHNL_GROUP_24G; group++) { + if (IS_PG_TXPWR_BASE_INVALID(pwr_info->IndexCCK_Base[path][group]) + || IS_PG_TXPWR_BASE_INVALID(pwr_info->IndexBW40_Base[path][group])) + return _FAIL; + } + for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) { + if (!HAL_SPEC_CHK_TX_CNT(hal_spec, tx_idx)) + continue; + if (IS_PG_TXPWR_DIFF_INVALID(pwr_info->CCK_Diff[path][tx_idx]) + || IS_PG_TXPWR_DIFF_INVALID(pwr_info->OFDM_Diff[path][tx_idx]) + || IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW20_Diff[path][tx_idx]) + || IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW40_Diff[path][tx_idx])) + return _FAIL; + } + } + + return _SUCCESS; +} + +static u8 hal_chk_pg_txpwr_info_5g(_adapter *adapter, TxPowerInfo5G *pwr_info) +{ +#ifdef CONFIG_IEEE80211_BAND_5GHZ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + u8 path, group, tx_idx; + + if (pwr_info == NULL || !hal_chk_band_cap(adapter, BAND_CAP_5G)) + return _SUCCESS; + + for (path = 0; path < MAX_RF_PATH; path++) { + if (!HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path)) + continue; + for (group = 0; group < MAX_CHNL_GROUP_5G; group++) + if (IS_PG_TXPWR_BASE_INVALID(pwr_info->IndexBW40_Base[path][group])) + return _FAIL; + for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) { + if (!HAL_SPEC_CHK_TX_CNT(hal_spec, tx_idx)) + continue; + if (IS_PG_TXPWR_DIFF_INVALID(pwr_info->OFDM_Diff[path][tx_idx]) + || IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW20_Diff[path][tx_idx]) + || IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW40_Diff[path][tx_idx]) + || IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW80_Diff[path][tx_idx]) + || IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW160_Diff[path][tx_idx])) + return _FAIL; + } + } +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + return _SUCCESS; +} + +static inline void hal_init_pg_txpwr_info_2g(_adapter *adapter, TxPowerInfo24G *pwr_info) +{ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + u8 path, group, tx_idx; + + if (pwr_info == NULL) + return; + + memset(pwr_info, 0, sizeof(TxPowerInfo24G)); + + /* init with invalid value */ + for (path = 0; path < MAX_RF_PATH; path++) { + for (group = 0; group < MAX_CHNL_GROUP_24G; group++) { + pwr_info->IndexCCK_Base[path][group] = PG_TXPWR_INVALID_BASE; + pwr_info->IndexBW40_Base[path][group] = PG_TXPWR_INVALID_BASE; + } + for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) { + pwr_info->CCK_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF; + pwr_info->OFDM_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF; + pwr_info->BW20_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF; + pwr_info->BW40_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF; + } + } + + /* init for dummy base and diff */ + for (path = 0; path < MAX_RF_PATH; path++) { + if (!HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path)) + break; + /* 2.4G BW40 base has 1 less group than CCK base*/ + pwr_info->IndexBW40_Base[path][MAX_CHNL_GROUP_24G - 1] = 0; + + /* dummy diff */ + pwr_info->CCK_Diff[path][0] = 0; /* 2.4G CCK-1TX */ + pwr_info->BW40_Diff[path][0] = 0; /* 2.4G BW40-1S */ + } +} + +static inline void hal_init_pg_txpwr_info_5g(_adapter *adapter, TxPowerInfo5G *pwr_info) +{ +#ifdef CONFIG_IEEE80211_BAND_5GHZ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + u8 path, group, tx_idx; + + if (pwr_info == NULL) + return; + + memset(pwr_info, 0, sizeof(TxPowerInfo5G)); + + /* init with invalid value */ + for (path = 0; path < MAX_RF_PATH; path++) { + for (group = 0; group < MAX_CHNL_GROUP_5G; group++) + pwr_info->IndexBW40_Base[path][group] = PG_TXPWR_INVALID_BASE; + for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) { + pwr_info->OFDM_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF; + pwr_info->BW20_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF; + pwr_info->BW40_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF; + pwr_info->BW80_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF; + pwr_info->BW160_Diff[path][tx_idx] = PG_TXPWR_INVALID_DIFF; + } + } + + for (path = 0; path < MAX_RF_PATH; path++) { + if (!HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path)) + break; + /* dummy diff */ + pwr_info->BW40_Diff[path][0] = 0; /* 5G BW40-1S */ + } +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ +} + +#if DBG_PG_TXPWR_READ +#define LOAD_PG_TXPWR_WARN_COND(_txpwr_src) 1 +#else +#define LOAD_PG_TXPWR_WARN_COND(_txpwr_src) (_txpwr_src > PG_TXPWR_SRC_PG_DATA) +#endif + +static u16 hal_load_pg_txpwr_info_path_2g( + _adapter *adapter, + TxPowerInfo24G *pwr_info, + u32 path, + u8 txpwr_src, + const struct map_t *txpwr_map, + u16 pg_offset) +{ +#define PG_TXPWR_1PATH_BYTE_NUM_2G 18 + + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + u16 offset = pg_offset; + u8 group, tx_idx; + u8 val; + u8 tmp_base; + s8 tmp_diff; + + if (pwr_info == NULL || !hal_chk_band_cap(adapter, BAND_CAP_2G)) { + offset += PG_TXPWR_1PATH_BYTE_NUM_2G; + goto exit; + } + + if (DBG_PG_TXPWR_READ) + RTW_INFO("%s [%c] offset:0x%03x\n", __func__, rf_path_char(path), offset); + + for (group = 0; group < MAX_CHNL_GROUP_24G; group++) { + if (HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path)) { + tmp_base = map_read8(txpwr_map, offset); + if (!IS_PG_TXPWR_BASE_INVALID(tmp_base) + && IS_PG_TXPWR_BASE_INVALID(pwr_info->IndexCCK_Base[path][group]) + ) { + pwr_info->IndexCCK_Base[path][group] = tmp_base; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 2G G%02d CCK-1T base:%u from %s\n", rf_path_char(path), group, tmp_base, pg_txpwr_src_str(txpwr_src)); + } + } + offset++; + } + + for (group = 0; group < MAX_CHNL_GROUP_24G - 1; group++) { + if (HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path)) { + tmp_base = map_read8(txpwr_map, offset); + if (!IS_PG_TXPWR_BASE_INVALID(tmp_base) + && IS_PG_TXPWR_BASE_INVALID(pwr_info->IndexBW40_Base[path][group]) + ) { + pwr_info->IndexBW40_Base[path][group] = tmp_base; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 2G G%02d BW40-1S base:%u from %s\n", rf_path_char(path), group, tmp_base, pg_txpwr_src_str(txpwr_src)); + } + } + offset++; + } + + for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) { + if (tx_idx == 0) { + if (HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path) && HAL_SPEC_CHK_TX_CNT(hal_spec, tx_idx)) { + val = map_read8(txpwr_map, offset); + tmp_diff = PG_TXPWR_MSB_DIFF_TO_S8BIT(val); + if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff) + && IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW20_Diff[path][tx_idx]) + ) { + pwr_info->BW20_Diff[path][tx_idx] = tmp_diff; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 2G BW20-%dS diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src)); + } + tmp_diff = PG_TXPWR_LSB_DIFF_TO_S8BIT(val); + if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff) + && IS_PG_TXPWR_DIFF_INVALID(pwr_info->OFDM_Diff[path][tx_idx]) + ) { + pwr_info->OFDM_Diff[path][tx_idx] = tmp_diff; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 2G OFDM-%dT diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src)); + } + } + offset++; + } else { + if (HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path) && HAL_SPEC_CHK_TX_CNT(hal_spec, tx_idx)) { + val = map_read8(txpwr_map, offset); + tmp_diff = PG_TXPWR_MSB_DIFF_TO_S8BIT(val); + if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff) + && IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW40_Diff[path][tx_idx]) + ) { + pwr_info->BW40_Diff[path][tx_idx] = tmp_diff; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 2G BW40-%dS diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src)); + + } + tmp_diff = PG_TXPWR_LSB_DIFF_TO_S8BIT(val); + if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff) + && IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW20_Diff[path][tx_idx]) + ) { + pwr_info->BW20_Diff[path][tx_idx] = tmp_diff; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 2G BW20-%dS diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src)); + } + } + offset++; + + if (HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path) && HAL_SPEC_CHK_TX_CNT(hal_spec, tx_idx)) { + val = map_read8(txpwr_map, offset); + tmp_diff = PG_TXPWR_MSB_DIFF_TO_S8BIT(val); + if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff) + && IS_PG_TXPWR_DIFF_INVALID(pwr_info->OFDM_Diff[path][tx_idx]) + ) { + pwr_info->OFDM_Diff[path][tx_idx] = tmp_diff; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 2G OFDM-%dT diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src)); + } + tmp_diff = PG_TXPWR_LSB_DIFF_TO_S8BIT(val); + if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff) + && IS_PG_TXPWR_DIFF_INVALID(pwr_info->CCK_Diff[path][tx_idx]) + ) { + pwr_info->CCK_Diff[path][tx_idx] = tmp_diff; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 2G CCK-%dT diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src)); + } + } + offset++; + } + } + + if (offset != pg_offset + PG_TXPWR_1PATH_BYTE_NUM_2G) { + RTW_ERR("%s parse %d bytes != %d\n", __func__, offset - pg_offset, PG_TXPWR_1PATH_BYTE_NUM_2G); + rtw_warn_on(1); + } + +exit: + return offset; +} + +static u16 hal_load_pg_txpwr_info_path_5g( + _adapter *adapter, + TxPowerInfo5G *pwr_info, + u32 path, + u8 txpwr_src, + const struct map_t *txpwr_map, + u16 pg_offset) +{ +#define PG_TXPWR_1PATH_BYTE_NUM_5G 24 + + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + u16 offset = pg_offset; + u8 group, tx_idx; + u8 val; + u8 tmp_base; + s8 tmp_diff; + +#ifdef CONFIG_IEEE80211_BAND_5GHZ + if (pwr_info == NULL || !hal_chk_band_cap(adapter, BAND_CAP_5G)) +#endif + { + offset += PG_TXPWR_1PATH_BYTE_NUM_5G; + goto exit; + } + +#ifdef CONFIG_IEEE80211_BAND_5GHZ + if (DBG_PG_TXPWR_READ) + RTW_INFO("%s[%c] eaddr:0x%03x\n", __func__, rf_path_char(path), offset); + + for (group = 0; group < MAX_CHNL_GROUP_5G; group++) { + if (HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path)) { + tmp_base = map_read8(txpwr_map, offset); + if (!IS_PG_TXPWR_BASE_INVALID(tmp_base) + && IS_PG_TXPWR_BASE_INVALID(pwr_info->IndexBW40_Base[path][group]) + ) { + pwr_info->IndexBW40_Base[path][group] = tmp_base; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 5G G%02d BW40-1S base:%u from %s\n", rf_path_char(path), group, tmp_base, pg_txpwr_src_str(txpwr_src)); + } + } + offset++; + } + + for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) { + if (tx_idx == 0) { + if (HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path) && HAL_SPEC_CHK_TX_CNT(hal_spec, tx_idx)) { + val = map_read8(txpwr_map, offset); + tmp_diff = PG_TXPWR_MSB_DIFF_TO_S8BIT(val); + if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff) + && IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW20_Diff[path][tx_idx]) + ) { + pwr_info->BW20_Diff[path][tx_idx] = tmp_diff; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 5G BW20-%dS diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src)); + } + tmp_diff = PG_TXPWR_LSB_DIFF_TO_S8BIT(val); + if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff) + && IS_PG_TXPWR_DIFF_INVALID(pwr_info->OFDM_Diff[path][tx_idx]) + ) { + pwr_info->OFDM_Diff[path][tx_idx] = tmp_diff; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 5G OFDM-%dT diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src)); + } + } + offset++; + } else { + if (HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path) && HAL_SPEC_CHK_TX_CNT(hal_spec, tx_idx)) { + val = map_read8(txpwr_map, offset); + tmp_diff = PG_TXPWR_MSB_DIFF_TO_S8BIT(val); + if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff) + && IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW40_Diff[path][tx_idx]) + ) { + pwr_info->BW40_Diff[path][tx_idx] = tmp_diff; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 5G BW40-%dS diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src)); + } + tmp_diff = PG_TXPWR_LSB_DIFF_TO_S8BIT(val); + if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff) + && IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW20_Diff[path][tx_idx]) + ) { + pwr_info->BW20_Diff[path][tx_idx] = tmp_diff; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 5G BW20-%dS diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src)); + } + } + offset++; + } + } + + /* OFDM diff 2T ~ 3T */ + if (HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path) && HAL_SPEC_CHK_TX_CNT(hal_spec, 1)) { + val = map_read8(txpwr_map, offset); + tmp_diff = PG_TXPWR_MSB_DIFF_TO_S8BIT(val); + if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff) + && IS_PG_TXPWR_DIFF_INVALID(pwr_info->OFDM_Diff[path][1]) + ) { + pwr_info->OFDM_Diff[path][1] = tmp_diff; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 5G OFDM-%dT diff:%d from %s\n", rf_path_char(path), 2, tmp_diff, pg_txpwr_src_str(txpwr_src)); + } + if (HAL_SPEC_CHK_TX_CNT(hal_spec, 2)) { + tmp_diff = PG_TXPWR_LSB_DIFF_TO_S8BIT(val); + if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff) + && IS_PG_TXPWR_DIFF_INVALID(pwr_info->OFDM_Diff[path][2]) + ) { + pwr_info->OFDM_Diff[path][2] = tmp_diff; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 5G OFDM-%dT diff:%d from %s\n", rf_path_char(path), 3, tmp_diff, pg_txpwr_src_str(txpwr_src)); + } + } + } + offset++; + + /* OFDM diff 4T */ + if (HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path) && HAL_SPEC_CHK_TX_CNT(hal_spec, 3)) { + val = map_read8(txpwr_map, offset); + tmp_diff = PG_TXPWR_LSB_DIFF_TO_S8BIT(val); + if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff) + && IS_PG_TXPWR_DIFF_INVALID(pwr_info->OFDM_Diff[path][3]) + ) { + pwr_info->OFDM_Diff[path][3] = tmp_diff; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 5G OFDM-%dT diff:%d from %s\n", rf_path_char(path), 4, tmp_diff, pg_txpwr_src_str(txpwr_src)); + } + } + offset++; + + for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) { + if (HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path) && HAL_SPEC_CHK_TX_CNT(hal_spec, tx_idx)) { + val = map_read8(txpwr_map, offset); + tmp_diff = PG_TXPWR_MSB_DIFF_TO_S8BIT(val); + if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff) + && IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW80_Diff[path][tx_idx]) + ) { + pwr_info->BW80_Diff[path][tx_idx] = tmp_diff; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 5G BW80-%dS diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src)); + } + tmp_diff = PG_TXPWR_LSB_DIFF_TO_S8BIT(val); + if (!IS_PG_TXPWR_DIFF_INVALID(tmp_diff) + && IS_PG_TXPWR_DIFF_INVALID(pwr_info->BW160_Diff[path][tx_idx]) + ) { + pwr_info->BW160_Diff[path][tx_idx] = tmp_diff; + if (LOAD_PG_TXPWR_WARN_COND(txpwr_src)) + RTW_INFO("[%c] 5G BW160-%dS diff:%d from %s\n", rf_path_char(path), tx_idx + 1, tmp_diff, pg_txpwr_src_str(txpwr_src)); + } + } + offset++; + } + + if (offset != pg_offset + PG_TXPWR_1PATH_BYTE_NUM_5G) { + RTW_ERR("%s parse %d bytes != %d\n", __func__, offset - pg_offset, PG_TXPWR_1PATH_BYTE_NUM_5G); + rtw_warn_on(1); + } + +#endif /* #ifdef CONFIG_IEEE80211_BAND_5GHZ */ + +exit: + return offset; +} + +static void hal_load_pg_txpwr_info( + _adapter *adapter, + TxPowerInfo24G *pwr_info_2g, + TxPowerInfo5G *pwr_info_5g, + u8 *pg_data, + bool AutoLoadFail +) +{ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + u8 path; + u16 pg_offset; + u8 txpwr_src = PG_TXPWR_SRC_PG_DATA; + struct map_t pg_data_map = MAP_ENT(184, 1, 0xFF, MAPSEG_PTR_ENT(0x00, 184, pg_data)); + const struct map_t *txpwr_map = NULL; + + /* init with invalid value and some dummy base and diff */ + hal_init_pg_txpwr_info_2g(adapter, pwr_info_2g); + hal_init_pg_txpwr_info_5g(adapter, pwr_info_5g); + +select_src: + pg_offset = 0x10; + + switch (txpwr_src) { + case PG_TXPWR_SRC_PG_DATA: + txpwr_map = &pg_data_map; + break; + case PG_TXPWR_SRC_IC_DEF: + txpwr_map = hal_pg_txpwr_def_info(adapter); + break; + case PG_TXPWR_SRC_DEF: + default: + txpwr_map = &pg_txpwr_def_info; + break; + }; + + if (txpwr_map == NULL) + goto end_parse; + + for (path = 0; path < MAX_RF_PATH ; path++) { + if (!HAL_SPEC_CHK_RF_PATH_2G(hal_spec, path) && !HAL_SPEC_CHK_RF_PATH_5G(hal_spec, path)) + break; + pg_offset = hal_load_pg_txpwr_info_path_2g(adapter, pwr_info_2g, path, txpwr_src, txpwr_map, pg_offset); + pg_offset = hal_load_pg_txpwr_info_path_5g(adapter, pwr_info_5g, path, txpwr_src, txpwr_map, pg_offset); + } + + if (hal_chk_pg_txpwr_info_2g(adapter, pwr_info_2g) == _SUCCESS + && hal_chk_pg_txpwr_info_5g(adapter, pwr_info_5g) == _SUCCESS) + goto exit; + +end_parse: + txpwr_src++; + if (txpwr_src < PG_TXPWR_SRC_NUM) + goto select_src; + + if (hal_chk_pg_txpwr_info_2g(adapter, pwr_info_2g) != _SUCCESS + || hal_chk_pg_txpwr_info_5g(adapter, pwr_info_5g) != _SUCCESS) + rtw_warn_on(1); + +exit: + if (DBG_PG_TXPWR_READ) { + if (pwr_info_2g) + dump_pg_txpwr_info_2g(RTW_DBGDUMP, pwr_info_2g, 4, 4); + if (pwr_info_5g) + dump_pg_txpwr_info_5g(RTW_DBGDUMP, pwr_info_5g, 4, 4); + } + + return; +} + +void hal_load_txpwr_info( + _adapter *adapter, + TxPowerInfo24G *pwr_info_2g, + TxPowerInfo5G *pwr_info_5g, + u8 *pg_data +) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + u8 max_tx_cnt = hal_spec->max_tx_cnt; + u8 rfpath, ch_idx, group, tx_idx; + + /* load from pg data (or default value) */ + hal_load_pg_txpwr_info(adapter, pwr_info_2g, pwr_info_5g, pg_data, false); + + /* transform to hal_data */ + for (rfpath = 0; rfpath < MAX_RF_PATH; rfpath++) { + + if (!pwr_info_2g || !HAL_SPEC_CHK_RF_PATH_2G(hal_spec, rfpath)) + goto bypass_2g; + + /* 2.4G base */ + for (ch_idx = 0; ch_idx < CENTER_CH_2G_NUM; ch_idx++) { + u8 cck_group; + + if (rtw_get_ch_group(ch_idx + 1, &group, &cck_group) != BAND_ON_2_4G) + continue; + + hal_data->Index24G_CCK_Base[rfpath][ch_idx] = pwr_info_2g->IndexCCK_Base[rfpath][cck_group]; + hal_data->Index24G_BW40_Base[rfpath][ch_idx] = pwr_info_2g->IndexBW40_Base[rfpath][group]; + } + + /* 2.4G diff */ + for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) { + if (tx_idx >= max_tx_cnt) + break; + + hal_data->CCK_24G_Diff[rfpath][tx_idx] = pwr_info_2g->CCK_Diff[rfpath][tx_idx]; + hal_data->OFDM_24G_Diff[rfpath][tx_idx] = pwr_info_2g->OFDM_Diff[rfpath][tx_idx]; + hal_data->BW20_24G_Diff[rfpath][tx_idx] = pwr_info_2g->BW20_Diff[rfpath][tx_idx]; + hal_data->BW40_24G_Diff[rfpath][tx_idx] = pwr_info_2g->BW40_Diff[rfpath][tx_idx]; + } +bypass_2g: + ; + +#ifdef CONFIG_IEEE80211_BAND_5GHZ + if (!pwr_info_5g || !HAL_SPEC_CHK_RF_PATH_5G(hal_spec, rfpath)) + goto bypass_5g; + + /* 5G base */ + for (ch_idx = 0; ch_idx < CENTER_CH_5G_ALL_NUM; ch_idx++) { + if (rtw_get_ch_group(center_ch_5g_all[ch_idx], &group, NULL) != BAND_ON_5G) + continue; + hal_data->Index5G_BW40_Base[rfpath][ch_idx] = pwr_info_5g->IndexBW40_Base[rfpath][group]; + } + + for (ch_idx = 0 ; ch_idx < CENTER_CH_5G_80M_NUM; ch_idx++) { + u8 upper, lower; + + if (rtw_get_ch_group(center_ch_5g_80m[ch_idx], &group, NULL) != BAND_ON_5G) + continue; + + upper = pwr_info_5g->IndexBW40_Base[rfpath][group]; + lower = pwr_info_5g->IndexBW40_Base[rfpath][group + 1]; + hal_data->Index5G_BW80_Base[rfpath][ch_idx] = (upper + lower) / 2; + } + + /* 5G diff */ + for (tx_idx = 0; tx_idx < MAX_TX_COUNT; tx_idx++) { + if (tx_idx >= max_tx_cnt) + break; + + hal_data->OFDM_5G_Diff[rfpath][tx_idx] = pwr_info_5g->OFDM_Diff[rfpath][tx_idx]; + hal_data->BW20_5G_Diff[rfpath][tx_idx] = pwr_info_5g->BW20_Diff[rfpath][tx_idx]; + hal_data->BW40_5G_Diff[rfpath][tx_idx] = pwr_info_5g->BW40_Diff[rfpath][tx_idx]; + hal_data->BW80_5G_Diff[rfpath][tx_idx] = pwr_info_5g->BW80_Diff[rfpath][tx_idx]; + } +bypass_5g: + ; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + } +} + +void dump_hal_txpwr_info_2g(void *sel, _adapter *adapter, u8 rfpath_num, u8 max_tx_cnt) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + int path, ch_idx, tx_idx; + + RTW_PRINT_SEL(sel, "2.4G\n"); + RTW_PRINT_SEL(sel, "CCK-1T base:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (ch_idx = 0; ch_idx < CENTER_CH_2G_NUM; ch_idx++) + _RTW_PRINT_SEL(sel, "%2d ", center_ch_2g[ch_idx]); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (ch_idx = 0; ch_idx < CENTER_CH_2G_NUM; ch_idx++) + _RTW_PRINT_SEL(sel, "%2u ", hal_data->Index24G_CCK_Base[path][ch_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "CCK diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%dT ", tx_idx + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", hal_data->CCK_24G_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "BW40-1S base:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (ch_idx = 0; ch_idx < CENTER_CH_2G_NUM; ch_idx++) + _RTW_PRINT_SEL(sel, "%2d ", center_ch_2g[ch_idx]); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (ch_idx = 0; ch_idx < CENTER_CH_2G_NUM; ch_idx++) + _RTW_PRINT_SEL(sel, "%2u ", hal_data->Index24G_BW40_Base[path][ch_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "OFDM diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%dT ", tx_idx + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", hal_data->OFDM_24G_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "BW20 diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%dS ", tx_idx + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", hal_data->BW20_24G_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "BW40 diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%dS ", tx_idx + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", hal_data->BW40_24G_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); +} + +void dump_hal_txpwr_info_5g(void *sel, _adapter *adapter, u8 rfpath_num, u8 max_tx_cnt) +{ +#ifdef CONFIG_IEEE80211_BAND_5GHZ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + int path, ch_idx, tx_idx; + u8 dump_section = 0; + u8 ch_idx_s = 0; + + RTW_PRINT_SEL(sel, "5G\n"); + RTW_PRINT_SEL(sel, "BW40-1S base:\n"); + do { + #define DUMP_5G_BW40_BASE_SECTION_NUM 3 + u8 end[DUMP_5G_BW40_BASE_SECTION_NUM] = {64, 144, 177}; + + RTW_PRINT_SEL(sel, "%4s ", ""); + for (ch_idx = ch_idx_s; ch_idx < CENTER_CH_5G_ALL_NUM; ch_idx++) { + _RTW_PRINT_SEL(sel, "%3d ", center_ch_5g_all[ch_idx]); + if (end[dump_section] == center_ch_5g_all[ch_idx]) + break; + } + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (ch_idx = ch_idx_s; ch_idx < CENTER_CH_5G_ALL_NUM; ch_idx++) { + _RTW_PRINT_SEL(sel, "%3u ", hal_data->Index5G_BW40_Base[path][ch_idx]); + if (end[dump_section] == center_ch_5g_all[ch_idx]) + break; + } + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + ch_idx_s = ch_idx + 1; + dump_section++; + if (dump_section >= DUMP_5G_BW40_BASE_SECTION_NUM) + break; + } while (1); + + RTW_PRINT_SEL(sel, "BW80-1S base:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (ch_idx = 0; ch_idx < CENTER_CH_5G_80M_NUM; ch_idx++) + _RTW_PRINT_SEL(sel, "%3d ", center_ch_5g_80m[ch_idx]); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (ch_idx = 0; ch_idx < CENTER_CH_5G_80M_NUM; ch_idx++) + _RTW_PRINT_SEL(sel, "%3u ", hal_data->Index5G_BW80_Base[path][ch_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "OFDM diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%dT ", tx_idx + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", hal_data->OFDM_5G_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "BW20 diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%dS ", tx_idx + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", hal_data->BW20_5G_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "BW40 diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%dS ", tx_idx + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", hal_data->BW40_5G_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); + + RTW_PRINT_SEL(sel, "BW80 diff:\n"); + RTW_PRINT_SEL(sel, "%4s ", ""); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%dS ", tx_idx + 1); + _RTW_PRINT_SEL(sel, "\n"); + for (path = 0; path < MAX_RF_PATH && path < rfpath_num; path++) { + RTW_PRINT_SEL(sel, "[%c]: ", rf_path_char(path)); + for (tx_idx = RF_1TX; tx_idx < MAX_TX_COUNT && tx_idx < max_tx_cnt; tx_idx++) + _RTW_PRINT_SEL(sel, "%2d ", hal_data->BW80_5G_Diff[path][tx_idx]); + _RTW_PRINT_SEL(sel, "\n"); + } + RTW_PRINT_SEL(sel, "\n"); +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ +} + +/* +* rtw_regsty_get_target_tx_power - +* +* Return dBm or -1 for undefined +*/ +static s8 rtw_regsty_get_target_tx_power( + PADAPTER Adapter, + u8 Band, + u8 RfPath, + RATE_SECTION RateSection +) +{ + struct registry_priv *regsty = adapter_to_regsty(Adapter); + s8 value = 0; + + if (RfPath > RF_PATH_D) { + RTW_PRINT("%s invalid RfPath:%d\n", __func__, RfPath); + return -1; + } + + if (Band != BAND_ON_2_4G + #ifdef CONFIG_IEEE80211_BAND_5GHZ + && Band != BAND_ON_5G + #endif + ) { + RTW_PRINT("%s invalid Band:%d\n", __func__, Band); + return -1; + } + + if (RateSection >= RATE_SECTION_NUM + #ifdef CONFIG_IEEE80211_BAND_5GHZ + || (Band == BAND_ON_5G && RateSection == CCK) + #endif + ) { + RTW_PRINT("%s invalid RateSection:%d in Band:%d, RfPath:%d\n", __func__ + , RateSection, Band, RfPath); + return -1; + } + + if (Band == BAND_ON_2_4G) + value = regsty->target_tx_pwr_2g[RfPath][RateSection]; +#ifdef CONFIG_IEEE80211_BAND_5GHZ + else /* BAND_ON_5G */ + value = regsty->target_tx_pwr_5g[RfPath][RateSection - 1]; +#endif + + return value; +} + +static bool rtw_regsty_chk_target_tx_power_valid(_adapter *adapter) +{ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + int path, tx_num, band, rs; + s8 target; + + for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) { + if (!hal_is_band_support(adapter, band)) + continue; + + for (path = 0; path < RF_PATH_MAX; path++) { + if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, path)) + break; + + for (rs = 0; rs < RATE_SECTION_NUM; rs++) { + tx_num = rate_section_to_tx_num(rs); + if (tx_num >= hal_spec->tx_nss_num) + continue; + + if (band == BAND_ON_5G && IS_CCK_RATE_SECTION(rs)) + continue; + + if (IS_VHT_RATE_SECTION(rs)) + continue; + + target = rtw_regsty_get_target_tx_power(adapter, band, path, rs); + if (target == -1) { + RTW_PRINT("%s return false for band:%d, path:%d, rs:%d, t:%d\n", __func__, band, path, rs, target); + return false; + } + } + } + } + + return true; +} + +/* +* PHY_GetTxPowerByRateBase - +* +* Return 2 times of dBm +*/ +u8 +PHY_GetTxPowerByRateBase( + PADAPTER Adapter, + u8 Band, + u8 RfPath, + u8 TxNum, + RATE_SECTION RateSection +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u8 value = 0; + + if (RfPath > RF_PATH_D) { + RTW_PRINT("%s invalid RfPath:%d\n", __func__, RfPath); + return 0; + } + + if (Band != BAND_ON_2_4G && Band != BAND_ON_5G) { + RTW_PRINT("%s invalid Band:%d\n", __func__, Band); + return 0; + } + + if (RateSection >= RATE_SECTION_NUM + || (Band == BAND_ON_5G && RateSection == CCK) + ) { + RTW_PRINT("%s invalid RateSection:%d in Band:%d, RfPath:%d, TxNum:%d\n", __func__ + , RateSection, Band, RfPath, TxNum); + return 0; + } + + if (Band == BAND_ON_2_4G) + value = pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][RateSection]; + else /* BAND_ON_5G */ + value = pHalData->TxPwrByRateBase5G[RfPath][TxNum][RateSection - 1]; + + return value; +} + +static void +phy_SetTxPowerByRateBase( + PADAPTER Adapter, + u8 Band, + u8 RfPath, + RATE_SECTION RateSection, + u8 TxNum, + u8 Value +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + if (RfPath > RF_PATH_D) { + RTW_PRINT("%s invalid RfPath:%d\n", __func__, RfPath); + return; + } + + if (Band != BAND_ON_2_4G && Band != BAND_ON_5G) { + RTW_PRINT("%s invalid Band:%d\n", __func__, Band); + return; + } + + if (RateSection >= RATE_SECTION_NUM + || (Band == BAND_ON_5G && RateSection == CCK) + ) { + RTW_PRINT("%s invalid RateSection:%d in %sG, RfPath:%d, TxNum:%d\n", __func__ + , RateSection, (Band == BAND_ON_2_4G) ? "2.4" : "5", RfPath, TxNum); + return; + } + + if (Band == BAND_ON_2_4G) + pHalData->TxPwrByRateBase2_4G[RfPath][TxNum][RateSection] = Value; + else /* BAND_ON_5G */ + pHalData->TxPwrByRateBase5G[RfPath][TxNum][RateSection - 1] = Value; +} + +static inline bool phy_is_txpwr_by_rate_undefined_of_band_path(_adapter *adapter, u8 band, u8 path) +{ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + u8 tx_num = 0, rate_idx = 0; + + for (tx_num = 0; tx_num < TX_PWR_BY_RATE_NUM_RF; tx_num++) { + if (tx_num >= hal_spec->max_tx_cnt || tx_num >= hal_spec->tx_nss_num) + goto exit; + for (rate_idx = 0; rate_idx < TX_PWR_BY_RATE_NUM_RATE; rate_idx++) { + if (hal_data->TxPwrByRateOffset[band][path][tx_num][rate_idx] != 0) + goto exit; + } + } + +exit: + return (tx_num >= hal_spec->max_tx_cnt || tx_num >= hal_spec->tx_nss_num) ? true : false; +} + +static inline void phy_txpwr_by_rate_duplicate_band_path(_adapter *adapter, u8 band, u8 s_path, u8 t_path) +{ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + u8 tx_num = 0, rate_idx = 0; + + for (tx_num = 0; tx_num < TX_PWR_BY_RATE_NUM_RF; tx_num++) + for (rate_idx = 0; rate_idx < TX_PWR_BY_RATE_NUM_RATE; rate_idx++) + hal_data->TxPwrByRateOffset[band][t_path][tx_num][rate_idx] = hal_data->TxPwrByRateOffset[band][s_path][tx_num][rate_idx]; +} + +static void phy_txpwr_by_rate_chk_for_path_dup(_adapter *adapter) +{ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + u8 band, path; + s8 src_path; + + for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) + for (path = RF_PATH_A; path < RF_PATH_MAX; path++) + hal_data->txpwr_by_rate_undefined_band_path[band][path] = 0; + + for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) { + if (!hal_is_band_support(adapter, band)) + continue; + + for (path = RF_PATH_A; path < RF_PATH_MAX; path++) { + if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, path)) + continue; + + if (phy_is_txpwr_by_rate_undefined_of_band_path(adapter, band, path)) + hal_data->txpwr_by_rate_undefined_band_path[band][path] = 1; + } + } + + for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) { + if (!hal_is_band_support(adapter, band)) + continue; + + src_path = -1; + for (path = RF_PATH_A; path < RF_PATH_MAX; path++) { + if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, path)) + continue; + + /* find src */ + if (src_path == -1 && hal_data->txpwr_by_rate_undefined_band_path[band][path] == 0) + src_path = path; + } + + if (src_path == -1) { + RTW_ERR("%s all power by rate undefined\n", __func__); + continue; + } + + for (path = RF_PATH_A; path < RF_PATH_MAX; path++) { + if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, path)) + continue; + + /* duplicate src to undefined one */ + if (hal_data->txpwr_by_rate_undefined_band_path[band][path] == 1) { + RTW_INFO("%s duplicate %s [%c] to [%c]\n", __func__ + , band_str(band), rf_path_char(src_path), rf_path_char(path)); + phy_txpwr_by_rate_duplicate_band_path(adapter, band, src_path, path); + } + } + } +} + +static void +phy_StoreTxPowerByRateBase( + PADAPTER pAdapter +) +{ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(pAdapter); + struct registry_priv *regsty = adapter_to_regsty(pAdapter); + + u8 rate_sec_base[RATE_SECTION_NUM] = { + MGN_11M, + MGN_54M, + MGN_MCS7, + MGN_MCS15, + MGN_MCS23, + MGN_MCS31, + MGN_VHT1SS_MCS7, + MGN_VHT2SS_MCS7, + MGN_VHT3SS_MCS7, + MGN_VHT4SS_MCS7, + }; + + u8 band, path, rs, tx_num, base, index; + + for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) { + if (!hal_is_band_support(pAdapter, band)) + continue; + + for (path = RF_PATH_A; path < RF_PATH_MAX; path++) { + if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, path)) + break; + + for (rs = 0; rs < RATE_SECTION_NUM; rs++) { + tx_num = rate_section_to_tx_num(rs); + if (tx_num >= hal_spec->tx_nss_num) + continue; + + if (band == BAND_ON_5G && IS_CCK_RATE_SECTION(rs)) + continue; + + if (IS_VHT_RATE_SECTION(rs)) + continue; + + if (regsty->target_tx_pwr_valid == true) + base = 2 * rtw_regsty_get_target_tx_power(pAdapter, band, path, rs); + else + base = _PHY_GetTxPowerByRate(pAdapter, band, path, tx_num, rate_sec_base[rs]); + phy_SetTxPowerByRateBase(pAdapter, band, path, rs, tx_num, base); + } + } + } +} + +void +PHY_GetRateValuesOfTxPowerByRate( + PADAPTER pAdapter, + u32 RegAddr, + u32 BitMask, + u32 Value, + u8 *Rate, + s8 *PwrByRateVal, + u8 *RateNum +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + struct PHY_DM_STRUCT *pDM_Odm = &pHalData->odmpriv; + u8 index = 0, i = 0; + + switch (RegAddr) { + case rTxAGC_A_Rate18_06: + case rTxAGC_B_Rate18_06: + Rate[0] = MGN_6M; + Rate[1] = MGN_9M; + Rate[2] = MGN_12M; + Rate[3] = MGN_18M; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case rTxAGC_A_Rate54_24: + case rTxAGC_B_Rate54_24: + Rate[0] = MGN_24M; + Rate[1] = MGN_36M; + Rate[2] = MGN_48M; + Rate[3] = MGN_54M; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case rTxAGC_A_CCK1_Mcs32: + Rate[0] = MGN_1M; + PwrByRateVal[0] = (s8)((((Value >> (8 + 4)) & 0xF)) * 10 + + ((Value >> 8) & 0xF)); + *RateNum = 1; + break; + + case rTxAGC_B_CCK11_A_CCK2_11: + if (BitMask == 0xffffff00) { + Rate[0] = MGN_2M; + Rate[1] = MGN_5_5M; + Rate[2] = MGN_11M; + for (i = 1; i < 4; ++i) { + PwrByRateVal[i - 1] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 3; + } else if (BitMask == 0x000000ff) { + Rate[0] = MGN_11M; + PwrByRateVal[0] = (s8)((((Value >> 4) & 0xF)) * 10 + + (Value & 0xF)); + *RateNum = 1; + } + break; + + case rTxAGC_A_Mcs03_Mcs00: + case rTxAGC_B_Mcs03_Mcs00: + Rate[0] = MGN_MCS0; + Rate[1] = MGN_MCS1; + Rate[2] = MGN_MCS2; + Rate[3] = MGN_MCS3; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case rTxAGC_A_Mcs07_Mcs04: + case rTxAGC_B_Mcs07_Mcs04: + Rate[0] = MGN_MCS4; + Rate[1] = MGN_MCS5; + Rate[2] = MGN_MCS6; + Rate[3] = MGN_MCS7; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case rTxAGC_A_Mcs11_Mcs08: + case rTxAGC_B_Mcs11_Mcs08: + Rate[0] = MGN_MCS8; + Rate[1] = MGN_MCS9; + Rate[2] = MGN_MCS10; + Rate[3] = MGN_MCS11; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case rTxAGC_A_Mcs15_Mcs12: + case rTxAGC_B_Mcs15_Mcs12: + Rate[0] = MGN_MCS12; + Rate[1] = MGN_MCS13; + Rate[2] = MGN_MCS14; + Rate[3] = MGN_MCS15; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + + break; + + case rTxAGC_B_CCK1_55_Mcs32: + Rate[0] = MGN_1M; + Rate[1] = MGN_2M; + Rate[2] = MGN_5_5M; + for (i = 1; i < 4; ++i) { + PwrByRateVal[i - 1] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 3; + break; + + case 0xC20: + case 0xE20: + case 0x1820: + case 0x1a20: + Rate[0] = MGN_1M; + Rate[1] = MGN_2M; + Rate[2] = MGN_5_5M; + Rate[3] = MGN_11M; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case 0xC24: + case 0xE24: + case 0x1824: + case 0x1a24: + Rate[0] = MGN_6M; + Rate[1] = MGN_9M; + Rate[2] = MGN_12M; + Rate[3] = MGN_18M; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case 0xC28: + case 0xE28: + case 0x1828: + case 0x1a28: + Rate[0] = MGN_24M; + Rate[1] = MGN_36M; + Rate[2] = MGN_48M; + Rate[3] = MGN_54M; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case 0xC2C: + case 0xE2C: + case 0x182C: + case 0x1a2C: + Rate[0] = MGN_MCS0; + Rate[1] = MGN_MCS1; + Rate[2] = MGN_MCS2; + Rate[3] = MGN_MCS3; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case 0xC30: + case 0xE30: + case 0x1830: + case 0x1a30: + Rate[0] = MGN_MCS4; + Rate[1] = MGN_MCS5; + Rate[2] = MGN_MCS6; + Rate[3] = MGN_MCS7; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case 0xC34: + case 0xE34: + case 0x1834: + case 0x1a34: + Rate[0] = MGN_MCS8; + Rate[1] = MGN_MCS9; + Rate[2] = MGN_MCS10; + Rate[3] = MGN_MCS11; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case 0xC38: + case 0xE38: + case 0x1838: + case 0x1a38: + Rate[0] = MGN_MCS12; + Rate[1] = MGN_MCS13; + Rate[2] = MGN_MCS14; + Rate[3] = MGN_MCS15; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case 0xC3C: + case 0xE3C: + case 0x183C: + case 0x1a3C: + Rate[0] = MGN_VHT1SS_MCS0; + Rate[1] = MGN_VHT1SS_MCS1; + Rate[2] = MGN_VHT1SS_MCS2; + Rate[3] = MGN_VHT1SS_MCS3; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case 0xC40: + case 0xE40: + case 0x1840: + case 0x1a40: + Rate[0] = MGN_VHT1SS_MCS4; + Rate[1] = MGN_VHT1SS_MCS5; + Rate[2] = MGN_VHT1SS_MCS6; + Rate[3] = MGN_VHT1SS_MCS7; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case 0xC44: + case 0xE44: + case 0x1844: + case 0x1a44: + Rate[0] = MGN_VHT1SS_MCS8; + Rate[1] = MGN_VHT1SS_MCS9; + Rate[2] = MGN_VHT2SS_MCS0; + Rate[3] = MGN_VHT2SS_MCS1; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case 0xC48: + case 0xE48: + case 0x1848: + case 0x1a48: + Rate[0] = MGN_VHT2SS_MCS2; + Rate[1] = MGN_VHT2SS_MCS3; + Rate[2] = MGN_VHT2SS_MCS4; + Rate[3] = MGN_VHT2SS_MCS5; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case 0xC4C: + case 0xE4C: + case 0x184C: + case 0x1a4C: + Rate[0] = MGN_VHT2SS_MCS6; + Rate[1] = MGN_VHT2SS_MCS7; + Rate[2] = MGN_VHT2SS_MCS8; + Rate[3] = MGN_VHT2SS_MCS9; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case 0xCD8: + case 0xED8: + case 0x18D8: + case 0x1aD8: + Rate[0] = MGN_MCS16; + Rate[1] = MGN_MCS17; + Rate[2] = MGN_MCS18; + Rate[3] = MGN_MCS19; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case 0xCDC: + case 0xEDC: + case 0x18DC: + case 0x1aDC: + Rate[0] = MGN_MCS20; + Rate[1] = MGN_MCS21; + Rate[2] = MGN_MCS22; + Rate[3] = MGN_MCS23; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case 0xCE0: + case 0xEE0: + case 0x18E0: + case 0x1aE0: + Rate[0] = MGN_VHT3SS_MCS0; + Rate[1] = MGN_VHT3SS_MCS1; + Rate[2] = MGN_VHT3SS_MCS2; + Rate[3] = MGN_VHT3SS_MCS3; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case 0xCE4: + case 0xEE4: + case 0x18E4: + case 0x1aE4: + Rate[0] = MGN_VHT3SS_MCS4; + Rate[1] = MGN_VHT3SS_MCS5; + Rate[2] = MGN_VHT3SS_MCS6; + Rate[3] = MGN_VHT3SS_MCS7; + for (i = 0; i < 4; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 4; + break; + + case 0xCE8: + case 0xEE8: + case 0x18E8: + case 0x1aE8: + Rate[0] = MGN_VHT3SS_MCS8; + Rate[1] = MGN_VHT3SS_MCS9; + for (i = 0; i < 2; ++i) { + PwrByRateVal[i] = (s8)((((Value >> (i * 8 + 4)) & 0xF)) * 10 + + ((Value >> (i * 8)) & 0xF)); + } + *RateNum = 2; + break; + + default: + RTW_PRINT("Invalid RegAddr 0x%x in %s()\n", RegAddr, __func__); + break; + }; +} + +static void +PHY_StoreTxPowerByRateNew( + PADAPTER pAdapter, + u32 Band, + u32 RfPath, + u32 TxNum, + u32 RegAddr, + u32 BitMask, + u32 Data +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + u8 i = 0, rates[4] = {0}, rateNum = 0; + s8 PwrByRateVal[4] = {0}; + + PHY_GetRateValuesOfTxPowerByRate(pAdapter, RegAddr, BitMask, Data, rates, PwrByRateVal, &rateNum); + + if (Band != BAND_ON_2_4G && Band != BAND_ON_5G) { + RTW_PRINT("Invalid Band %d\n", Band); + return; + } + + if (RfPath > ODM_RF_PATH_D) { + RTW_PRINT("Invalid RfPath %d\n", RfPath); + return; + } + + if (TxNum > ODM_RF_PATH_D) { + RTW_PRINT("Invalid TxNum %d\n", TxNum); + return; + } + + for (i = 0; i < rateNum; ++i) { + u8 rate_idx = PHY_GetRateIndexOfTxPowerByRate(rates[i]); + + if (IS_1T_RATE(rates[i])) + pHalData->TxPwrByRateOffset[Band][RfPath][RF_1TX][rate_idx] = PwrByRateVal[i]; + else if (IS_2T_RATE(rates[i])) + pHalData->TxPwrByRateOffset[Band][RfPath][RF_2TX][rate_idx] = PwrByRateVal[i]; + else if (IS_3T_RATE(rates[i])) + pHalData->TxPwrByRateOffset[Band][RfPath][RF_3TX][rate_idx] = PwrByRateVal[i]; + else if (IS_4T_RATE(rates[i])) + pHalData->TxPwrByRateOffset[Band][RfPath][RF_4TX][rate_idx] = PwrByRateVal[i]; + else + rtw_warn_on(1); + } +} + +void +PHY_InitTxPowerByRate( + PADAPTER pAdapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + u8 band = 0, rfPath = 0, TxNum = 0, rate = 0, i = 0, j = 0; + + for (band = BAND_ON_2_4G; band <= BAND_ON_5G; ++band) + for (rfPath = 0; rfPath < TX_PWR_BY_RATE_NUM_RF; ++rfPath) + for (TxNum = 0; TxNum < TX_PWR_BY_RATE_NUM_RF; ++TxNum) + for (rate = 0; rate < TX_PWR_BY_RATE_NUM_RATE; ++rate) + pHalData->TxPwrByRateOffset[band][rfPath][TxNum][rate] = 0; +} + +void +phy_store_tx_power_by_rate( + PADAPTER pAdapter, + u32 Band, + u32 RfPath, + u32 TxNum, + u32 RegAddr, + u32 BitMask, + u32 Data +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + struct PHY_DM_STRUCT *pDM_Odm = &pHalData->odmpriv; + + if (pDM_Odm->phy_reg_pg_version > 0) + PHY_StoreTxPowerByRateNew(pAdapter, Band, RfPath, TxNum, RegAddr, BitMask, Data); + else + RTW_INFO("Invalid PHY_REG_PG.txt version %d\n", pDM_Odm->phy_reg_pg_version); + +} + +static void +phy_ConvertTxPowerByRateInDbmToRelativeValues( + PADAPTER pAdapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + u8 base = 0, i = 0, value = 0, + band = 0, path = 0, txNum = 0, index = 0, + startIndex = 0, endIndex = 0; + u8 cckRates[4] = {MGN_1M, MGN_2M, MGN_5_5M, MGN_11M}, + ofdmRates[8] = {MGN_6M, MGN_9M, MGN_12M, MGN_18M, MGN_24M, MGN_36M, MGN_48M, MGN_54M}, + mcs0_7Rates[8] = {MGN_MCS0, MGN_MCS1, MGN_MCS2, MGN_MCS3, MGN_MCS4, MGN_MCS5, MGN_MCS6, MGN_MCS7}, + mcs8_15Rates[8] = {MGN_MCS8, MGN_MCS9, MGN_MCS10, MGN_MCS11, MGN_MCS12, MGN_MCS13, MGN_MCS14, MGN_MCS15}, + mcs16_23Rates[8] = {MGN_MCS16, MGN_MCS17, MGN_MCS18, MGN_MCS19, MGN_MCS20, MGN_MCS21, MGN_MCS22, MGN_MCS23}, + vht1ssRates[10] = {MGN_VHT1SS_MCS0, MGN_VHT1SS_MCS1, MGN_VHT1SS_MCS2, MGN_VHT1SS_MCS3, MGN_VHT1SS_MCS4, + MGN_VHT1SS_MCS5, MGN_VHT1SS_MCS6, MGN_VHT1SS_MCS7, MGN_VHT1SS_MCS8, MGN_VHT1SS_MCS9}, + vht2ssRates[10] = {MGN_VHT2SS_MCS0, MGN_VHT2SS_MCS1, MGN_VHT2SS_MCS2, MGN_VHT2SS_MCS3, MGN_VHT2SS_MCS4, + MGN_VHT2SS_MCS5, MGN_VHT2SS_MCS6, MGN_VHT2SS_MCS7, MGN_VHT2SS_MCS8, MGN_VHT2SS_MCS9}, + vht3ssRates[10] = {MGN_VHT3SS_MCS0, MGN_VHT3SS_MCS1, MGN_VHT3SS_MCS2, MGN_VHT3SS_MCS3, MGN_VHT3SS_MCS4, + MGN_VHT3SS_MCS5, MGN_VHT3SS_MCS6, MGN_VHT3SS_MCS7, MGN_VHT3SS_MCS8, MGN_VHT3SS_MCS9}; + + /* RTW_INFO("===>PHY_ConvertTxPowerByRateInDbmToRelativeValues()\n" ); */ + + for (band = BAND_ON_2_4G; band <= BAND_ON_5G; ++band) { + for (path = ODM_RF_PATH_A; path <= ODM_RF_PATH_D; ++path) { + for (txNum = RF_1TX; txNum < RF_MAX_TX_NUM; ++txNum) { + /* CCK */ + if (band == BAND_ON_2_4G) { + base = PHY_GetTxPowerByRateBase(pAdapter, band, path, txNum, CCK); + for (i = 0; i < sizeof(cckRates); ++i) { + value = PHY_GetTxPowerByRate(pAdapter, band, path, txNum, cckRates[i]); + PHY_SetTxPowerByRate(pAdapter, band, path, txNum, cckRates[i], value - base); + } + } + + /* OFDM */ + base = PHY_GetTxPowerByRateBase(pAdapter, band, path, txNum, OFDM); + for (i = 0; i < sizeof(ofdmRates); ++i) { + value = PHY_GetTxPowerByRate(pAdapter, band, path, txNum, ofdmRates[i]); + PHY_SetTxPowerByRate(pAdapter, band, path, txNum, ofdmRates[i], value - base); + } + + /* HT MCS0~7 */ + base = PHY_GetTxPowerByRateBase(pAdapter, band, path, txNum, HT_1SS); + for (i = 0; i < sizeof(mcs0_7Rates); ++i) { + value = PHY_GetTxPowerByRate(pAdapter, band, path, txNum, mcs0_7Rates[i]); + PHY_SetTxPowerByRate(pAdapter, band, path, txNum, mcs0_7Rates[i], value - base); + } + + /* HT MCS8~15 */ + base = PHY_GetTxPowerByRateBase(pAdapter, band, path, txNum, HT_2SS); + for (i = 0; i < sizeof(mcs8_15Rates); ++i) { + value = PHY_GetTxPowerByRate(pAdapter, band, path, txNum, mcs8_15Rates[i]); + PHY_SetTxPowerByRate(pAdapter, band, path, txNum, mcs8_15Rates[i], value - base); + } + + /* HT MCS16~23 */ + base = PHY_GetTxPowerByRateBase(pAdapter, band, path, txNum, HT_3SS); + for (i = 0; i < sizeof(mcs16_23Rates); ++i) { + value = PHY_GetTxPowerByRate(pAdapter, band, path, txNum, mcs16_23Rates[i]); + PHY_SetTxPowerByRate(pAdapter, band, path, txNum, mcs16_23Rates[i], value - base); + } + + /* VHT 1SS */ + base = PHY_GetTxPowerByRateBase(pAdapter, band, path, txNum, VHT_1SS); + for (i = 0; i < sizeof(vht1ssRates); ++i) { + value = PHY_GetTxPowerByRate(pAdapter, band, path, txNum, vht1ssRates[i]); + PHY_SetTxPowerByRate(pAdapter, band, path, txNum, vht1ssRates[i], value - base); + } + + /* VHT 2SS */ + base = PHY_GetTxPowerByRateBase(pAdapter, band, path, txNum, VHT_2SS); + for (i = 0; i < sizeof(vht2ssRates); ++i) { + value = PHY_GetTxPowerByRate(pAdapter, band, path, txNum, vht2ssRates[i]); + PHY_SetTxPowerByRate(pAdapter, band, path, txNum, vht2ssRates[i], value - base); + } + + /* VHT 3SS */ + base = PHY_GetTxPowerByRateBase(pAdapter, band, path, txNum, VHT_3SS); + for (i = 0; i < sizeof(vht3ssRates); ++i) { + value = PHY_GetTxPowerByRate(pAdapter, band, path, txNum, vht3ssRates[i]); + PHY_SetTxPowerByRate(pAdapter, band, path, txNum, vht3ssRates[i], value - base); + } + } + } + } + + /* RTW_INFO("<===PHY_ConvertTxPowerByRateInDbmToRelativeValues()\n" ); */ +} + +/* + * This function must be called if the value in the PHY_REG_PG.txt(or header) + * is exact dBm values + */ +void +PHY_TxPowerByRateConfiguration( + PADAPTER pAdapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + + phy_txpwr_by_rate_chk_for_path_dup(pAdapter); + phy_StoreTxPowerByRateBase(pAdapter); + phy_ConvertTxPowerByRateInDbmToRelativeValues(pAdapter); +} + +void +phy_set_tx_power_index_by_rate_section( + PADAPTER pAdapter, + u8 RFPath, + u8 Channel, + u8 RateSection +) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter); + + if (RateSection >= RATE_SECTION_NUM) { + RTW_INFO("Invalid RateSection %d in %s", RateSection, __func__); + rtw_warn_on(1); + goto exit; + } + + if (RateSection == CCK && pHalData->current_band_type != BAND_ON_2_4G) + goto exit; + + PHY_SetTxPowerIndexByRateArray(pAdapter, RFPath, pHalData->current_channel_bw, Channel, + rates_by_sections[RateSection].rates, rates_by_sections[RateSection].rate_num); + +exit: + return; +} + +static bool phy_GetChnlIndex(u8 Channel, u8 *ChannelIdx) +{ + u8 i = 0; + bool bIn24G = true; + + if (Channel <= 14) { + bIn24G = true; + *ChannelIdx = Channel - 1; + } else { + bIn24G = false; + + for (i = 0; i < CENTER_CH_5G_ALL_NUM; ++i) { + if (center_ch_5g_all[i] == Channel) { + *ChannelIdx = i; + return bIn24G; + } + } + } + + return bIn24G; +} + +u8 +PHY_GetTxPowerIndexBase( + PADAPTER pAdapter, + u8 RFPath, + u8 Rate, + CHANNEL_WIDTH BandWidth, + u8 Channel, + bool * bIn24G +) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter); + struct PHY_DM_STRUCT *pDM_Odm = &pHalData->odmpriv; + u8 i = 0; /* default set to 1S */ + u8 txPower = 0; + u8 chnlIdx = (Channel - 1); + + if (HAL_IsLegalChannel(pAdapter, Channel) == false) { + chnlIdx = 0; + RTW_INFO("Illegal channel!!\n"); + } + + *bIn24G = phy_GetChnlIndex(Channel, &chnlIdx); + + /* RTW_INFO("[%s] Channel Index: %d\n", (*bIn24G?"2.4G":"5G"), chnlIdx); */ + + if (*bIn24G) { /* 3 ============================== 2.4 G ============================== */ + if (IS_CCK_RATE(Rate)) + txPower = pHalData->Index24G_CCK_Base[RFPath][chnlIdx]; + else if (MGN_6M <= Rate) + txPower = pHalData->Index24G_BW40_Base[RFPath][chnlIdx]; + else + RTW_INFO("PHY_GetTxPowerIndexBase: INVALID Rate(0x%02x).\n", Rate); + + /* RTW_INFO("Base Tx power(RF-%c, Rate #%d, Channel Index %d) = 0x%X\n", */ + /* ((RFPath==0)?'A':'B'), Rate, chnlIdx, txPower); */ + + /* OFDM-1T */ + if ((MGN_6M <= Rate && Rate <= MGN_54M) && !IS_CCK_RATE(Rate)) { + txPower += pHalData->OFDM_24G_Diff[RFPath][TX_1S]; + /* RTW_INFO("+PowerDiff 2.4G (RF-%c): (OFDM-1T) = (%d)\n", ((RFPath==0)?'A':'B'), pHalData->OFDM_24G_Diff[RFPath][TX_1S]); */ + } + /* BW20-1S, BW20-2S */ + if (BandWidth == CHANNEL_WIDTH_20) { + if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW20_24G_Diff[RFPath][TX_1S]; + if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW20_24G_Diff[RFPath][TX_2S]; + if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW20_24G_Diff[RFPath][TX_3S]; + if ((MGN_MCS24 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW20_24G_Diff[RFPath][TX_4S]; + + /* RTW_INFO("+PowerDiff 2.4G (RF-%c): (BW20-1S, BW20-2S, BW20-3S, BW20-4S) = (%d, %d, %d, %d)\n", ((RFPath==0)?'A':(RFPath==1)?'B':(RFPath==2)?'C':'D'), */ + /* pHalData->BW20_24G_Diff[RFPath][TX_1S], pHalData->BW20_24G_Diff[RFPath][TX_2S], */ + /* pHalData->BW20_24G_Diff[RFPath][TX_3S], pHalData->BW20_24G_Diff[RFPath][TX_4S]); */ + } + /* BW40-1S, BW40-2S */ + else if (BandWidth == CHANNEL_WIDTH_40) { + if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW40_24G_Diff[RFPath][TX_1S]; + if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW40_24G_Diff[RFPath][TX_2S]; + if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW40_24G_Diff[RFPath][TX_3S]; + if ((MGN_MCS24 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW40_24G_Diff[RFPath][TX_4S]; + + /* RTW_INFO("+PowerDiff 2.4G (RF-%c): (BW40-1S, BW40-2S, BW40-3S, BW40-4S) = (%d, %d, %d, %d)\n", ((RFPath==0)?'A':(RFPath==1)?'B':(RFPath==2)?'C':'D'), */ + /* pHalData->BW40_24G_Diff[RFPath][TX_1S], pHalData->BW40_24G_Diff[RFPath][TX_2S], */ + /* pHalData->BW40_24G_Diff[RFPath][TX_3S], pHalData->BW40_24G_Diff[RFPath][TX_4S]); */ + } + /* Willis suggest adopt BW 40M power index while in BW 80 mode */ + else if (BandWidth == CHANNEL_WIDTH_80) { + if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW40_24G_Diff[RFPath][TX_1S]; + if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW40_24G_Diff[RFPath][TX_2S]; + if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW40_24G_Diff[RFPath][TX_3S]; + if ((MGN_MCS24 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW40_24G_Diff[RFPath][TX_4S]; + + /* RTW_INFO("+PowerDiff 2.4G (RF-%c): (BW40-1S, BW40-2S, BW40-3S, BW40-4T) = (%d, %d, %d, %d) P.S. Current is in BW 80MHz\n", ((RFPath==0)?'A':(RFPath==1)?'B':(RFPath==2)?'C':'D'), */ + /* pHalData->BW40_24G_Diff[RFPath][TX_1S], pHalData->BW40_24G_Diff[RFPath][TX_2S], */ + /* pHalData->BW40_24G_Diff[RFPath][TX_3S], pHalData->BW40_24G_Diff[RFPath][TX_4S]); */ + } + } +#ifdef CONFIG_IEEE80211_BAND_5GHZ + else { /* 3 ============================== 5 G ============================== */ + if (MGN_6M <= Rate) + txPower = pHalData->Index5G_BW40_Base[RFPath][chnlIdx]; + else + RTW_INFO("===>PHY_GetTxPowerIndexBase: INVALID Rate(0x%02x).\n", Rate); + + /* RTW_INFO("Base Tx power(RF-%c, Rate #%d, Channel Index %d) = 0x%X\n", */ + /* ((RFPath==0)?'A':'B'), Rate, chnlIdx, txPower); */ + + /* OFDM-1T */ + if ((MGN_6M <= Rate && Rate <= MGN_54M) && !IS_CCK_RATE(Rate)) { + txPower += pHalData->OFDM_5G_Diff[RFPath][TX_1S]; + /* RTW_INFO("+PowerDiff 5G (RF-%c): (OFDM-1T) = (%d)\n", ((RFPath==0)?'A':'B'), pHalData->OFDM_5G_Diff[RFPath][TX_1S]); */ + } + + /* BW20-1S, BW20-2S */ + if (BandWidth == CHANNEL_WIDTH_20) { + if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW20_5G_Diff[RFPath][TX_1S]; + if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW20_5G_Diff[RFPath][TX_2S]; + if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW20_5G_Diff[RFPath][TX_3S]; + if ((MGN_MCS24 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW20_5G_Diff[RFPath][TX_4S]; + + /* RTW_INFO("+PowerDiff 5G (RF-%c): (BW20-1S, BW20-2S, BW20-3S, BW20-4S) = (%d, %d, %d, %d)\n", ((RFPath==0)?'A':(RFPath==1)?'B':(RFPath==2)?'C':'D'), */ + /* pHalData->BW20_5G_Diff[RFPath][TX_1S], pHalData->BW20_5G_Diff[RFPath][TX_2S], */ + /* pHalData->BW20_5G_Diff[RFPath][TX_3S], pHalData->BW20_5G_Diff[RFPath][TX_4S]); */ + } + /* BW40-1S, BW40-2S */ + else if (BandWidth == CHANNEL_WIDTH_40) { + if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW40_5G_Diff[RFPath][TX_1S]; + if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW40_5G_Diff[RFPath][TX_2S]; + if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW40_5G_Diff[RFPath][TX_3S]; + if ((MGN_MCS24 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW40_5G_Diff[RFPath][TX_4S]; + + /* RTW_INFO("+PowerDiff 5G(RF-%c): (BW40-1S, BW40-2S) = (%d, %d, %d, %d)\n", ((RFPath==0)?'A':(RFPath==1)?'B':(RFPath==2)?'C':'D'), */ + /* pHalData->BW40_5G_Diff[RFPath][TX_1S], pHalData->BW40_5G_Diff[RFPath][TX_2S], */ + /* pHalData->BW40_5G_Diff[RFPath][TX_3S], pHalData->BW40_5G_Diff[RFPath][TX_4S]); */ + } + /* BW80-1S, BW80-2S */ + else if (BandWidth == CHANNEL_WIDTH_80) { + /* <20121220, Kordan> Get the index of array "Index5G_BW80_Base". */ + for (i = 0; i < CENTER_CH_5G_80M_NUM; ++i) + if (center_ch_5g_80m[i] == Channel) + chnlIdx = i; + + txPower = pHalData->Index5G_BW80_Base[RFPath][chnlIdx]; + + if ((MGN_MCS0 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT1SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += + pHalData->BW80_5G_Diff[RFPath][TX_1S]; + if ((MGN_MCS8 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT2SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW80_5G_Diff[RFPath][TX_2S]; + if ((MGN_MCS16 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT3SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW80_5G_Diff[RFPath][TX_3S]; + if ((MGN_MCS23 <= Rate && Rate <= MGN_MCS31) || (MGN_VHT4SS_MCS0 <= Rate && Rate <= MGN_VHT4SS_MCS9)) + txPower += pHalData->BW80_5G_Diff[RFPath][TX_4S]; + + /* RTW_INFO("+PowerDiff 5G(RF-%c): (BW80-1S, BW80-2S, BW80-3S, BW80-4S) = (%d, %d, %d, %d)\n",((RFPath==0)?'A':(RFPath==1)?'B':(RFPath==2)?'C':'D'), */ + /* pHalData->BW80_5G_Diff[RFPath][TX_1S], pHalData->BW80_5G_Diff[RFPath][TX_2S], */ + /* pHalData->BW80_5G_Diff[RFPath][TX_3S], pHalData->BW80_5G_Diff[RFPath][TX_4S]); */ + } + } +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + + return txPower; +} + +s8 +PHY_GetTxPowerTrackingOffset( + PADAPTER pAdapter, + u8 RFPath, + u8 Rate +) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter); + struct PHY_DM_STRUCT *pDM_Odm = &pHalData->odmpriv; + s8 offset = 0; + + if (pDM_Odm->rf_calibrate_info.txpowertrack_control == false) + return offset; + + if ((Rate == MGN_1M) || (Rate == MGN_2M) || (Rate == MGN_5_5M) || (Rate == MGN_11M)) { + offset = pDM_Odm->rf_calibrate_info.remnant_cck_swing_idx; + /*RTW_INFO("+Remnant_CCKSwingIdx = 0x%x\n", RFPath, Rate, pRFCalibrateInfo->Remnant_CCKSwingIdx);*/ + } else { + offset = pDM_Odm->rf_calibrate_info.remnant_ofdm_swing_idx[RFPath]; + /*RTW_INFO("+Remanant_OFDMSwingIdx[RFPath %u][Rate 0x%x] = 0x%x\n", RFPath, Rate, pRFCalibrateInfo->Remnant_OFDMSwingIdx[RFPath]); */ + + } + + return offset; +} + +/*The same as MRateToHwRate in hal_com.c*/ +u8 +PHY_GetRateIndexOfTxPowerByRate( + u8 Rate +) +{ + u8 index = 0; + switch (Rate) { + case MGN_1M: + index = 0; + break; + case MGN_2M: + index = 1; + break; + case MGN_5_5M: + index = 2; + break; + case MGN_11M: + index = 3; + break; + case MGN_6M: + index = 4; + break; + case MGN_9M: + index = 5; + break; + case MGN_12M: + index = 6; + break; + case MGN_18M: + index = 7; + break; + case MGN_24M: + index = 8; + break; + case MGN_36M: + index = 9; + break; + case MGN_48M: + index = 10; + break; + case MGN_54M: + index = 11; + break; + case MGN_MCS0: + index = 12; + break; + case MGN_MCS1: + index = 13; + break; + case MGN_MCS2: + index = 14; + break; + case MGN_MCS3: + index = 15; + break; + case MGN_MCS4: + index = 16; + break; + case MGN_MCS5: + index = 17; + break; + case MGN_MCS6: + index = 18; + break; + case MGN_MCS7: + index = 19; + break; + case MGN_MCS8: + index = 20; + break; + case MGN_MCS9: + index = 21; + break; + case MGN_MCS10: + index = 22; + break; + case MGN_MCS11: + index = 23; + break; + case MGN_MCS12: + index = 24; + break; + case MGN_MCS13: + index = 25; + break; + case MGN_MCS14: + index = 26; + break; + case MGN_MCS15: + index = 27; + break; + case MGN_MCS16: + index = 28; + break; + case MGN_MCS17: + index = 29; + break; + case MGN_MCS18: + index = 30; + break; + case MGN_MCS19: + index = 31; + break; + case MGN_MCS20: + index = 32; + break; + case MGN_MCS21: + index = 33; + break; + case MGN_MCS22: + index = 34; + break; + case MGN_MCS23: + index = 35; + break; + case MGN_MCS24: + index = 36; + break; + case MGN_MCS25: + index = 37; + break; + case MGN_MCS26: + index = 38; + break; + case MGN_MCS27: + index = 39; + break; + case MGN_MCS28: + index = 40; + break; + case MGN_MCS29: + index = 41; + break; + case MGN_MCS30: + index = 42; + break; + case MGN_MCS31: + index = 43; + break; + case MGN_VHT1SS_MCS0: + index = 44; + break; + case MGN_VHT1SS_MCS1: + index = 45; + break; + case MGN_VHT1SS_MCS2: + index = 46; + break; + case MGN_VHT1SS_MCS3: + index = 47; + break; + case MGN_VHT1SS_MCS4: + index = 48; + break; + case MGN_VHT1SS_MCS5: + index = 49; + break; + case MGN_VHT1SS_MCS6: + index = 50; + break; + case MGN_VHT1SS_MCS7: + index = 51; + break; + case MGN_VHT1SS_MCS8: + index = 52; + break; + case MGN_VHT1SS_MCS9: + index = 53; + break; + case MGN_VHT2SS_MCS0: + index = 54; + break; + case MGN_VHT2SS_MCS1: + index = 55; + break; + case MGN_VHT2SS_MCS2: + index = 56; + break; + case MGN_VHT2SS_MCS3: + index = 57; + break; + case MGN_VHT2SS_MCS4: + index = 58; + break; + case MGN_VHT2SS_MCS5: + index = 59; + break; + case MGN_VHT2SS_MCS6: + index = 60; + break; + case MGN_VHT2SS_MCS7: + index = 61; + break; + case MGN_VHT2SS_MCS8: + index = 62; + break; + case MGN_VHT2SS_MCS9: + index = 63; + break; + case MGN_VHT3SS_MCS0: + index = 64; + break; + case MGN_VHT3SS_MCS1: + index = 65; + break; + case MGN_VHT3SS_MCS2: + index = 66; + break; + case MGN_VHT3SS_MCS3: + index = 67; + break; + case MGN_VHT3SS_MCS4: + index = 68; + break; + case MGN_VHT3SS_MCS5: + index = 69; + break; + case MGN_VHT3SS_MCS6: + index = 70; + break; + case MGN_VHT3SS_MCS7: + index = 71; + break; + case MGN_VHT3SS_MCS8: + index = 72; + break; + case MGN_VHT3SS_MCS9: + index = 73; + break; + case MGN_VHT4SS_MCS0: + index = 74; + break; + case MGN_VHT4SS_MCS1: + index = 75; + break; + case MGN_VHT4SS_MCS2: + index = 76; + break; + case MGN_VHT4SS_MCS3: + index = 77; + break; + case MGN_VHT4SS_MCS4: + index = 78; + break; + case MGN_VHT4SS_MCS5: + index = 79; + break; + case MGN_VHT4SS_MCS6: + index = 80; + break; + case MGN_VHT4SS_MCS7: + index = 81; + break; + case MGN_VHT4SS_MCS8: + index = 82; + break; + case MGN_VHT4SS_MCS9: + index = 83; + break; + default: + RTW_INFO("Invalid rate 0x%x in %s\n", Rate, __func__); + break; + }; + + return index; +} + +s8 +_PHY_GetTxPowerByRate( + PADAPTER pAdapter, + u8 Band, + u8 RFPath, + u8 TxNum, + u8 Rate +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + s8 value = 0; + u8 rateIndex = PHY_GetRateIndexOfTxPowerByRate(Rate); + + if (Band != BAND_ON_2_4G && Band != BAND_ON_5G) { + RTW_INFO("Invalid band %d in %s\n", Band, __func__); + goto exit; + } + if (RFPath > ODM_RF_PATH_D) { + RTW_INFO("Invalid RfPath %d in %s\n", RFPath, __func__); + goto exit; + } + if (TxNum >= RF_MAX_TX_NUM) { + RTW_INFO("Invalid TxNum %d in %s\n", TxNum, __func__); + goto exit; + } + if (rateIndex >= TX_PWR_BY_RATE_NUM_RATE) { + RTW_INFO("Invalid RateIndex %d in %s\n", rateIndex, __func__); + goto exit; + } + + value = pHalData->TxPwrByRateOffset[Band][RFPath][TxNum][rateIndex]; + +exit: + return value; +} + + +s8 +PHY_GetTxPowerByRate( + PADAPTER pAdapter, + u8 Band, + u8 RFPath, + u8 TxNum, + u8 Rate +) +{ + if (!phy_is_tx_power_by_rate_needed(pAdapter)) + return 0; + + return _PHY_GetTxPowerByRate(pAdapter, Band, RFPath, TxNum, Rate); +} + +#ifdef CONFIG_PHYDM_POWERTRACK_BY_TSSI +s8 +PHY_GetTxPowerByRateOriginal( + PADAPTER pAdapter, + u8 Band, + u8 RFPath, + u8 TxNum, + u8 Rate +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + s8 value = 0, limit = 0; + u8 rateIndex = PHY_GetRateIndexOfTxPowerByRate(Rate); + + if ((pAdapter->registrypriv.RegEnableTxPowerByRate == 2 && pHalData->EEPROMRegulatory == 2) || + pAdapter->registrypriv.RegEnableTxPowerByRate == 0) + return 0; + + if (Band != BAND_ON_2_4G && Band != BAND_ON_5G) { + DBG_871X("Invalid band %d in %s\n", Band, __func__); + return value; + } + if (RFPath > ODM_RF_PATH_D) { + DBG_871X("Invalid RfPath %d in %s\n", RFPath, __func__); + return value; + } + if (TxNum >= RF_MAX_TX_NUM) { + DBG_871X("Invalid TxNum %d in %s\n", TxNum, __func__); + return value; + } + if (rateIndex >= TX_PWR_BY_RATE_NUM_RATE) { + DBG_871X("Invalid RateIndex %d in %s\n", rateIndex, __func__); + return value; + } + + value = pHalData->TxPwrByRate[Band][RFPath][TxNum][rateIndex]; + + return value; +} + +#endif + + +void +PHY_SetTxPowerByRate( + PADAPTER pAdapter, + u8 Band, + u8 RFPath, + u8 TxNum, + u8 Rate, + s8 Value +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + u8 rateIndex = PHY_GetRateIndexOfTxPowerByRate(Rate); + + if (Band != BAND_ON_2_4G && Band != BAND_ON_5G) { + RTW_INFO("Invalid band %d in %s\n", Band, __func__); + return; + } + if (RFPath > ODM_RF_PATH_D) { + RTW_INFO("Invalid RfPath %d in %s\n", RFPath, __func__); + return; + } + if (TxNum >= RF_MAX_TX_NUM) { + RTW_INFO("Invalid TxNum %d in %s\n", TxNum, __func__); + return; + } + if (rateIndex >= TX_PWR_BY_RATE_NUM_RATE) { + RTW_INFO("Invalid RateIndex %d in %s\n", rateIndex, __func__); + return; + } + + pHalData->TxPwrByRateOffset[Band][RFPath][TxNum][rateIndex] = Value; +} + +void +phy_set_tx_power_level_by_path( + PADAPTER Adapter, + u8 channel, + u8 path +) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter); + bool bIsIn24G = (pHalData->current_band_type == BAND_ON_2_4G); + + /* if ( pMgntInfo->RegNByteAccess == 0 ) */ + { + if (bIsIn24G) + phy_set_tx_power_index_by_rate_section(Adapter, path, channel, CCK); + + phy_set_tx_power_index_by_rate_section(Adapter, path, channel, OFDM); + phy_set_tx_power_index_by_rate_section(Adapter, path, channel, HT_MCS0_MCS7); + + if (pHalData->NumTotalRFPath >= 2) + phy_set_tx_power_index_by_rate_section(Adapter, path, channel, HT_MCS8_MCS15); + } +} + +#ifndef DBG_TX_POWER_IDX +#define DBG_TX_POWER_IDX 0 +#endif + +void +PHY_SetTxPowerIndexByRateArray( + PADAPTER pAdapter, + u8 RFPath, + CHANNEL_WIDTH BandWidth, + u8 Channel, + u8 *Rates, + u8 RateArraySize +) +{ + u32 powerIndex = 0; + int i = 0; + + for (i = 0; i < RateArraySize; ++i) { +#if DBG_TX_POWER_IDX + struct txpwr_idx_comp tic; + + powerIndex = rtw_hal_get_tx_power_index(pAdapter, RFPath, Rates[i], BandWidth, Channel, &tic); + RTW_INFO("TXPWR: [%c][%s]ch:%u, %s, pwr_idx:%u = %u + (%d=%d:%d) + (%d) + (%d)\n" + , rf_path_char(RFPath), ch_width_str(BandWidth), Channel, MGN_RATE_STR(Rates[i]) + , powerIndex, tic.base, (tic.by_rate > tic.limit ? tic.limit : tic.by_rate), tic.by_rate, tic.limit, tic.tpt, tic.ebias); +#else + powerIndex = phy_get_tx_power_index(pAdapter, RFPath, Rates[i], BandWidth, Channel); +#endif + PHY_SetTxPowerIndex(pAdapter, powerIndex, RFPath, Rates[i]); + } +} + +static s8 phy_GetWorldWideLimit(s8 *LimitTable) +{ + s8 min = LimitTable[0]; + u8 i = 0; + + for (i = 0; i < MAX_REGULATION_NUM; ++i) { + if (LimitTable[i] < min) + min = LimitTable[i]; + } + + return min; +} + +static s8 phy_GetChannelIndexOfTxPowerLimit(u8 Band, u8 Channel) +{ + s8 channelIndex = -1; + u8 i = 0; + + if (Band == BAND_ON_2_4G) + channelIndex = Channel - 1; + else if (Band == BAND_ON_5G) { + for (i = 0; i < CENTER_CH_5G_ALL_NUM; ++i) { + if (center_ch_5g_all[i] == Channel) + channelIndex = i; + } + } else + RTW_PRINT("Invalid Band %d in %s\n", Band, __func__); + + if (channelIndex == -1) + RTW_PRINT("Invalid Channel %d of Band %d in %s\n", Channel, Band, __func__); + + return channelIndex; +} + +static s8 _phy_get_txpwr_lmt( + PADAPTER Adapter, + u32 RegPwrTblSel, + BAND_TYPE Band, + CHANNEL_WIDTH Bandwidth, + u8 RfPath, + u8 DataRate, + u8 Channel, + bool no_sc +) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(Adapter); + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(Adapter); + s8 regulation = -1, bw = -1, rs = -1; + u8 cch = 0; + u8 bw_bmp = 0; + s8 min_lmt = MAX_POWER_INDEX; + s8 tmp_lmt; + u8 final_bw = Bandwidth, final_cch = Channel; + + if ((Adapter->registrypriv.RegEnableTxPowerLimit == 2 && hal_data->EEPROMRegulatory != 1) || + Adapter->registrypriv.RegEnableTxPowerLimit == 0) + goto exit; + + switch (RegPwrTblSel) { + case 1: + regulation = TXPWR_LMT_ETSI; + break; + case 2: + regulation = TXPWR_LMT_MKK; + break; + case 3: + regulation = TXPWR_LMT_FCC; + break; + case 4: + regulation = TXPWR_LMT_WW; + break; + default: + regulation = (Band == BAND_ON_2_4G) ? hal_data->Regulation2_4G : hal_data->Regulation5G; + break; + } + + if (Band != BAND_ON_2_4G && Band != BAND_ON_5G) { + RTW_ERR("%s invalid band:%u\n", __func__, Band); + rtw_warn_on(1); + goto exit; + } + + if (IS_CCK_RATE(DataRate)) + rs = CCK; + else if (IS_OFDM_RATE(DataRate)) + rs = OFDM; + else if (IS_HT1SS_RATE(DataRate)) + rs = HT_1SS; + else if (IS_HT2SS_RATE(DataRate)) + rs = HT_2SS; + else if (IS_HT3SS_RATE(DataRate)) + rs = HT_3SS; + else if (IS_HT4SS_RATE(DataRate)) + rs = HT_4SS; + else if (IS_VHT1SS_RATE(DataRate)) + rs = VHT_1SS; + else if (IS_VHT2SS_RATE(DataRate)) + rs = VHT_2SS; + else if (IS_VHT3SS_RATE(DataRate)) + rs = VHT_3SS; + else if (IS_VHT4SS_RATE(DataRate)) + rs = VHT_4SS; + else { + RTW_ERR("%s invalid rate 0x%x\n", __func__, DataRate); + rtw_warn_on(1); + goto exit; + } + + if (Band == BAND_ON_5G && rs == CCK) { + RTW_ERR("Wrong rate No CCK(0x%x) in 5G Band\n", DataRate); + goto exit; + } + + if (no_sc == true) { + /* use the input center channel and bandwidth directly */ + cch = Channel; + bw_bmp = ch_width_to_bw_cap(Bandwidth); + } else { + /* + * find the possible tx bandwidth bmp for this rate, and then will get center channel for each bandwidth + * if no possible tx bandwidth bmp, select valid bandwidth up to current RF bandwidth into bmp + */ + if (rs == CCK || rs == OFDM) + bw_bmp = BW_CAP_20M; /* CCK, OFDM only BW 20M */ + else if (IS_HT_RATE_SECTION(rs)) { + bw_bmp = rtw_get_tx_bw_bmp_of_ht_rate(dvobj, DataRate, Bandwidth); + if (bw_bmp == 0) + bw_bmp = ch_width_to_bw_cap(Bandwidth > CHANNEL_WIDTH_40 ? CHANNEL_WIDTH_40 : Bandwidth); + } else if (IS_VHT_RATE_SECTION(rs)) { + bw_bmp = rtw_get_tx_bw_bmp_of_vht_rate(dvobj, DataRate, Bandwidth); + if (bw_bmp == 0) + bw_bmp = ch_width_to_bw_cap(Bandwidth > CHANNEL_WIDTH_160 ? CHANNEL_WIDTH_160 : Bandwidth); + } else + rtw_warn_on(1); + } + + if (bw_bmp == 0) + goto exit; + + /* loop for each possible tx bandwidth to find minimum limit */ + for (bw = CHANNEL_WIDTH_20; bw <= Bandwidth; bw++) { + s8 ch_idx; + + if (!(ch_width_to_bw_cap(bw) & bw_bmp)) + continue; + + if (no_sc == false) { + if (bw == CHANNEL_WIDTH_20) + cch = hal_data->cch_20; + else if (bw == CHANNEL_WIDTH_40) + cch = hal_data->cch_40; + else if (bw == CHANNEL_WIDTH_80) + cch = hal_data->cch_80; + else { + cch = 0; + rtw_warn_on(1); + } + } + + ch_idx = phy_GetChannelIndexOfTxPowerLimit(Band, cch); + if (ch_idx == -1) + continue; + + if (Band == BAND_ON_2_4G) { + s8 limits[MAX_REGULATION_NUM] = {0}; + u8 i = 0; + + for (i = 0; i < MAX_REGULATION_NUM; ++i) + limits[i] = hal_data->TxPwrLimit_2_4G[i][bw][rs][ch_idx][RfPath]; + + tmp_lmt = (regulation == TXPWR_LMT_WW) ? phy_GetWorldWideLimit(limits) : + hal_data->TxPwrLimit_2_4G[regulation][bw][rs][ch_idx][RfPath]; + + } else if (Band == BAND_ON_5G) { + s8 limits[MAX_REGULATION_NUM] = {0}; + u8 i = 0; + + for (i = 0; i < MAX_REGULATION_NUM; ++i) + limits[i] = hal_data->TxPwrLimit_5G[i][bw][rs][ch_idx][RfPath]; + + tmp_lmt = (regulation == TXPWR_LMT_WW) ? phy_GetWorldWideLimit(limits) : + hal_data->TxPwrLimit_5G[regulation][bw][rs][ch_idx][RfPath]; + } else + continue; + + if (min_lmt >= tmp_lmt) { + min_lmt = tmp_lmt; + final_cch = cch; + final_bw = bw; + } + } + +exit: + return min_lmt; +} + +inline s8 +PHY_GetTxPowerLimit( + PADAPTER Adapter, + u32 RegPwrTblSel, + BAND_TYPE Band, + CHANNEL_WIDTH Bandwidth, + u8 RfPath, + u8 DataRate, + u8 Channel +) +{ + bool no_sc = false; + + /* MP mode channel don't use secondary channel */ + if (rtw_mi_mp_mode_check(Adapter) == true) + no_sc = true; + + return _phy_get_txpwr_lmt(Adapter, RegPwrTblSel, Band, Bandwidth, RfPath, DataRate, Channel, no_sc); +} + +inline s8 +PHY_GetTxPowerLimit_no_sc( + PADAPTER Adapter, + u32 RegPwrTblSel, + BAND_TYPE Band, + CHANNEL_WIDTH Bandwidth, + u8 RfPath, + u8 DataRate, + u8 Channel +) +{ + return _phy_get_txpwr_lmt(Adapter, RegPwrTblSel, Band, Bandwidth, RfPath, DataRate, Channel, true); +} + +#ifdef CONFIG_PHYDM_POWERTRACK_BY_TSSI +s8 +PHY_GetTxPowerLimitOriginal( + PADAPTER Adapter, + u32 RegPwrTblSel, + BAND_TYPE Band, + CHANNEL_WIDTH Bandwidth, + u8 RfPath, + u8 DataRate, + u8 Channel +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + s16 band = -1, regulation = -1, bandwidth = -1, + rateSection = -1, channel = -1; + s8 powerLimit = MAX_POWER_INDEX; + + if ((Adapter->registrypriv.RegEnableTxPowerLimit == 2 && pHalData->EEPROMRegulatory != 1) || + Adapter->registrypriv.RegEnableTxPowerLimit == 0) + return MAX_POWER_INDEX; + + switch (Adapter->registrypriv.RegPwrTblSel) { + case 1: + regulation = TXPWR_LMT_ETSI; + break; + + case 2: + regulation = TXPWR_LMT_MKK; + break; + + case 3: + regulation = TXPWR_LMT_FCC; + break; + + case 4: + regulation = TXPWR_LMT_WW; + break; + + default: + regulation = (Band == BAND_ON_2_4G) ? pHalData->Regulation2_4G + : pHalData->Regulation5G; + break; + } + + /*DBG_871X("pMgntInfo->RegPwrTblSel %d, final regulation %d\n", Adapter->registrypriv.RegPwrTblSel, regulation );*/ + + + if (Band == BAND_ON_2_4G) + band = 0; + else if (Band == BAND_ON_5G) + band = 1; + + if (Bandwidth == CHANNEL_WIDTH_20) + bandwidth = 0; + else if (Bandwidth == CHANNEL_WIDTH_40) + bandwidth = 1; + else if (Bandwidth == CHANNEL_WIDTH_80) + bandwidth = 2; + else if (Bandwidth == CHANNEL_WIDTH_160) + bandwidth = 3; + + switch (DataRate) { + case MGN_1M: + case MGN_2M: + case MGN_5_5M: + case MGN_11M: + rateSection = 0; + break; + + case MGN_6M: + case MGN_9M: + case MGN_12M: + case MGN_18M: + case MGN_24M: + case MGN_36M: + case MGN_48M: + case MGN_54M: + rateSection = 1; + break; + + case MGN_MCS0: + case MGN_MCS1: + case MGN_MCS2: + case MGN_MCS3: + case MGN_MCS4: + case MGN_MCS5: + case MGN_MCS6: + case MGN_MCS7: + rateSection = 2; + break; + + case MGN_MCS8: + case MGN_MCS9: + case MGN_MCS10: + case MGN_MCS11: + case MGN_MCS12: + case MGN_MCS13: + case MGN_MCS14: + case MGN_MCS15: + rateSection = 3; + break; + + case MGN_MCS16: + case MGN_MCS17: + case MGN_MCS18: + case MGN_MCS19: + case MGN_MCS20: + case MGN_MCS21: + case MGN_MCS22: + case MGN_MCS23: + rateSection = 4; + break; + + case MGN_MCS24: + case MGN_MCS25: + case MGN_MCS26: + case MGN_MCS27: + case MGN_MCS28: + case MGN_MCS29: + case MGN_MCS30: + case MGN_MCS31: + rateSection = 5; + break; + + case MGN_VHT1SS_MCS0: + case MGN_VHT1SS_MCS1: + case MGN_VHT1SS_MCS2: + case MGN_VHT1SS_MCS3: + case MGN_VHT1SS_MCS4: + case MGN_VHT1SS_MCS5: + case MGN_VHT1SS_MCS6: + case MGN_VHT1SS_MCS7: + case MGN_VHT1SS_MCS8: + case MGN_VHT1SS_MCS9: + rateSection = 6; + break; + + case MGN_VHT2SS_MCS0: + case MGN_VHT2SS_MCS1: + case MGN_VHT2SS_MCS2: + case MGN_VHT2SS_MCS3: + case MGN_VHT2SS_MCS4: + case MGN_VHT2SS_MCS5: + case MGN_VHT2SS_MCS6: + case MGN_VHT2SS_MCS7: + case MGN_VHT2SS_MCS8: + case MGN_VHT2SS_MCS9: + rateSection = 7; + break; + + case MGN_VHT3SS_MCS0: + case MGN_VHT3SS_MCS1: + case MGN_VHT3SS_MCS2: + case MGN_VHT3SS_MCS3: + case MGN_VHT3SS_MCS4: + case MGN_VHT3SS_MCS5: + case MGN_VHT3SS_MCS6: + case MGN_VHT3SS_MCS7: + case MGN_VHT3SS_MCS8: + case MGN_VHT3SS_MCS9: + rateSection = 8; + break; + + case MGN_VHT4SS_MCS0: + case MGN_VHT4SS_MCS1: + case MGN_VHT4SS_MCS2: + case MGN_VHT4SS_MCS3: + case MGN_VHT4SS_MCS4: + case MGN_VHT4SS_MCS5: + case MGN_VHT4SS_MCS6: + case MGN_VHT4SS_MCS7: + case MGN_VHT4SS_MCS8: + case MGN_VHT4SS_MCS9: + rateSection = 9; + break; + + default: + DBG_871X("Wrong rate 0x%x\n", DataRate); + break; + } + + if (Band == BAND_ON_5G && rateSection == 0) + DBG_871X("Wrong rate 0x%x: No CCK in 5G Band\n", DataRate); + + /*workaround for wrong index combination to obtain tx power limit,*/ + /*OFDM only exists in BW 20M*/ + if (rateSection == 1) + bandwidth = 0; + + /*workaround for wrong index combination to obtain tx power limit,*/ + /*CCK table will only be given in BW 20M*/ + if (rateSection == 0) + bandwidth = 0; + + /*workaround for wrong indxe combination to obtain tx power limit,*/ + /*HT on 80M will reference to HT on 40M*/ + if ((rateSection == 2 || rateSection == 3) && Band == BAND_ON_5G && bandwidth == 2) + bandwidth = 1; + + if (Band == BAND_ON_2_4G) + channel = phy_GetChannelIndexOfTxPowerLimit(BAND_ON_2_4G, Channel); + else if (Band == BAND_ON_5G) + channel = phy_GetChannelIndexOfTxPowerLimit(BAND_ON_5G, Channel); + else if (Band == BAND_ON_BOTH) + /*BAND_ON_BOTH don't care temporarily*/ + + if (band == -1 || regulation == -1 || bandwidth == -1 || + rateSection == -1 || channel == -1) { + /*DBG_871X("Wrong index value to access power limit table [band %d][regulation %d][bandwidth %d][rf_path %d][rate_section %d][chnlGroup %d]\n",*/ + /* band, regulation, bandwidth, RfPath, rateSection, channelGroup );*/ + + return MAX_POWER_INDEX; + } + + if (Band == BAND_ON_2_4G) { + s8 limits[10] = {0}; + u8 i = 0; + + if (bandwidth >= MAX_2_4G_BANDWIDTH_NUM) + bandwidth = MAX_2_4G_BANDWIDTH_NUM - 1; + + for (i = 0; i < MAX_REGULATION_NUM; ++i) + limits[i] = pHalData->TxPwrLimit_2_4G_Original[i][bandwidth][rateSection][channel][RfPath]; + + powerLimit = (regulation == TXPWR_LMT_WW) ? phy_GetWorldWideLimit(limits) : + pHalData->TxPwrLimit_2_4G_Original[regulation][bandwidth][rateSection][channel][RfPath]; + + } else if (Band == BAND_ON_5G) { + s8 limits[10] = {0}; + u8 i = 0; + + for (i = 0; i < MAX_REGULATION_NUM; ++i) + limits[i] = pHalData->TxPwrLimit_5G_Original[i][bandwidth][rateSection][channel][RfPath]; + + powerLimit = (regulation == TXPWR_LMT_WW) ? phy_GetWorldWideLimit(limits) : + pHalData->TxPwrLimit_5G_Original[regulation][bandwidth][rateSection][channel][RfPath]; + } else + DBG_871X("No power limit table of the specified band\n"); + + /*combine 5G VHT & HT rate*/ + /*5G 20M and 40M HT and VHT can cross reference*/ + /* + if (Band == BAND_ON_5G && powerLimit == MAX_POWER_INDEX) { + if (bandwidth == 0 || bandwidth == 1) { + if (rateSection == 2) + powerLimit = pHalData->TxPwrLimit_5G_Original[regulation] + [bandwidth][4][channelGroup][RfPath]; + else if (rateSection == 4) + powerLimit = pHalData->TxPwrLimit_5G_Original[regulation] + [bandwidth][2][channelGroup][RfPath]; + else if (rateSection == 3) + powerLimit = pHalData->TxPwrLimit_5G_Original[regulation] + [bandwidth][5][channelGroup][RfPath]; + else if (rateSection == 5) + powerLimit = pHalData->TxPwrLimit_5G_Original[regulation] + [bandwidth][3][channelGroup][RfPath]; + } + } + */ + /*DBG_871X("TxPwrLmt[Regulation %d][Band %d][BW %d][RFPath %d][Rate 0x%x][Chnl %d] = %d\n",*/ + /* regulation, pHalData->current_band_type, Bandwidth, RfPath, DataRate, Channel, powerLimit);*/ + return powerLimit; +} +#endif + +static void phy_CrossReferenceHTAndVHTTxPowerLimit(PADAPTER pAdapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + u8 regulation, bw, channel, rs, ref_rs; + int ht_ref_vht_5g_20_40 = 0; + int vht_ref_ht_5g_20_40 = 0; + int ht_has_ref_5g_20_40 = 0; + int vht_has_ref_5g_20_40 = 0; + + pHalData->tx_pwr_lmt_5g_20_40_ref = 0; + + for (regulation = 0; regulation < MAX_REGULATION_NUM; ++regulation) { + + for (bw = 0; bw < MAX_5G_BANDWIDTH_NUM; ++bw) { + + for (channel = 0; channel < CENTER_CH_5G_ALL_NUM; ++channel) { + + for (rs = 0; rs < MAX_RATE_SECTION_NUM; ++rs) { + + /* 5G 20M 40M VHT and HT can cross reference */ + if (bw == CHANNEL_WIDTH_20 || bw == CHANNEL_WIDTH_40) { + if (rs == HT_1SS) + ref_rs = VHT_1SS; + else if (rs == HT_2SS) + ref_rs = VHT_2SS; + else if (rs == HT_3SS) + ref_rs = VHT_3SS; + else if (rs == HT_4SS) + ref_rs = VHT_4SS; + else if (rs == VHT_1SS) + ref_rs = HT_1SS; + else if (rs == VHT_2SS) + ref_rs = HT_2SS; + else if (rs == VHT_3SS) + ref_rs = HT_3SS; + else if (rs == VHT_4SS) + ref_rs = HT_4SS; + else + continue; + + if (pHalData->TxPwrLimit_5G[regulation][bw][ref_rs][channel][RF_PATH_A] == MAX_POWER_INDEX) + continue; + + if (IS_HT_RATE_SECTION(rs)) + ht_has_ref_5g_20_40++; + else if (IS_VHT_RATE_SECTION(rs)) + vht_has_ref_5g_20_40++; + else + continue; + + if (pHalData->TxPwrLimit_5G[regulation][bw][rs][channel][RF_PATH_A] != MAX_POWER_INDEX) + continue; + + if (IS_HT_RATE_SECTION(rs) && IS_VHT_RATE_SECTION(ref_rs)) + ht_ref_vht_5g_20_40++; + else if (IS_VHT_RATE_SECTION(rs) && IS_HT_RATE_SECTION(ref_rs)) + vht_ref_ht_5g_20_40++; + + if (0) + RTW_INFO("reg:%u, bw:%u, ch:%u, %s ref %s\n" + , regulation, bw, channel + , rate_section_str(rs), rate_section_str(ref_rs)); + + pHalData->TxPwrLimit_5G[regulation][bw][rs][channel][RF_PATH_A] = + pHalData->TxPwrLimit_5G[regulation][bw][ref_rs][channel][RF_PATH_A]; + } + + } + } + } + } + + if (0) { + RTW_INFO("ht_ref_vht_5g_20_40:%d, ht_has_ref_5g_20_40:%d\n", ht_ref_vht_5g_20_40, ht_has_ref_5g_20_40); + RTW_INFO("vht_ref_hht_5g_20_40:%d, vht_has_ref_5g_20_40:%d\n", vht_ref_ht_5g_20_40, vht_has_ref_5g_20_40); + } + + /* 5G 20M&40M HT all come from VHT*/ + if (ht_ref_vht_5g_20_40 && ht_has_ref_5g_20_40 == ht_ref_vht_5g_20_40) + pHalData->tx_pwr_lmt_5g_20_40_ref |= TX_PWR_LMT_REF_HT_FROM_VHT; + + /* 5G 20M&40M VHT all come from HT*/ + if (vht_ref_ht_5g_20_40 && vht_has_ref_5g_20_40 == vht_ref_ht_5g_20_40) + pHalData->tx_pwr_lmt_5g_20_40_ref |= TX_PWR_LMT_REF_VHT_FROM_HT; +} + +void +PHY_ConvertTxPowerLimitToPowerIndex( + PADAPTER Adapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u8 base; + u8 regulation, bw, channel, rateSection; + s8 tempValue = 0, tempPwrLmt = 0; + u8 rfPath = 0; + + if (pHalData->odmpriv.phy_reg_pg_value_type != PHY_REG_PG_EXACT_VALUE) { + rtw_warn_on(1); + return; + } + + phy_CrossReferenceHTAndVHTTxPowerLimit(Adapter); + + for (regulation = 0; regulation < MAX_REGULATION_NUM; ++regulation) { + + for (bw = 0; bw < MAX_2_4G_BANDWIDTH_NUM; ++bw) { + + for (channel = 0; channel < CENTER_CH_2G_NUM; ++channel) { + + for (rateSection = CCK; rateSection <= HT_4SS; ++rateSection) { + tempPwrLmt = pHalData->TxPwrLimit_2_4G[regulation][bw][rateSection][channel][RF_PATH_A]; + + if (tempPwrLmt != MAX_POWER_INDEX) { + + for (rfPath = RF_PATH_A; rfPath < MAX_RF_PATH; ++rfPath) { + base = PHY_GetTxPowerByRateBase(Adapter, BAND_ON_2_4G, rfPath, rate_section_to_tx_num(rateSection), rateSection); + tempValue = tempPwrLmt - base; + pHalData->TxPwrLimit_2_4G[regulation][bw][rateSection][channel][rfPath] = tempValue; + } + } + } + } + } + } +} + +/* +* PHY_InitTxPowerLimit - Set all hal_data.TxPwrLimit_2_4G, TxPwrLimit_5G array to MAX_POWER_INDEX +*/ +void +PHY_InitTxPowerLimit( + PADAPTER Adapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u8 i, j, k, l, m; + + for (i = 0; i < MAX_REGULATION_NUM; ++i) + for (j = 0; j < MAX_2_4G_BANDWIDTH_NUM; ++j) + for (k = 0; k < MAX_RATE_SECTION_NUM; ++k) + for (m = 0; m < CENTER_CH_2G_NUM; ++m) + for (l = 0; l < MAX_RF_PATH; ++l) + pHalData->TxPwrLimit_2_4G[i][j][k][m][l] = MAX_POWER_INDEX; + + for (i = 0; i < MAX_REGULATION_NUM; ++i) + for (j = 0; j < MAX_5G_BANDWIDTH_NUM; ++j) + for (k = 0; k < MAX_RATE_SECTION_NUM; ++k) + for (m = 0; m < CENTER_CH_5G_ALL_NUM; ++m) + for (l = 0; l < MAX_RF_PATH; ++l) + pHalData->TxPwrLimit_5G[i][j][k][m][l] = MAX_POWER_INDEX; +} + +/* +* phy_set_tx_power_limit - Parsing TX power limit from phydm array, called by odm_ConfigBB_TXPWR_LMT_XXX in phydm +*/ +void +phy_set_tx_power_limit( + struct PHY_DM_STRUCT *pDM_Odm, + u8 *Regulation, + u8 *Band, + u8 *Bandwidth, + u8 *RateSection, + u8 *RfPath, + u8 *Channel, + u8 *PowerLimit +) +{ + PADAPTER Adapter = pDM_Odm->adapter; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u8 regulation = 0, bandwidth = 0, rateSection = 0, channel; + s8 powerLimit = 0, prevPowerLimit, channelIndex; + + if (0) + RTW_INFO("Index of power limit table [band %s][regulation %s][bw %s][rate section %s][rf path %s][chnl %s][val %s]\n" + , Band, Regulation, Bandwidth, RateSection, RfPath, Channel, PowerLimit); + + if (GetU1ByteIntegerFromStringInDecimal((s8 *)Channel, &channel) == false + || GetU1ByteIntegerFromStringInDecimal((s8 *)PowerLimit, &powerLimit) == false + ) { + RTW_PRINT("Illegal index of power limit table [ch %s][val %s]\n", Channel, PowerLimit); + return; + } + + powerLimit = powerLimit > MAX_POWER_INDEX ? MAX_POWER_INDEX : powerLimit; + + if (eqNByte(Regulation, (u8 *)("FCC"), 3)) + regulation = TXPWR_LMT_FCC; + else if (eqNByte(Regulation, (u8 *)("MKK"), 3)) + regulation = TXPWR_LMT_MKK; + else if (eqNByte(Regulation, (u8 *)("ETSI"), 4)) + regulation = TXPWR_LMT_ETSI; + else if (eqNByte(Regulation, (u8 *)("WW13"), 4)) + regulation = TXPWR_LMT_WW; + else { + RTW_PRINT("unknown regulation:%s", Regulation); + return; + } + + if (eqNByte(RateSection, (u8 *)("CCK"), 3) && eqNByte(RfPath, (u8 *)("1T"), 2)) + rateSection = CCK; + else if (eqNByte(RateSection, (u8 *)("OFDM"), 4) && eqNByte(RfPath, (u8 *)("1T"), 2)) + rateSection = OFDM; + else if (eqNByte(RateSection, (u8 *)("HT"), 2) && eqNByte(RfPath, (u8 *)("1T"), 2)) + rateSection = HT_1SS; + else if (eqNByte(RateSection, (u8 *)("HT"), 2) && eqNByte(RfPath, (u8 *)("2T"), 2)) + rateSection = HT_2SS; + else if (eqNByte(RateSection, (u8 *)("HT"), 2) && eqNByte(RfPath, (u8 *)("3T"), 2)) + rateSection = HT_3SS; + else if (eqNByte(RateSection, (u8 *)("HT"), 2) && eqNByte(RfPath, (u8 *)("4T"), 2)) + rateSection = HT_4SS; + else if (eqNByte(RateSection, (u8 *)("VHT"), 3) && eqNByte(RfPath, (u8 *)("1T"), 2)) + rateSection = VHT_1SS; + else if (eqNByte(RateSection, (u8 *)("VHT"), 3) && eqNByte(RfPath, (u8 *)("2T"), 2)) + rateSection = VHT_2SS; + else if (eqNByte(RateSection, (u8 *)("VHT"), 3) && eqNByte(RfPath, (u8 *)("3T"), 2)) + rateSection = VHT_3SS; + else if (eqNByte(RateSection, (u8 *)("VHT"), 3) && eqNByte(RfPath, (u8 *)("4T"), 2)) + rateSection = VHT_4SS; + else { + RTW_PRINT("Wrong rate section: (%s,%s)\n", RateSection, RfPath); + return; + } + + if (eqNByte(Bandwidth, (u8 *)("20M"), 3)) + bandwidth = CHANNEL_WIDTH_20; + else if (eqNByte(Bandwidth, (u8 *)("40M"), 3)) + bandwidth = CHANNEL_WIDTH_40; + else if (eqNByte(Bandwidth, (u8 *)("80M"), 3)) + bandwidth = CHANNEL_WIDTH_80; + else { + RTW_PRINT("unknown bandwidth: %s\n", Bandwidth); + return; + } + + if (eqNByte(Band, (u8 *)("2.4G"), 4)) { + channelIndex = phy_GetChannelIndexOfTxPowerLimit(BAND_ON_2_4G, channel); + + if (channelIndex == -1) { + RTW_PRINT("unsupported channel: %d at 2.4G\n", channel); + return; + } + + if (bandwidth >= MAX_2_4G_BANDWIDTH_NUM) { + RTW_PRINT("unsupported bandwidth: %s at 2.4G\n", Bandwidth); + return; + } + + prevPowerLimit = pHalData->TxPwrLimit_2_4G[regulation][bandwidth][rateSection][channelIndex][RF_PATH_A]; + + if (prevPowerLimit != MAX_POWER_INDEX) + RTW_PRINT("duplicate tx power limit combination [band %s][regulation %s][bw %s][rate section %s][rf path %s][chnl %s]\n" + , Band, Regulation, Bandwidth, RateSection, RfPath, Channel); + + if (powerLimit < prevPowerLimit) + pHalData->TxPwrLimit_2_4G[regulation][bandwidth][rateSection][channelIndex][RF_PATH_A] = powerLimit; + + if (0) + RTW_INFO("2.4G Band value : [regulation %d][bw %d][rate_section %d][chnl %d][val %d]\n" + , regulation, bandwidth, rateSection, channelIndex, pHalData->TxPwrLimit_2_4G[regulation][bandwidth][rateSection][channelIndex][ODM_RF_PATH_A]); + } else if (eqNByte(Band, (u8 *)("5G"), 2)) { + + channelIndex = phy_GetChannelIndexOfTxPowerLimit(BAND_ON_5G, channel); + + if (channelIndex == -1) { + RTW_PRINT("unsupported channel: %d at 5G\n", channel); + return; + } + + prevPowerLimit = pHalData->TxPwrLimit_5G[regulation][bandwidth][rateSection][channelIndex][RF_PATH_A]; + + if (prevPowerLimit != MAX_POWER_INDEX) + RTW_PRINT("duplicate tx power limit combination [band %s][regulation %s][bw %s][rate section %s][rf path %s][chnl %s]\n" + , Band, Regulation, Bandwidth, RateSection, RfPath, Channel); + + if (powerLimit < prevPowerLimit) + pHalData->TxPwrLimit_5G[regulation][bandwidth][rateSection][channelIndex][RF_PATH_A] = powerLimit; + + if (0) + RTW_INFO("5G Band value : [regulation %d][bw %d][rate_section %d][chnl %d][val %d]\n" + , regulation, bandwidth, rateSection, channel, pHalData->TxPwrLimit_5G[regulation][bandwidth][rateSection][channelIndex][RF_PATH_A]); + } else { + RTW_PRINT("Cannot recognize the band info in %s\n", Band); + return; + } +} + +u8 +phy_get_tx_power_index( + PADAPTER pAdapter, + u8 RFPath, + u8 Rate, + CHANNEL_WIDTH BandWidth, + u8 Channel +) +{ + return rtw_hal_get_tx_power_index(pAdapter, RFPath, Rate, BandWidth, Channel, NULL); +} + +void +PHY_SetTxPowerIndex( + PADAPTER pAdapter, + u32 PowerIndex, + u8 RFPath, + u8 Rate +) +{ + if (IS_HARDWARE_TYPE_8188E(pAdapter)) + PHY_SetTxPowerIndex_8188E(pAdapter, PowerIndex, RFPath, Rate); +} + +void dump_tx_power_idx_title(void *sel, _adapter *adapter) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + u8 bw = hal_data->current_channel_bw; + + RTW_PRINT_SEL(sel, "%s", ch_width_str(bw)); + if (bw >= CHANNEL_WIDTH_80) + _RTW_PRINT_SEL(sel, ", cch80:%u", hal_data->cch_80); + if (bw >= CHANNEL_WIDTH_40) + _RTW_PRINT_SEL(sel, ", cch40:%u", hal_data->cch_40); + _RTW_PRINT_SEL(sel, ", cch20:%u\n", hal_data->cch_20); + + RTW_PRINT_SEL(sel, "%-4s %-9s %-3s %-4s %-3s %-4s %-4s %-3s %-5s\n" + , "path", "rate", "pwr", "base", "", "(byr", "lmt)", "tpt", "ebias"); +} + +void dump_tx_power_idx_by_path_rs(void *sel, _adapter *adapter, u8 rfpath, u8 rs) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + u8 power_idx; + struct txpwr_idx_comp tic; + u8 tx_num, i; + u8 band = hal_data->current_band_type; + u8 cch = hal_data->current_channel; + u8 bw = hal_data->current_channel_bw; + + if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, rfpath)) + return; + + if (rs >= RATE_SECTION_NUM) + return; + + tx_num = rate_section_to_tx_num(rs); + if (tx_num >= hal_spec->tx_nss_num || tx_num >= hal_spec->max_tx_cnt) + return; + + if (band == BAND_ON_5G && IS_CCK_RATE_SECTION(rs)) + return; + + if (IS_VHT_RATE_SECTION(rs)) + return; + + for (i = 0; i < rates_by_sections[rs].rate_num; i++) { + power_idx = rtw_hal_get_tx_power_index(adapter, rfpath, rates_by_sections[rs].rates[i], bw, cch, &tic); + + RTW_PRINT_SEL(sel, "%4c %9s %3u %4u %3d (%3d %3d) %3d %5d\n" + , rf_path_char(rfpath), MGN_RATE_STR(rates_by_sections[rs].rates[i]) + , power_idx, tic.base, (tic.by_rate > tic.limit ? tic.limit : tic.by_rate), tic.by_rate, tic.limit, tic.tpt, tic.ebias); + } +} + +void dump_tx_power_idx(void *sel, _adapter *adapter) +{ + u8 rfpath, rs; + + dump_tx_power_idx_title(sel, adapter); + for (rfpath = RF_PATH_A; rfpath < RF_PATH_MAX; rfpath++) + for (rs = CCK; rs < RATE_SECTION_NUM; rs++) + dump_tx_power_idx_by_path_rs(sel, adapter, rfpath, rs); +} + +bool phy_is_tx_power_limit_needed(_adapter *adapter) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + struct registry_priv *regsty = dvobj_to_regsty(adapter_to_dvobj(adapter)); + + if (regsty->RegEnableTxPowerLimit == 1 + || (regsty->RegEnableTxPowerLimit == 2 && hal_data->EEPROMRegulatory == 1)) + return true; + return false; +} + +bool phy_is_tx_power_by_rate_needed(_adapter *adapter) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + struct registry_priv *regsty = dvobj_to_regsty(adapter_to_dvobj(adapter)); + + if (regsty->RegEnableTxPowerByRate == 1 + || (regsty->RegEnableTxPowerByRate == 2 && hal_data->EEPROMRegulatory != 2)) + return true; + return false; +} + +int phy_load_tx_power_by_rate(_adapter *adapter, u8 chk_file) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + struct registry_priv *regsty = dvobj_to_regsty(adapter_to_dvobj(adapter)); + int ret = _FAIL; + + hal_data->txpwr_by_rate_loaded = 0; + PHY_InitTxPowerByRate(adapter); + + /* tx power limit is based on tx power by rate */ + hal_data->txpwr_limit_loaded = 0; + +#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE + if (chk_file + && phy_ConfigBBWithPgParaFile(adapter, PHY_FILE_PHY_REG_PG) == _SUCCESS + ) { + hal_data->txpwr_by_rate_from_file = 1; + goto post_hdl; + } +#endif + +#ifdef CONFIG_EMBEDDED_FWIMG + if (HAL_STATUS_SUCCESS == odm_config_bb_with_header_file(&hal_data->odmpriv, CONFIG_BB_PHY_REG_PG)) { + RTW_INFO("default power by rate loaded\n"); + hal_data->txpwr_by_rate_from_file = 0; + goto post_hdl; + } +#endif + + RTW_ERR("%s():Read Tx power by rate fail\n", __func__); + goto exit; + +post_hdl: + if (hal_data->odmpriv.phy_reg_pg_value_type != PHY_REG_PG_EXACT_VALUE) { + rtw_warn_on(1); + goto exit; + } + + PHY_TxPowerByRateConfiguration(adapter); + hal_data->txpwr_by_rate_loaded = 1; + + ret = _SUCCESS; + +exit: + return ret; +} + +int phy_load_tx_power_limit(_adapter *adapter, u8 chk_file) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + struct registry_priv *regsty = dvobj_to_regsty(adapter_to_dvobj(adapter)); + int ret = _FAIL; + + hal_data->txpwr_limit_loaded = 0; + PHY_InitTxPowerLimit(adapter); + + if (!hal_data->txpwr_by_rate_loaded && regsty->target_tx_pwr_valid != true) { + RTW_ERR("%s():Read Tx power limit before target tx power is specify\n", __func__); + goto exit; + } + +#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE + if (chk_file + && PHY_ConfigRFWithPowerLimitTableParaFile(adapter, PHY_FILE_TXPWR_LMT) == _SUCCESS + ) { + hal_data->txpwr_limit_from_file = 1; + goto post_hdl; + } +#endif + +#ifdef CONFIG_EMBEDDED_FWIMG + if (HAL_STATUS_SUCCESS == odm_config_rf_with_header_file(&hal_data->odmpriv, CONFIG_RF_TXPWR_LMT, (enum odm_rf_radio_path_e)0)) { + RTW_INFO("default power limit loaded\n"); + hal_data->txpwr_limit_from_file = 0; + goto post_hdl; + } +#endif + + RTW_ERR("%s():Read Tx power limit fail\n", __func__); + goto exit; + +post_hdl: + PHY_ConvertTxPowerLimitToPowerIndex(adapter); + hal_data->txpwr_limit_loaded = 1; + ret = _SUCCESS; + +exit: + return ret; +} + +void phy_load_tx_power_ext_info(_adapter *adapter, u8 chk_file) +{ + struct registry_priv *regsty = adapter_to_regsty(adapter); + + /* check registy target tx power */ + regsty->target_tx_pwr_valid = rtw_regsty_chk_target_tx_power_valid(adapter); + + /* power by rate and limit */ + if (phy_is_tx_power_by_rate_needed(adapter) + || (phy_is_tx_power_limit_needed(adapter) && regsty->target_tx_pwr_valid != true) + ) + phy_load_tx_power_by_rate(adapter, chk_file); + + if (phy_is_tx_power_limit_needed(adapter)) + phy_load_tx_power_limit(adapter, chk_file); +} + +inline void phy_reload_tx_power_ext_info(_adapter *adapter) +{ + phy_load_tx_power_ext_info(adapter, 1); +} + +inline void phy_reload_default_tx_power_ext_info(_adapter *adapter) +{ + phy_load_tx_power_ext_info(adapter, 0); +} + +void dump_tx_power_ext_info(void *sel, _adapter *adapter) +{ + struct registry_priv *regsty = adapter_to_regsty(adapter); + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + + if (regsty->target_tx_pwr_valid == true) + RTW_PRINT_SEL(sel, "target_tx_power: from registry\n"); + else if (phy_is_tx_power_by_rate_needed(adapter)) + RTW_PRINT_SEL(sel, "target_tx_power: from power by rate\n"); + else + RTW_PRINT_SEL(sel, "target_tx_power: unavailable\n"); + + RTW_PRINT_SEL(sel, "tx_power_by_rate: %s, %s, %s\n" + , phy_is_tx_power_by_rate_needed(adapter) ? "enabled" : "disabled" + , hal_data->txpwr_by_rate_loaded ? "loaded" : "unloaded" + , hal_data->txpwr_by_rate_from_file ? "file" : "default" + ); + + RTW_PRINT_SEL(sel, "tx_power_limit: %s, %s, %s\n" + , phy_is_tx_power_limit_needed(adapter) ? "enabled" : "disabled" + , hal_data->txpwr_limit_loaded ? "loaded" : "unloaded" + , hal_data->txpwr_limit_from_file ? "file" : "default" + ); +} + +void dump_target_tx_power(void *sel, _adapter *adapter) +{ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + struct registry_priv *regsty = adapter_to_regsty(adapter); + int path, tx_num, band, rs; + u8 target; + + for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) { + if (!hal_is_band_support(adapter, band)) + continue; + + for (path = 0; path < RF_PATH_MAX; path++) { + if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, path)) + break; + + RTW_PRINT_SEL(sel, "[%s][%c]%s\n", band_str(band), rf_path_char(path) + , (regsty->target_tx_pwr_valid == false && hal_data->txpwr_by_rate_undefined_band_path[band][path]) ? "(dup)" : ""); + + for (rs = 0; rs < RATE_SECTION_NUM; rs++) { + tx_num = rate_section_to_tx_num(rs); + if (tx_num >= hal_spec->tx_nss_num) + continue; + + if (band == BAND_ON_5G && IS_CCK_RATE_SECTION(rs)) + continue; + + if (IS_VHT_RATE_SECTION(rs)) + continue; + + target = PHY_GetTxPowerByRateBase(adapter, band, path, rate_section_to_tx_num(rs), rs); + + if (target % 2) + _RTW_PRINT_SEL(sel, "%7s: %2d.5\n", rate_section_str(rs), target / 2); + else + _RTW_PRINT_SEL(sel, "%7s: %4d\n", rate_section_str(rs), target / 2); + } + } + } + +exit: + return; +} + +void dump_tx_power_by_rate(void *sel, _adapter *adapter) +{ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + int path, tx_num, band, n, rs; + u8 rate_num, max_rate_num, base; + s8 by_rate_offset; + + for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) { + if (!hal_is_band_support(adapter, band)) + continue; + + for (path = 0; path < RF_PATH_MAX; path++) { + if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, path)) + break; + + RTW_PRINT_SEL(sel, "[%s][%c]%s\n", band_str(band), rf_path_char(path) + , hal_data->txpwr_by_rate_undefined_band_path[band][path] ? "(dup)" : ""); + + for (rs = 0; rs < RATE_SECTION_NUM; rs++) { + tx_num = rate_section_to_tx_num(rs); + if (tx_num >= hal_spec->tx_nss_num) + continue; + + if (band == BAND_ON_5G && IS_CCK_RATE_SECTION(rs)) + continue; + + if (IS_VHT_RATE_SECTION(rs)) + continue; + + max_rate_num = 8; + rate_num = rate_section_rate_num(rs); + base = PHY_GetTxPowerByRateBase(adapter, band, path, tx_num, rs); + + RTW_PRINT_SEL(sel, "%7s: ", rate_section_str(rs)); + + /* dump power by rate in db */ + for (n = rate_num - 1; n >= 0; n--) { + by_rate_offset = PHY_GetTxPowerByRate(adapter, band, path, tx_num, rates_by_sections[rs].rates[n]); + + if ((base + by_rate_offset) % 2) + _RTW_PRINT_SEL(sel, "%2d.5 ", (base + by_rate_offset) / 2); + else + _RTW_PRINT_SEL(sel, "%4d ", (base + by_rate_offset) / 2); + } + for (n = 0; n < max_rate_num - rate_num; n++) + _RTW_PRINT_SEL(sel, "%4s ", ""); + + _RTW_PRINT_SEL(sel, "|"); + + /* dump power by rate in offset */ + for (n = rate_num - 1; n >= 0; n--) { + by_rate_offset = PHY_GetTxPowerByRate(adapter, band, path, tx_num, rates_by_sections[rs].rates[n]); + _RTW_PRINT_SEL(sel, "%3d ", by_rate_offset); + } + RTW_PRINT_SEL(sel, "\n"); + + } + } + } +} + +void dump_tx_power_limit(void *sel, _adapter *adapter) +{ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + struct registry_priv *regsty = dvobj_to_regsty(adapter_to_dvobj(adapter)); + + int bw, band, ch_num, rs, i, path; + u8 ch, n, rd, rfpath_num; + + for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) { + if (!hal_is_band_support(adapter, band)) + continue; + + rd = (band == BAND_ON_2_4G ? hal_data->Regulation2_4G : hal_data->Regulation5G); + rfpath_num = (band == BAND_ON_2_4G ? hal_spec->rfpath_num_2g : hal_spec->rfpath_num_5g); + + for (bw = 0; bw < MAX_5G_BANDWIDTH_NUM; bw++) { + + if (bw >= CHANNEL_WIDTH_160) + break; + if (band == BAND_ON_2_4G && bw >= CHANNEL_WIDTH_80) + break; + + if (band == BAND_ON_2_4G) + ch_num = CENTER_CH_2G_NUM; + else + ch_num = center_chs_5g_num(bw); + + if (ch_num == 0) { + rtw_warn_on(1); + break; + } + + for (rs = 0; rs < RATE_SECTION_NUM; rs++) { + if (band == BAND_ON_2_4G && IS_VHT_RATE_SECTION(rs)) + continue; + if (band == BAND_ON_5G && IS_CCK_RATE_SECTION(rs)) + continue; + if (bw > CHANNEL_WIDTH_20 && (IS_CCK_RATE_SECTION(rs) || IS_OFDM_RATE_SECTION(rs))) + continue; + if (bw > CHANNEL_WIDTH_40 && IS_HT_RATE_SECTION(rs)) + continue; + + if (rate_section_to_tx_num(rs) >= hal_spec->tx_nss_num) + continue; + + if (IS_VHT_RATE_SECTION(rs)) + continue; + + /* by pass 5G 20M, 40M pure reference */ + if (band == BAND_ON_5G && (bw == CHANNEL_WIDTH_20 || bw == CHANNEL_WIDTH_40)) { + if (hal_data->tx_pwr_lmt_5g_20_40_ref == TX_PWR_LMT_REF_HT_FROM_VHT) { + if (IS_HT_RATE_SECTION(rs)) + continue; + } else if (hal_data->tx_pwr_lmt_5g_20_40_ref == TX_PWR_LMT_REF_VHT_FROM_HT) { + if (IS_VHT_RATE_SECTION(rs) && bw <= CHANNEL_WIDTH_40) + continue; + } + } + + RTW_PRINT_SEL(sel, "[%s][%s][%s]\n" + , band_str(band) + , ch_width_str(bw) + , rate_section_str(rs) + ); + + /* header for limit in db */ + RTW_PRINT_SEL(sel, "%3s %5s %5s %5s %5s " + , "ch" + , (rd == TXPWR_LMT_FCC ? "*FCC" : "FCC") + , (rd == TXPWR_LMT_ETSI ? "*ETSI" : "ETSI") + , (rd == TXPWR_LMT_MKK ? "*MKK" : "MKK") + , (rd == TXPWR_LMT_WW ? "*WW" : "WW") + ); + + /* header for limit offset */ + for (path = 0; path < RF_PATH_MAX; path++) { + if (path >= rfpath_num) + break; + _RTW_PRINT_SEL(sel, "|%3c %3c %3c %3c " + , (rd == TXPWR_LMT_FCC ? rf_path_char(path) : ' ') + , (rd == TXPWR_LMT_ETSI ? rf_path_char(path) : ' ') + , (rd == TXPWR_LMT_MKK ? rf_path_char(path) : ' ') + , (rd == TXPWR_LMT_WW ? rf_path_char(path) : ' ') + ); + } + _RTW_PRINT_SEL(sel, "\n"); + + for (n = 0; n < ch_num; n++) { + s8 limit_idx[RF_PATH_MAX][MAX_REGULATION_NUM]; + s8 limit_offset[MAX_REGULATION_NUM]; + u8 base; + + if (band == BAND_ON_2_4G) + ch = n + 1; + else + ch = center_chs_5g(bw, n); + + if (ch == 0) { + rtw_warn_on(1); + break; + } + + /* dump limit in db (calculate from path A) */ + limit_offset[0] = PHY_GetTxPowerLimit_no_sc(adapter, 3, band, bw, RF_PATH_A, rates_by_sections[rs].rates[0], ch); /* FCC */ + limit_offset[1] = PHY_GetTxPowerLimit_no_sc(adapter, 1, band, bw, RF_PATH_A, rates_by_sections[rs].rates[0], ch); /* ETSI */ + limit_offset[2] = PHY_GetTxPowerLimit_no_sc(adapter, 2, band, bw, RF_PATH_A, rates_by_sections[rs].rates[0], ch); /* MKK */ + limit_offset[3] = PHY_GetTxPowerLimit_no_sc(adapter, 4, band, bw, RF_PATH_A, rates_by_sections[rs].rates[0], ch); /* WW */ + + base = PHY_GetTxPowerByRateBase(adapter, band, RF_PATH_A, rate_section_to_tx_num(rs), rs); + + RTW_PRINT_SEL(sel, "%3u ", ch); + for (i = 0; i < MAX_REGULATION_NUM; i++) { + if (limit_offset[i] == MAX_POWER_INDEX) { + limit_idx[0][i] = MAX_POWER_INDEX; + _RTW_PRINT_SEL(sel, "%5s ", "NA"); + } else { + limit_idx[0][i] = limit_offset[i] + base; + if ((limit_offset[i] + base) % 2) + _RTW_PRINT_SEL(sel, "%3d.5 ", (limit_offset[i] + base) / 2); + else + _RTW_PRINT_SEL(sel, "%5d ", (limit_offset[i] + base) / 2); + } + } + + /* dump limit offset of each path */ + for (path = 0; path < RF_PATH_MAX; path++) { + if (path >= rfpath_num) + break; + limit_offset[0] = PHY_GetTxPowerLimit_no_sc(adapter, 3, band, bw, path, rates_by_sections[rs].rates[0], ch); /* FCC */ + limit_offset[1] = PHY_GetTxPowerLimit_no_sc(adapter, 1, band, bw, path, rates_by_sections[rs].rates[0], ch); /* ETSI */ + limit_offset[2] = PHY_GetTxPowerLimit_no_sc(adapter, 2, band, bw, path, rates_by_sections[rs].rates[0], ch); /* MKK */ + limit_offset[3] = PHY_GetTxPowerLimit_no_sc(adapter, 4, band, bw, path, rates_by_sections[rs].rates[0], ch); /* WW */ + + base = PHY_GetTxPowerByRateBase(adapter, band, path, rate_section_to_tx_num(rs), rs); + + _RTW_PRINT_SEL(sel, "|"); + for (i = 0; i < MAX_REGULATION_NUM; i++) { + if (limit_offset[i] == MAX_POWER_INDEX) { + limit_idx[path][i] = MAX_POWER_INDEX; + _RTW_PRINT_SEL(sel, "%3s ", "NA"); + } else { + limit_idx[path][i] = limit_offset[i] + base; + _RTW_PRINT_SEL(sel, "%3d ", limit_offset[i]); + } + } + } + + /* compare limit_idx of each path, print 'x' when mismatch */ + if (rfpath_num > 1) { + for (i = 0; i < MAX_REGULATION_NUM; i++) { + for (path = 0; path < RF_PATH_MAX; path++) { + if (path >= rfpath_num) + break; + if (limit_idx[path][i] != limit_idx[(path + 1) % rfpath_num][i]) + break; + } + if (path >= rfpath_num) + _RTW_PRINT_SEL(sel, " "); + else + _RTW_PRINT_SEL(sel, "x"); + } + } + _RTW_PRINT_SEL(sel, "\n"); + + } + RTW_PRINT_SEL(sel, "\n"); + } /* loop for rate sections */ + } /* loop for bandwidths */ + } /* loop for bands */ +} + +/* + * phy file path is stored in global char array rtw_phy_para_file_path + * need to care about racing + */ +int rtw_get_phy_file_path(_adapter *adapter, const char *file_name) +{ +#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + int len = 0; + + if (file_name) { + len += snprintf(rtw_phy_para_file_path, PATH_LENGTH_MAX, "%s", rtw_phy_file_path); + #if defined(CONFIG_MULTIDRV) || defined(REALTEK_CONFIG_PATH_WITH_IC_NAME_FOLDER) + len += snprintf(rtw_phy_para_file_path + len, PATH_LENGTH_MAX - len, "%s/", hal_spec->ic_name); + #endif + len += snprintf(rtw_phy_para_file_path + len, PATH_LENGTH_MAX - len, "%s", file_name); + + return true; + } +#endif + return false; +} + +#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE +int +phy_ConfigMACWithParaFile( + PADAPTER Adapter, + char *pFileName +) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter); + int rlen = 0, rtStatus = _FAIL; + char *szLine, *ptmp; + u32 u4bRegOffset, u4bRegValue, u4bMove; + + if (!(Adapter->registrypriv.load_phy_file & LOAD_MAC_PARA_FILE)) + return rtStatus; + + memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN); + + if ((pHalData->mac_reg_len == 0) && (pHalData->mac_reg == NULL)) { + rtw_get_phy_file_path(Adapter, pFileName); + if (rtw_is_file_readable(rtw_phy_para_file_path) == true) { + rlen = rtw_retrieve_from_file(rtw_phy_para_file_path, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN); + if (rlen > 0) { + rtStatus = _SUCCESS; + pHalData->mac_reg = rtw_zvmalloc(rlen); + if (pHalData->mac_reg) { + memcpy(pHalData->mac_reg, pHalData->para_file_buf, rlen); + pHalData->mac_reg_len = rlen; + } else + RTW_INFO("%s mac_reg alloc fail !\n", __func__); + } + } + } else { + if ((pHalData->mac_reg_len != 0) && (pHalData->mac_reg != NULL)) { + memcpy(pHalData->para_file_buf, pHalData->mac_reg, pHalData->mac_reg_len); + rtStatus = _SUCCESS; + } else + RTW_INFO("%s(): Critical Error !!!\n", __func__); + } + + if (rtStatus == _SUCCESS) { + ptmp = pHalData->para_file_buf; + for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) { + if (!IsCommentString(szLine)) { + /* Get 1st hex value as register offset */ + if (GetHexValueFromString(szLine, &u4bRegOffset, &u4bMove)) { + if (u4bRegOffset == 0xffff) { + /* Ending. */ + break; + } + + /* Get 2nd hex value as register value. */ + szLine += u4bMove; + if (GetHexValueFromString(szLine, &u4bRegValue, &u4bMove)) + rtw_write8(Adapter, u4bRegOffset, (u8)u4bRegValue); + } + } + } + } else + RTW_INFO("%s(): No File %s, Load from HWImg Array!\n", __func__, pFileName); + + return rtStatus; +} + +int +phy_ConfigBBWithParaFile( + PADAPTER Adapter, + char *pFileName, + u32 ConfigType +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + int rlen = 0, rtStatus = _FAIL; + char *szLine, *ptmp; + u32 u4bRegOffset, u4bRegValue, u4bMove; + char *pBuf = NULL; + u32 *pBufLen = NULL; + + if (!(Adapter->registrypriv.load_phy_file & LOAD_BB_PARA_FILE)) + return rtStatus; + + switch (ConfigType) { + case CONFIG_BB_PHY_REG: + pBuf = pHalData->bb_phy_reg; + pBufLen = &pHalData->bb_phy_reg_len; + break; + case CONFIG_BB_AGC_TAB: + pBuf = pHalData->bb_agc_tab; + pBufLen = &pHalData->bb_agc_tab_len; + break; + default: + RTW_INFO("Unknown ConfigType!! %d\r\n", ConfigType); + break; + } + + memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN); + + if ((pBufLen != NULL) && (*pBufLen == 0) && (pBuf == NULL)) { + rtw_get_phy_file_path(Adapter, pFileName); + if (rtw_is_file_readable(rtw_phy_para_file_path) == true) { + rlen = rtw_retrieve_from_file(rtw_phy_para_file_path, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN); + if (rlen > 0) { + rtStatus = _SUCCESS; + pBuf = rtw_zvmalloc(rlen); + if (pBuf) { + memcpy(pBuf, pHalData->para_file_buf, rlen); + *pBufLen = rlen; + + switch (ConfigType) { + case CONFIG_BB_PHY_REG: + pHalData->bb_phy_reg = pBuf; + break; + case CONFIG_BB_AGC_TAB: + pHalData->bb_agc_tab = pBuf; + break; + } + } else + RTW_INFO("%s(): ConfigType %d alloc fail !\n", __func__, ConfigType); + } + } + } else { + if ((pBufLen != NULL) && (*pBufLen != 0) && (pBuf != NULL)) { + memcpy(pHalData->para_file_buf, pBuf, *pBufLen); + rtStatus = _SUCCESS; + } else + RTW_INFO("%s(): Critical Error !!!\n", __func__); + } + + if (rtStatus == _SUCCESS) { + ptmp = pHalData->para_file_buf; + for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) { + if (!IsCommentString(szLine)) { + /* Get 1st hex value as register offset. */ + if (GetHexValueFromString(szLine, &u4bRegOffset, &u4bMove)) { + if (u4bRegOffset == 0xffff) { + /* Ending. */ + break; + } else if (u4bRegOffset == 0xfe || u4bRegOffset == 0xffe) { +#ifdef CONFIG_LONG_DELAY_ISSUE + rtw_msleep_os(50); +#else + rtw_mdelay_os(50); +#endif + } else if (u4bRegOffset == 0xfd) + rtw_mdelay_os(5); + else if (u4bRegOffset == 0xfc) + rtw_mdelay_os(1); + else if (u4bRegOffset == 0xfb) + rtw_udelay_os(50); + else if (u4bRegOffset == 0xfa) + rtw_udelay_os(5); + else if (u4bRegOffset == 0xf9) + rtw_udelay_os(1); + + /* Get 2nd hex value as register value. */ + szLine += u4bMove; + if (GetHexValueFromString(szLine, &u4bRegValue, &u4bMove)) { + /* RTW_INFO("[BB-ADDR]%03lX=%08lX\n", u4bRegOffset, u4bRegValue); */ + phy_set_bb_reg(Adapter, u4bRegOffset, bMaskDWord, u4bRegValue); + + if (u4bRegOffset == 0xa24) + pHalData->odmpriv.rf_calibrate_info.rega24 = u4bRegValue; + + /* Add 1us delay between BB/RF register setting. */ + rtw_udelay_os(1); + } + } + } + } + } else + RTW_INFO("%s(): No File %s, Load from HWImg Array!\n", __func__, pFileName); + + return rtStatus; +} + +static void phy_DecryptBBPgParaFile(PADAPTER Adapter, char *buffer) +{ + u32 i = 0, j = 0; + u8 map[95] = {0}; + u8 currentChar; + char *BufOfLines, *ptmp; + + /* RTW_INFO("=====>phy_DecryptBBPgParaFile()\n"); */ + /* 32 the ascii code of the first visable char, 126 the last one */ + for (i = 0; i < 95; ++i) + map[i] = (u8)(94 - i); + + ptmp = buffer; + i = 0; + for (BufOfLines = GetLineFromBuffer(ptmp); BufOfLines != NULL; BufOfLines = GetLineFromBuffer(ptmp)) { + /* RTW_INFO("Encrypted Line: %s\n", BufOfLines); */ + + for (j = 0; j < strlen(BufOfLines); ++j) { + currentChar = BufOfLines[j]; + + if (currentChar == '\0') + break; + + currentChar -= (u8)((((i + j) * 3) % 128)); + + BufOfLines[j] = map[currentChar - 32] + 32; + } + /* RTW_INFO("Decrypted Line: %s\n", BufOfLines ); */ + if (strlen(BufOfLines) != 0) + i++; + BufOfLines[strlen(BufOfLines)] = '\n'; + } +} + +static int phy_ParseBBPgParaFile(PADAPTER Adapter, char *buffer) +{ + int rtStatus = _SUCCESS; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + char *szLine, *ptmp; + u32 u4bRegOffset, u4bRegMask, u4bRegValue; + u32 u4bMove; + bool firstLine = true; + u8 tx_num = 0; + u8 band = 0, rf_path = 0; + + /* RTW_INFO("=====>phy_ParseBBPgParaFile()\n"); */ + + if (Adapter->registrypriv.RegDecryptCustomFile == 1) + phy_DecryptBBPgParaFile(Adapter, buffer); + + ptmp = buffer; + for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) { + if (isAllSpaceOrTab(szLine, sizeof(*szLine))) + continue; + + if (!IsCommentString(szLine)) { + /* Get header info (relative value or exact value) */ + if (firstLine) { + if (eqNByte(szLine, (u8 *)("#[v1]"), 5)) { + + pHalData->odmpriv.phy_reg_pg_version = szLine[3] - '0'; + /* RTW_INFO("This is a new format PHY_REG_PG.txt\n"); */ + } else if (eqNByte(szLine, (u8 *)("#[v0]"), 5)) { + pHalData->odmpriv.phy_reg_pg_version = szLine[3] - '0'; + /* RTW_INFO("This is a old format PHY_REG_PG.txt ok\n"); */ + } else { + RTW_INFO("The format in PHY_REG_PG are invalid %s\n", szLine); + return _FAIL; + } + + if (eqNByte(szLine + 5, (u8 *)("[Exact]#"), 8)) { + pHalData->odmpriv.phy_reg_pg_value_type = PHY_REG_PG_EXACT_VALUE; + /* RTW_INFO("The values in PHY_REG_PG are exact values ok\n"); */ + firstLine = false; + continue; + } else if (eqNByte(szLine + 5, (u8 *)("[Relative]#"), 11)) { + pHalData->odmpriv.phy_reg_pg_value_type = PHY_REG_PG_RELATIVE_VALUE; + /* RTW_INFO("The values in PHY_REG_PG are relative values ok\n"); */ + firstLine = false; + continue; + } else { + RTW_INFO("The values in PHY_REG_PG are invalid %s\n", szLine); + return _FAIL; + } + } + + if (pHalData->odmpriv.phy_reg_pg_version == 0) { + /* Get 1st hex value as register offset. */ + if (GetHexValueFromString(szLine, &u4bRegOffset, &u4bMove)) { + szLine += u4bMove; + if (u4bRegOffset == 0xffff) { + /* Ending. */ + break; + } + + /* Get 2nd hex value as register mask. */ + if (GetHexValueFromString(szLine, &u4bRegMask, &u4bMove)) + szLine += u4bMove; + else + return _FAIL; + + if (pHalData->odmpriv.phy_reg_pg_value_type == PHY_REG_PG_RELATIVE_VALUE) { + /* Get 3rd hex value as register value. */ + if (GetHexValueFromString(szLine, &u4bRegValue, &u4bMove)) { + phy_store_tx_power_by_rate(Adapter, 0, 0, 1, u4bRegOffset, u4bRegMask, u4bRegValue); + /* RTW_INFO("[ADDR] %03X=%08X Mask=%08x\n", u4bRegOffset, u4bRegValue, u4bRegMask); */ + } else + return _FAIL; + } else if (pHalData->odmpriv.phy_reg_pg_value_type == PHY_REG_PG_EXACT_VALUE) { + u32 combineValue = 0; + u8 integer = 0, fraction = 0; + + if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove)) + szLine += u4bMove; + else + return _FAIL; + + integer *= 2; + if (fraction == 5) + integer += 1; + combineValue |= (((integer / 10) << 4) + (integer % 10)); + /* RTW_INFO(" %d", integer ); */ + + if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove)) + szLine += u4bMove; + else + return _FAIL; + + integer *= 2; + if (fraction == 5) + integer += 1; + combineValue <<= 8; + combineValue |= (((integer / 10) << 4) + (integer % 10)); + /* RTW_INFO(" %d", integer ); */ + + if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove)) + szLine += u4bMove; + else + return _FAIL; + + integer *= 2; + if (fraction == 5) + integer += 1; + combineValue <<= 8; + combineValue |= (((integer / 10) << 4) + (integer % 10)); + /* RTW_INFO(" %d", integer ); */ + + if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove)) + szLine += u4bMove; + else + return _FAIL; + + integer *= 2; + if (fraction == 5) + integer += 1; + combineValue <<= 8; + combineValue |= (((integer / 10) << 4) + (integer % 10)); + /* RTW_INFO(" %d", integer ); */ + phy_store_tx_power_by_rate(Adapter, 0, 0, 1, u4bRegOffset, u4bRegMask, combineValue); + + /* RTW_INFO("[ADDR] 0x%3x = 0x%4x\n", u4bRegOffset, combineValue ); */ + } + } + } else if (pHalData->odmpriv.phy_reg_pg_version > 0) { + u32 index = 0, cnt = 0; + + if (eqNByte(szLine, "0xffff", 6)) + break; + + if (!eqNByte("#[END]#", szLine, 7)) { + /* load the table label info */ + if (szLine[0] == '#') { + index = 0; + if (eqNByte(szLine, "#[2.4G]" , 7)) { + band = BAND_ON_2_4G; + index += 8; + } else if (eqNByte(szLine, "#[5G]", 5)) { + band = BAND_ON_5G; + index += 6; + } else { + RTW_INFO("Invalid band %s in PHY_REG_PG.txt\n", szLine); + return _FAIL; + } + + rf_path = szLine[index] - 'A'; + /* RTW_INFO(" Table label Band %d, RfPath %d\n", band, rf_path ); */ + } else { /* load rows of tables */ + if (szLine[1] == '1') + tx_num = RF_1TX; + else if (szLine[1] == '2') + tx_num = RF_2TX; + else if (szLine[1] == '3') + tx_num = RF_3TX; + else if (szLine[1] == '4') + tx_num = RF_4TX; + else { + RTW_INFO("Invalid row in PHY_REG_PG.txt '%c'(%d)\n", szLine[1], szLine[1]); + return _FAIL; + } + + while (szLine[index] != ']') + ++index; + ++index;/* skip ] */ + + /* Get 2nd hex value as register offset. */ + szLine += index; + if (GetHexValueFromString(szLine, &u4bRegOffset, &u4bMove)) + szLine += u4bMove; + else + return _FAIL; + + /* Get 2nd hex value as register mask. */ + if (GetHexValueFromString(szLine, &u4bRegMask, &u4bMove)) + szLine += u4bMove; + else + return _FAIL; + + if (pHalData->odmpriv.phy_reg_pg_value_type == PHY_REG_PG_RELATIVE_VALUE) { + /* Get 3rd hex value as register value. */ + if (GetHexValueFromString(szLine, &u4bRegValue, &u4bMove)) { + phy_store_tx_power_by_rate(Adapter, band, rf_path, tx_num, u4bRegOffset, u4bRegMask, u4bRegValue); + /* RTW_INFO("[ADDR] %03X (tx_num %d) =%08X Mask=%08x\n", u4bRegOffset, tx_num, u4bRegValue, u4bRegMask); */ + } else + return _FAIL; + } else if (pHalData->odmpriv.phy_reg_pg_value_type == PHY_REG_PG_EXACT_VALUE) { + u32 combineValue = 0; + u8 integer = 0, fraction = 0; + + if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove)) + szLine += u4bMove; + else + return _FAIL; + + integer *= 2; + if (fraction == 5) + integer += 1; + combineValue |= (((integer / 10) << 4) + (integer % 10)); + /* RTW_INFO(" %d", integer ); */ + + if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove)) + szLine += u4bMove; + else + return _FAIL; + + integer *= 2; + if (fraction == 5) + integer += 1; + combineValue <<= 8; + combineValue |= (((integer / 10) << 4) + (integer % 10)); + /* RTW_INFO(" %d", integer ); */ + + if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove)) + szLine += u4bMove; + else + return _FAIL; + + integer *= 2; + if (fraction == 5) + integer += 1; + combineValue <<= 8; + combineValue |= (((integer / 10) << 4) + (integer % 10)); + /* RTW_INFO(" %d", integer ); */ + + if (GetFractionValueFromString(szLine, &integer, &fraction, &u4bMove)) + szLine += u4bMove; + else + return _FAIL; + + integer *= 2; + if (fraction == 5) + integer += 1; + combineValue <<= 8; + combineValue |= (((integer / 10) << 4) + (integer % 10)); + /* RTW_INFO(" %d", integer ); */ + phy_store_tx_power_by_rate(Adapter, band, rf_path, tx_num, u4bRegOffset, u4bRegMask, combineValue); + + /* RTW_INFO("[ADDR] 0x%3x (tx_num %d) = 0x%4x\n", u4bRegOffset, tx_num, combineValue ); */ + } + } + } + } + } + } + /* RTW_INFO("<=====phy_ParseBBPgParaFile()\n"); */ + return rtStatus; +} + +int +phy_ConfigBBWithPgParaFile( + PADAPTER Adapter, + const char *pFileName) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + int rlen = 0, rtStatus = _FAIL; + + if (!(Adapter->registrypriv.load_phy_file & LOAD_BB_PG_PARA_FILE)) + return rtStatus; + + memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN); + + if (pHalData->bb_phy_reg_pg == NULL) { + rtw_get_phy_file_path(Adapter, pFileName); + if (rtw_is_file_readable(rtw_phy_para_file_path) == true) { + rlen = rtw_retrieve_from_file(rtw_phy_para_file_path, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN); + if (rlen > 0) { + rtStatus = _SUCCESS; + pHalData->bb_phy_reg_pg = rtw_zvmalloc(rlen); + if (pHalData->bb_phy_reg_pg) { + memcpy(pHalData->bb_phy_reg_pg, pHalData->para_file_buf, rlen); + pHalData->bb_phy_reg_pg_len = rlen; + } else + RTW_INFO("%s bb_phy_reg_pg alloc fail !\n", __func__); + } + } + } else { + if ((pHalData->bb_phy_reg_pg_len != 0) && (pHalData->bb_phy_reg_pg != NULL)) { + memcpy(pHalData->para_file_buf, pHalData->bb_phy_reg_pg, pHalData->bb_phy_reg_pg_len); + rtStatus = _SUCCESS; + } else + RTW_INFO("%s(): Critical Error !!!\n", __func__); + } + + if (rtStatus == _SUCCESS) { + /* RTW_INFO("phy_ConfigBBWithPgParaFile(): read %s ok\n", pFileName); */ + phy_ParseBBPgParaFile(Adapter, pHalData->para_file_buf); + } else + RTW_INFO("%s(): No File %s, Load from HWImg Array!\n", __func__, pFileName); + + return rtStatus; +} + +#if (MP_DRIVER == 1) + +int +phy_ConfigBBWithMpParaFile( + PADAPTER Adapter, + char *pFileName +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + int rlen = 0, rtStatus = _FAIL; + char *szLine, *ptmp; + u32 u4bRegOffset, u4bRegValue, u4bMove; + + if (!(Adapter->registrypriv.load_phy_file & LOAD_BB_MP_PARA_FILE)) + return rtStatus; + + memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN); + + if ((pHalData->bb_phy_reg_mp_len == 0) && (pHalData->bb_phy_reg_mp == NULL)) { + rtw_get_phy_file_path(Adapter, pFileName); + if (rtw_is_file_readable(rtw_phy_para_file_path) == true) { + rlen = rtw_retrieve_from_file(rtw_phy_para_file_path, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN); + if (rlen > 0) { + rtStatus = _SUCCESS; + pHalData->bb_phy_reg_mp = rtw_zvmalloc(rlen); + if (pHalData->bb_phy_reg_mp) { + memcpy(pHalData->bb_phy_reg_mp, pHalData->para_file_buf, rlen); + pHalData->bb_phy_reg_mp_len = rlen; + } else + RTW_INFO("%s bb_phy_reg_mp alloc fail !\n", __func__); + } + } + } else { + if ((pHalData->bb_phy_reg_mp_len != 0) && (pHalData->bb_phy_reg_mp != NULL)) { + memcpy(pHalData->para_file_buf, pHalData->bb_phy_reg_mp, pHalData->bb_phy_reg_mp_len); + rtStatus = _SUCCESS; + } else + RTW_INFO("%s(): Critical Error !!!\n", __func__); + } + + if (rtStatus == _SUCCESS) { + /* RTW_INFO("phy_ConfigBBWithMpParaFile(): read %s ok\n", pFileName); */ + + ptmp = pHalData->para_file_buf; + for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) { + if (!IsCommentString(szLine)) { + /* Get 1st hex value as register offset. */ + if (GetHexValueFromString(szLine, &u4bRegOffset, &u4bMove)) { + if (u4bRegOffset == 0xffff) { + /* Ending. */ + break; + } else if (u4bRegOffset == 0xfe || u4bRegOffset == 0xffe) { +#ifdef CONFIG_LONG_DELAY_ISSUE + rtw_msleep_os(50); +#else + rtw_mdelay_os(50); +#endif + } else if (u4bRegOffset == 0xfd) + rtw_mdelay_os(5); + else if (u4bRegOffset == 0xfc) + rtw_mdelay_os(1); + else if (u4bRegOffset == 0xfb) + rtw_udelay_os(50); + else if (u4bRegOffset == 0xfa) + rtw_udelay_os(5); + else if (u4bRegOffset == 0xf9) + rtw_udelay_os(1); + + /* Get 2nd hex value as register value. */ + szLine += u4bMove; + if (GetHexValueFromString(szLine, &u4bRegValue, &u4bMove)) { + /* RTW_INFO("[ADDR]%03lX=%08lX\n", u4bRegOffset, u4bRegValue); */ + phy_set_bb_reg(Adapter, u4bRegOffset, bMaskDWord, u4bRegValue); + + /* Add 1us delay between BB/RF register setting. */ + rtw_udelay_os(1); + } + } + } + } + } else + RTW_INFO("%s(): No File %s, Load from HWImg Array!\n", __func__, pFileName); + + return rtStatus; +} + +#endif + +int +PHY_ConfigRFWithParaFile( + PADAPTER Adapter, + char *pFileName, + u8 eRFPath +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + int rlen = 0, rtStatus = _FAIL; + char *szLine, *ptmp; + u32 u4bRegOffset, u4bRegValue, u4bMove; + u16 i; + char *pBuf = NULL; + u32 *pBufLen = NULL; + + if (!(Adapter->registrypriv.load_phy_file & LOAD_RF_PARA_FILE)) + return rtStatus; + + switch (eRFPath) { + case ODM_RF_PATH_A: + pBuf = pHalData->rf_radio_a; + pBufLen = &pHalData->rf_radio_a_len; + break; + case ODM_RF_PATH_B: + pBuf = pHalData->rf_radio_b; + pBufLen = &pHalData->rf_radio_b_len; + break; + default: + RTW_INFO("Unknown RF path!! %d\r\n", eRFPath); + break; + } + + memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN); + + if ((pBufLen != NULL) && (*pBufLen == 0) && (pBuf == NULL)) { + rtw_get_phy_file_path(Adapter, pFileName); + if (rtw_is_file_readable(rtw_phy_para_file_path) == true) { + rlen = rtw_retrieve_from_file(rtw_phy_para_file_path, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN); + if (rlen > 0) { + rtStatus = _SUCCESS; + pBuf = rtw_zvmalloc(rlen); + if (pBuf) { + memcpy(pBuf, pHalData->para_file_buf, rlen); + *pBufLen = rlen; + + switch (eRFPath) { + case ODM_RF_PATH_A: + pHalData->rf_radio_a = pBuf; + break; + case ODM_RF_PATH_B: + pHalData->rf_radio_b = pBuf; + break; + } + } else + RTW_INFO("%s(): eRFPath=%d alloc fail !\n", __func__, eRFPath); + } + } + } else { + if ((pBufLen != NULL) && (*pBufLen != 0) && (pBuf != NULL)) { + memcpy(pHalData->para_file_buf, pBuf, *pBufLen); + rtStatus = _SUCCESS; + } else + RTW_INFO("%s(): Critical Error !!!\n", __func__); + } + + if (rtStatus == _SUCCESS) { + /* RTW_INFO("%s(): read %s successfully\n", __func__, pFileName); */ + + ptmp = pHalData->para_file_buf; + for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) { + if (!IsCommentString(szLine)) { + /* Get 1st hex value as register offset. */ + if (GetHexValueFromString(szLine, &u4bRegOffset, &u4bMove)) { + if (u4bRegOffset == 0xfe || u4bRegOffset == 0xffe) { + /* Deay specific ms. Only RF configuration require delay. */ +#ifdef CONFIG_LONG_DELAY_ISSUE + rtw_msleep_os(50); +#else + rtw_mdelay_os(50); +#endif + } else if (u4bRegOffset == 0xfd) { + /* delay_ms(5); */ + for (i = 0; i < 100; i++) + rtw_udelay_os(MAX_STALL_TIME); + } else if (u4bRegOffset == 0xfc) { + /* delay_ms(1); */ + for (i = 0; i < 20; i++) + rtw_udelay_os(MAX_STALL_TIME); + } else if (u4bRegOffset == 0xfb) + rtw_udelay_os(50); + else if (u4bRegOffset == 0xfa) + rtw_udelay_os(5); + else if (u4bRegOffset == 0xf9) + rtw_udelay_os(1); + else if (u4bRegOffset == 0xffff) + break; + + /* Get 2nd hex value as register value. */ + szLine += u4bMove; + if (GetHexValueFromString(szLine, &u4bRegValue, &u4bMove)) { + phy_set_rf_reg(Adapter, eRFPath, u4bRegOffset, bRFRegOffsetMask, u4bRegValue); + + /* Temp add, for frequency lock, if no delay, that may cause */ + /* frequency shift, ex: 2412MHz => 2417MHz */ + /* If frequency shift, the following action may works. */ + /* Fractional-N table in radio_a.txt */ + /* 0x2a 0x00001 */ /* channel 1 */ + /* 0x2b 0x00808 frequency divider. */ + /* 0x2b 0x53333 */ + /* 0x2c 0x0000c */ + rtw_udelay_os(1); + } + } + } + } + } else + RTW_INFO("%s(): No File %s, Load from HWImg Array!\n", __func__, pFileName); + + return rtStatus; +} + +static void initDeltaSwingIndexTables( + PADAPTER Adapter, + char *Band, + char *Path, + char *Sign, + char *Channel, + char *Rate, + char *Data +) +{ +#define STR_EQUAL_5G(_band, _path, _sign, _rate, _chnl) \ + ((strcmp(Band, _band) == 0) && (strcmp(Path, _path) == 0) && (strcmp(Sign, _sign) == 0) &&\ + (strcmp(Rate, _rate) == 0) && (strcmp(Channel, _chnl) == 0)\ + ) +#define STR_EQUAL_2G(_band, _path, _sign, _rate) \ + ((strcmp(Band, _band) == 0) && (strcmp(Path, _path) == 0) && (strcmp(Sign, _sign) == 0) &&\ + (strcmp(Rate, _rate) == 0)\ + ) + +#define STORE_SWING_TABLE(_array, _iteratedIdx) \ + do { \ + for (token = strsep(&Data, delim); token != NULL; token = strsep(&Data, delim)) {\ + sscanf(token, "%d", &idx);\ + _array[_iteratedIdx++] = (u8)idx;\ + } } while (0)\ + + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + struct PHY_DM_STRUCT *pDM_Odm = &pHalData->odmpriv; + struct odm_rf_calibration_structure *pRFCalibrateInfo = &(pDM_Odm->rf_calibrate_info); + u32 j = 0; + char *token; + char delim[] = ","; + u32 idx = 0; + + /* RTW_INFO("===>initDeltaSwingIndexTables(): Band: %s;\nPath: %s;\nSign: %s;\nChannel: %s;\nRate: %s;\n, Data: %s;\n", */ + /* Band, Path, Sign, Channel, Rate, Data); */ + + if (STR_EQUAL_2G("2G", "A", "+", "CCK")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_2g_cck_a_p, j); + else if (STR_EQUAL_2G("2G", "A", "-", "CCK")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_2g_cck_a_n, j); + else if (STR_EQUAL_2G("2G", "B", "+", "CCK")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_2g_cck_b_p, j); + else if (STR_EQUAL_2G("2G", "B", "-", "CCK")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_2g_cck_b_n, j); + else if (STR_EQUAL_2G("2G", "A", "+", "ALL")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_2ga_p, j); + else if (STR_EQUAL_2G("2G", "A", "-", "ALL")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_2ga_n, j); + else if (STR_EQUAL_2G("2G", "B", "+", "ALL")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_2gb_p, j); + else if (STR_EQUAL_2G("2G", "B", "-", "ALL")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_2gb_n, j); + else if (STR_EQUAL_5G("5G", "A", "+", "ALL", "0")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5ga_p[0], j); + else if (STR_EQUAL_5G("5G", "A", "-", "ALL", "0")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5ga_n[0], j); + else if (STR_EQUAL_5G("5G", "B", "+", "ALL", "0")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5gb_p[0], j); + else if (STR_EQUAL_5G("5G", "B", "-", "ALL", "0")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5gb_n[0], j); + else if (STR_EQUAL_5G("5G", "A", "+", "ALL", "1")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5ga_p[1], j); + else if (STR_EQUAL_5G("5G", "A", "-", "ALL", "1")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5ga_n[1], j); + else if (STR_EQUAL_5G("5G", "B", "+", "ALL", "1")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5gb_p[1], j); + else if (STR_EQUAL_5G("5G", "B", "-", "ALL", "1")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5gb_n[1], j); + else if (STR_EQUAL_5G("5G", "A", "+", "ALL", "2")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5ga_p[2], j); + else if (STR_EQUAL_5G("5G", "A", "-", "ALL", "2")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5ga_n[2], j); + else if (STR_EQUAL_5G("5G", "B", "+", "ALL", "2")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5gb_p[2], j); + else if (STR_EQUAL_5G("5G", "B", "-", "ALL", "2")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5gb_n[2], j); + else if (STR_EQUAL_5G("5G", "A", "+", "ALL", "3")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5ga_p[3], j); + else if (STR_EQUAL_5G("5G", "A", "-", "ALL", "3")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5ga_n[3], j); + else if (STR_EQUAL_5G("5G", "B", "+", "ALL", "3")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5gb_p[3], j); + else if (STR_EQUAL_5G("5G", "B", "-", "ALL", "3")) + STORE_SWING_TABLE(pRFCalibrateInfo->delta_swing_table_idx_5gb_n[3], j); + else + RTW_INFO("===>initDeltaSwingIndexTables(): The input is invalid!!\n"); +} + +int +PHY_ConfigRFWithTxPwrTrackParaFile( + PADAPTER Adapter, + char *pFileName +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + struct PHY_DM_STRUCT *pDM_Odm = &pHalData->odmpriv; + struct odm_rf_calibration_structure *pRFCalibrateInfo = &(pDM_Odm->rf_calibrate_info); + int rlen = 0, rtStatus = _FAIL; + char *szLine, *ptmp; + u32 i = 0, j = 0; + char c = 0; + + if (!(Adapter->registrypriv.load_phy_file & LOAD_RF_TXPWR_TRACK_PARA_FILE)) + return rtStatus; + + memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN); + + if ((pHalData->rf_tx_pwr_track_len == 0) && (pHalData->rf_tx_pwr_track == NULL)) { + rtw_get_phy_file_path(Adapter, pFileName); + if (rtw_is_file_readable(rtw_phy_para_file_path) == true) { + rlen = rtw_retrieve_from_file(rtw_phy_para_file_path, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN); + if (rlen > 0) { + rtStatus = _SUCCESS; + pHalData->rf_tx_pwr_track = rtw_zvmalloc(rlen); + if (pHalData->rf_tx_pwr_track) { + memcpy(pHalData->rf_tx_pwr_track, pHalData->para_file_buf, rlen); + pHalData->rf_tx_pwr_track_len = rlen; + } else + RTW_INFO("%s rf_tx_pwr_track alloc fail !\n", __func__); + } + } + } else { + if ((pHalData->rf_tx_pwr_track_len != 0) && (pHalData->rf_tx_pwr_track != NULL)) { + memcpy(pHalData->para_file_buf, pHalData->rf_tx_pwr_track, pHalData->rf_tx_pwr_track_len); + rtStatus = _SUCCESS; + } else + RTW_INFO("%s(): Critical Error !!!\n", __func__); + } + + if (rtStatus == _SUCCESS) { + /* RTW_INFO("%s(): read %s successfully\n", __func__, pFileName); */ + + ptmp = pHalData->para_file_buf; + for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) { + if (!IsCommentString(szLine)) { + char band[5] = "", path[5] = "", sign[5] = ""; + char chnl[5] = "", rate[10] = ""; + char data[300] = ""; /* 100 is too small */ + + if (strlen(szLine) < 10 || szLine[0] != '[') + continue; + + strncpy(band, szLine + 1, 2); + strncpy(path, szLine + 5, 1); + strncpy(sign, szLine + 8, 1); + + i = 10; /* szLine+10 */ + if (!ParseQualifiedString(szLine, &i, rate, '[', ']')) { + /* RTW_INFO("Fail to parse rate!\n"); */ + } + if (!ParseQualifiedString(szLine, &i, chnl, '[', ']')) { + /* RTW_INFO("Fail to parse channel group!\n"); */ + } + while (szLine[i] != '{' && i < strlen(szLine)) + i++; + if (!ParseQualifiedString(szLine, &i, data, '{', '}')) { + /* RTW_INFO("Fail to parse data!\n"); */ + } + + initDeltaSwingIndexTables(Adapter, band, path, sign, chnl, rate, data); + } + } + } else + RTW_INFO("%s(): No File %s, Load from HWImg Array!\n", __func__, pFileName); + return rtStatus; +} + +static int phy_ParsePowerLimitTableFile( + PADAPTER Adapter, + char *buffer +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + struct PHY_DM_STRUCT *pDM_Odm = &(pHalData->odmpriv); + u32 i = 0, forCnt = 0; + u8 loadingStage = 0, limitValue = 0, fraction = 0; + char *szLine, *ptmp; + int rtStatus = _SUCCESS; + char band[10], bandwidth[10], rateSection[10], + regulation[TXPWR_LMT_MAX_REGULATION_NUM][10], rfPath[10], colNumBuf[10]; + u8 colNum = 0; + + RTW_INFO("===>phy_ParsePowerLimitTableFile()\n"); + + if (Adapter->registrypriv.RegDecryptCustomFile == 1) + phy_DecryptBBPgParaFile(Adapter, buffer); + + ptmp = buffer; + for (szLine = GetLineFromBuffer(ptmp); szLine != NULL; szLine = GetLineFromBuffer(ptmp)) { + if (isAllSpaceOrTab(szLine, sizeof(*szLine))) + continue; + + /* skip comment */ + if (IsCommentString(szLine)) + continue; + + if (loadingStage == 0) { + for (forCnt = 0; forCnt < TXPWR_LMT_MAX_REGULATION_NUM; ++forCnt) + memset((void *) regulation[forCnt], 0, 10); + memset((void *) band, 0, 10); + memset((void *) bandwidth, 0, 10); + memset((void *) rateSection, 0, 10); + memset((void *) rfPath, 0, 10); + memset((void *) colNumBuf, 0, 10); + + if (szLine[0] != '#' || szLine[1] != '#') + continue; + + /* skip the space */ + i = 2; + while (szLine[i] == ' ' || szLine[i] == '\t') + ++i; + + szLine[--i] = ' '; /* return the space in front of the regulation info */ + + /* Parse the label of the table */ + if (!ParseQualifiedString(szLine, &i, band, ' ', ',')) { + RTW_INFO("Fail to parse band!\n"); + return _FAIL; + } + if (!ParseQualifiedString(szLine, &i, bandwidth, ' ', ',')) { + RTW_INFO("Fail to parse bandwidth!\n"); + return _FAIL; + } + if (!ParseQualifiedString(szLine, &i, rfPath, ' ', ',')) { + RTW_INFO("Fail to parse rf path!\n"); + return _FAIL; + } + if (!ParseQualifiedString(szLine, &i, rateSection, ' ', ',')) { + RTW_INFO("Fail to parse rate!\n"); + return _FAIL; + } + + loadingStage = 1; + } else if (loadingStage == 1) { + if (szLine[0] != '#' || szLine[1] != '#') + continue; + + /* skip the space */ + i = 2; + while (szLine[i] == ' ' || szLine[i] == '\t') + ++i; + + if (!eqNByte((u8 *)(szLine + i), (u8 *)("START"), 5)) { + RTW_INFO("Lost \"## START\" label\n"); + return _FAIL; + } + + loadingStage = 2; + } else if (loadingStage == 2) { + if (szLine[0] != '#' || szLine[1] != '#') + continue; + + /* skip the space */ + i = 2; + while (szLine[i] == ' ' || szLine[i] == '\t') + ++i; + + if (!ParseQualifiedString(szLine, &i, colNumBuf, '#', '#')) { + RTW_INFO("Fail to parse column number!\n"); + return _FAIL; + } + + if (!GetU1ByteIntegerFromStringInDecimal(colNumBuf, &colNum)) + return _FAIL; + + if (colNum > TXPWR_LMT_MAX_REGULATION_NUM) { + RTW_INFO("unvalid col number %d (greater than max %d)\n", + colNum, TXPWR_LMT_MAX_REGULATION_NUM); + return _FAIL; + } + + for (forCnt = 0; forCnt < colNum; ++forCnt) { + u8 regulation_name_cnt = 0; + + /* skip the space */ + while (szLine[i] == ' ' || szLine[i] == '\t') + ++i; + + while (szLine[i] != ' ' && szLine[i] != '\t' && szLine[i] != '\0') + regulation[forCnt][regulation_name_cnt++] = szLine[i++]; + /* RTW_INFO("regulation %s!\n", regulation[forCnt]); */ + + if (regulation_name_cnt == 0) { + RTW_INFO("unvalid number of regulation!\n"); + return _FAIL; + } + } + + loadingStage = 3; + } else if (loadingStage == 3) { + char channel[10] = {0}, powerLimit[10] = {0}; + u8 cnt = 0; + + /* the table ends */ + if (szLine[0] == '#' && szLine[1] == '#') { + i = 2; + while (szLine[i] == ' ' || szLine[i] == '\t') + ++i; + + if (eqNByte((u8 *)(szLine + i), (u8 *)("END"), 3)) { + loadingStage = 0; + continue; + } else { + RTW_INFO("Wrong format\n"); + RTW_INFO("<===== phy_ParsePowerLimitTableFile()\n"); + return _FAIL; + } + } + + if ((szLine[0] != 'c' && szLine[0] != 'C') || + (szLine[1] != 'h' && szLine[1] != 'H')) { + RTW_INFO("Meet wrong channel => power limt pair '%c','%c'(%d,%d)\n", szLine[0], szLine[1], szLine[0], szLine[1]); + continue; + } + i = 2;/* move to the location behind 'h' */ + + /* load the channel number */ + cnt = 0; + while (szLine[i] >= '0' && szLine[i] <= '9') { + channel[cnt] = szLine[i]; + ++cnt; + ++i; + } + /* RTW_INFO("chnl %s!\n", channel); */ + + for (forCnt = 0; forCnt < colNum; ++forCnt) { + /* skip the space between channel number and the power limit value */ + while (szLine[i] == ' ' || szLine[i] == '\t') + ++i; + + /* load the power limit value */ + cnt = 0; + fraction = 0; + memset((void *) powerLimit, 0, 10); + while ((szLine[i] >= '0' && szLine[i] <= '9') || szLine[i] == '.') { + if (szLine[i] == '.') { + if ((szLine[i + 1] >= '0' && szLine[i + 1] <= '9')) { + fraction = szLine[i + 1]; + i += 2; + } else { + RTW_INFO("Wrong fraction in TXPWR_LMT.txt\n"); + return _FAIL; + } + + break; + } + + powerLimit[cnt] = szLine[i]; + ++cnt; + ++i; + } + + if (powerLimit[0] == '\0') { + powerLimit[0] = '6'; + powerLimit[1] = '3'; + i += 2; + } else { + if (!GetU1ByteIntegerFromStringInDecimal(powerLimit, &limitValue)) + return _FAIL; + + limitValue *= 2; + cnt = 0; + if (fraction == '5') + ++limitValue; + + /* the value is greater or equal to 100 */ + if (limitValue >= 100) { + powerLimit[cnt++] = limitValue / 100 + '0'; + limitValue %= 100; + + if (limitValue >= 10) { + powerLimit[cnt++] = limitValue / 10 + '0'; + limitValue %= 10; + } else + powerLimit[cnt++] = '0'; + + powerLimit[cnt++] = limitValue + '0'; + } + /* the value is greater or equal to 10 */ + else if (limitValue >= 10) { + powerLimit[cnt++] = limitValue / 10 + '0'; + limitValue %= 10; + powerLimit[cnt++] = limitValue + '0'; + } + /* the value is less than 10 */ + else + powerLimit[cnt++] = limitValue + '0'; + + powerLimit[cnt] = '\0'; + } + + /* RTW_INFO("ch%s => %s\n", channel, powerLimit); */ + + /* store the power limit value */ + phy_set_tx_power_limit(pDM_Odm, (u8 *)regulation[forCnt], (u8 *)band, + (u8 *)bandwidth, (u8 *)rateSection, (u8 *)rfPath, (u8 *)channel, (u8 *)powerLimit); + + } + } else { + RTW_INFO("Abnormal loading stage in phy_ParsePowerLimitTableFile()!\n"); + rtStatus = _FAIL; + break; + } + } + + RTW_INFO("<===phy_ParsePowerLimitTableFile()\n"); + return rtStatus; +} + +int +PHY_ConfigRFWithPowerLimitTableParaFile( + PADAPTER Adapter, + const char *pFileName +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + int rlen = 0, rtStatus = _FAIL; + + if (!(Adapter->registrypriv.load_phy_file & LOAD_RF_TXPWR_LMT_PARA_FILE)) + return rtStatus; + + memset(pHalData->para_file_buf, 0, MAX_PARA_FILE_BUF_LEN); + + if (pHalData->rf_tx_pwr_lmt == NULL) { + rtw_get_phy_file_path(Adapter, pFileName); + if (rtw_is_file_readable(rtw_phy_para_file_path) == true) { + rlen = rtw_retrieve_from_file(rtw_phy_para_file_path, pHalData->para_file_buf, MAX_PARA_FILE_BUF_LEN); + if (rlen > 0) { + rtStatus = _SUCCESS; + pHalData->rf_tx_pwr_lmt = rtw_zvmalloc(rlen); + if (pHalData->rf_tx_pwr_lmt) { + memcpy(pHalData->rf_tx_pwr_lmt, pHalData->para_file_buf, rlen); + pHalData->rf_tx_pwr_lmt_len = rlen; + } else + RTW_INFO("%s rf_tx_pwr_lmt alloc fail !\n", __func__); + } + } + } else { + if ((pHalData->rf_tx_pwr_lmt_len != 0) && (pHalData->rf_tx_pwr_lmt != NULL)) { + memcpy(pHalData->para_file_buf, pHalData->rf_tx_pwr_lmt, pHalData->rf_tx_pwr_lmt_len); + rtStatus = _SUCCESS; + } else + RTW_INFO("%s(): Critical Error !!!\n", __func__); + } + + if (rtStatus == _SUCCESS) { + /* RTW_INFO("%s(): read %s ok\n", __func__, pFileName); */ + rtStatus = phy_ParsePowerLimitTableFile(Adapter, pHalData->para_file_buf); + } else + RTW_INFO("%s(): No File %s, Load from HWImg Array!\n", __func__, pFileName); + + return rtStatus; +} + +void phy_free_filebuf_mask(_adapter *padapter, u8 mask) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + if (pHalData->mac_reg && (mask & LOAD_MAC_PARA_FILE)) { + rtw_vmfree(pHalData->mac_reg, pHalData->mac_reg_len); + pHalData->mac_reg = NULL; + } + if (mask & LOAD_BB_PARA_FILE) { + if (pHalData->bb_phy_reg) { + rtw_vmfree(pHalData->bb_phy_reg, pHalData->bb_phy_reg_len); + pHalData->bb_phy_reg = NULL; + } + if (pHalData->bb_agc_tab) { + rtw_vmfree(pHalData->bb_agc_tab, pHalData->bb_agc_tab_len); + pHalData->bb_agc_tab = NULL; + } + } + if (pHalData->bb_phy_reg_pg && (mask & LOAD_BB_PG_PARA_FILE)) { + rtw_vmfree(pHalData->bb_phy_reg_pg, pHalData->bb_phy_reg_pg_len); + pHalData->bb_phy_reg_pg = NULL; + } + if (pHalData->bb_phy_reg_mp && (mask & LOAD_BB_MP_PARA_FILE)) { + rtw_vmfree(pHalData->bb_phy_reg_mp, pHalData->bb_phy_reg_mp_len); + pHalData->bb_phy_reg_mp = NULL; + } + if (mask & LOAD_RF_PARA_FILE) { + if (pHalData->rf_radio_a) { + rtw_vmfree(pHalData->rf_radio_a, pHalData->rf_radio_a_len); + pHalData->rf_radio_a = NULL; + } + if (pHalData->rf_radio_b) { + rtw_vmfree(pHalData->rf_radio_b, pHalData->rf_radio_b_len); + pHalData->rf_radio_b = NULL; + } + } + if (pHalData->rf_tx_pwr_track && (mask & LOAD_RF_TXPWR_TRACK_PARA_FILE)) { + rtw_vmfree(pHalData->rf_tx_pwr_track, pHalData->rf_tx_pwr_track_len); + pHalData->rf_tx_pwr_track = NULL; + } + if (pHalData->rf_tx_pwr_lmt && (mask & LOAD_RF_TXPWR_LMT_PARA_FILE)) { + rtw_vmfree(pHalData->rf_tx_pwr_lmt, pHalData->rf_tx_pwr_lmt_len); + pHalData->rf_tx_pwr_lmt = NULL; + } +} + +inline void phy_free_filebuf(_adapter *padapter) +{ + phy_free_filebuf_mask(padapter, 0xFF); +} + +#endif diff --git a/drivers/staging/rtl8188eu/hal/hal_dm.c b/drivers/staging/rtl8188eu/hal/hal_dm.c new file mode 100644 index 000000000000..b7dfd4fe40bd --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal_dm.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#include +#include + +/* A mapping from HalData to ODM. */ +static enum odm_board_type_e boardType(u8 InterfaceSel) +{ + enum odm_board_type_e board = ODM_BOARD_DEFAULT; + + INTERFACE_SELECT_USB usb = (INTERFACE_SELECT_USB)InterfaceSel; + switch (usb) { + case INTF_SEL1_USB_High_Power: + board |= ODM_BOARD_EXT_LNA; + board |= ODM_BOARD_EXT_PA; + break; + case INTF_SEL2_MINICARD: + board |= ODM_BOARD_MINICARD; + break; + case INTF_SEL4_USB_Combo: + board |= ODM_BOARD_BT; + break; + case INTF_SEL5_USB_Combo_MF: + board |= ODM_BOARD_BT; + break; + case INTF_SEL0_USB: + case INTF_SEL3_USB_Solo: + default: + board = ODM_BOARD_DEFAULT; + break; + } + return board; +} + +void Init_ODM_ComInfo(_adapter *adapter) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(adapter); + struct PHY_DM_STRUCT *pDM_Odm = &(pHalData->odmpriv); + struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter); + int i; + + memset(pDM_Odm, 0, sizeof(*pDM_Odm)); + + pDM_Odm->adapter = adapter; + + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_PLATFORM, ODM_CE); + + rtw_odm_init_ic_type(adapter); + + if (rtw_get_intf_type(adapter) == RTW_GSPI) + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_INTERFACE, ODM_ITRF_SDIO); + else + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_INTERFACE, rtw_get_intf_type(adapter)); + + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_MP_TEST_CHIP, IS_NORMAL_CHIP(pHalData->version_id)); + + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_PATCH_ID, pHalData->CustomerID); + + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_BWIFI_TEST, adapter->registrypriv.wifi_spec); + + + if (pHalData->rf_type == RF_1T1R) + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_1T1R); + else if (pHalData->rf_type == RF_1T2R) + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_1T2R); + else if (pHalData->rf_type == RF_2T2R) + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_2T2R); + else if (pHalData->rf_type == RF_2T2R_GREEN) + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_2T2R_GREEN); + else if (pHalData->rf_type == RF_2T3R) + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_2T3R); + else if (pHalData->rf_type == RF_2T4R) + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_2T4R); + else if (pHalData->rf_type == RF_3T3R) + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_3T3R); + else if (pHalData->rf_type == RF_3T4R) + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_3T4R); + else if (pHalData->rf_type == RF_4T4R) + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_4T4R); + else + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_XTXR); + + + { + /* 1 ======= BoardType: ODM_CMNINFO_BOARD_TYPE ======= */ + u8 odm_board_type = ODM_BOARD_DEFAULT; + + if (pHalData->ExternalLNA_2G != 0) { + odm_board_type |= ODM_BOARD_EXT_LNA; + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_EXT_LNA, 1); + } + if (pHalData->external_lna_5g != 0) { + odm_board_type |= ODM_BOARD_EXT_LNA_5G; + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_5G_EXT_LNA, 1); + } + if (pHalData->ExternalPA_2G != 0) { + odm_board_type |= ODM_BOARD_EXT_PA; + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_EXT_PA, 1); + } + if (pHalData->external_pa_5g != 0) { + odm_board_type |= ODM_BOARD_EXT_PA_5G; + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_5G_EXT_PA, 1); + } + if (pHalData->EEPROMBluetoothCoexist) + odm_board_type |= ODM_BOARD_BT; + + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_BOARD_TYPE, odm_board_type); + /* 1 ============== End of BoardType ============== */ + } + + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_DOMAIN_CODE_2G, pHalData->Regulation2_4G); + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_DOMAIN_CODE_5G, pHalData->Regulation5G); + +#ifdef CONFIG_DFS_MASTER + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_DFS_REGION_DOMAIN, adapter->registrypriv.dfs_region_domain); + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_DFS_MASTER_ENABLE, &(adapter_to_rfctl(adapter)->dfs_master_enabled)); +#endif + + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_GPA, pHalData->TypeGPA); + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_APA, pHalData->TypeAPA); + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_GLNA, pHalData->TypeGLNA); + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_ALNA, pHalData->TypeALNA); + + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_RFE_TYPE, pHalData->rfe_type); + + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_EXT_TRSW, 0); + + /*Add by YuChen for kfree init*/ + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_REGRFKFREEENABLE, adapter->registrypriv.RegPwrTrimEnable); + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_RFKFREEENABLE, pHalData->RfKFreeEnable); + + /*Antenna diversity relative parameters*/ + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_ANT_DIV, &(pHalData->AntDivCfg)); + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_RF_ANTENNA_TYPE, pHalData->TRxAntDivType); + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_BE_FIX_TX_ANT, pHalData->b_fix_tx_ant); + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_WITH_EXT_ANTENNA_SWITCH, pHalData->with_extenal_ant_switch); + + /*Add by YuChen for adaptivity init*/ + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_ADAPTIVITY, &(adapter->registrypriv.adaptivity_en)); + phydm_adaptivity_info_init(pDM_Odm, PHYDM_ADAPINFO_CARRIER_SENSE_ENABLE, (adapter->registrypriv.adaptivity_mode != 0) ? true : false); + phydm_adaptivity_info_init(pDM_Odm, PHYDM_ADAPINFO_DCBACKOFF, adapter->registrypriv.adaptivity_dc_backoff); + phydm_adaptivity_info_init(pDM_Odm, PHYDM_ADAPINFO_DYNAMICLINKADAPTIVITY, (adapter->registrypriv.adaptivity_dml != 0) ? true : false); + phydm_adaptivity_info_init(pDM_Odm, PHYDM_ADAPINFO_TH_L2H_INI, adapter->registrypriv.adaptivity_th_l2h_ini); + phydm_adaptivity_info_init(pDM_Odm, PHYDM_ADAPINFO_TH_EDCCA_HL_DIFF, adapter->registrypriv.adaptivity_th_edcca_hl_diff); + +#ifdef CONFIG_IQK_PA_OFF + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_IQKPAOFF, 1); +#endif + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_IQKFWOFFLOAD, pHalData->RegIQKFWOffload); + + /* Pointer reference */ + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_TX_UNI, &(dvobj->traffic_stat.tx_bytes)); + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_RX_UNI, &(dvobj->traffic_stat.rx_bytes)); + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_WM_MODE, &(pmlmeext->cur_wireless_mode)); + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_BAND, &(pHalData->current_band_type)); + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_FORCED_RATE, &(pHalData->ForcedDataRate)); + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_FORCED_IGI_LB, &(pHalData->u1ForcedIgiLb)); + + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_SEC_CHNL_OFFSET, &(pHalData->nCur40MhzPrimeSC)); + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_SEC_MODE, &(adapter->securitypriv.dot11PrivacyAlgrthm)); + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_BW, &(pHalData->current_channel_bw)); + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_CHNL, &(pHalData->current_channel)); + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_NET_CLOSED, &(adapter->net_closed)); + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_FORCED_IGI_LB, &(pHalData->u1ForcedIgiLb)); + + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_SCAN, &(pmlmepriv->bScanInProcess)); + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_POWER_SAVING, &(pwrctl->bpower_saving)); + /*Add by Yuchen for phydm beamforming*/ + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_TX_TP, &(dvobj->traffic_stat.cur_tx_tp)); + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_RX_TP, &(dvobj->traffic_stat.cur_rx_tp)); + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_ANT_TEST, &(pHalData->antenna_test)); + odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_HUBUSBMODE, &(dvobj->usb_speed)); + for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) + odm_cmn_info_ptr_array_hook(pDM_Odm, ODM_CMNINFO_STA_STATUS, i, NULL); + + phydm_init_debug_setting(pDM_Odm); + + /* TODO */ + /* odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_BT_OPERATION, false); */ + /* odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_BT_DISABLE_EDCA, false); */ +} diff --git a/drivers/staging/rtl8188eu/hal/hal_dm.h b/drivers/staging/rtl8188eu/hal/hal_dm.h new file mode 100644 index 000000000000..7f6e9928288e --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal_dm.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#ifndef __HAL_DM_H__ +#define __HAL_DM_H__ + +void Init_ODM_ComInfo(_adapter *adapter); + +#endif /* __HAL_DM_H__ */ diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c new file mode 100644 index 000000000000..2ca6e68f4edd --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal_intf.c @@ -0,0 +1,1279 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#define _HAL_INTF_C_ + +#include +#include + +const u32 _chip_type_to_odm_ic_type[] = { + 0, + ODM_RTL8188E, + ODM_RTL8192E, + ODM_RTL8812, + ODM_RTL8821, + ODM_RTL8723B, + ODM_RTL8814A, + ODM_RTL8703B, + ODM_RTL8188F, + ODM_RTL8822B, + ODM_RTL8723D, + ODM_RTL8821C, + 0, +}; + +void rtw_hal_chip_configure(_adapter *padapter) +{ + padapter->hal_func.intf_chip_configure(padapter); +} + +/* + * Description: + * Read chip internal ROM data + * + * Return: + * _SUCCESS success + * _FAIL fail + */ +u8 rtw_hal_read_chip_info(_adapter *padapter) +{ + u8 rtn = _SUCCESS; + u8 hci_type = rtw_get_intf_type(padapter); + u32 start = jiffies; + + /* before access eFuse, make sure card enable has been called */ + if ((hci_type == RTW_SDIO || hci_type == RTW_GSPI) + && !rtw_is_hw_init_completed(padapter)) + rtw_hal_power_on(padapter); + + rtn = padapter->hal_func.read_adapter_info(padapter); + + if ((hci_type == RTW_SDIO || hci_type == RTW_GSPI) + && !rtw_is_hw_init_completed(padapter)) + rtw_hal_power_off(padapter); + + RTW_INFO("%s in %d ms\n", __func__, rtw_get_passing_time_ms(start)); + + return rtn; +} + +void rtw_hal_read_chip_version(_adapter *padapter) +{ + padapter->hal_func.read_chip_version(padapter); + rtw_odm_init_ic_type(padapter); +} + +void rtw_hal_def_value_init(_adapter *padapter) +{ + if (is_primary_adapter(padapter)) { + padapter->hal_func.init_default_value(padapter); + + rtw_init_hal_com_default_value(padapter); + + { + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter); + + /* hal_spec is ready here */ + dvobj->macid_ctl.num = rtw_min(hal_spec->macid_num, MACID_NUM_SW_LIMIT); + + dvobj->cam_ctl.sec_cap = hal_spec->sec_cap; + dvobj->cam_ctl.num = rtw_min(hal_spec->sec_cam_ent_num, SEC_CAM_ENT_NUM_SW_LIMIT); + } + } +} + +u8 rtw_hal_data_init(_adapter *padapter) +{ + if (is_primary_adapter(padapter)) { + padapter->hal_data_sz = sizeof(HAL_DATA_TYPE); + padapter->HalData = rtw_zvmalloc(padapter->hal_data_sz); + if (padapter->HalData == NULL) { + RTW_INFO("cant not alloc memory for HAL DATA\n"); + return _FAIL; + } + } + return _SUCCESS; +} + +void rtw_hal_data_deinit(_adapter *padapter) +{ + if (is_primary_adapter(padapter)) { + if (padapter->HalData) { +#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE + phy_free_filebuf(padapter); +#endif + rtw_vmfree(padapter->HalData, padapter->hal_data_sz); + padapter->HalData = NULL; + padapter->hal_data_sz = 0; + } + } +} + +void rtw_hal_free_data(_adapter *padapter) +{ + /* free HAL Data */ + rtw_hal_data_deinit(padapter); +} +void rtw_hal_dm_init(_adapter *padapter) +{ + if (is_primary_adapter(padapter)) { + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + + padapter->hal_func.dm_init(padapter); + + spin_lock_init(&pHalData->IQKSpinLock); + + phy_load_tx_power_ext_info(padapter, 1); + } +} +void rtw_hal_dm_deinit(_adapter *padapter) +{ + if (is_primary_adapter(padapter)) { + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + + padapter->hal_func.dm_deinit(padapter); + } +} + +void rtw_hal_sw_led_init(_adapter *padapter) +{ + if (padapter->hal_func.InitSwLeds) + padapter->hal_func.InitSwLeds(padapter); +} + +void rtw_hal_sw_led_deinit(_adapter *padapter) +{ + if (padapter->hal_func.DeInitSwLeds) + padapter->hal_func.DeInitSwLeds(padapter); +} + +u32 rtw_hal_power_on(_adapter *padapter) +{ + return padapter->hal_func.hal_power_on(padapter); +} +void rtw_hal_power_off(_adapter *padapter) +{ + struct macid_ctl_t *macid_ctl = &padapter->dvobj->macid_ctl; + + memset(macid_ctl->h2c_msr, 0, MACID_NUM_SW_LIMIT); + + padapter->hal_func.hal_power_off(padapter); +} + + +static void rtw_hal_init_opmode(_adapter *padapter) +{ + NDIS_802_11_NETWORK_INFRASTRUCTURE networkType = Ndis802_11InfrastructureMax; + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + sint fw_state; + + fw_state = get_fwstate(pmlmepriv); + + if (fw_state & WIFI_ADHOC_STATE) + networkType = Ndis802_11IBSS; + else if (fw_state & WIFI_STATION_STATE) + networkType = Ndis802_11Infrastructure; + else if (fw_state & WIFI_AP_STATE) + networkType = Ndis802_11APMode; + else + return; + + rtw_setopmode_cmd(padapter, networkType, false); +} + +uint rtw_hal_init(_adapter *padapter) +{ + uint status = _SUCCESS; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + int i; + + status = padapter->hal_func.hal_init(padapter); + + if (status == _SUCCESS) { + pHalData->hw_init_completed = true; + rtw_restore_mac_addr(padapter); + + if (padapter->registrypriv.notch_filter == 1) + rtw_hal_notch_filter(padapter, 1); + + for (i = 0; i < dvobj->iface_nums; i++) + rtw_sec_restore_wep_key(dvobj->padapters[i]); + + rtw_led_control(padapter, LED_CTL_POWER_ON); + + init_hw_mlme_ext(padapter); + + rtw_hal_init_opmode(padapter); + +#ifdef CONFIG_RF_POWER_TRIM + rtw_bb_rf_gain_offset(padapter); +#endif /*CONFIG_RF_POWER_TRIM*/ + + } else { + pHalData->hw_init_completed = false; + RTW_INFO("rtw_hal_init: hal_init fail\n"); + } + + + return status; + +} + +uint rtw_hal_deinit(_adapter *padapter) +{ + uint status = _SUCCESS; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + int i; + + status = padapter->hal_func.hal_deinit(padapter); + + if (status == _SUCCESS) { + rtw_led_control(padapter, LED_CTL_POWER_OFF); + pHalData->hw_init_completed = false; + } else + RTW_INFO("\n rtw_hal_deinit: hal_init fail\n"); + + + return status; +} + +void rtw_hal_set_hwreg(_adapter *padapter, u8 variable, u8 *val) +{ + padapter->hal_func.set_hw_reg_handler(padapter, variable, val); +} + +void rtw_hal_get_hwreg(_adapter *padapter, u8 variable, u8 *val) +{ + padapter->hal_func.GetHwRegHandler(padapter, variable, val); +} + +u8 rtw_hal_set_def_var(_adapter *padapter, HAL_DEF_VARIABLE eVariable, void * pValue) +{ + return padapter->hal_func.SetHalDefVarHandler(padapter, eVariable, pValue); +} +u8 rtw_hal_get_def_var(_adapter *padapter, HAL_DEF_VARIABLE eVariable, void * pValue) +{ + return padapter->hal_func.get_hal_def_var_handler(padapter, eVariable, pValue); +} + +void rtw_hal_set_odm_var(_adapter *padapter, HAL_ODM_VARIABLE eVariable, void * pValue1, bool bSet) +{ + padapter->hal_func.SetHalODMVarHandler(padapter, eVariable, pValue1, bSet); +} +void rtw_hal_get_odm_var(_adapter *padapter, HAL_ODM_VARIABLE eVariable, void * pValue1, void * pValue2) +{ + padapter->hal_func.GetHalODMVarHandler(padapter, eVariable, pValue1, pValue2); +} + +/* FOR SDIO & PCIE */ +void rtw_hal_enable_interrupt(_adapter *padapter) +{ +} + +/* FOR SDIO & PCIE */ +void rtw_hal_disable_interrupt(_adapter *padapter) +{ +} + +u8 rtw_hal_check_ips_status(_adapter *padapter) +{ + u8 val = false; + if (padapter->hal_func.check_ips_status) + val = padapter->hal_func.check_ips_status(padapter); + else + RTW_INFO("%s: hal_func.check_ips_status is NULL!\n", __func__); + + return val; +} + +s32 rtw_hal_fw_dl(_adapter *padapter, u8 wowlan) +{ + return padapter->hal_func.fw_dl(padapter, wowlan); +} + +#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) +void rtw_hal_clear_interrupt(_adapter *padapter) +{ +} +#endif + +u32 rtw_hal_inirp_init(_adapter *padapter) +{ + if (is_primary_adapter(padapter)) + return padapter->hal_func.inirp_init(padapter); + return _SUCCESS; +} +u32 rtw_hal_inirp_deinit(_adapter *padapter) +{ + + if (is_primary_adapter(padapter)) + return padapter->hal_func.inirp_deinit(padapter); + + return _SUCCESS; +} + +/* for USB Auto-suspend */ +u8 rtw_hal_intf_ps_func(_adapter *padapter, HAL_INTF_PS_FUNC efunc_id, u8 *val) +{ + if (padapter->hal_func.interface_ps_func) + return padapter->hal_func.interface_ps_func(padapter, efunc_id, val); + return _FAIL; +} + +s32 rtw_hal_xmitframe_enqueue(_adapter *padapter, struct xmit_frame *pxmitframe) +{ + return padapter->hal_func.hal_xmitframe_enqueue(padapter, pxmitframe); +} + +s32 rtw_hal_xmit(_adapter *padapter, struct xmit_frame *pxmitframe) +{ + return padapter->hal_func.hal_xmit(padapter, pxmitframe); +} + +/* + * [IMPORTANT] This function would be run in interrupt context. + */ +s32 rtw_hal_mgnt_xmit(_adapter *padapter, struct xmit_frame *pmgntframe) +{ + s32 ret = _FAIL; + u8 *pframe, subtype; + struct rtw_ieee80211_hdr *pwlanhdr; + struct sta_info *psta; + struct sta_priv *pstapriv = &padapter->stapriv; + + update_mgntframe_attrib_addr(padapter, pmgntframe); + pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; + subtype = get_frame_sub_type(pframe); /* bit(7)~bit(2) */ + + /* pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; */ + /* memcpy(pmgntframe->attrib.ra, pwlanhdr->addr1, ETH_ALEN); */ + +#ifdef CONFIG_IEEE80211W + if (padapter->securitypriv.binstallBIPkey == true && (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC || + subtype == WIFI_ACTION)) { + if (IS_MCAST(pmgntframe->attrib.ra) && pmgntframe->attrib.key_type != IEEE80211W_NO_KEY) { + pmgntframe->attrib.encrypt = _BIP_; + /* pmgntframe->attrib.bswenc = true; */ + } else if (pmgntframe->attrib.key_type != IEEE80211W_NO_KEY) { + psta = rtw_get_stainfo(pstapriv, pmgntframe->attrib.ra); + if (psta && psta->bpairwise_key_installed == true) { + pmgntframe->attrib.encrypt = _AES_; + pmgntframe->attrib.bswenc = true; + } else { + RTW_INFO("%s, %d, bpairwise_key_installed is false\n", __func__, __LINE__); + goto no_mgmt_coalesce; + } + } + RTW_INFO("encrypt=%d, bswenc=%d\n", pmgntframe->attrib.encrypt, pmgntframe->attrib.bswenc); + rtw_mgmt_xmitframe_coalesce(padapter, pmgntframe->pkt, pmgntframe); + } +#endif /* CONFIG_IEEE80211W */ +no_mgmt_coalesce: + ret = padapter->hal_func.mgnt_xmit(padapter, pmgntframe); + return ret; +} + +s32 rtw_hal_init_xmit_priv(_adapter *padapter) +{ + return padapter->hal_func.init_xmit_priv(padapter); +} +void rtw_hal_free_xmit_priv(_adapter *padapter) +{ + padapter->hal_func.free_xmit_priv(padapter); +} + +s32 rtw_hal_init_recv_priv(_adapter *padapter) +{ + return padapter->hal_func.init_recv_priv(padapter); +} +void rtw_hal_free_recv_priv(_adapter *padapter) +{ + padapter->hal_func.free_recv_priv(padapter); +} + +void rtw_update_ramask(_adapter *padapter, struct sta_info *psta, u32 mac_id, u8 rssi_level, u8 is_update_bw) +{ + struct macid_cfg h2c_macid_cfg; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj); + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter); + u8 disable_cck_rate = false, MimoPs_enable = false; + u32 ratr_bitmap_msb = 0, ratr_bitmap_lsb = 0; + u64 mask = 0, rate_bitmap = 0; + u8 bw, short_gi; + + if (psta == NULL) { + RTW_ERR(FUNC_ADPT_FMT" macid:%u, sta is NULL\n", FUNC_ADPT_ARG(padapter), mac_id); + rtw_warn_on(1); + return; + } + memset(&h2c_macid_cfg, 0, sizeof(struct macid_cfg)); + + bw = rtw_get_tx_bw_mode(padapter, psta); + short_gi = query_ra_short_GI(psta, bw); + + ratr_bitmap_msb = (u32)(psta->ra_mask >> 32); + ratr_bitmap_lsb = (u32)(psta->ra_mask); + + phydm_update_hal_ra_mask(&hal_data->odmpriv, psta->wireless_mode, hal_data->rf_type, bw, MimoPs_enable, disable_cck_rate, &ratr_bitmap_msb, &ratr_bitmap_lsb, rssi_level); + mask = (((u64)ratr_bitmap_msb) << 32) | ((u64)ratr_bitmap_lsb); + + +#ifdef CONFIG_BT_COEXIST + if (hal_data->EEPROMBluetoothCoexist == 1) { + rate_bitmap = rtw_btcoex_GetRaMask(padapter); + mask &= ~rate_bitmap; + } +#endif /* CONFIG_BT_COEXIST */ + +#ifdef CONFIG_CMCC_TEST +#ifdef CONFIG_BT_COEXIST + if (pmlmeext->cur_wireless_mode & WIRELESS_11G) { + if (mac_id == 0) { + RTW_INFO("CMCC_BT update raid entry, mask=0x%x\n", mask); + /*mask &=0xffffffc0; //disable CCK & <12M OFDM rate for 11G mode for CMCC */ + mask &= 0xffffff00; /*disable CCK & <24M OFDM rate for 11G mode for CMCC */ + RTW_INFO("CMCC_BT update raid entry, mask=0x%x\n", mask); + } + } +#endif +#endif + + /*set correct initial date rate for each mac_id */ + hal_data->INIDATA_RATE[mac_id] = psta->init_rate; + + + RTW_INFO("%s => mac_id:%d, networkType:0x%02x, mask:0x%016llx\n\t ==> rssi_level:%d, rate_bitmap:0x%016llx, shortGIrate=%d\n\t ==> bw:%d, ignore_bw:0x%d\n", + __func__, mac_id, psta->wireless_mode, mask, rssi_level, rate_bitmap, short_gi, bw, (!is_update_bw)); + + rtw_macid_ctl_set_bw(macid_ctl, mac_id, bw); + rtw_macid_ctl_set_vht_en(macid_ctl, mac_id, is_supported_vht(psta->wireless_mode)); + rtw_macid_ctl_set_rate_bmp0(macid_ctl, mac_id, mask); + rtw_macid_ctl_set_rate_bmp1(macid_ctl, mac_id, mask >> 32); + rtw_update_tx_rate_bmp(adapter_to_dvobj(padapter)); + + h2c_macid_cfg.mac_id = mac_id; + h2c_macid_cfg.rate_id = psta->raid; + h2c_macid_cfg.bandwidth = bw; + h2c_macid_cfg.ignore_bw = (!is_update_bw); + h2c_macid_cfg.short_gi = short_gi; + h2c_macid_cfg.ra_mask = mask; + + padapter->hal_func.update_ra_mask_handler(padapter, psta, &h2c_macid_cfg); +} + +void rtw_hal_update_ra_mask(struct sta_info *psta, u8 rssi_level, u8 is_update_bw) +{ + _adapter *padapter; + struct mlme_priv *pmlmepriv; + + if (!psta) + return; + + padapter = psta->padapter; + + pmlmepriv = &(padapter->mlmepriv); + + if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) + add_RATid(padapter, psta, rssi_level, is_update_bw); + else { + psta->raid = rtw_hal_networktype_to_raid(padapter, psta); + rtw_update_ramask(padapter, psta, psta->mac_id, rssi_level, is_update_bw); + } +} + +/* Start specifical interface thread */ +void rtw_hal_start_thread(_adapter *padapter) +{ +} +/* Start specifical interface thread */ +void rtw_hal_stop_thread(_adapter *padapter) +{ +} + +u32 rtw_hal_read_bbreg(_adapter *padapter, u32 RegAddr, u32 BitMask) +{ + u32 data = 0; + if (padapter->hal_func.read_bbreg) + data = padapter->hal_func.read_bbreg(padapter, RegAddr, BitMask); + return data; +} +void rtw_hal_write_bbreg(_adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data) +{ + if (padapter->hal_func.write_bbreg) + padapter->hal_func.write_bbreg(padapter, RegAddr, BitMask, Data); +} + +u32 rtw_hal_read_rfreg(_adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask) +{ + u32 data = 0; + + if (padapter->hal_func.read_rfreg) { + data = padapter->hal_func.read_rfreg(padapter, eRFPath, RegAddr, BitMask); + + if (match_rf_read_sniff_ranges(eRFPath, RegAddr, BitMask)) { + RTW_INFO("DBG_IO rtw_hal_read_rfreg(%u, 0x%04x, 0x%08x) read:0x%08x(0x%08x)\n" + , eRFPath, RegAddr, BitMask, (data << PHY_CalculateBitShift(BitMask)), data); + } + } + + return data; +} + +void rtw_hal_write_rfreg(_adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask, u32 Data) +{ + if (padapter->hal_func.write_rfreg) { + + if (match_rf_write_sniff_ranges(eRFPath, RegAddr, BitMask)) { + RTW_INFO("DBG_IO rtw_hal_write_rfreg(%u, 0x%04x, 0x%08x) write:0x%08x(0x%08x)\n" + , eRFPath, RegAddr, BitMask, (Data << PHY_CalculateBitShift(BitMask)), Data); + } + + padapter->hal_func.write_rfreg(padapter, eRFPath, RegAddr, BitMask, Data); + + } +} + +#if defined(CONFIG_SUPPORT_USB_INT) +void rtw_hal_interrupt_handler(_adapter *padapter, u16 pkt_len, u8 *pbuf) +{ + padapter->hal_func.interrupt_handler(padapter, pkt_len, pbuf); +} +#endif + +void rtw_hal_set_chnl_bw(_adapter *padapter, u8 channel, CHANNEL_WIDTH Bandwidth, u8 Offset40, u8 Offset80) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + struct PHY_DM_STRUCT *pDM_Odm = &(pHalData->odmpriv); + u8 cch_160 = Bandwidth == CHANNEL_WIDTH_160 ? channel : 0; + u8 cch_80 = Bandwidth == CHANNEL_WIDTH_80 ? channel : 0; + u8 cch_40 = Bandwidth == CHANNEL_WIDTH_40 ? channel : 0; + u8 cch_20 = Bandwidth == CHANNEL_WIDTH_20 ? channel : 0; + + odm_acquire_spin_lock(pDM_Odm, RT_IQK_SPINLOCK); + if (pDM_Odm->rf_calibrate_info.is_iqk_in_progress == true) + RTW_ERR("%s, %d, IQK may race condition\n", __func__, __LINE__); + odm_release_spin_lock(pDM_Odm, RT_IQK_SPINLOCK); + + /* MP mode channel don't use secondary channel */ + if (rtw_mi_mp_mode_check(padapter) == false) { + if (cch_80 != 0) + cch_40 = rtw_get_scch_by_cch_offset(cch_80, CHANNEL_WIDTH_80, Offset80); + if (cch_40 != 0) + cch_20 = rtw_get_scch_by_cch_offset(cch_40, CHANNEL_WIDTH_40, Offset40); + } + + pHalData->cch_80 = cch_80; + pHalData->cch_40 = cch_40; + pHalData->cch_20 = cch_20; + + if (0) + RTW_INFO("%s cch:%u, %s, offset40:%u, offset80:%u (%u, %u, %u)\n", __func__ + , channel, ch_width_str(Bandwidth), Offset40, Offset80 + , pHalData->cch_80, pHalData->cch_40, pHalData->cch_20); + + padapter->hal_func.set_chnl_bw_handler(padapter, channel, Bandwidth, Offset40, Offset80); +} + +void rtw_hal_set_tx_power_level(_adapter *padapter, u8 channel) +{ + if (padapter->hal_func.set_tx_power_level_handler) + padapter->hal_func.set_tx_power_level_handler(padapter, channel); +} + +void rtw_hal_get_tx_power_level(_adapter *padapter, s32 *powerlevel) +{ + if (padapter->hal_func.get_tx_power_level_handler) + padapter->hal_func.get_tx_power_level_handler(padapter, powerlevel); +} + +void rtw_hal_dm_watchdog(_adapter *padapter) +{ +#ifdef CONFIG_MCC_MODE + if (MCC_EN(padapter)) { + if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) + return; + } +#endif /* CONFIG_MCC_MODE */ + + padapter->hal_func.hal_dm_watchdog(padapter); + +} + +#ifdef CONFIG_LPS_LCLK_WD_TIMER +void rtw_hal_dm_watchdog_in_lps(_adapter *padapter) +{ +#if defined(CONFIG_CONCURRENT_MODE) +#ifndef CONFIG_FW_MULTI_PORT_SUPPORT + if (padapter->hw_port != HW_PORT0) + return; +#endif +#endif + + if (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == true) { + padapter->hal_func.hal_dm_watchdog_in_lps(padapter);/* this function caller is in interrupt context */ + } +} +#endif + +void rtw_hal_bcn_related_reg_setting(_adapter *padapter) +{ + padapter->hal_func.SetBeaconRelatedRegistersHandler(padapter); +} + +#ifdef CONFIG_HOSTAPD_MLME +s32 rtw_hal_hostap_mgnt_xmit_entry(_adapter *padapter, _pkt *pkt) +{ + if (padapter->hal_func.hostap_mgnt_xmit_entry) + return padapter->hal_func.hostap_mgnt_xmit_entry(padapter, pkt); + return _FAIL; +} +#endif /* CONFIG_HOSTAPD_MLME */ + +#ifdef DBG_CONFIG_ERROR_DETECT +void rtw_hal_sreset_init(_adapter *padapter) +{ + padapter->hal_func.sreset_init_value(padapter); +} +void rtw_hal_sreset_reset(_adapter *padapter) +{ + padapter = GET_PRIMARY_ADAPTER(padapter); + padapter->hal_func.silentreset(padapter); +} + +void rtw_hal_sreset_reset_value(_adapter *padapter) +{ + padapter->hal_func.sreset_reset_value(padapter); +} + +void rtw_hal_sreset_xmit_status_check(_adapter *padapter) +{ + padapter->hal_func.sreset_xmit_status_check(padapter); +} +void rtw_hal_sreset_linked_status_check(_adapter *padapter) +{ + padapter->hal_func.sreset_linked_status_check(padapter); +} +u8 rtw_hal_sreset_get_wifi_status(_adapter *padapter) +{ + return padapter->hal_func.sreset_get_wifi_status(padapter); +} + +bool rtw_hal_sreset_inprogress(_adapter *padapter) +{ + padapter = GET_PRIMARY_ADAPTER(padapter); + return padapter->hal_func.sreset_inprogress(padapter); +} +#endif /* DBG_CONFIG_ERROR_DETECT */ + +#ifdef CONFIG_IOL +int rtw_hal_iol_cmd(ADAPTER *adapter, struct xmit_frame *xmit_frame, u32 max_waiting_ms, u32 bndy_cnt) +{ + if (adapter->hal_func.IOL_exec_cmds_sync) + return adapter->hal_func.IOL_exec_cmds_sync(adapter, xmit_frame, max_waiting_ms, bndy_cnt); + return _FAIL; +} +#endif + +#ifdef CONFIG_XMIT_THREAD_MODE +s32 rtw_hal_xmit_thread_handler(_adapter *padapter) +{ + return padapter->hal_func.xmit_thread_handler(padapter); +} +#endif + +#ifdef CONFIG_RECV_THREAD_MODE +s32 rtw_hal_recv_hdl(_adapter *adapter) +{ + return adapter->hal_func.recv_hdl(adapter); +} +#endif + +void rtw_hal_notch_filter(_adapter *adapter, bool enable) +{ + if (adapter->hal_func.hal_notch_filter) + adapter->hal_func.hal_notch_filter(adapter, enable); +} + +#ifdef CONFIG_FW_C2H_REG +inline bool rtw_hal_c2h_valid(_adapter *adapter, u8 *buf) +{ + HAL_DATA_TYPE *HalData = GET_HAL_DATA(adapter); + HAL_VERSION *hal_ver = &HalData->version_id; + bool ret = _FAIL; + + ret = C2H_ID_88XX(buf) || C2H_PLEN_88XX(buf); + + return ret; +} + +inline s32 rtw_hal_c2h_evt_read(_adapter *adapter, u8 *buf) +{ + HAL_DATA_TYPE *HalData = GET_HAL_DATA(adapter); + HAL_VERSION *hal_ver = &HalData->version_id; + s32 ret = _FAIL; + + ret = c2h_evt_read_88xx(adapter, buf); + + return ret; +} + +bool rtw_hal_c2h_reg_hdr_parse(_adapter *adapter, u8 *buf, u8 *id, u8 *seq, u8 *plen, u8 **payload) +{ + HAL_DATA_TYPE *HalData = GET_HAL_DATA(adapter); + HAL_VERSION *hal_ver = &HalData->version_id; + bool ret = _FAIL; + + *id = C2H_ID_88XX(buf); + *seq = C2H_SEQ_88XX(buf); + *plen = C2H_PLEN_88XX(buf); + *payload = C2H_PAYLOAD_88XX(buf); + ret = _SUCCESS; + + return ret; +} +#endif /* CONFIG_FW_C2H_REG */ + +#ifdef CONFIG_FW_C2H_PKT +bool rtw_hal_c2h_pkt_hdr_parse(_adapter *adapter, u8 *buf, u16 len, u8 *id, u8 *seq, u8 *plen, u8 **payload) +{ + HAL_DATA_TYPE *HalData = GET_HAL_DATA(adapter); + HAL_VERSION *hal_ver = &HalData->version_id; + bool ret = _FAIL; + + if (!buf || len > 256 || len < 3) + goto exit; + + *id = C2H_ID_88XX(buf); + *seq = C2H_SEQ_88XX(buf); + *plen = len - 2; + *payload = C2H_PAYLOAD_88XX(buf); + ret = _SUCCESS; + +exit: + return ret; +} +#endif /* CONFIG_FW_C2H_PKT */ + +s32 c2h_handler(_adapter *adapter, u8 id, u8 seq, u8 plen, u8 *payload) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + struct PHY_DM_STRUCT *odm = &hal_data->odmpriv; + u8 sub_id = 0; + s32 ret = _SUCCESS; + + switch (id) { + case C2H_DBG: + RTW_INFO_DUMP("C2H_DBG: ", payload, plen); + break; + case C2H_FW_SCAN_COMPLETE: + RTW_INFO("[C2H], FW Scan Complete\n"); + break; +#ifdef CONFIG_BT_COEXIST + case C2H_BT_INFO: + rtw_btcoex_BtInfoNotify(adapter, plen, payload); + break; + case C2H_BT_MP_INFO: + rtw_btcoex_BtMpRptNotify(adapter, plen, payload); + break; + case C2H_MAILBOX_STATUS: + RTW_INFO_DUMP("C2H_MAILBOX_STATUS: ", payload, plen); + break; +#endif /* CONFIG_BT_COEXIST */ + case C2H_IQK_FINISH: + c2h_iqk_offload(adapter, payload, plen); + break; +#if defined(CONFIG_TDLS) && defined(CONFIG_TDLS_CH_SW) + case C2H_FW_CHNL_SWITCH_COMPLETE: + rtw_tdls_chsw_oper_done(adapter); + break; + case C2H_BCN_EARLY_RPT: + rtw_tdls_ch_sw_back_to_base_chnl(adapter); + break; +#endif +#ifdef CONFIG_MCC_MODE + case C2H_MCC: + rtw_hal_mcc_c2h_handler(adapter, plen, payload); + break; +#endif + +#ifdef CONFIG_RTW_MAC_HIDDEN_RPT + case C2H_MAC_HIDDEN_RPT: + c2h_mac_hidden_rpt_hdl(adapter, payload, plen); + break; + case C2H_MAC_HIDDEN_RPT_2: + c2h_mac_hidden_rpt_2_hdl(adapter, payload, plen); + break; +#endif + + case C2H_DEFEATURE_DBG: + c2h_defeature_dbg_hdl(adapter, payload, plen); + break; + +#ifdef CONFIG_RTW_CUSTOMER_STR + case C2H_CUSTOMER_STR_RPT: + c2h_customer_str_rpt_hdl(adapter, payload, plen); + break; + case C2H_CUSTOMER_STR_RPT_2: + c2h_customer_str_rpt_2_hdl(adapter, payload, plen); + break; +#endif + + case C2H_EXTEND: + sub_id = payload[0]; + __attribute__ ((__fallthrough__));/* FALL THRU */ + default: + if (phydm_c2H_content_parsing(odm, id, plen, payload) != true) + ret = _FAIL; + break; + } + +exit: + if (ret != _SUCCESS) { + if (id == C2H_EXTEND) + RTW_WARN("%s: unknown C2H(0x%02x, 0x%02x)\n", __func__, id, sub_id); + else + RTW_WARN("%s: unknown C2H(0x%02x)\n", __func__, id); + } + + return ret; +} + +#ifndef RTW_HALMAC +s32 rtw_hal_c2h_handler(_adapter *adapter, u8 id, u8 seq, u8 plen, u8 *payload) +{ + s32 ret = _FAIL; + + ret = adapter->hal_func.c2h_handler(adapter, id, seq, plen, payload); + if (ret != _SUCCESS) + ret = c2h_handler(adapter, id, seq, plen, payload); + + return ret; +} + +s32 rtw_hal_c2h_id_handle_directly(_adapter *adapter, u8 id, u8 seq, u8 plen, u8 *payload) +{ + switch (id) { + case C2H_CCX_TX_RPT: + case C2H_BT_MP_INFO: + case C2H_FW_CHNL_SWITCH_COMPLETE: + case C2H_IQK_FINISH: + case C2H_MCC: + case C2H_BCN_EARLY_RPT: + case C2H_AP_REQ_TXRPT: + case C2H_SPC_STAT: + return true; + default: + return false; + } +} +#endif /* !RTW_HALMAC */ + +s32 rtw_hal_is_disable_sw_channel_plan(PADAPTER padapter) +{ + return GET_HAL_DATA(padapter)->bDisableSWChannelPlan; +} + +s32 rtw_hal_macid_sleep(PADAPTER padapter, u8 macid) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj); + u8 support; + + support = false; + rtw_hal_get_def_var(padapter, HAL_DEF_MACID_SLEEP, &support); + if (false == support) + return _FAIL; + + if (macid >= macid_ctl->num) { + RTW_ERR(FUNC_ADPT_FMT": Invalid macid(%u)\n", + FUNC_ADPT_ARG(padapter), macid); + return _FAIL; + } + + rtw_hal_set_hwreg(padapter, HW_VAR_MACID_SLEEP, &macid); + + return _SUCCESS; +} + +s32 rtw_hal_macid_wakeup(PADAPTER padapter, u8 macid) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj); + u8 support; + + support = false; + rtw_hal_get_def_var(padapter, HAL_DEF_MACID_SLEEP, &support); + if (false == support) + return _FAIL; + + if (macid >= macid_ctl->num) { + RTW_ERR(FUNC_ADPT_FMT": Invalid macid(%u)\n", + FUNC_ADPT_ARG(padapter), macid); + return _FAIL; + } + + rtw_hal_set_hwreg(padapter, HW_VAR_MACID_WAKEUP, &macid); + + return _SUCCESS; +} + +s32 rtw_hal_fill_h2c_cmd(PADAPTER padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer) +{ + _adapter *pri_adapter = GET_PRIMARY_ADAPTER(padapter); + + if (pri_adapter->bFWReady == true) + return padapter->hal_func.fill_h2c_cmd(padapter, ElementID, CmdLen, pCmdBuffer); + else if (padapter->registrypriv.mp_mode == 0) + RTW_PRINT(FUNC_ADPT_FMT" FW doesn't exit when no MP mode, by pass H2C id:0x%02x\n" + , FUNC_ADPT_ARG(padapter), ElementID); + return _FAIL; +} + +void rtw_hal_fill_fake_txdesc(_adapter *padapter, u8 *pDesc, u32 BufferLen, + u8 IsPsPoll, u8 IsBTQosNull, u8 bDataFrame) +{ + padapter->hal_func.fill_fake_txdesc(padapter, pDesc, BufferLen, IsPsPoll, IsBTQosNull, bDataFrame); + +} +u8 rtw_hal_get_txbuff_rsvd_page_num(_adapter *adapter, bool wowlan) +{ + return adapter->hal_func.hal_get_tx_buff_rsvd_page_num(adapter, wowlan); +} + +#ifdef CONFIG_GPIO_API +void rtw_hal_update_hisr_hsisr_ind(_adapter *padapter, u32 flag) +{ + if (padapter->hal_func.update_hisr_hsisr_ind) + padapter->hal_func.update_hisr_hsisr_ind(padapter, flag); +} + +int rtw_hal_gpio_func_check(_adapter *padapter, u8 gpio_num) +{ + int ret = _SUCCESS; + + if (padapter->hal_func.hal_gpio_func_check) + ret = padapter->hal_func.hal_gpio_func_check(padapter, gpio_num); + + return ret; +} + +void rtw_hal_gpio_multi_func_reset(_adapter *padapter, u8 gpio_num) +{ + if (padapter->hal_func.hal_gpio_multi_func_reset) + padapter->hal_func.hal_gpio_multi_func_reset(padapter, gpio_num); +} +#endif + +void rtw_hal_fw_correct_bcn(_adapter *padapter) +{ + if (padapter->hal_func.fw_correct_bcn) + padapter->hal_func.fw_correct_bcn(padapter); +} + +void rtw_hal_set_tx_power_index(PADAPTER padapter, u32 powerindex, u8 rfpath, u8 rate) +{ + return padapter->hal_func.set_tx_power_index_handler(padapter, powerindex, rfpath, rate); +} + +u8 rtw_hal_get_tx_power_index(PADAPTER padapter, u8 rfpath, u8 rate, u8 bandwidth, u8 channel, struct txpwr_idx_comp *tic) +{ + return padapter->hal_func.get_tx_power_index_handler(padapter, rfpath, rate, bandwidth, channel, tic); +} + +#ifdef RTW_HALMAC +/* + * Description: + * Initialize MAC registers + * + * Return: + * true success + * false fail + */ +u8 rtw_hal_init_mac_register(PADAPTER adapter) +{ + return adapter->hal_func.init_mac_register(adapter); +} + +/* + * Description: + * Initialize PHY(BB/RF) related functions + * + * Return: + * true success + * false fail + */ +u8 rtw_hal_init_phy(PADAPTER adapter) +{ + return adapter->hal_func.init_phy(adapter); +} +#endif /* RTW_HALMAC */ + +#ifdef CONFIG_RFKILL_POLL +bool rtw_hal_rfkill_poll(_adapter *adapter, u8 *valid) +{ + bool ret; + + if (adapter->hal_func.hal_radio_onoff_check) + ret = adapter->hal_func.hal_radio_onoff_check(adapter, valid); + else { + *valid = 0; + ret = false; + } + return ret; +} +#endif + +#define rtw_hal_error_msg(ops_fun) \ + RTW_PRINT("### %s - Error : Please hook hal_func.%s ###\n", __func__, ops_fun) + +u8 rtw_hal_ops_check(_adapter *padapter) +{ + u8 ret = _SUCCESS; + /*** initialize section ***/ + if (NULL == padapter->hal_func.read_chip_version) { + rtw_hal_error_msg("read_chip_version"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.init_default_value) { + rtw_hal_error_msg("init_default_value"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.intf_chip_configure) { + rtw_hal_error_msg("intf_chip_configure"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.read_adapter_info) { + rtw_hal_error_msg("read_adapter_info"); + ret = _FAIL; + } + + if (NULL == padapter->hal_func.hal_power_on) { + rtw_hal_error_msg("hal_power_on"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.hal_power_off) { + rtw_hal_error_msg("hal_power_off"); + ret = _FAIL; + } + + if (NULL == padapter->hal_func.hal_init) { + rtw_hal_error_msg("hal_init"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.hal_deinit) { + rtw_hal_error_msg("hal_deinit"); + ret = _FAIL; + } + + /*** xmit section ***/ + if (NULL == padapter->hal_func.init_xmit_priv) { + rtw_hal_error_msg("init_xmit_priv"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.free_xmit_priv) { + rtw_hal_error_msg("free_xmit_priv"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.hal_xmit) { + rtw_hal_error_msg("hal_xmit"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.mgnt_xmit) { + rtw_hal_error_msg("mgnt_xmit"); + ret = _FAIL; + } +#ifdef CONFIG_XMIT_THREAD_MODE + if (NULL == padapter->hal_func.xmit_thread_handler) { + rtw_hal_error_msg("xmit_thread_handler"); + ret = _FAIL; + } +#endif + if (NULL == padapter->hal_func.hal_xmitframe_enqueue) { + rtw_hal_error_msg("hal_xmitframe_enqueue"); + ret = _FAIL; + } + + /*** recv section ***/ + if (NULL == padapter->hal_func.init_recv_priv) { + rtw_hal_error_msg("init_recv_priv"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.free_recv_priv) { + rtw_hal_error_msg("free_recv_priv"); + ret = _FAIL; + } +#ifdef CONFIG_RECV_THREAD_MODE + if (NULL == padapter->hal_func.recv_hdl) { + rtw_hal_error_msg("recv_hdl"); + ret = _FAIL; + } +#endif + if (NULL == padapter->hal_func.inirp_init) { + rtw_hal_error_msg("inirp_init"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.inirp_deinit) { + rtw_hal_error_msg("inirp_deinit"); + ret = _FAIL; + } + + + /*** interrupt hdl section ***/ +#if (defined(CONFIG_SUPPORT_USB_INT)) + if (NULL == padapter->hal_func.interrupt_handler) { + rtw_hal_error_msg("interrupt_handler"); + ret = _FAIL; + } +#endif /*#if ((CONFIG_SUPPORT_USB_INT))*/ + + /*** DM section ***/ + if (NULL == padapter->hal_func.dm_init) { + rtw_hal_error_msg("dm_init"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.dm_deinit) { + rtw_hal_error_msg("dm_deinit"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.hal_dm_watchdog) { + rtw_hal_error_msg("hal_dm_watchdog"); + ret = _FAIL; + } +#ifdef CONFIG_LPS_LCLK_WD_TIMER + if (NULL == padapter->hal_func.hal_dm_watchdog_in_lps) { + rtw_hal_error_msg("hal_dm_watchdog_in_lps"); + ret = _FAIL; + } +#endif + + /*** xxx section ***/ + if (NULL == padapter->hal_func.set_chnl_bw_handler) { + rtw_hal_error_msg("set_chnl_bw_handler"); + ret = _FAIL; + } + + if (NULL == padapter->hal_func.set_hw_reg_handler) { + rtw_hal_error_msg("set_hw_reg_handler"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.GetHwRegHandler) { + rtw_hal_error_msg("GetHwRegHandler"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.get_hal_def_var_handler) { + rtw_hal_error_msg("get_hal_def_var_handler"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.SetHalDefVarHandler) { + rtw_hal_error_msg("SetHalDefVarHandler"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.GetHalODMVarHandler) { + rtw_hal_error_msg("GetHalODMVarHandler"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.SetHalODMVarHandler) { + rtw_hal_error_msg("SetHalODMVarHandler"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.update_ra_mask_handler) { + rtw_hal_error_msg("update_ra_mask_handler"); + ret = _FAIL; + } + + if (NULL == padapter->hal_func.SetBeaconRelatedRegistersHandler) { + rtw_hal_error_msg("SetBeaconRelatedRegistersHandler"); + ret = _FAIL; + } + + if (NULL == padapter->hal_func.fill_h2c_cmd) { + rtw_hal_error_msg("fill_h2c_cmd"); + ret = _FAIL; + } + +#ifdef RTW_HALMAC + if (NULL == padapter->hal_func.hal_mac_c2h_handler) { + rtw_hal_error_msg("hal_mac_c2h_handler"); + ret = _FAIL; + } +#endif + +#if defined(CONFIG_LPS) || defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) + if (NULL == padapter->hal_func.fill_fake_txdesc) { + rtw_hal_error_msg("fill_fake_txdesc"); + ret = _FAIL; + } +#endif + if (NULL == padapter->hal_func.hal_get_tx_buff_rsvd_page_num) { + rtw_hal_error_msg("hal_get_tx_buff_rsvd_page_num"); + ret = _FAIL; + } + + if (NULL == padapter->hal_func.fw_dl) { + rtw_hal_error_msg("fw_dl"); + ret = _FAIL; + } + + if (!padapter->hal_func.get_tx_power_index_handler) { + rtw_hal_error_msg("get_tx_power_index_handler"); + ret = _FAIL; + } + + /*** SReset section ***/ +#ifdef DBG_CONFIG_ERROR_DETECT + if (NULL == padapter->hal_func.sreset_init_value) { + rtw_hal_error_msg("sreset_init_value"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.sreset_reset_value) { + rtw_hal_error_msg("sreset_reset_value"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.silentreset) { + rtw_hal_error_msg("silentreset"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.sreset_xmit_status_check) { + rtw_hal_error_msg("sreset_xmit_status_check"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.sreset_linked_status_check) { + rtw_hal_error_msg("sreset_linked_status_check"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.sreset_get_wifi_status) { + rtw_hal_error_msg("sreset_get_wifi_status"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.sreset_inprogress) { + rtw_hal_error_msg("sreset_inprogress"); + ret = _FAIL; + } +#endif /* #ifdef DBG_CONFIG_ERROR_DETECT */ + +#ifdef RTW_HALMAC + if (NULL == padapter->hal_func.init_mac_register) { + rtw_hal_error_msg("init_mac_register"); + ret = _FAIL; + } + if (NULL == padapter->hal_func.init_phy) { + rtw_hal_error_msg("init_phy"); + ret = _FAIL; + } +#endif /* RTW_HALMAC */ + +#ifdef CONFIG_RFKILL_POLL + if (padapter->hal_func.hal_radio_onoff_check == NULL) { + rtw_hal_error_msg("hal_radio_onoff_check"); + ret = _FAIL; + } +#endif + return ret; +} diff --git a/drivers/staging/rtl8188eu/hal/hal_mcc.c b/drivers/staging/rtl8188eu/hal/hal_mcc.c new file mode 100644 index 000000000000..a564cc6509e7 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal_mcc.c @@ -0,0 +1,1862 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#ifdef CONFIG_MCC_MODE +#define _HAL_MCC_C_ + +#include /* PADAPTER */ +#include /* mcc structure */ +#include /* HAL_DATA */ +#include /* power control */ + +#define MCC_DURATION_IDX 0 +#define MCC_TSF_SYNC_OFFSET_IDX 1 +#define MCC_START_TIME_OFFSET_IDX 2 +#define MCC_INTERVAL_IDX 3 +#define MCC_GUARD_OFFSET0_IDX 4 +#define MCC_GUARD_OFFSET1_IDX 5 +#define TU 1024 /* 1 TU equals 1024 microseconds */ +/* port 1 druration, TSF sync offset, start time offset, interval (unit:TU (1024 microseconds))*/ +u8 mcc_switch_channel_policy_table[][6]={ + {35, 50, 30, 100, 0, 0}, + {19, 50, 40, 100, 2, 2}, + {25, 50, 30, 100, 5, 5}, +}; + +const int mcc_max_policy_num = sizeof(mcc_switch_channel_policy_table) /sizeof(u8) /6; + +static void dump_iqk_val_table(PADAPTER padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct hal_iqk_reg_backup *iqk_reg_backup = pHalData->iqk_reg_backup; + u8 total_rf_path = pHalData->NumTotalRFPath; + u8 rf_path_idx = 0; + u8 backup_chan_idx = 0; + u8 backup_reg_idx = 0; + + RTW_INFO("=============dump IQK backup table================\n"); + for (backup_chan_idx = 0; backup_chan_idx < MAX_IQK_INFO_BACKUP_CHNL_NUM; backup_chan_idx++) { + for (rf_path_idx = 0; rf_path_idx < total_rf_path; rf_path_idx++) { + for(backup_reg_idx = 0; backup_reg_idx < MAX_IQK_INFO_BACKUP_REG_NUM; backup_reg_idx++) { + RTW_INFO("ch:%d. bw:%d. rf path:%d. reg[%d] = 0x%02x \n" + , iqk_reg_backup[backup_chan_idx].central_chnl + , iqk_reg_backup[backup_chan_idx].bw_mode + , rf_path_idx + , backup_reg_idx + , iqk_reg_backup[backup_chan_idx].reg_backup[rf_path_idx][backup_reg_idx] + ); + } + } + } + RTW_INFO("=============================================\n"); +} + +static void rtw_hal_mcc_build_p2p_noa_attr(PADAPTER padapter, u8 *ie, u32 *ie_len) +{ + struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv); + u8 p2p_noa_attr_ie[MAX_P2P_IE_LEN] = {0x00}; + u32 p2p_noa_attr_len = 0; + u8 noa_desc_num = 1; + u8 opp_ps = 0; /* Disable OppPS */ + u8 noa_count = 255; + u32 noa_duration = 0x20; + u32 noa_interval = 0x64; + u8 noa_index = 0; + u8 mcc_policy_idx = 0; + + mcc_policy_idx = pmccobjpriv->policy_index; + noa_duration = mcc_switch_channel_policy_table[mcc_policy_idx][MCC_DURATION_IDX]; + noa_interval = mcc_switch_channel_policy_table[mcc_policy_idx][MCC_INTERVAL_IDX]; + + /* P2P OUI(4 bytes) */ + memcpy(p2p_noa_attr_ie, P2P_OUI, 4); + p2p_noa_attr_len = p2p_noa_attr_len + 4; + + /* attrute ID(1 byte) */ + p2p_noa_attr_ie[p2p_noa_attr_len] = P2P_ATTR_NOA; + p2p_noa_attr_len = p2p_noa_attr_len + 1; + + /* attrute length(2 bytes) length = noa_desc_num*13 + 2 */ + RTW_PUT_LE16(p2p_noa_attr_ie + p2p_noa_attr_len, (noa_desc_num*13 + 2)); + p2p_noa_attr_len = p2p_noa_attr_len + 2; + + /* Index (1 byte) */ + p2p_noa_attr_ie[p2p_noa_attr_len] = noa_index; + p2p_noa_attr_len = p2p_noa_attr_len + 1; + + /* CTWindow and OppPS Parameters (1 byte) */ + p2p_noa_attr_ie[p2p_noa_attr_len] = opp_ps; + p2p_noa_attr_len = p2p_noa_attr_len+ 1; + + /* NoA Count (1 byte) */ + p2p_noa_attr_ie[p2p_noa_attr_len] = noa_count; + p2p_noa_attr_len = p2p_noa_attr_len + 1; + + /* NoA Duration (4 bytes) unit: microseconds */ + RTW_PUT_LE32(p2p_noa_attr_ie + p2p_noa_attr_len, (noa_duration * TU)); + p2p_noa_attr_len = p2p_noa_attr_len + 4; + + /* NoA Interval (4 bytes) unit: microseconds */ + RTW_PUT_LE32(p2p_noa_attr_ie + p2p_noa_attr_len, (noa_interval * TU)); + p2p_noa_attr_len = p2p_noa_attr_len + 4; + + /* NoA Start Time (4 bytes) unit: microseconds */ + RTW_PUT_LE32(p2p_noa_attr_ie + p2p_noa_attr_len, pmccadapriv->noa_start_time); + if (0) + RTW_INFO("indxe:%d, start_time=0x%02x:0x%02x:0x%02x:0x%02x\n" + , noa_index + , p2p_noa_attr_ie[p2p_noa_attr_len] + , p2p_noa_attr_ie[p2p_noa_attr_len + 1] + , p2p_noa_attr_ie[p2p_noa_attr_len + 2] + , p2p_noa_attr_ie[p2p_noa_attr_len + 3]); + + p2p_noa_attr_len = p2p_noa_attr_len + 4; + rtw_set_ie(ie, _VENDOR_SPECIFIC_IE_, p2p_noa_attr_len, (u8 *)p2p_noa_attr_ie, ie_len); +} + + +/** + * rtw_hal_mcc_update_go_p2p_ie - update go p2p ie(add NoA attribute) + * @padapter: the adapter to be update go p2p ie + */ +static void rtw_hal_mcc_update_go_p2p_ie(PADAPTER padapter) +{ + struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv; + u8 *pos = NULL; + + + /* no noa attribute, build it */ + if (pmccadapriv->p2p_go_noa_ie_len == 0) + rtw_hal_mcc_build_p2p_noa_attr(padapter, pmccadapriv->p2p_go_noa_ie, &pmccadapriv->p2p_go_noa_ie_len); + else { + /* has noa attribut, modify it */ + /* update index */ + pos = pmccadapriv->p2p_go_noa_ie + pmccadapriv->p2p_go_noa_ie_len - 15; + /* 0~255 */ + (*pos) = ((*pos) + 1) % 256; + if (1) + RTW_INFO("indxe:%d\n", (*pos)); + + /* update start time */ + pos = pmccadapriv->p2p_go_noa_ie + pmccadapriv->p2p_go_noa_ie_len - 4; + RTW_PUT_LE32(pos, pmccadapriv->noa_start_time); + if (0) + RTW_INFO("start_time=0x%02x:0x%02x:0x%02x:0x%02x\n" + , ((u8*)(pos))[0] + , ((u8*)(pos))[1] + , ((u8*)(pos))[2] + , ((u8*)(pos))[3]); + + } + + if (0) { + u8 i = 0; + RTW_INFO("p2p_go_noa_ie_len:%d\n", pmccadapriv->p2p_go_noa_ie_len); + + for (i = 0;i < pmccadapriv->p2p_go_noa_ie_len; i++) { + if ((i+1)%8 != 0) + printk("0x%02x ", pmccadapriv->p2p_go_noa_ie[i]); + else + printk("0x%02x\n", pmccadapriv->p2p_go_noa_ie[i]); + } + printk("\n"); + } + update_beacon(padapter, _VENDOR_SPECIFIC_IE_, P2P_OUI, true); +} + +/** + * rtw_hal_mcc_remove_go_p2p_ie - remove go p2p ie(add NoA attribute) + * @padapter: the adapter to be update go p2p ie + */ +static void rtw_hal_mcc_remove_go_p2p_ie(PADAPTER padapter) +{ + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv; + + /* chech has noa ie or not */ + if (pmccadapriv->p2p_go_noa_ie_len == 0) + return; + + pmccadapriv->p2p_go_noa_ie_len = 0; + update_beacon(padapter, _VENDOR_SPECIFIC_IE_, P2P_OUI, true); +} + +/* restore IQK value for all interface */ +void rtw_hal_mcc_restore_iqk_val(PADAPTER padapter) +{ + u8 take_care_iqk = false; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + _adapter *iface = NULL; + u8 i = 0; + + rtw_hal_get_hwreg(padapter, HW_VAR_CH_SW_NEED_TO_TAKE_CARE_IQK_INFO, &take_care_iqk); + if (take_care_iqk == true && MCC_EN(padapter)) { + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (iface == NULL) + continue; + + rtw_hal_ch_sw_iqk_info_restore(iface, CH_SW_USE_CASE_MCC); + } + } + + if (0) + dump_iqk_val_table(padapter); +} + +u8 rtw_hal_check_mcc_status(PADAPTER padapter, u8 mcc_status) +{ + struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv); + + if (pmccobjpriv->mcc_status & (mcc_status)) + return true; + else + return false; +} + +void rtw_hal_set_mcc_status(PADAPTER padapter, u8 mcc_status) +{ + struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv); + + pmccobjpriv->mcc_status |= (mcc_status); +} + +void rtw_hal_clear_mcc_status(PADAPTER padapter, u8 mcc_status) +{ + struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv); + + pmccobjpriv->mcc_status &= (~mcc_status); +} + +void rtw_hal_mcc_update_switch_channel_policy_table(PADAPTER padapter) +{ + struct registry_priv *registry_par = &padapter->registrypriv; + u8 idx = 0; + + if (registry_par->rtw_mcc_policy_table_idx < 0) + return; + + if (registry_par->rtw_mcc_policy_table_idx >= mcc_max_policy_num) { + RTW_INFO("[MCC] mcc_policy_table_idx error, do not update policy table\n"); + return; + } + + idx = registry_par->rtw_mcc_policy_table_idx; + + if (registry_par->rtw_mcc_duration > 0) + mcc_switch_channel_policy_table[idx][MCC_DURATION_IDX] = registry_par->rtw_mcc_duration; + + if (registry_par->rtw_mcc_tsf_sync_offset > 0) + mcc_switch_channel_policy_table[idx][MCC_TSF_SYNC_OFFSET_IDX] = registry_par->rtw_mcc_tsf_sync_offset; + + if (registry_par->rtw_mcc_start_time_offset > 0) + mcc_switch_channel_policy_table[idx][MCC_START_TIME_OFFSET_IDX] = registry_par->rtw_mcc_start_time_offset; + + if (registry_par->rtw_mcc_interval > 0) + mcc_switch_channel_policy_table[idx][MCC_INTERVAL_IDX] = registry_par->rtw_mcc_interval; + + if (registry_par->rtw_mcc_guard_offset0 >= 0) + mcc_switch_channel_policy_table[idx][MCC_GUARD_OFFSET0_IDX] = registry_par->rtw_mcc_guard_offset0; + + if (registry_par->rtw_mcc_guard_offset1 >= 0) + mcc_switch_channel_policy_table[idx][MCC_GUARD_OFFSET1_IDX] = registry_par->rtw_mcc_guard_offset1; + +} + +static void rtw_hal_config_mcc_switch_channel_setting(PADAPTER padapter) +{ + struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv; + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv); + struct registry_priv *registry_par = &padapter->registrypriv; + u8 interval = pmlmepriv->cur_network.network.Configuration.BeaconPeriod; + u8 i = 0; + s8 mcc_policy_idx = 0; + + rtw_hal_mcc_update_switch_channel_policy_table(padapter); + mcc_policy_idx = registry_par->rtw_mcc_policy_table_idx; + + if (mcc_policy_idx < 0 || mcc_policy_idx >= mcc_max_policy_num) { + pmccobjpriv->policy_index = 0; + RTW_INFO("[MCC] can't find table(%d,%d,%d), use default policy(%d)\n" + , pmccobjpriv->duration, interval, mcc_policy_idx, pmccobjpriv->policy_index); + } else + pmccobjpriv->policy_index = mcc_policy_idx; + + RTW_INFO("[MCC] policy(%d): %d,%d,%d,%d,%d,%d\n" + , pmccobjpriv->policy_index + , mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_DURATION_IDX] + , mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_TSF_SYNC_OFFSET_IDX] + , mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_START_TIME_OFFSET_IDX] + , mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_INTERVAL_IDX] + , mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_GUARD_OFFSET0_IDX] + , mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_GUARD_OFFSET1_IDX]); + +} + +static void rtw_hal_config_mcc_role_setting(PADAPTER padapter) +{ + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + struct mcc_obj_priv *pmccobjpriv = &(pdvobjpriv->mcc_objpriv); + struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct wlan_network *cur_network = &(pmlmepriv->cur_network); + struct sta_priv *pstapriv = &padapter->stapriv; + struct sta_info *psta = NULL; + struct registry_priv *preg = &padapter->registrypriv; + u8 policy_index = 0; + u8 mcc_duration = 0; + u8 mcc_interval = 0; + + policy_index = pmccobjpriv->policy_index; + mcc_duration = mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_DURATION_IDX] + - mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_GUARD_OFFSET0_IDX] + - mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_GUARD_OFFSET1_IDX]; + mcc_interval = mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_INTERVAL_IDX]; + + /* GO/AP is 1nd order GC/STA is 2nd order */ + switch (pmccadapriv->role) { + case MCC_ROLE_STA: + case MCC_ROLE_GC: + pmccadapriv->order = 1; + pmccadapriv->mcc_duration = mcc_duration; + + switch (pmlmeext->cur_bwmode) { + case CHANNEL_WIDTH_20: + /* + * target tx byte(bytes) = target tx tp(Mbits/sec) * 1024 * 1024 / 8 * (duration(ms) / 1024) + * = target tx tp(Mbits/sec) * 128 * duration(ms) + * note: + * target tx tp(Mbits/sec) * 1024 * 1024 / 8 ==> Mbits to bytes + * duration(ms) / 1024 ==> msec to sec + */ + pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_sta_bw20_target_tx_tp * 128 * pmccadapriv->mcc_duration; + break; + case CHANNEL_WIDTH_40: + pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_sta_bw40_target_tx_tp * 128 * pmccadapriv->mcc_duration; + break; + case CHANNEL_WIDTH_80: + pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_sta_bw80_target_tx_tp * 128 * pmccadapriv->mcc_duration; + break; + case CHANNEL_WIDTH_160: + case CHANNEL_WIDTH_80_80: + RTW_INFO(FUNC_ADPT_FMT": not support bwmode = %d\n" + , FUNC_ADPT_ARG(padapter), pmlmeext->cur_bwmode); + break; + } + + /* assign used mac to avoid affecting RA */ + pmccadapriv->mgmt_queue_macid = MCC_ROLE_STA_GC_MGMT_QUEUE_MACID; + + psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress); + if (psta) { + /* combine AP/GO macid and mgmt queue macid to bitmap */ + pmccadapriv->mcc_macid_bitmap = BIT(psta->mac_id) | BIT(pmccadapriv->mgmt_queue_macid); + } else { + RTW_INFO(FUNC_ADPT_FMT":AP/GO station info is NULL\n", FUNC_ADPT_ARG(padapter)); + rtw_warn_on(1); + } + break; + case MCC_ROLE_AP: + case MCC_ROLE_GO: + pmccadapriv->order = 0; + /* total druation value equals interval */ + pmccadapriv->mcc_duration = mcc_interval - mcc_duration; + pmccadapriv->p2p_go_noa_ie_len = 0; /* not NoA attribute at init time */ + + switch (pmlmeext->cur_bwmode) { + case CHANNEL_WIDTH_20: + pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_ap_bw20_target_tx_tp * 128 * pmccadapriv->mcc_duration; + break; + case CHANNEL_WIDTH_40: + pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_ap_bw40_target_tx_tp * 128 * pmccadapriv->mcc_duration; + break; + case CHANNEL_WIDTH_80: + pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_ap_bw80_target_tx_tp * 128 * pmccadapriv->mcc_duration; + break; + case CHANNEL_WIDTH_160: + case CHANNEL_WIDTH_80_80: + RTW_INFO(FUNC_ADPT_FMT": not support bwmode = %d\n" + , FUNC_ADPT_ARG(padapter), pmlmeext->cur_bwmode); + break; + } + + + psta = rtw_get_bcmc_stainfo(padapter); + + if (psta != NULL) + pmccadapriv->mgmt_queue_macid = psta->mac_id; + else { + pmccadapriv->mgmt_queue_macid = MCC_ROLE_SOFTAP_GO_MGMT_QUEUE_MACID; + RTW_INFO(FUNC_ADPT_FMT":bcmc station is NULL, use macid %d\n" + , FUNC_ADPT_ARG(padapter), pmccadapriv->mgmt_queue_macid); + } + + /* combine client macid and mgmt queue macid to bitmap */ + pmccadapriv->mcc_macid_bitmap = (0xff << 8) | BIT(pmccadapriv->mgmt_queue_macid); + break; + default: + RTW_INFO("Unknown role\n"); + rtw_warn_on(1); + break; + } + + pmccobjpriv->iface[pmccadapriv->order] = padapter; + RTW_INFO(FUNC_ADPT_FMT": order:%d, role:%d, mcc duration:%d, target tx bytes:%d, mgmt queue macid:%d, bitmap:0x%02x\n" + , FUNC_ADPT_ARG(padapter), pmccadapriv->order, pmccadapriv->role, pmccadapriv->mcc_duration + , pmccadapriv->mcc_target_tx_bytes_to_port, pmccadapriv->mgmt_queue_macid, pmccadapriv->mcc_macid_bitmap); +} + +static void rtw_hal_clear_mcc_macid(PADAPTER padapter) +{ + u16 media_status_rpt; + struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv; + + switch (pmccadapriv->role) { + case MCC_ROLE_STA: + case MCC_ROLE_GC: + break; + case MCC_ROLE_AP: + case MCC_ROLE_GO: + /* nothing to do */ + break; + default: + RTW_INFO("Unknown role\n"); + rtw_warn_on(1); + break; + } +} +static u8 rtw_hal_decide_mcc_role(PADAPTER padapter) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + _adapter *iface = NULL; + struct mcc_adapter_priv *pmccadapriv = NULL; + struct wifidirect_info *pwdinfo = NULL; + struct mlme_priv *pmlmepriv = NULL; + u8 ret = _SUCCESS, i = 0; + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (iface == NULL) + continue; + + pmccadapriv = &iface->mcc_adapterpriv; + + if (MLME_IS_GO(iface)) + pmccadapriv->role = MCC_ROLE_GO; + else if (MLME_IS_AP(iface)) + pmccadapriv->role = MCC_ROLE_AP; + else if (MLME_IS_GC(iface)) + pmccadapriv->role = MCC_ROLE_GC; + else if (MLME_IS_STA(iface)) + pmccadapriv->role = MCC_ROLE_STA; + else { + pwdinfo = &iface->wdinfo; + pmlmepriv = &iface->mlmepriv; + + RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(iface)); + RTW_INFO("Unknown:P2P state:%d, mlme state:0x%2x, mlmext info state:0x%02x\n", + pwdinfo->role, pmlmepriv->fw_state, iface->mlmeextpriv.mlmext_info.state); + rtw_warn_on(1); + ret = _FAIL; + goto exit; + } + + if (ret == _SUCCESS) + rtw_hal_config_mcc_role_setting(iface); + } + +exit: + return ret; +} + +static void rtw_hal_init_mcc_parameter(PADAPTER padapter) +{ +} + +static void rtw_hal_construct_CTS(PADAPTER padapter, u8 *pframe, u32 *pLength) +{ + u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + /* frame type, length = 1*/ + set_frame_sub_type(pframe, WIFI_RTS); + + /* frame control flag, length = 1 */ + *(pframe + 1) = 0; + + /* frame duration, length = 2 */ + *(pframe + 2) = 0x00; + *(pframe + 3) = 0x78; + + /* frame recvaddr, length = 6 */ + memcpy((pframe + 4), broadcast_addr, ETH_ALEN); + memcpy((pframe + 4 + ETH_ALEN), adapter_mac_addr(padapter), ETH_ALEN); + memcpy((pframe + 4 + ETH_ALEN*2), adapter_mac_addr(padapter), ETH_ALEN); + *pLength = 22; +} + +u8 rtw_hal_dl_mcc_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 *index, + u8 tx_desc, u32 page_size, u8 *page_num, u32 *total_pkt_len, + RSVDPAGE_LOC *rsvd_page_loc) +{ + u32 len = 0; + _adapter *iface = NULL; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv); + struct mlme_ext_info *pmlmeinfo = NULL; + struct mlme_ext_priv *pmlmeext = NULL; + u8 ret = _SUCCESS, i = 0, order = 0, CurtPktPageNum = 0; + u8 bssid[ETH_ALEN] = {0}; + + /* check proccess mcc start setting */ + if (!rtw_hal_check_mcc_status(adapter, MCC_STATUS_PROCESS_MCC_START_SETTING)) { + ret = _FAIL; + goto exit; + } + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (iface == NULL) + continue; + + order = iface->mcc_adapterpriv.order; + dvobj->mcc_objpriv.mcc_loc_rsvd_paga[order] = *page_num; + + switch (iface->mcc_adapterpriv.role) { + case MCC_ROLE_STA: + case MCC_ROLE_GC: + /* Build NULL DATA */ + RTW_INFO("LocNull(order:%d): %d\n" + , order, dvobj->mcc_objpriv.mcc_loc_rsvd_paga[order]); + len = 0; + pmlmeext = &iface->mlmeextpriv; + pmlmeinfo = &pmlmeext->mlmext_info; + + memcpy(bssid, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); + rtw_hal_construct_NullFunctionData(iface + , &pframe[*index], &len, bssid, false, 0, 0, false); + rtw_hal_fill_fake_txdesc(iface, &pframe[*index-tx_desc], + len, false, false, false); + + CurtPktPageNum = (u8)PageNum(tx_desc + len, page_size); + *page_num += CurtPktPageNum; + *index += (CurtPktPageNum * page_size); + *total_pkt_len = *index + len; + break; + case MCC_ROLE_AP: + /* Bulid CTS */ + RTW_INFO("LocCTS(order:%d): %d\n" + , order, dvobj->mcc_objpriv.mcc_loc_rsvd_paga[order]); + + len = 0; + rtw_hal_construct_CTS(iface, &pframe[*index], &len); + rtw_hal_fill_fake_txdesc(iface, &pframe[*index-tx_desc], + len, false, false, false); + + CurtPktPageNum = (u8)PageNum(tx_desc + len, page_size); + *page_num += CurtPktPageNum; + *index += (CurtPktPageNum * page_size); + *total_pkt_len = *index + len; + break; + case MCC_ROLE_GO: + /* To DO */ + break; + } + } +exit: + return ret; +} + +/* +* 1. Download MCC rsvd page +* 2. Re-Download beacon after download rsvd page +*/ +static void rtw_hal_set_fw_mcc_rsvd_page(PADAPTER padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + PADAPTER port0_iface = dvobj_get_port0_adapter(dvobj); + PADAPTER iface = NULL; + struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv); + u8 mstatus = RT_MEDIA_CONNECT, i = 0; + + RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter)); + + rtw_hal_set_hwreg(port0_iface, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus)); + + /* Re-Download beacon */ + for (i = 0; i < dvobj->iface_nums; i++) { + iface = pmccobjpriv->iface[i]; + pmccadapriv = &iface->mcc_adapterpriv; + if (pmccadapriv->role == MCC_ROLE_AP + || pmccadapriv->role == MCC_ROLE_GO) + tx_beacon_hdl(iface, NULL); + } +} + +static void rtw_hal_set_mcc_rsvdpage_cmd(_adapter *padapter) +{ + u8 cmd[H2C_MCC_LOCATION_LEN] = {0}, i = 0, order = 0; + _adapter *iface = NULL; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv); + + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (iface == NULL) + continue; + + order = iface->mcc_adapterpriv.order; + if (order >= H2C_MCC_LOCATION_LEN) { + RTW_INFO(FUNC_ADPT_FMT" only support 3 interface at most(%d)\n" + , FUNC_ADPT_ARG(padapter), order); + continue; + } + + SET_H2CCMD_MCC_RSVDPAGE_LOC((cmd + order), (pmccobjpriv->mcc_loc_rsvd_paga[order])); + } + +#ifdef CONFIG_MCC_MODE_DEBUG + RTW_INFO("=========================\n"); + RTW_INFO("MCC RSVD PAGE LOC:\n"); + for (i = 0; i < H2C_MCC_LOCATION_LEN; i++) + pr_dbg("0x%x ", cmd[i]); + pr_dbg("\n"); + RTW_INFO("=========================\n"); +#endif /* CONFIG_MCC_MODE_DEBUG */ + + rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_LOCATION, H2C_MCC_LOCATION_LEN, cmd); +} + +static void rtw_hal_set_mcc_noa_cmd(PADAPTER padapter) +{ + struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv; + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv); + u8 cmd[H2C_MCC_NOA_PARAM_LEN] = {0}; + u8 policy_idx = pmccobjpriv->policy_index; + u8 noa_fw_eable = 1; + u8 noa_tsf_sync_offset = mcc_switch_channel_policy_table[policy_idx][MCC_TSF_SYNC_OFFSET_IDX]; + u8 noa_start_time_offset = mcc_switch_channel_policy_table[policy_idx][MCC_START_TIME_OFFSET_IDX]; + u8 noa_interval = mcc_switch_channel_policy_table[policy_idx][MCC_INTERVAL_IDX]; + u8 guard_offset0 = mcc_switch_channel_policy_table[policy_idx][MCC_GUARD_OFFSET0_IDX]; + u8 guard_offset1 = mcc_switch_channel_policy_table[policy_idx][MCC_GUARD_OFFSET1_IDX]; + u8 swchannel_early_time = MCC_SWCH_FW_EARLY_TIME; + u8 i = 0; + + /* FW set NOA enable */ + SET_H2CCMD_MCC_NOA_FW_EN(cmd, noa_fw_eable); + /* TSF Sync offset */ + SET_H2CCMD_MCC_NOA_TSF_SYNC_OFFSET(cmd, noa_tsf_sync_offset); + /* NoA start time offset */ + SET_H2CCMD_MCC_NOA_START_TIME(cmd, (noa_start_time_offset + guard_offset0)); + /* NoA interval */ + SET_H2CCMD_MCC_NOA_INTERVAL(cmd, noa_interval); + /* Early time to inform driver by C2H before switch channel */ + SET_H2CCMD_MCC_EARLY_TIME(cmd, swchannel_early_time); + +#ifdef CONFIG_MCC_MODE_DEBUG + RTW_INFO("=========================\n"); + RTW_INFO("NoA:\n"); + for (i = 0; i < H2C_MCC_NOA_PARAM_LEN; i++) + pr_dbg("0x%x ", cmd[i]); + pr_dbg("\n"); + RTW_INFO("=========================\n"); +#endif /* CONFIG_MCC_MODE_DEBUG */ + + rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_NOA_PARAM, H2C_MCC_NOA_PARAM_LEN, cmd); +} + +static void rtw_hal_set_mcc_IQK_offload_cmd(PADAPTER padapter) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv); + struct mcc_adapter_priv *pmccadapriv = NULL; + _adapter *iface = NULL; + u8 cmd[H2C_MCC_IQK_PARAM_LEN] = {0}, bready = 0, i = 0, order = 0; + u16 TX_X = 0, TX_Y = 0, RX_X = 0, RX_Y = 0; + u8 total_rf_path = GET_HAL_DATA(padapter)->NumTotalRFPath; + u8 rf_path_idx = 0, last_order = MAX_MCC_NUM - 1, last_rf_path_index = total_rf_path - 1; + + /* by order, last order & last_rf_path_index must set ready bit = 1 */ + for (i = 0; i < dvobj->iface_nums; i++) { + iface = pmccobjpriv->iface[i]; + if (iface == NULL) + continue; + + pmccadapriv = &iface->mcc_adapterpriv; + order = pmccadapriv->order; + + for (rf_path_idx = 0; rf_path_idx < total_rf_path; rf_path_idx ++) { + + memset(cmd, 0, H2C_MCC_IQK_PARAM_LEN); + TX_X = pmccadapriv->mcc_iqk_arr[rf_path_idx].TX_X & 0x7ff;/* [10:0] */ + TX_Y = pmccadapriv->mcc_iqk_arr[rf_path_idx].TX_Y & 0x7ff;/* [10:0] */ + RX_X = pmccadapriv->mcc_iqk_arr[rf_path_idx].RX_X & 0x3ff;/* [9:0] */ + RX_Y = pmccadapriv->mcc_iqk_arr[rf_path_idx].RX_Y & 0x3ff;/* [9:0] */ + + /* ready or not */ + if (order == last_order && rf_path_idx == last_rf_path_index) + bready = 1; + else + bready = 0; + + SET_H2CCMD_MCC_IQK_READY(cmd, bready); + SET_H2CCMD_MCC_IQK_ORDER(cmd, order); + SET_H2CCMD_MCC_IQK_PATH(cmd, rf_path_idx); + + /* fill RX_X[7:0] to (cmd+1)[7:0] bitlen=8 */ + SET_H2CCMD_MCC_IQK_RX_L(cmd, (u8)(RX_X & 0xff)); + /* fill RX_X[9:8] to (cmd+2)[1:0] bitlen=2 */ + SET_H2CCMD_MCC_IQK_RX_M1(cmd, (u8)((RX_X >> 8) & 0x03)); + /* fill RX_Y[5:0] to (cmd+2)[7:2] bitlen=6 */ + SET_H2CCMD_MCC_IQK_RX_M2(cmd, (u8)(RX_Y & 0x3f)); + /* fill RX_Y[9:6] to (cmd+3)[3:0] bitlen=4 */ + SET_H2CCMD_MCC_IQK_RX_H(cmd, (u8)((RX_Y >> 6) & 0x0f)); + + + /* fill TX_X[7:0] to (cmd+4)[7:0] bitlen=8 */ + SET_H2CCMD_MCC_IQK_TX_L(cmd, (u8)(TX_X & 0xff)); + /* fill TX_X[10:8] to (cmd+5)[2:0] bitlen=3 */ + SET_H2CCMD_MCC_IQK_TX_M1(cmd, (u8)((TX_X >> 8) & 0x07)); + /* fill TX_Y[4:0] to (cmd+5)[7:3] bitlen=5 */ + SET_H2CCMD_MCC_IQK_TX_M2(cmd, (u8)(TX_Y & 0x1f)); + /* fill TX_Y[10:5] to (cmd+6)[5:0] bitlen=6 */ + SET_H2CCMD_MCC_IQK_TX_H(cmd, (u8)((TX_Y >> 5) & 0x3f)); + +#ifdef CONFIG_MCC_MODE_DEBUG + RTW_INFO("=========================\n"); + RTW_INFO(FUNC_ADPT_FMT" IQK:\n", FUNC_ADPT_ARG(iface)); + RTW_INFO("TX_X: 0x%02x\n", TX_X); + RTW_INFO("TX_Y: 0x%02x\n", TX_Y); + RTW_INFO("RX_X: 0x%02x\n", RX_X); + RTW_INFO("RX_Y: 0x%02x\n", RX_Y); + RTW_INFO("cmd[0]:0x%02x\n", cmd[0]); + RTW_INFO("cmd[1]:0x%02x\n", cmd[1]); + RTW_INFO("cmd[2]:0x%02x\n", cmd[2]); + RTW_INFO("cmd[3]:0x%02x\n", cmd[3]); + RTW_INFO("cmd[4]:0x%02x\n", cmd[4]); + RTW_INFO("cmd[5]:0x%02x\n", cmd[5]); + RTW_INFO("cmd[6]:0x%02x\n", cmd[6]); + RTW_INFO("=========================\n"); +#endif /* CONFIG_MCC_MODE_DEBUG */ + + rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_IQK_PARAM, H2C_MCC_IQK_PARAM_LEN, cmd); + } + } +} + + +static void rtw_hal_set_mcc_macid_cmd(PADAPTER padapter) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct mcc_adapter_priv *pmccadapriv = NULL; + _adapter *iface = NULL; + u8 cmd[H2C_MCC_MACID_BITMAP_LEN] = {0}, i = 0, order = 0; + u16 bitmap = 0; + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (iface == NULL) + continue; + + pmccadapriv = &iface->mcc_adapterpriv; + order = pmccadapriv->order; + bitmap = pmccadapriv->mcc_macid_bitmap; + + if (order >= (H2C_MCC_MACID_BITMAP_LEN/2)) { + RTW_INFO(FUNC_ADPT_FMT" only support 3 interface at most(%d)\n" + , FUNC_ADPT_ARG(padapter), order); + continue; + } + SET_H2CCMD_MCC_MACID_BITMAP_L((cmd + order * 2), (u8)(bitmap & 0xff)); + SET_H2CCMD_MCC_MACID_BITMAP_H((cmd + order * 2), (u8)((bitmap >> 8) & 0xff)); + } + +#ifdef CONFIG_MCC_MODE_DEBUG + RTW_INFO("=========================\n"); + RTW_INFO("MACID BITMAP: "); + for (i = 0; i < H2C_MCC_MACID_BITMAP_LEN; i++) + pr_dbg("0x%x ", cmd[i]); + pr_dbg("\n"); + RTW_INFO("=========================\n"); +#endif /* CONFIG_MCC_MODE_DEBUG */ + rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_MACID_BITMAP, H2C_MCC_MACID_BITMAP_LEN, cmd); +} + +static void rtw_hal_set_mcc_ctrl_cmd(PADAPTER padapter, u8 stop) +{ + u8 cmd[H2C_MCC_CTRL_LEN] = {0}, i = 0; + u8 order = 0, totalnum = 0, chidx = 0, bw = 0, bw40sc = 0, bw80sc = 0; + u8 duration = 0, role = 0, incurch = 0, rfetype = 0, distxnull = 0, c2hrpt = 0, chscan = 0; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv); + struct mlme_ext_priv *pmlmeext = NULL; + struct mlme_ext_info *pmlmeinfo = NULL; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + _adapter *iface = NULL; + + RTW_INFO(FUNC_ADPT_FMT": stop=%d\n", FUNC_ADPT_ARG(padapter), stop); + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = pmccobjpriv->iface[i]; + if (iface == NULL) + continue; + + if (stop) { + if (iface != padapter) + continue; + } + + + order = iface->mcc_adapterpriv.order; + if (!stop) + totalnum = dvobj->iface_nums; + else + totalnum = 0xff; /* 0xff means stop */ + + pmlmeext = &iface->mlmeextpriv; + chidx = pmlmeext->cur_channel; + bw = pmlmeext->cur_bwmode; + bw40sc = pmlmeext->cur_ch_offset; + + /* decide 80 band width offset */ + if (bw == CHANNEL_WIDTH_80) { + u8 center_ch = rtw_get_center_ch(chidx, bw, bw40sc); + + if (center_ch > chidx) + bw80sc = HAL_PRIME_CHNL_OFFSET_LOWER; + else if (center_ch < chidx) + bw80sc = HAL_PRIME_CHNL_OFFSET_UPPER; + else + bw80sc = HAL_PRIME_CHNL_OFFSET_DONT_CARE; + } else + bw80sc = HAL_PRIME_CHNL_OFFSET_DONT_CARE; + + duration = iface->mcc_adapterpriv.mcc_duration; + role = iface->mcc_adapterpriv.role; + + incurch = false; + + if (IS_HARDWARE_TYPE_8812(padapter)) + rfetype = pHalData->rfe_type; /* RFETYPE (only for 8812)*/ + else + rfetype = 0; + + /* STA/GC TX NULL data to inform AP/GC for ps mode */ + switch (role) { + case MCC_ROLE_GO: + case MCC_ROLE_AP: + distxnull = MCC_DISABLE_TX_NULL; + break; + case MCC_ROLE_GC: + case MCC_ROLE_STA: + distxnull = MCC_ENABLE_TX_NULL; + break; + } + + c2hrpt = MCC_C2H_REPORT_ALL_STATUS; + chscan = MCC_CHIDX; + + SET_H2CCMD_MCC_CTRL_ORDER(cmd, order); + SET_H2CCMD_MCC_CTRL_TOTALNUM(cmd, totalnum); + SET_H2CCMD_MCC_CTRL_CHIDX(cmd, chidx); + SET_H2CCMD_MCC_CTRL_BW(cmd, bw); + SET_H2CCMD_MCC_CTRL_BW40SC(cmd, bw40sc); + SET_H2CCMD_MCC_CTRL_BW80SC(cmd, bw80sc); + SET_H2CCMD_MCC_CTRL_DURATION(cmd, duration); + SET_H2CCMD_MCC_CTRL_ROLE(cmd, role); + SET_H2CCMD_MCC_CTRL_INCURCH(cmd, incurch); + SET_H2CCMD_MCC_CTRL_RFETYPE(cmd, rfetype); + SET_H2CCMD_MCC_CTRL_DISTXNULL(cmd, distxnull); + SET_H2CCMD_MCC_CTRL_C2HRPT(cmd, c2hrpt); + SET_H2CCMD_MCC_CTRL_CHSCAN(cmd, chscan); + +#ifdef CONFIG_MCC_MODE_DEBUG + RTW_INFO("=========================\n"); + RTW_INFO(FUNC_ADPT_FMT" MCC INFO:\n", FUNC_ADPT_ARG(iface)); + RTW_INFO("cmd[0]:0x%02x\n", cmd[0]); + RTW_INFO("cmd[1]:0x%02x\n", cmd[1]); + RTW_INFO("cmd[2]:0x%02x\n", cmd[2]); + RTW_INFO("cmd[3]:0x%02x\n", cmd[3]); + RTW_INFO("cmd[4]:0x%02x\n", cmd[4]); + RTW_INFO("cmd[5]:0x%02x\n", cmd[5]); + RTW_INFO("cmd[6]:0x%02x\n", cmd[6]); + RTW_INFO("=========================\n"); +#endif /* CONFIG_MCC_MODE_DEBUG */ + + rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_CTRL, H2C_MCC_CTRL_LEN, cmd); + } +} + +static u8 rtw_hal_set_mcc_start_setting(PADAPTER padapter, u8 status) +{ + u8 ret = _SUCCESS; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj); + + if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) { + rtw_warn_on(1); + RTW_INFO("PS mode is not active before start mcc, force exit ps mode\n"); + LeaveAllPowerSaveModeDirect(padapter); + } + + if (dvobj->iface_nums > MAX_MCC_NUM) { + RTW_INFO("%s: current iface num(%d) > MAX_MCC_NUM(%d)\n", __func__, dvobj->iface_nums, MAX_MCC_NUM); + ret = _FAIL; + goto exit; + } + + /* configure mcc switch channel setting */ + rtw_hal_config_mcc_switch_channel_setting(padapter); + + if (rtw_hal_decide_mcc_role(padapter) == _FAIL) { + ret = _FAIL; + goto exit; + } + + /* set mcc status to indicate process mcc start setting */ + rtw_hal_set_mcc_status(padapter, MCC_STATUS_PROCESS_MCC_START_SETTING); + + /* only download rsvd page for connect */ + if (status == MCC_SETCMD_STATUS_START_CONNECT) { + /* download mcc rsvd page */ + rtw_hal_set_fw_mcc_rsvd_page(padapter); + rtw_hal_set_mcc_rsvdpage_cmd(padapter); + } + + /* configure NoA setting */ + rtw_hal_set_mcc_noa_cmd(padapter); + + /* IQK value offload */ + rtw_hal_set_mcc_IQK_offload_cmd(padapter); + + /* set mac id to fw */ + rtw_hal_set_mcc_macid_cmd(padapter); + + /* set mcc parameter */ + rtw_hal_set_mcc_ctrl_cmd(padapter, false); + +exit: + return ret; +} + +static void rtw_hal_set_mcc_stop_setting(PADAPTER padapter, u8 status) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + _adapter *iface = NULL; + u8 i = 0; + /* + * when adapter disconnect, stop mcc mod + * total=0xf means stop mcc mode + */ + + switch (status) { + default: + /* let fw switch to other interface channel */ + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (iface == NULL) + continue; + /* use other interface to set cmd */ + if (iface != padapter) { + rtw_hal_set_mcc_ctrl_cmd(iface, true); + break; + } + } + break; + } +} + +static void rtw_hal_mcc_status_hdl(PADAPTER padapter, u8 status) +{ + switch (status) { + case MCC_SETCMD_STATUS_STOP_DISCONNECT: + rtw_hal_clear_mcc_status(padapter, MCC_STATUS_NEED_MCC | MCC_STATUS_DOING_MCC); + break; + case MCC_SETCMD_STATUS_STOP_SCAN_START: + rtw_hal_set_mcc_status(padapter, MCC_STATUS_NEED_MCC); + rtw_hal_clear_mcc_status(padapter, MCC_STATUS_DOING_MCC); + break; + + case MCC_SETCMD_STATUS_START_CONNECT: + case MCC_SETCMD_STATUS_START_SCAN_DONE: + rtw_hal_set_mcc_status(padapter, MCC_STATUS_NEED_MCC | MCC_STATUS_DOING_MCC); + break; + default: + RTW_INFO(FUNC_ADPT_FMT" error status(%d)\n", FUNC_ADPT_ARG(padapter), status); + break; + } +} + +static void rtw_hal_mcc_stop_posthdl(PADAPTER padapter) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + _adapter *iface = NULL; + u8 i = 0; + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (iface == NULL) + continue; + /* release network queue */ + rtw_netif_wake_queue(iface->pnetdev); + iface->mcc_adapterpriv.mcc_tx_bytes_from_kernel = 0; + iface->mcc_adapterpriv.mcc_last_tx_bytes_from_kernel = 0; + iface->mcc_adapterpriv.mcc_tx_bytes_to_port = 0; + + if (iface->mcc_adapterpriv.role == MCC_ROLE_GO) + rtw_hal_mcc_remove_go_p2p_ie(iface); + } +} + +static void rtw_hal_mcc_start_posthdl(PADAPTER padapter) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + _adapter *iface = NULL; + u8 i = 0; + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (iface == NULL) + continue; + iface->mcc_adapterpriv.mcc_tx_bytes_from_kernel = 0; + iface->mcc_adapterpriv.mcc_last_tx_bytes_from_kernel = 0; + iface->mcc_adapterpriv.mcc_tx_bytes_to_port = 0; + } +} + +/* + * rtw_hal_set_mcc_setting - set mcc setting + * @padapter: currnet padapter to stop/start MCC + * @stop: stop mcc or not + * @return val: 1 for SUCCESS, 0 for fail + */ +static u8 rtw_hal_set_mcc_setting(PADAPTER padapter, u8 status) +{ + u8 ret = _FAIL; + struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv); + u8 stop = (status < MCC_SETCMD_STATUS_START_CONNECT) ? true : false; + u32 start_time = jiffies; + + RTW_INFO("===> "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter)); + + rtw_sctx_init(&pmccobjpriv->mcc_sctx, MCC_EXPIRE_TIME); + pmccobjpriv->mcc_c2h_status = MCC_RPT_MAX; + + if (stop == false) { + /* handle mcc start */ + if (rtw_hal_set_mcc_start_setting(padapter, status) == _FAIL) + goto exit; + + /* wait for C2H */ + if (!rtw_sctx_wait(&pmccobjpriv->mcc_sctx, __func__)) + RTW_INFO(FUNC_ADPT_FMT": wait for mcc start C2H time out\n", FUNC_ADPT_ARG(padapter)); + else + ret = _SUCCESS; + + if (ret == _SUCCESS) { + RTW_INFO(FUNC_ADPT_FMT": mcc start sucecssfully\n", FUNC_ADPT_ARG(padapter)); + rtw_hal_mcc_start_posthdl(padapter); + } + } else { + + /* set mcc status to indicate process mcc start setting */ + rtw_hal_set_mcc_status(padapter, MCC_STATUS_PROCESS_MCC_STOP_SETTING); + + /* handle mcc stop */ + rtw_hal_set_mcc_stop_setting(padapter, status); + + /* wait for C2H */ + if (!rtw_sctx_wait(&pmccobjpriv->mcc_sctx, __func__)) + RTW_INFO(FUNC_ADPT_FMT": wait for mcc stop C2H time out\n", FUNC_ADPT_ARG(padapter)); + else { + ret = _SUCCESS; + rtw_hal_mcc_stop_posthdl(padapter); + } + } + +exit: + + rtw_hal_mcc_status_hdl(padapter, status); + /* clear mcc status */ + rtw_hal_clear_mcc_status(padapter + , MCC_STATUS_PROCESS_MCC_START_SETTING | MCC_STATUS_PROCESS_MCC_STOP_SETTING); + + RTW_INFO(FUNC_ADPT_FMT" in %dms <===\n" + , FUNC_ADPT_ARG(padapter), rtw_get_passing_time_ms(start_time)); + return ret; +} + +/** + * rtw_hal_mcc_check_case_not_limit_traffic - handler flow ctrl for special case + * @cur_iface: fw stay channel setting of this iface + * @next_iface: fw will swich channel setting of this iface + */ +static void rtw_hal_mcc_check_case_not_limit_traffic(PADAPTER cur_iface, PADAPTER next_iface) +{ + u8 cur_bw = cur_iface->mlmeextpriv.cur_bwmode; + u8 next_bw = next_iface->mlmeextpriv.cur_bwmode; + + /* for both interface are VHT80, doesn't limit_traffic according to iperf results */ + if (cur_bw == CHANNEL_WIDTH_80 && next_bw == CHANNEL_WIDTH_80) { + cur_iface->mcc_adapterpriv.mcc_tp_limit = false; + next_iface->mcc_adapterpriv.mcc_tp_limit = false; + } +} + + +/** + * rtw_hal_mcc_sw_ch_fw_notify_hdl - handler flow ctrl + */ +static void rtw_hal_mcc_sw_ch_fw_notify_hdl(PADAPTER padapter) +{ + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + struct mcc_obj_priv *pmccobjpriv = &(pdvobjpriv->mcc_objpriv); + struct mcc_adapter_priv *cur_mccadapriv = NULL, *next_mccadapriv = NULL; + _adapter *iface = NULL, *cur_iface = NULL, *next_iface = NULL; + struct registry_priv *preg = &padapter->registrypriv; + u8 cur_op_ch = pdvobjpriv->oper_channel; + u8 i = 0, iface_num = pdvobjpriv->iface_nums, cur_order = 0, next_order = 0; + static u8 cnt = 1; + u32 single_tx_cri = preg->rtw_mcc_single_tx_cri; + + for (i = 0; i < iface_num; i++) { + iface = pdvobjpriv->padapters[i]; + if (cur_op_ch == iface->mlmeextpriv.cur_channel) { + cur_iface = iface; + cur_mccadapriv = &cur_iface->mcc_adapterpriv; + cur_order = cur_mccadapriv->order; + next_order = (cur_order + 1) % iface_num; + next_iface = pmccobjpriv->iface[next_order]; + next_mccadapriv = &next_iface->mcc_adapterpriv; + break; + } + } + + /* check other interface tx busy traffic or not under every 2 switch channel notify(Mbits/100ms) */ + if (cnt == 2) { + cur_mccadapriv->mcc_tp = (cur_mccadapriv->mcc_tx_bytes_from_kernel + - cur_mccadapriv->mcc_last_tx_bytes_from_kernel) * 10 * 8 / 1024 / 1024; + cur_mccadapriv->mcc_last_tx_bytes_from_kernel = cur_mccadapriv->mcc_tx_bytes_from_kernel; + + next_mccadapriv->mcc_tp = (next_mccadapriv->mcc_tx_bytes_from_kernel + - next_mccadapriv->mcc_last_tx_bytes_from_kernel) * 10 * 8 / 1024 / 1024; + next_mccadapriv->mcc_last_tx_bytes_from_kernel = next_mccadapriv->mcc_tx_bytes_from_kernel; + + cnt = 1; + } else + cnt = 2; + + /* check single TX or cuncurrnet TX */ + if (next_mccadapriv->mcc_tp < single_tx_cri) { + /* single TX, does not stop */ + cur_mccadapriv->mcc_tx_stop = false; + cur_mccadapriv->mcc_tp_limit = false; + } else { + /* concurrent TX, stop */ + cur_mccadapriv->mcc_tx_stop = true; + cur_mccadapriv->mcc_tp_limit = true; + } + + if (cur_mccadapriv->mcc_tp < single_tx_cri) { + next_mccadapriv->mcc_tx_stop = false; + next_mccadapriv->mcc_tp_limit = false; + } else { + next_mccadapriv->mcc_tx_stop = false; + next_mccadapriv->mcc_tp_limit = true; + next_mccadapriv->mcc_tx_bytes_to_port = 0; + } + + /* stop current iface kernel queue or not */ + if (cur_mccadapriv->mcc_tx_stop) + rtw_netif_stop_queue(cur_iface->pnetdev); + else + rtw_netif_wake_queue(cur_iface->pnetdev); + + /* stop next iface kernel queue or not */ + if (next_mccadapriv->mcc_tx_stop) + rtw_netif_stop_queue(next_iface->pnetdev); + else + rtw_netif_wake_queue(next_iface->pnetdev); + + /* start xmit tasklet */ + rtw_os_xmit_schedule(next_iface); + + rtw_hal_mcc_check_case_not_limit_traffic(cur_iface, next_iface); + + if (0) { + RTW_INFO("order:%d, mcc_tx_stop:%d, mcc_tp:%d\n", + cur_mccadapriv->order, cur_mccadapriv->mcc_tx_stop, cur_mccadapriv->mcc_tp); + dump_os_queue(0, cur_iface); + RTW_INFO("order:%d, mcc_tx_stop:%d, mcc_tp:%d\n", + next_mccadapriv->order, next_mccadapriv->mcc_tx_stop, next_mccadapriv->mcc_tp); + dump_os_queue(0, next_iface); + } +} + +static void rtw_hal_mcc_update_noa_start_time_hdl(PADAPTER padapter, u8 buflen, u8 *tmpBuf) +{ + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + struct mcc_obj_priv *pmccobjpriv = &(pdvobjpriv->mcc_objpriv); + struct mcc_adapter_priv *pmccadapriv = NULL; + PADAPTER iface = NULL; + u8 i = 0; + u8 policy_idx = pmccobjpriv->policy_index; + u8 noa_tsf_sync_offset = mcc_switch_channel_policy_table[policy_idx][MCC_TSF_SYNC_OFFSET_IDX]; + u8 noa_start_time_offset = mcc_switch_channel_policy_table[policy_idx][MCC_START_TIME_OFFSET_IDX]; + + for (i = 0; i < pdvobjpriv->iface_nums; i++) { + iface = pdvobjpriv->padapters[i]; + if (iface == NULL) + continue; + + pmccadapriv = &iface->mcc_adapterpriv; + /* GO & channel match */ + if (pmccadapriv->role == MCC_ROLE_GO) { + /* convert GO TBTT from FW to noa_start_time(TU convert to mircosecond) */ + pmccadapriv->noa_start_time = RTW_GET_LE32(tmpBuf + 2) + noa_start_time_offset * TU; + + if (0) { + RTW_INFO("TBTT:0x%02x\n", RTW_GET_LE32(tmpBuf + 2)); + RTW_INFO("noa_tsf_sync_offset:%d, noa_start_time_offset:%d\n", noa_tsf_sync_offset, noa_start_time_offset); + RTW_INFO(FUNC_ADPT_FMT"buf=0x%02x:0x%02x:0x%02x:0x%02x, noa_start_time=0x%02x\n" + , FUNC_ADPT_ARG(iface) + , tmpBuf[2] + , tmpBuf[3] + , tmpBuf[4] + , tmpBuf[5] + ,pmccadapriv->noa_start_time); + } + + rtw_hal_mcc_update_go_p2p_ie(iface); + + break; + } + } + +} + +/** + * rtw_hal_mcc_c2h_handler - mcc c2h handler + */ +void rtw_hal_mcc_c2h_handler(PADAPTER padapter, u8 buflen, u8 *tmpBuf) +{ + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv); + struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv; + struct submit_ctx *mcc_sctx = &pmccobjpriv->mcc_sctx; + unsigned long irqL; + + /* RTW_INFO("[length]=%d, [C2H data]="MAC_FMT"\n", buflen, MAC_ARG(tmpBuf)); */ + /* To avoid reg is set, but driver recive c2h to set wrong oper_channel */ + if (MCC_RPT_STOPMCC == pmccobjpriv->mcc_c2h_status) { + RTW_INFO(FUNC_ADPT_FMT" MCC alread stops return\n", FUNC_ADPT_ARG(padapter)); + return; + } + + pmccobjpriv->mcc_c2h_status = tmpBuf[0]; + switch (pmccobjpriv->mcc_c2h_status) { + case MCC_RPT_SUCCESS: + pdvobjpriv->oper_channel = tmpBuf[1]; + _enter_critical_bh(&pmccobjpriv->mcc_lock, &irqL); + pmccobjpriv->cur_mcc_success_cnt++; + _exit_critical_bh(&pmccobjpriv->mcc_lock, &irqL); + break; + case MCC_RPT_TXNULL_FAIL: + RTW_INFO("[MCC] TXNULL FAIL\n"); + break; + case MCC_RPT_STOPMCC: + RTW_INFO("[MCC] MCC stop (time:%d)\n", jiffies); + pmccobjpriv->mcc_c2h_status = MCC_RPT_STOPMCC; + rtw_sctx_done(&mcc_sctx); + break; + case MCC_RPT_READY: + _enter_critical_bh(&pmccobjpriv->mcc_lock, &irqL); + /* initialize counter & time */ + pmccobjpriv->mcc_launch_time = jiffies; + pmccobjpriv->mcc_c2h_status = MCC_RPT_READY; + pmccobjpriv->cur_mcc_success_cnt = 0; + pmccobjpriv->prev_mcc_success_cnt = 0; + pmccobjpriv->mcc_tolerance_time = MCC_TOLERANCE_TIME; + _exit_critical_bh(&pmccobjpriv->mcc_lock, &irqL); + + RTW_INFO("[MCC] MCC ready (time:%d)\n", pmccobjpriv->mcc_launch_time); + rtw_sctx_done(&mcc_sctx); + break; + case MCC_RPT_SWICH_CHANNEL_NOTIFY: + pdvobjpriv->oper_channel = tmpBuf[1]; + rtw_hal_mcc_sw_ch_fw_notify_hdl(padapter); + break; + case MCC_RPT_UPDATE_NOA_START_TIME: + rtw_hal_mcc_update_noa_start_time_hdl(padapter, buflen, tmpBuf); + break; + default: + /* RTW_INFO("[MCC] Other MCC status(%d)\n", pmccobjpriv->mcc_c2h_status); */ + break; + } +} + + +/** + * rtw_hal_mcc_sw_status_check - check mcc swich channel status + * @padapter: primary adapter + */ +void rtw_hal_mcc_sw_status_check(PADAPTER padapter) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv); + struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj); + u8 cur_cnt = 0, prev_cnt = 0, diff_cnt = 0, check_ret = _FAIL; + unsigned long irqL; + +/* #define MCC_RESTART 1 */ + + if (!MCC_EN(padapter)) + return; + + _enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL); + + if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) { + + if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) { + rtw_warn_on(1); + RTW_INFO("PS mode is not active under mcc, force exit ps mode\n"); + LeaveAllPowerSaveModeDirect(padapter); + } + + if (rtw_get_passing_time_ms(pmccobjpriv->mcc_launch_time) > 2000) { + _enter_critical_bh(&pmccobjpriv->mcc_lock, &irqL); + + cur_cnt = pmccobjpriv->cur_mcc_success_cnt; + prev_cnt = pmccobjpriv->prev_mcc_success_cnt; + if (cur_cnt < prev_cnt) + diff_cnt = (cur_cnt + 255) - prev_cnt; + else + diff_cnt = cur_cnt - prev_cnt; + + if (diff_cnt < 30) { + pmccobjpriv->mcc_tolerance_time--; + RTW_INFO("%s: diff_cnt:%d, tolerance_time:%d\n", + __func__, diff_cnt, pmccobjpriv->mcc_tolerance_time); + } else + pmccobjpriv->mcc_tolerance_time = MCC_TOLERANCE_TIME; + + pmccobjpriv->prev_mcc_success_cnt = pmccobjpriv->cur_mcc_success_cnt; + + if (pmccobjpriv->mcc_tolerance_time != 0) + check_ret = _SUCCESS; + + _exit_critical_bh(&pmccobjpriv->mcc_lock, &irqL); + + if (check_ret != _SUCCESS) { + RTW_INFO("============ MCC swich channel check fail (%d)=============\n", diff_cnt); + /* restart MCC */ + #ifdef MCC_RESTART + rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_STOP_DISCONNECT); + rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_START_CONNECT); + #endif /* MCC_RESTART */ + } + } else { + _enter_critical_bh(&pmccobjpriv->mcc_lock, &irqL); + pmccobjpriv->prev_mcc_success_cnt = pmccobjpriv->cur_mcc_success_cnt; + _exit_critical_bh(&pmccobjpriv->mcc_lock, &irqL); + } + + } + _exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL); +} + +/** + * rtw_hal_mcc_change_scan_flag - change scan flag under mcc + * + * MCC mode under sitesurvey goto AP channel to tx bcn & data + * MCC mode under sitesurvey doesn't support TX data for station mode (FW not support) + * + * @padapter: the adapter to be change scan flag + * @ch: pointer to rerurn ch + * @bw: pointer to rerurn bw + * @offset: pointer to rerurn offset + */ +u8 rtw_hal_mcc_change_scan_flag(PADAPTER padapter, u8 *ch, u8 *bw, u8 *offset) +{ + u8 need_ch_setting_union = true, i = 0, flags = 0, role = 0; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct mcc_adapter_priv *pmccadapriv = NULL; + struct mlme_ext_priv *pmlmeext = NULL; + + if (!MCC_EN(padapter)) + goto exit; + + if (!rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC)) + goto exit; + + for (i = 0; i < dvobj->iface_nums; i++) { + if (!dvobj->padapters[i]) + continue; + + pmlmeext = &dvobj->padapters[i]->mlmeextpriv; + pmccadapriv = &dvobj->padapters[i]->mcc_adapterpriv; + role = pmccadapriv->role; + + switch (role) { + case MCC_ROLE_AP: + case MCC_ROLE_GO: + *ch = pmlmeext->cur_channel; + *bw = pmlmeext->cur_bwmode; + *offset = pmlmeext->cur_ch_offset; + need_ch_setting_union = false; + break; + case MCC_ROLE_STA: + case MCC_ROLE_GC: + break; + default: + RTW_INFO("unknown role\n"); + rtw_warn_on(1); + break; + } + + /* check other scan flag */ + flags = mlmeext_scan_backop_flags(pmlmeext); + if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_PS_ANNC)) + flags &= ~SS_BACKOP_PS_ANNC; + + if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_TX_RESUME)) + flags &= ~SS_BACKOP_TX_RESUME; + + mlmeext_assign_scan_backop_flags(pmlmeext, flags); + + } +exit: + return need_ch_setting_union; +} + +/** + * rtw_hal_mcc_calc_tx_bytes_from_kernel - calculte tx bytes from kernel to check concurrent tx or not + * @padapter: the adapter to be record tx bytes + * @len: data len + */ +inline void rtw_hal_mcc_calc_tx_bytes_from_kernel(PADAPTER padapter, u32 len) +{ + struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv; + + if (MCC_EN(padapter)) { + if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) { + pmccadapriv->mcc_tx_bytes_from_kernel += len; + if (0) + RTW_INFO("%s(order:%d): mcc tx bytes from kernel:%lld\n" + , __func__, pmccadapriv->order, pmccadapriv->mcc_tx_bytes_from_kernel); + } + } +} + +/** + * rtw_hal_mcc_calc_tx_bytes_to_port - calculte tx bytes to write port in order to flow crtl + * @padapter: the adapter to be record tx bytes + * @len: data len + */ +inline void rtw_hal_mcc_calc_tx_bytes_to_port(PADAPTER padapter, u32 len) +{ + if (MCC_EN(padapter)) { + struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv); + struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv; + + if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) + pmccadapriv->mcc_tx_bytes_to_port += len; + if (0) + RTW_INFO("%s(order:%d): mcc tx bytes to port:%d, mcc target tx bytes to port:%d\n" + , __func__, pmccadapriv->order, pmccadapriv->mcc_tx_bytes_to_port + , pmccadapriv->mcc_target_tx_bytes_to_port); + } +} + +/** + * rtw_hal_mcc_stop_tx_bytes_to_port - stop write port to hw or not + * @padapter: the adapter to be stopped + */ +inline u8 rtw_hal_mcc_stop_tx_bytes_to_port(PADAPTER padapter) +{ + if (MCC_EN(padapter)) { + struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv); + struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv; + + if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) { + if (pmccadapriv->mcc_tp_limit) { + if (pmccadapriv->mcc_tx_bytes_to_port >= pmccadapriv->mcc_target_tx_bytes_to_port) { + pmccadapriv->mcc_tx_stop = true; + rtw_netif_stop_queue(padapter->pnetdev); + return true; + } + } + } + } + + return false; +} + +/** + * rtw_hal_set_mcc_setting_scan_start - setting mcc under scan start + * @padapter: the adapter to be setted + * @ch_setting_changed: softap channel setting to be changed or not + */ +u8 rtw_hal_set_mcc_setting_scan_start(PADAPTER padapter) +{ + u8 ret = _FAIL; + + if (MCC_EN(padapter)) { + struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv); + + _enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL); + if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC)) { + if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) { + ret = rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_STOP_SCAN_START); + /* issue null data to all station connected to AP before scan */ + rtw_hal_mcc_issue_null_data(padapter, 0, 1); + } + } + _exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL); + } + + return ret; +} + +/** + * rtw_hal_set_mcc_setting_scan_complete - setting mcc after scan commplete + * @padapter: the adapter to be setted + * @ch_setting_changed: softap channel setting to be changed or not + */ +u8 rtw_hal_set_mcc_setting_scan_complete(PADAPTER padapter) +{ + u8 ret = _FAIL; + + if (MCC_EN(padapter)) { + struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv); + + _enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL); + + if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC)) + ret = rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_START_SCAN_DONE); + + _exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL); + } + + return ret; +} + + +/** + * rtw_hal_set_mcc_setting_start_bss_network - setting mcc under softap start + * @padapter: the adapter to be setted + * @chbw_grouped: channel bw offset can not be allowed or not + */ +u8 rtw_hal_set_mcc_setting_start_bss_network(PADAPTER padapter, u8 chbw_allow) +{ + u8 ret = _FAIL; + + if (MCC_EN(padapter)) { + /* channel bw offset can not be allowed, start MCC */ + if (chbw_allow == false) { + struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv); + + rtw_hal_mcc_restore_iqk_val(padapter); + _enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL); + ret = rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_START_CONNECT); + _exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL); + } + } + + return ret; +} + +/** + * rtw_hal_set_mcc_setting_disconnect - setting mcc under mlme disconnect(stop softap/disconnect from AP) + * @padapter: the adapter to be setted + */ +u8 rtw_hal_set_mcc_setting_disconnect(PADAPTER padapter) +{ + u8 ret = _FAIL; + + if (MCC_EN(padapter)) { + struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv); + + _enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL); + if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC)) { + if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) + ret = rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_STOP_DISCONNECT); + } + _exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL); + } + + return ret; +} + +/** + * rtw_hal_set_mcc_setting_join_done_chk_ch - setting mcc under join done + * @padapter: the adapter to be checked + */ +u8 rtw_hal_set_mcc_setting_join_done_chk_ch(PADAPTER padapter) +{ + u8 ret = _FAIL; + + if (MCC_EN(padapter)) { + struct mi_state mstate; + + rtw_mi_status_no_self(padapter, &mstate); + + if (MSTATE_STA_LD_NUM(&mstate) || MSTATE_STA_LG_NUM(&mstate) || MSTATE_AP_NUM(&mstate)) { + bool chbw_allow = true; + u8 u_ch, u_offset, u_bw; + struct mlme_ext_priv *cur_mlmeext = &padapter->mlmeextpriv; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + + if (rtw_mi_get_ch_setting_union_no_self(padapter, &u_ch, &u_bw, &u_offset) <= 0) { + dump_adapters_status(RTW_DBGDUMP , dvobj); + rtw_warn_on(1); + } + + RTW_INFO(FUNC_ADPT_FMT" union no self: %u,%u,%u\n" + , FUNC_ADPT_ARG(padapter), u_ch, u_bw, u_offset); + + /* chbw_allow? */ + chbw_allow = rtw_is_chbw_grouped(cur_mlmeext->cur_channel + , cur_mlmeext->cur_bwmode, cur_mlmeext->cur_ch_offset + , u_ch, u_bw, u_offset); + + RTW_INFO(FUNC_ADPT_FMT" chbw_allow:%d\n" + , FUNC_ADPT_ARG(padapter), chbw_allow); + + /* if chbw_allow = false, start MCC setting */ + if (chbw_allow == false) { + struct mcc_obj_priv *pmccobjpriv = &dvobj->mcc_objpriv; + + rtw_hal_mcc_restore_iqk_val(padapter); + _enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL); + ret = rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_START_CONNECT); + _exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL); + } + } + } + + return ret; +} + +/** + * rtw_hal_set_mcc_setting_chk_start_clnt_join - check change channel under start clnt join + * @padapter: the adapter to be checked + * @ch: pointer to rerurn ch + * @bw: pointer to rerurn bw + * @offset: pointer to rerurn offset + * @chbw_allow: allow to use adapter's channel setting + */ +u8 rtw_hal_set_mcc_setting_chk_start_clnt_join(PADAPTER padapter, u8 *ch, u8 *bw, u8 *offset, u8 chbw_allow) +{ + u8 ret = _FAIL; + + /* if chbw_allow = false under en_mcc = true, we do not change channel related setting */ + if (MCC_EN(padapter)) { + /* restore union channel related setting to current channel related setting */ + if (chbw_allow == false) { + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + + *ch = pmlmeext->cur_channel; + *bw = pmlmeext->cur_bwmode; + *offset = pmlmeext->cur_ch_offset; + + RTW_INFO(FUNC_ADPT_FMT" en_mcc:%d(%d,%d,%d,)\n" + , FUNC_ADPT_ARG(padapter), padapter->registrypriv.en_mcc + , *ch, *bw, *offset); + ret = _SUCCESS; + } + } + + return ret; +} + +static void rtw_hal_mcc_dump_noa_content(void *sel, PADAPTER padapter) +{ + struct mcc_adapter_priv *pmccadapriv = NULL; + u8 *pos = NULL; + pmccadapriv = &padapter->mcc_adapterpriv; + /* last position for NoA attribute */ + pos = pmccadapriv->p2p_go_noa_ie + pmccadapriv->p2p_go_noa_ie_len; + + + RTW_PRINT_SEL(sel, "\nStart to dump NoA Content\n"); + RTW_PRINT_SEL(sel, "NoA Counts:%d\n", *(pos - 13)); + RTW_PRINT_SEL(sel, "NoA Duration(TU):%d\n", (RTW_GET_LE32(pos - 12))/TU); + RTW_PRINT_SEL(sel, "NoA Interval(TU):%d\n", (RTW_GET_LE32(pos - 8))/TU); + RTW_PRINT_SEL(sel, "NoA Start time(microseconds):0x%02x\n", RTW_GET_LE32(pos - 4)); + RTW_PRINT_SEL(sel, "End to dump NoA Content\n"); +} + +void rtw_hal_dump_mcc_info(void *sel, struct dvobj_priv *dvobj) +{ + struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv); + struct mcc_adapter_priv *pmccadapriv = NULL; + _adapter *iface = NULL, *adapter = NULL; + struct registry_priv *regpriv = NULL; + u8 i = 0; + + /* regpriv is common for all adapter */ + adapter = dvobj->padapters[IFACE_ID0]; + + RTW_PRINT_SEL(sel, "**********************************************\n"); + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (!iface) + continue; + + regpriv = &iface->registrypriv; + pmccadapriv = &iface->mcc_adapterpriv; + if (pmccadapriv) { + RTW_PRINT_SEL(sel, "adapter mcc info:\n"); + RTW_PRINT_SEL(sel, "ifname:%s\n", ADPT_ARG(iface)); + RTW_PRINT_SEL(sel, "order:%d\n", pmccadapriv->order); + RTW_PRINT_SEL(sel, "duration:%d\n", pmccadapriv->mcc_duration); + RTW_PRINT_SEL(sel, "target tx bytes:%d\n", pmccadapriv->mcc_target_tx_bytes_to_port); + RTW_PRINT_SEL(sel, "current TP:%d\n", pmccadapriv->mcc_tp); + RTW_PRINT_SEL(sel, "mgmt queue macid:%d\n", pmccadapriv->mgmt_queue_macid); + RTW_PRINT_SEL(sel, "macid bitmap:0x%02x\n\n", pmccadapriv->mcc_macid_bitmap); + RTW_PRINT_SEL(sel, "registry data:\n"); + RTW_PRINT_SEL(sel, "en_mcc:%d\n", regpriv->en_mcc); + RTW_PRINT_SEL(sel, "ap target tx TP(BW:20M):%d Mbps\n", regpriv->rtw_mcc_ap_bw20_target_tx_tp); + RTW_PRINT_SEL(sel, "ap target tx TP(BW:40M):%d Mbps\n", regpriv->rtw_mcc_ap_bw40_target_tx_tp); + RTW_PRINT_SEL(sel, "ap target tx TP(BW:80M):%d Mbps\n", regpriv->rtw_mcc_ap_bw80_target_tx_tp); + RTW_PRINT_SEL(sel, "sta target tx TP(BW:20M):%d Mbps\n", regpriv->rtw_mcc_sta_bw20_target_tx_tp); + RTW_PRINT_SEL(sel, "sta target tx TP(BW:40M ):%d Mbps\n", regpriv->rtw_mcc_sta_bw40_target_tx_tp); + RTW_PRINT_SEL(sel, "sta target tx TP(BW:80M):%d Mbps\n", regpriv->rtw_mcc_sta_bw80_target_tx_tp); + RTW_PRINT_SEL(sel, "single tx criteria:%d Mbps\n", regpriv->rtw_mcc_single_tx_cri); + if (MLME_IS_GO(iface)) + rtw_hal_mcc_dump_noa_content(sel, iface); + RTW_PRINT_SEL(sel, "**********************************************\n"); + } + } + RTW_PRINT_SEL(sel, "------------------------------------------\n"); + RTW_PRINT_SEL(sel, "policy index:%d\n", pmccobjpriv->policy_index); + RTW_PRINT_SEL(sel, "------------------------------------------\n"); + RTW_PRINT_SEL(sel, "define data:\n"); + RTW_PRINT_SEL(sel, "ap target tx TP(BW:20M):%d Mbps\n", MCC_AP_BW20_TARGET_TX_TP); + RTW_PRINT_SEL(sel, "ap target tx TP(BW:40M):%d Mbps\n", MCC_AP_BW40_TARGET_TX_TP); + RTW_PRINT_SEL(sel, "ap target tx TP(BW:80M):%d Mbps\n", MCC_AP_BW80_TARGET_TX_TP); + RTW_PRINT_SEL(sel, "sta target tx TP(BW:20M):%d Mbps\n", MCC_STA_BW20_TARGET_TX_TP); + RTW_PRINT_SEL(sel, "sta target tx TP(BW:40M):%d Mbps\n", MCC_STA_BW40_TARGET_TX_TP); + RTW_PRINT_SEL(sel, "sta target tx TP(BW:80M):%d Mbps\n", MCC_STA_BW80_TARGET_TX_TP); + RTW_PRINT_SEL(sel, "single tx criteria:%d Mbps\n", MCC_SINGLE_TX_CRITERIA); + RTW_PRINT_SEL(sel, "------------------------------------------\n"); +} + +inline void update_mcc_mgntframe_attrib(_adapter *padapter, struct pkt_attrib *pattrib) +{ + if (MCC_EN(padapter)) { + if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) { + /* use QSLT_MGNT to check mgnt queue or bcn queue */ + if (pattrib->qsel == QSLT_MGNT) { + pattrib->mac_id = padapter->mcc_adapterpriv.mgmt_queue_macid; + pattrib->qsel = QSLT_VO; + } + } + } +} + +inline u8 rtw_hal_mcc_link_status_chk(_adapter *padapter, const char *msg) +{ + u8 ret = true, i = 0; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + _adapter *iface; + struct mlme_ext_priv *mlmeext; + + if (MCC_EN(padapter)) { + if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC)) { + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + mlmeext = &iface->mlmeextpriv; + if (mlmeext_scan_state(mlmeext) != SCAN_DISABLE) { + #ifdef DBG_EXPIRATION_CHK + RTW_INFO(FUNC_ADPT_FMT" don't enter %s under scan for MCC mode\n", FUNC_ADPT_ARG(padapter), msg); + #endif + ret = false; + goto exit; + } + } + } + } + +exit: + return ret; +} + +void rtw_hal_mcc_issue_null_data(_adapter *padapter, u8 chbw_allow, u8 ps_mode) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + _adapter *iface = NULL; + u32 start = jiffies; + u8 i = 0; + + if (!MCC_EN(padapter)) + return; + + if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) + return; + + if (chbw_allow == true) + return; + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + /* issue null data to inform ap station will leave */ + if (is_client_associated_to_ap(iface)) { + struct mlme_ext_priv *mlmeext = &iface->mlmeextpriv; + u8 ch = mlmeext->cur_channel; + u8 bw = mlmeext->cur_bwmode; + u8 offset = mlmeext->cur_ch_offset; + + set_channel_bwmode(iface, ch, bw, offset); + issue_nulldata(iface, NULL, ps_mode, 3, 50); + } + } + RTW_INFO("%s(%d ms)\n", __func__, rtw_get_passing_time_ms(start)); +} + +u8 *rtw_hal_mcc_append_go_p2p_ie(PADAPTER padapter, u8 *pframe, u32 *len) +{ + struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv; + + if (!MCC_EN(padapter)) + return pframe; + + if (!rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) + return pframe; + + if (pmccadapriv->p2p_go_noa_ie_len == 0) + return pframe; + + memcpy(pframe, pmccadapriv->p2p_go_noa_ie, pmccadapriv->p2p_go_noa_ie_len); + *len = *len + pmccadapriv->p2p_go_noa_ie_len; + + return pframe + pmccadapriv->p2p_go_noa_ie_len; +} + +void rtw_hal_dump_mcc_policy_table(void *sel) +{ + u8 idx = 0; + RTW_PRINT_SEL(sel, "duration\t,tsf sync offset\t,start time offset\t,interval\t,guard offset0\t,guard offset1\n"); + + for (idx = 0; idx < mcc_max_policy_num; idx ++) { + RTW_PRINT_SEL(sel, "%d\t\t,%d\t\t\t,%d\t\t\t,%d\t\t,%d\t\t,%d\n" + , mcc_switch_channel_policy_table[idx][MCC_DURATION_IDX] + , mcc_switch_channel_policy_table[idx][MCC_TSF_SYNC_OFFSET_IDX] + , mcc_switch_channel_policy_table[idx][MCC_START_TIME_OFFSET_IDX] + , mcc_switch_channel_policy_table[idx][MCC_INTERVAL_IDX] + , mcc_switch_channel_policy_table[idx][MCC_GUARD_OFFSET0_IDX] + , mcc_switch_channel_policy_table[idx][MCC_GUARD_OFFSET1_IDX]); + } +} + +#endif /* CONFIG_MCC_MODE */ diff --git a/drivers/staging/rtl8188eu/hal/hal_mp.c b/drivers/staging/rtl8188eu/hal/hal_mp.c new file mode 100644 index 000000000000..58dd2adf05df --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal_mp.c @@ -0,0 +1,883 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#define _HAL_MP_C_ + +#include + +#ifdef CONFIG_MP_INCLUDED + +#ifdef RTW_HALMAC + #include /* struct HAL_DATA_TYPE, RF register definition and etc. */ +#else /* !RTW_HALMAC */ + #include +#endif /* !RTW_HALMAC */ + + +static u8 MgntQuery_NssTxRate(u16 Rate) +{ + u8 NssNum = RF_TX_NUM_NONIMPLEMENT; + + if ((Rate >= MGN_MCS8 && Rate <= MGN_MCS15) || + (Rate >= MGN_VHT2SS_MCS0 && Rate <= MGN_VHT2SS_MCS9)) + NssNum = RF_2TX; + else if ((Rate >= MGN_MCS16 && Rate <= MGN_MCS23) || + (Rate >= MGN_VHT3SS_MCS0 && Rate <= MGN_VHT3SS_MCS9)) + NssNum = RF_3TX; + else if ((Rate >= MGN_MCS24 && Rate <= MGN_MCS31) || + (Rate >= MGN_VHT4SS_MCS0 && Rate <= MGN_VHT4SS_MCS9)) + NssNum = RF_4TX; + else + NssNum = RF_1TX; + + return NssNum; +} + +void hal_mpt_SwitchRfSetting(PADAPTER pAdapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + PMPT_CONTEXT pMptCtx = &(pAdapter->mppriv.mpt_ctx); + u8 ChannelToSw = pMptCtx->MptChannelToSw; + u32 ulRateIdx = pMptCtx->mpt_rate_index; + u32 ulbandwidth = pMptCtx->MptBandWidth; + + /* <20120525, Kordan> Dynamic mechanism for APK, asked by Dennis.*/ + if (IS_HARDWARE_TYPE_8188E(pAdapter)) { + phy_set_rf_reg(pAdapter, ODM_RF_PATH_A, RF_0x52, 0x000F0, pMptCtx->backup0x52_RF_A); + phy_set_rf_reg(pAdapter, ODM_RF_PATH_B, RF_0x52, 0x000F0, pMptCtx->backup0x52_RF_B); + } +} + +s32 hal_mpt_SetPowerTracking(PADAPTER padapter, u8 enable) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct PHY_DM_STRUCT *pDM_Odm = &(pHalData->odmpriv); + + + if (!netif_running(padapter->pnetdev)) { + return _FAIL; + } + + if (check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == false) { + return _FAIL; + } + if (enable) + pDM_Odm->rf_calibrate_info.txpowertrack_control = true; + else + pDM_Odm->rf_calibrate_info.txpowertrack_control = false; + + return _SUCCESS; +} + +void hal_mpt_GetPowerTracking(PADAPTER padapter, u8 *enable) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct PHY_DM_STRUCT *pDM_Odm = &(pHalData->odmpriv); + + + *enable = pDM_Odm->rf_calibrate_info.txpowertrack_control; +} + + +void hal_mpt_CCKTxPowerAdjust(PADAPTER Adapter, bool bInCH14) +{ + u32 TempVal = 0, TempVal2 = 0, TempVal3 = 0; + u32 CurrCCKSwingVal = 0, CCKSwingIndex = 12; + u8 i; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + PMPT_CONTEXT pMptCtx = &(Adapter->mppriv.mpt_ctx); + u8 u1Channel = pHalData->current_channel; + u32 ulRateIdx = pMptCtx->mpt_rate_index; + u8 DataRate = 0xFF; + + DataRate = mpt_to_mgnt_rate(ulRateIdx); + + if (u1Channel == 14 && IS_CCK_RATE(DataRate)) + pHalData->bCCKinCH14 = true; + else + pHalData->bCCKinCH14 = false; + + /* get current cck swing value and check 0xa22 & 0xa23 later to match the table.*/ + CurrCCKSwingVal = read_bbreg(Adapter, rCCK0_TxFilter1, bMaskHWord); + + if (!pHalData->bCCKinCH14) { + /* Readback the current bb cck swing value and compare with the table to */ + /* get the current swing index */ + for (i = 0; i < CCK_TABLE_SIZE; i++) { + if (((CurrCCKSwingVal & 0xff) == (u32)cck_swing_table_ch1_ch13[i][0]) && + (((CurrCCKSwingVal & 0xff00) >> 8) == (u32)cck_swing_table_ch1_ch13[i][1])) { + CCKSwingIndex = i; + break; + } + } + + /*Write 0xa22 0xa23*/ + TempVal = cck_swing_table_ch1_ch13[CCKSwingIndex][0] + + (cck_swing_table_ch1_ch13[CCKSwingIndex][1] << 8); + + + /*Write 0xa24 ~ 0xa27*/ + TempVal2 = 0; + TempVal2 = cck_swing_table_ch1_ch13[CCKSwingIndex][2] + + (cck_swing_table_ch1_ch13[CCKSwingIndex][3] << 8) + + (cck_swing_table_ch1_ch13[CCKSwingIndex][4] << 16) + + (cck_swing_table_ch1_ch13[CCKSwingIndex][5] << 24); + + /*Write 0xa28 0xa29*/ + TempVal3 = 0; + TempVal3 = cck_swing_table_ch1_ch13[CCKSwingIndex][6] + + (cck_swing_table_ch1_ch13[CCKSwingIndex][7] << 8); + } else { + for (i = 0; i < CCK_TABLE_SIZE; i++) { + if (((CurrCCKSwingVal & 0xff) == (u32)cck_swing_table_ch14[i][0]) && + (((CurrCCKSwingVal & 0xff00) >> 8) == (u32)cck_swing_table_ch14[i][1])) { + CCKSwingIndex = i; + break; + } + } + + /*Write 0xa22 0xa23*/ + TempVal = cck_swing_table_ch14[CCKSwingIndex][0] + + (cck_swing_table_ch14[CCKSwingIndex][1] << 8); + + /*Write 0xa24 ~ 0xa27*/ + TempVal2 = 0; + TempVal2 = cck_swing_table_ch14[CCKSwingIndex][2] + + (cck_swing_table_ch14[CCKSwingIndex][3] << 8) + + (cck_swing_table_ch14[CCKSwingIndex][4] << 16) + + (cck_swing_table_ch14[CCKSwingIndex][5] << 24); + + /*Write 0xa28 0xa29*/ + TempVal3 = 0; + TempVal3 = cck_swing_table_ch14[CCKSwingIndex][6] + + (cck_swing_table_ch14[CCKSwingIndex][7] << 8); + } + + write_bbreg(Adapter, rCCK0_TxFilter1, bMaskHWord, TempVal); + write_bbreg(Adapter, rCCK0_TxFilter2, bMaskDWord, TempVal2); + write_bbreg(Adapter, rCCK0_DebugPort, bMaskLWord, TempVal3); +} + +void hal_mpt_SetChannel(PADAPTER pAdapter) +{ + u8 eRFPath; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + struct PHY_DM_STRUCT *pDM_Odm = &(pHalData->odmpriv); + struct mp_priv *pmp = &pAdapter->mppriv; + u8 channel = pmp->channel; + u8 bandwidth = pmp->bandwidth; + + hal_mpt_SwitchRfSetting(pAdapter); + + pHalData->bSwChnl = true; + pHalData->bSetChnlBW = true; + rtw_hal_set_chnl_bw(pAdapter, channel, bandwidth, 0, 0); + + hal_mpt_CCKTxPowerAdjust(pAdapter, pHalData->bCCKinCH14); + +} + +/* + * Notice + * Switch bandwitdth may change center frequency(channel) + */ +void hal_mpt_SetBandwidth(PADAPTER pAdapter) +{ + struct mp_priv *pmp = &pAdapter->mppriv; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + + u8 channel = pmp->channel; + u8 bandwidth = pmp->bandwidth; + + pHalData->bSwChnl = true; + pHalData->bSetChnlBW = true; + rtw_hal_set_chnl_bw(pAdapter, channel, bandwidth, 0, 0); + + hal_mpt_SwitchRfSetting(pAdapter); +} + +static void mpt_SetTxPower_Old(PADAPTER pAdapter, MPT_TXPWR_DEF Rate, u8 *pTxPower) +{ + switch (Rate) { + case MPT_CCK: { + u32 TxAGC = 0, pwr = 0; + u8 rf; + + pwr = pTxPower[ODM_RF_PATH_A]; + if (pwr < 0x3f) { + TxAGC = (pwr << 16) | (pwr << 8) | (pwr); + phy_set_bb_reg(pAdapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, pTxPower[ODM_RF_PATH_A]); + phy_set_bb_reg(pAdapter, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, TxAGC); + } + pwr = pTxPower[ODM_RF_PATH_B]; + if (pwr < 0x3f) { + TxAGC = (pwr << 16) | (pwr << 8) | (pwr); + phy_set_bb_reg(pAdapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, pTxPower[ODM_RF_PATH_B]); + phy_set_bb_reg(pAdapter, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, TxAGC); + } + } + break; + + case MPT_OFDM_AND_HT: { + u32 TxAGC = 0; + u8 pwr = 0, rf; + + pwr = pTxPower[0]; + if (pwr < 0x3f) { + TxAGC |= ((pwr << 24) | (pwr << 16) | (pwr << 8) | pwr); + RTW_INFO("HT Tx-rf(A) Power = 0x%x\n", TxAGC); + phy_set_bb_reg(pAdapter, rTxAGC_A_Rate18_06, bMaskDWord, TxAGC); + phy_set_bb_reg(pAdapter, rTxAGC_A_Rate54_24, bMaskDWord, TxAGC); + phy_set_bb_reg(pAdapter, rTxAGC_A_Mcs03_Mcs00, bMaskDWord, TxAGC); + phy_set_bb_reg(pAdapter, rTxAGC_A_Mcs07_Mcs04, bMaskDWord, TxAGC); + phy_set_bb_reg(pAdapter, rTxAGC_A_Mcs11_Mcs08, bMaskDWord, TxAGC); + phy_set_bb_reg(pAdapter, rTxAGC_A_Mcs15_Mcs12, bMaskDWord, TxAGC); + } + TxAGC = 0; + pwr = pTxPower[1]; + if (pwr < 0x3f) { + TxAGC |= ((pwr << 24) | (pwr << 16) | (pwr << 8) | pwr); + RTW_INFO("HT Tx-rf(B) Power = 0x%x\n", TxAGC); + phy_set_bb_reg(pAdapter, rTxAGC_B_Rate18_06, bMaskDWord, TxAGC); + phy_set_bb_reg(pAdapter, rTxAGC_B_Rate54_24, bMaskDWord, TxAGC); + phy_set_bb_reg(pAdapter, rTxAGC_B_Mcs03_Mcs00, bMaskDWord, TxAGC); + phy_set_bb_reg(pAdapter, rTxAGC_B_Mcs07_Mcs04, bMaskDWord, TxAGC); + phy_set_bb_reg(pAdapter, rTxAGC_B_Mcs11_Mcs08, bMaskDWord, TxAGC); + phy_set_bb_reg(pAdapter, rTxAGC_B_Mcs15_Mcs12, bMaskDWord, TxAGC); + } + } + break; + + default: + break; + } + RTW_INFO("<===mpt_SetTxPower_Old()\n"); +} + +static void +mpt_SetTxPower( + PADAPTER pAdapter, + MPT_TXPWR_DEF Rate, + u8 * pTxPower +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + + u8 path = 0 , i = 0, MaxRate = MGN_6M; + u8 StartPath = ODM_RF_PATH_A, EndPath = ODM_RF_PATH_B; + + switch (Rate) { + case MPT_CCK: { + u8 rate[] = {MGN_1M, MGN_2M, MGN_5_5M, MGN_11M}; + + for (path = StartPath; path <= EndPath; path++) + for (i = 0; i < sizeof(rate); ++i) + PHY_SetTxPowerIndex(pAdapter, pTxPower[path], path, rate[i]); + } + break; + case MPT_OFDM: { + u8 rate[] = { + MGN_6M, MGN_9M, MGN_12M, MGN_18M, + MGN_24M, MGN_36M, MGN_48M, MGN_54M, + }; + + for (path = StartPath; path <= EndPath; path++) + for (i = 0; i < sizeof(rate); ++i) + PHY_SetTxPowerIndex(pAdapter, pTxPower[path], path, rate[i]); + } + break; + case MPT_HT: { + u8 rate[] = { + MGN_MCS0, MGN_MCS1, MGN_MCS2, MGN_MCS3, MGN_MCS4, + MGN_MCS5, MGN_MCS6, MGN_MCS7, MGN_MCS8, MGN_MCS9, + MGN_MCS10, MGN_MCS11, MGN_MCS12, MGN_MCS13, MGN_MCS14, + MGN_MCS15, MGN_MCS16, MGN_MCS17, MGN_MCS18, MGN_MCS19, + MGN_MCS20, MGN_MCS21, MGN_MCS22, MGN_MCS23, MGN_MCS24, + MGN_MCS25, MGN_MCS26, MGN_MCS27, MGN_MCS28, MGN_MCS29, + MGN_MCS30, MGN_MCS31, + }; + if (pHalData->rf_type == RF_3T3R) + MaxRate = MGN_MCS23; + else if (pHalData->rf_type == RF_2T2R) + MaxRate = MGN_MCS15; + else + MaxRate = MGN_MCS7; + for (path = StartPath; path <= EndPath; path++) { + for (i = 0; i < sizeof(rate); ++i) { + if (rate[i] > MaxRate) + break; + PHY_SetTxPowerIndex(pAdapter, pTxPower[path], path, rate[i]); + } + } + } + break; + case MPT_VHT: { + u8 rate[] = { + MGN_VHT1SS_MCS0, MGN_VHT1SS_MCS1, MGN_VHT1SS_MCS2, MGN_VHT1SS_MCS3, MGN_VHT1SS_MCS4, + MGN_VHT1SS_MCS5, MGN_VHT1SS_MCS6, MGN_VHT1SS_MCS7, MGN_VHT1SS_MCS8, MGN_VHT1SS_MCS9, + MGN_VHT2SS_MCS0, MGN_VHT2SS_MCS1, MGN_VHT2SS_MCS2, MGN_VHT2SS_MCS3, MGN_VHT2SS_MCS4, + MGN_VHT2SS_MCS5, MGN_VHT2SS_MCS6, MGN_VHT2SS_MCS7, MGN_VHT2SS_MCS8, MGN_VHT2SS_MCS9, + MGN_VHT3SS_MCS0, MGN_VHT3SS_MCS1, MGN_VHT3SS_MCS2, MGN_VHT3SS_MCS3, MGN_VHT3SS_MCS4, + MGN_VHT3SS_MCS5, MGN_VHT3SS_MCS6, MGN_VHT3SS_MCS7, MGN_VHT3SS_MCS8, MGN_VHT3SS_MCS9, + MGN_VHT4SS_MCS0, MGN_VHT4SS_MCS1, MGN_VHT4SS_MCS2, MGN_VHT4SS_MCS3, MGN_VHT4SS_MCS4, + MGN_VHT4SS_MCS5, MGN_VHT4SS_MCS6, MGN_VHT4SS_MCS7, MGN_VHT4SS_MCS8, MGN_VHT4SS_MCS9, + }; + if (pHalData->rf_type == RF_3T3R) + MaxRate = MGN_VHT3SS_MCS9; + else if (pHalData->rf_type == RF_2T2R || pHalData->rf_type == RF_2T4R) + MaxRate = MGN_VHT2SS_MCS9; + else + MaxRate = MGN_VHT1SS_MCS9; + + for (path = StartPath; path <= EndPath; path++) { + for (i = 0; i < sizeof(rate); ++i) { + if (rate[i] > MaxRate) + break; + PHY_SetTxPowerIndex(pAdapter, pTxPower[path], path, rate[i]); + } + } + } + break; + default: + RTW_INFO("<===mpt_SetTxPower: Illegal channel!!\n"); + break; + } +} + +void hal_mpt_SetTxPower(PADAPTER pAdapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + PMPT_CONTEXT pMptCtx = &(pAdapter->mppriv.mpt_ctx); + struct PHY_DM_STRUCT *pDM_Odm = &pHalData->odmpriv; + + if (pHalData->rf_chip < RF_TYPE_MAX) { + if (IS_HARDWARE_TYPE_8188E(pAdapter)) { + u8 path = (pHalData->antenna_tx_path == ANTENNA_A) ? (ODM_RF_PATH_A) : (ODM_RF_PATH_B); + + RTW_INFO("===> MPT_ProSetTxPower: Old\n"); + + mpt_SetTxPower_Old(pAdapter, MPT_CCK, pMptCtx->TxPwrLevel); + mpt_SetTxPower_Old(pAdapter, MPT_OFDM_AND_HT, pMptCtx->TxPwrLevel); + + } else { + RTW_INFO("===> MPT_ProSetTxPower: Jaguar/Jaguar2\n"); + mpt_SetTxPower(pAdapter, MPT_CCK, pMptCtx->TxPwrLevel); + mpt_SetTxPower(pAdapter, MPT_OFDM, pMptCtx->TxPwrLevel); + mpt_SetTxPower(pAdapter, MPT_HT, pMptCtx->TxPwrLevel); + mpt_SetTxPower(pAdapter, MPT_VHT, pMptCtx->TxPwrLevel); + } + } else + RTW_INFO("RFChipID < RF_TYPE_MAX, the RF chip is not supported - %d\n", pHalData->rf_chip); + + odm_clear_txpowertracking_state(pDM_Odm); +} + +void hal_mpt_SetDataRate(PADAPTER pAdapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + PMPT_CONTEXT pMptCtx = &(pAdapter->mppriv.mpt_ctx); + u32 DataRate; + + DataRate = mpt_to_mgnt_rate(pMptCtx->mpt_rate_index); + + hal_mpt_SwitchRfSetting(pAdapter); + + hal_mpt_CCKTxPowerAdjust(pAdapter, pHalData->bCCKinCH14); +} + +#define RF_PATH_AB 22 + +static void mpt_SetRFPath_819X(PADAPTER pAdapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + PMPT_CONTEXT pMptCtx = &(pAdapter->mppriv.mpt_ctx); + u32 ulAntennaTx, ulAntennaRx; + R_ANTENNA_SELECT_OFDM *p_ofdm_tx; /* OFDM Tx register */ + R_ANTENNA_SELECT_CCK *p_cck_txrx; + u8 r_rx_antenna_ofdm = 0, r_ant_select_cck_val = 0; + u8 chgTx = 0, chgRx = 0; + u32 r_ant_sel_cck_val = 0, r_ant_select_ofdm_val = 0, r_ofdm_tx_en_val = 0; + + ulAntennaTx = pHalData->antenna_tx_path; + ulAntennaRx = pHalData->AntennaRxPath; + + p_ofdm_tx = (R_ANTENNA_SELECT_OFDM *)&r_ant_select_ofdm_val; + p_cck_txrx = (R_ANTENNA_SELECT_CCK *)&r_ant_select_cck_val; + + p_ofdm_tx->r_ant_ht1 = 0x1; + p_ofdm_tx->r_ant_ht2 = 0x2;/*Second TX RF path is A*/ + p_ofdm_tx->r_ant_non_ht = 0x3;/*/ 0x1+0x2=0x3 */ + + switch (ulAntennaTx) { + case ANTENNA_A: + p_ofdm_tx->r_tx_antenna = 0x1; + r_ofdm_tx_en_val = 0x1; + p_ofdm_tx->r_ant_l = 0x1; + p_ofdm_tx->r_ant_ht_s1 = 0x1; + p_ofdm_tx->r_ant_non_ht_s1 = 0x1; + p_cck_txrx->r_ccktx_enable = 0x8; + chgTx = 1; + /*/ From SD3 Willis suggestion !!! Set RF A=TX and B as standby*/ + { + phy_set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 2); + phy_set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 1); + r_ofdm_tx_en_val = 0x3; + /*/ Power save*/ + /*/cosa r_ant_select_ofdm_val = 0x11111111;*/ + /*/ We need to close RFB by SW control*/ + if (pHalData->rf_type == RF_2T2R) { + phy_set_bb_reg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT10, 0); + phy_set_bb_reg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT26, 1); + phy_set_bb_reg(pAdapter, rFPGA0_XB_RFInterfaceOE, BIT10, 0); + phy_set_bb_reg(pAdapter, rFPGA0_XAB_RFParameter, BIT1, 1); + phy_set_bb_reg(pAdapter, rFPGA0_XAB_RFParameter, BIT17, 0); + } + } + pMptCtx->mpt_rf_path = ODM_RF_PATH_A; + break; + case ANTENNA_B: + p_ofdm_tx->r_tx_antenna = 0x2; + r_ofdm_tx_en_val = 0x2; + p_ofdm_tx->r_ant_l = 0x2; + p_ofdm_tx->r_ant_ht_s1 = 0x2; + p_ofdm_tx->r_ant_non_ht_s1 = 0x2; + p_cck_txrx->r_ccktx_enable = 0x4; + chgTx = 1; + /*/ From SD3 Willis suggestion !!! Set RF A as standby*/ + { + phy_set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 1); + phy_set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 2); + + /*/ 2008/10/31 MH From SD3 Willi's suggestion. We must read RF 1T table.*/ + /*/ 2009/01/08 MH From Sd3 Willis. We need to close RFA by SW control*/ + if (pHalData->rf_type == RF_2T2R || pHalData->rf_type == RF_1T2R) { + phy_set_bb_reg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT10, 1); + phy_set_bb_reg(pAdapter, rFPGA0_XA_RFInterfaceOE, BIT10, 0); + phy_set_bb_reg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT26, 0); + /*/phy_set_bb_reg(pAdapter, rFPGA0_XB_RFInterfaceOE, BIT10, 0);*/ + phy_set_bb_reg(pAdapter, rFPGA0_XAB_RFParameter, BIT1, 0); + phy_set_bb_reg(pAdapter, rFPGA0_XAB_RFParameter, BIT17, 1); + } + } + pMptCtx->mpt_rf_path = ODM_RF_PATH_B; + break; + case ANTENNA_AB:/*/ For 8192S*/ + p_ofdm_tx->r_tx_antenna = 0x3; + r_ofdm_tx_en_val = 0x3; + p_ofdm_tx->r_ant_l = 0x3; + p_ofdm_tx->r_ant_ht_s1 = 0x3; + p_ofdm_tx->r_ant_non_ht_s1 = 0x3; + p_cck_txrx->r_ccktx_enable = 0xC; + chgTx = 1; + /*/ From SD3Willis suggestion !!! Set RF B as standby*/ + { + phy_set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 2); + phy_set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 2); + /* Disable Power save*/ + /*cosa r_ant_select_ofdm_val = 0x3321333;*/ + /* 2009/01/08 MH From Sd3 Willis. We need to enable RFA/B by SW control*/ + if (pHalData->rf_type == RF_2T2R) { + phy_set_bb_reg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT10, 0); + + phy_set_bb_reg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT26, 0); + /*/phy_set_bb_reg(pAdapter, rFPGA0_XB_RFInterfaceOE, BIT10, 0);*/ + phy_set_bb_reg(pAdapter, rFPGA0_XAB_RFParameter, BIT1, 1); + phy_set_bb_reg(pAdapter, rFPGA0_XAB_RFParameter, BIT17, 1); + } + } + pMptCtx->mpt_rf_path = ODM_RF_PATH_AB; + break; + default: + break; + } + switch (ulAntennaRx) { + case ANTENNA_A: + r_rx_antenna_ofdm = 0x1; /* A*/ + p_cck_txrx->r_cckrx_enable = 0x0; /* default: A*/ + p_cck_txrx->r_cckrx_enable_2 = 0x0; /* option: A*/ + chgRx = 1; + break; + case ANTENNA_B: + r_rx_antenna_ofdm = 0x2; /*/ B*/ + p_cck_txrx->r_cckrx_enable = 0x1; /*/ default: B*/ + p_cck_txrx->r_cckrx_enable_2 = 0x1; /*/ option: B*/ + chgRx = 1; + break; + case ANTENNA_AB:/*/ For 8192S and 8192E/U...*/ + r_rx_antenna_ofdm = 0x3;/*/ AB*/ + p_cck_txrx->r_cckrx_enable = 0x0;/*/ default:A*/ + p_cck_txrx->r_cckrx_enable_2 = 0x1;/*/ option:B*/ + chgRx = 1; + break; + default: + break; + } + + + if (chgTx && chgRx) { + switch (pHalData->rf_chip) { + case RF_8225: + case RF_8256: + case RF_6052: + /*/r_ant_sel_cck_val = r_ant_select_cck_val;*/ + phy_set_bb_reg(pAdapter, rFPGA1_TxInfo, 0x7fffffff, r_ant_select_ofdm_val); /*/OFDM Tx*/ + phy_set_bb_reg(pAdapter, rFPGA0_TxInfo, 0x0000000f, r_ofdm_tx_en_val); /*/OFDM Tx*/ + phy_set_bb_reg(pAdapter, rOFDM0_TRxPathEnable, 0x0000000f, r_rx_antenna_ofdm); /*/OFDM Rx*/ + phy_set_bb_reg(pAdapter, rOFDM1_TRxPathEnable, 0x0000000f, r_rx_antenna_ofdm); /*/OFDM Rx*/ + phy_set_bb_reg(pAdapter, rCCK0_AFESetting, bMaskByte3, r_ant_select_cck_val);/*/r_ant_sel_cck_val); /CCK TxRx*/ + break; + + default: + RTW_INFO("Unsupported RFChipID for switching antenna.\n"); + break; + } + } +} /* MPT_ProSetRFPath */ + + +void hal_mpt_SetAntenna(PADAPTER pAdapter) + +{ + RTW_INFO("Do %s\n", __func__); + mpt_SetRFPath_819X(pAdapter); + RTW_INFO("mpt_SetRFPath_819X Do %s\n", __func__); +} + +s32 hal_mpt_SetThermalMeter(PADAPTER pAdapter, u8 target_ther) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + + if (!netif_running(pAdapter->pnetdev)) { + return _FAIL; + } + + + if (check_fwstate(&pAdapter->mlmepriv, WIFI_MP_STATE) == false) { + return _FAIL; + } + + + target_ther &= 0xff; + if (target_ther < 0x07) + target_ther = 0x07; + else if (target_ther > 0x1d) + target_ther = 0x1d; + + pHalData->eeprom_thermal_meter = target_ther; + + return _SUCCESS; +} + + +void hal_mpt_TriggerRFThermalMeter(PADAPTER pAdapter) +{ + phy_set_rf_reg(pAdapter, ODM_RF_PATH_A, 0x42, BIT17 | BIT16, 0x03); + +} + + +u8 hal_mpt_ReadRFThermalMeter(PADAPTER pAdapter) + +{ + u32 ThermalValue = 0; + + ThermalValue = (u8)phy_query_rf_reg(pAdapter, ODM_RF_PATH_A, 0x42, 0xfc00); /*0x42: RF Reg[15:10]*/ + return (u8)ThermalValue; + +} + +void hal_mpt_GetThermalMeter(PADAPTER pAdapter, u8 *value) +{ + hal_mpt_TriggerRFThermalMeter(pAdapter); + rtw_msleep_os(1000); + *value = hal_mpt_ReadRFThermalMeter(pAdapter); +} + +void hal_mpt_SetSingleCarrierTx(PADAPTER pAdapter, u8 bStart) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + + pAdapter->mppriv.mpt_ctx.bSingleCarrier = bStart; + + if (bStart) {/*/ Start Single Carrier.*/ + /*/ Start Single Carrier.*/ + /*/ 1. if OFDM block on?*/ + if (!phy_query_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn)) + phy_set_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn, 1); /*set OFDM block on*/ + + /*/ 2. set CCK test mode off, set to CCK normal mode*/ + phy_set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0); + + /*/ 3. turn on scramble setting*/ + phy_set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, 1); + + /*/ 4. Turn On Continue Tx and turn off the other test modes.*/ + phy_set_bb_reg(pAdapter, rOFDM1_LSTF, BIT30 | BIT29 | BIT28, OFDM_SingleCarrier); + } else { + /*/ Stop Single Carrier.*/ + /*/ Stop Single Carrier.*/ + /*/ Turn off all test modes.*/ + phy_set_bb_reg(pAdapter, rOFDM1_LSTF, BIT30 | BIT29 | BIT28, OFDM_ALL_OFF); + + rtw_msleep_os(10); + /*/BB Reset*/ + phy_set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0); + phy_set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1); + } +} + + +void hal_mpt_SetSingleToneTx(PADAPTER pAdapter, u8 bStart) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + PMPT_CONTEXT pMptCtx = &(pAdapter->mppriv.mpt_ctx); + u32 ulAntennaTx = pHalData->antenna_tx_path; + static u32 regRF = 0, regBB0 = 0, regBB1 = 0, regBB2 = 0, regBB3 = 0; + u8 rfPath; + + switch (ulAntennaTx) { + case ANTENNA_B: + rfPath = ODM_RF_PATH_B; + break; + case ANTENNA_C: + rfPath = ODM_RF_PATH_C; + break; + case ANTENNA_D: + rfPath = ODM_RF_PATH_D; + break; + case ANTENNA_A: + default: + rfPath = ODM_RF_PATH_A; + break; + } + + pAdapter->mppriv.mpt_ctx.is_single_tone = bStart; + if (bStart) { + /*/ Start Single Tone.*/ + /*/ <20120326, Kordan> To amplify the power of tone for Xtal calibration. (asked by Edlu)*/ + if (IS_HARDWARE_TYPE_8188E(pAdapter)) { + regRF = phy_query_rf_reg(pAdapter, rfPath, lna_low_gain_3, bRFRegOffsetMask); + phy_set_rf_reg(pAdapter, ODM_RF_PATH_A, lna_low_gain_3, BIT1, 0x1); /*/ RF LO enabled*/ + phy_set_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn, 0x0); + phy_set_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn, 0x0); + } else { /*/ Turn On SingleTone and turn off the other test modes.*/ + phy_set_bb_reg(pAdapter, rOFDM1_LSTF, BIT30 | BIT29 | BIT28, OFDM_SingleTone); + } + write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500); + write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500); + } else {/*/ Stop Single Ton e.*/ + if (IS_HARDWARE_TYPE_8188E(pAdapter)) { + phy_set_rf_reg(pAdapter, ODM_RF_PATH_A, lna_low_gain_3, bRFRegOffsetMask, regRF); + phy_set_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn, 0x1); + phy_set_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn, 0x1); + } + write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100); + write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100); + } +} + +void hal_mpt_SetCarrierSuppressionTx(PADAPTER pAdapter, u8 bStart) +{ + u8 Rate; + + pAdapter->mppriv.mpt_ctx.is_carrier_suppression = bStart; + + Rate = HwRateToMPTRate(pAdapter->mppriv.rateidx); + if (bStart) {/* Start Carrier Suppression.*/ + if (Rate <= MPT_RATE_11M) { + /*/ 1. if CCK block on?*/ + if (!read_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn)) + write_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn, bEnable);/*set CCK block on*/ + + /*/Turn Off All Test Mode*/ + phy_set_bb_reg(pAdapter, rOFDM1_LSTF, BIT30 | BIT29 | BIT28, OFDM_ALL_OFF); + + write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, 0x2); /*/transmit mode*/ + write_bbreg(pAdapter, rCCK0_System, bCCKScramble, 0x0); /*/turn off scramble setting*/ + + /*/Set CCK Tx Test Rate*/ + write_bbreg(pAdapter, rCCK0_System, bCCKTxRate, 0x0); /*/Set FTxRate to 1Mbps*/ + } + + /*Set for dynamic set Power index*/ + write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500); + write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500); + + } else {/* Stop Carrier Suppression.*/ + + if (Rate <= MPT_RATE_11M) { + write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, 0x0); /*normal mode*/ + write_bbreg(pAdapter, rCCK0_System, bCCKScramble, 0x1); /*turn on scramble setting*/ + + /*BB Reset*/ + write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x0); + write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x1); + } + /*Stop for dynamic set Power index*/ + write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100); + write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100); + } + RTW_INFO("\n MPT_ProSetCarrierSupp() is finished.\n"); +} + +u32 hal_mpt_query_phytxok(PADAPTER pAdapter) +{ + PMPT_CONTEXT pMptCtx = &(pAdapter->mppriv.mpt_ctx); + RT_PMAC_TX_INFO PMacTxInfo = pMptCtx->PMacTxInfo; + u16 count = 0; + + if (IS_MPT_CCK_RATE(PMacTxInfo.TX_RATE)) + count = phy_query_bb_reg(pAdapter, 0xF50, bMaskLWord); /* [15:0]*/ + else + count = phy_query_bb_reg(pAdapter, 0xF50, bMaskHWord); /* [31:16]*/ + + if (count > 50000) { + rtw_reset_phy_trx_ok_counters(pAdapter); + pAdapter->mppriv.tx.sended += count; + count = 0; + } + + return pAdapter->mppriv.tx.sended + count; + +} + +static void mpt_StopCckContTx( + PADAPTER pAdapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + PMPT_CONTEXT pMptCtx = &(pAdapter->mppriv.mpt_ctx); + u8 u1bReg; + + pMptCtx->bCckContTx = false; + pMptCtx->bOfdmContTx = false; + + phy_set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0x0); /*normal mode*/ + phy_set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, 0x1); /*turn on scramble setting*/ + + /*BB Reset*/ + phy_set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0); + phy_set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1); + + phy_set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100); + phy_set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100); + +} /* mpt_StopCckContTx */ + + +static void mpt_StopOfdmContTx( + PADAPTER pAdapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + PMPT_CONTEXT pMptCtx = &(pAdapter->mppriv.mpt_ctx); + u8 u1bReg; + u32 data; + + pMptCtx->bCckContTx = false; + pMptCtx->bOfdmContTx = false; + + phy_set_bb_reg(pAdapter, rOFDM1_LSTF, BIT30 | BIT29 | BIT28, OFDM_ALL_OFF); + + rtw_mdelay_os(10); + + /*BB Reset*/ + phy_set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0); + phy_set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1); + + phy_set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100); + phy_set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100); +} /* mpt_StopOfdmContTx */ + + +static void mpt_StartCckContTx( + PADAPTER pAdapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + PMPT_CONTEXT pMptCtx = &(pAdapter->mppriv.mpt_ctx); + u32 cckrate; + + /* 1. if CCK block on */ + if (!phy_query_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn)) + phy_set_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn, 1);/*set CCK block on*/ + + /*Turn Off All Test Mode*/ + phy_set_bb_reg(pAdapter, rOFDM1_LSTF, BIT30 | BIT29 | BIT28, OFDM_ALL_OFF); + + cckrate = pAdapter->mppriv.rateidx; + + phy_set_bb_reg(pAdapter, rCCK0_System, bCCKTxRate, cckrate); + + phy_set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0x2); /*transmit mode*/ + phy_set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, 0x1); /*turn on scramble setting*/ + + phy_set_bb_reg(pAdapter, 0xa14, 0x300, 0x3); /* 0xa15[1:0] = 11 force cck rxiq = 0*/ + phy_set_bb_reg(pAdapter, rOFDM0_TRMuxPar, 0x10000, 0x1); /* 0xc08[16] = 1 force ofdm rxiq = ofdm txiq*/ + phy_set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter2, BIT14, 1); + phy_set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter2, BIT14, 1); + phy_set_bb_reg(pAdapter, 0x0B34, BIT14, 1); + + phy_set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500); + phy_set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500); + + pMptCtx->bCckContTx = true; + pMptCtx->bOfdmContTx = false; + +} /* mpt_StartCckContTx */ + + +static void mpt_StartOfdmContTx( + PADAPTER pAdapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + PMPT_CONTEXT pMptCtx = &(pAdapter->mppriv.mpt_ctx); + + /* 1. if OFDM block on?*/ + if (!phy_query_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn)) + phy_set_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn, 1);/*set OFDM block on*/ + + /* 2. set CCK test mode off, set to CCK normal mode*/ + phy_set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0); + + /* 3. turn on scramble setting*/ + phy_set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, 1); + + phy_set_bb_reg(pAdapter, 0xa14, 0x300, 0x3); /* 0xa15[1:0] = 2b'11*/ + phy_set_bb_reg(pAdapter, rOFDM0_TRMuxPar, 0x10000, 0x1); /* 0xc08[16] = 1*/ + + /* 4. Turn On Continue Tx and turn off the other test modes.*/ + phy_set_bb_reg(pAdapter, rOFDM1_LSTF, BIT30 | BIT29 | BIT28, OFDM_ContinuousTx); + + phy_set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500); + phy_set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500); + + pMptCtx->bCckContTx = false; + pMptCtx->bOfdmContTx = true; +} /* mpt_StartOfdmContTx */ + +void hal_mpt_SetContinuousTx(PADAPTER pAdapter, u8 bStart) +{ + u8 Rate; + + RT_TRACE(_module_mp_, _drv_info_, + ("SetContinuousTx: rate:%d\n", pAdapter->mppriv.rateidx)); + Rate = HwRateToMPTRate(pAdapter->mppriv.rateidx); + pAdapter->mppriv.mpt_ctx.is_start_cont_tx = bStart; + + if (Rate <= MPT_RATE_11M) { + if (bStart) + mpt_StartCckContTx(pAdapter); + else + mpt_StopCckContTx(pAdapter); + + } else if (Rate >= MPT_RATE_6M) { + if (bStart) + mpt_StartOfdmContTx(pAdapter); + else + mpt_StopOfdmContTx(pAdapter); + } +} + +#endif /* CONFIG_MP_INCLUDE*/ diff --git a/drivers/staging/rtl8188eu/hal/hal_phy.c b/drivers/staging/rtl8188eu/hal/hal_phy.c new file mode 100644 index 000000000000..1a2385aae25a --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal_phy.c @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#define _HAL_PHY_C_ + +#include + +/* ******************************************************************************** + * Constant. + * ******************************************************************************** + * 2008/11/20 MH For Debug only, RF */ +static RF_SHADOW_T RF_Shadow[RF6052_MAX_PATH][RF6052_MAX_REG]; + +/** +* Function: PHY_CalculateBitShift +* +* OverView: Get shifted position of the BitMask +* +* Input: +* u32 BitMask, +* +* Output: none +* Return: u32 Return the shift bit bit position of the mask +*/ +u32 +PHY_CalculateBitShift( + u32 BitMask +) +{ + u32 i; + + for (i = 0; i <= 31; i++) { + if (((BitMask >> i) & 0x1) == 1) + break; + } + + return i; +} + + +/* + * ==> RF shadow Operation API Code Section!!! + * + *----------------------------------------------------------------------------- + * Function: PHY_RFShadowRead + * PHY_RFShadowWrite + * PHY_RFShadowCompare + * PHY_RFShadowRecorver + * PHY_RFShadowCompareAll + * PHY_RFShadowRecorverAll + * PHY_RFShadowCompareFlagSet + * PHY_RFShadowRecorverFlagSet + * + * Overview: When we set RF register, we must write shadow at first. + * When we are running, we must compare shadow abd locate error addr. + * Decide to recorver or not. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/20/2008 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +u32 +PHY_RFShadowRead( + PADAPTER Adapter, + u8 eRFPath, + u32 Offset) +{ + return RF_Shadow[eRFPath][Offset].Value; + +} /* PHY_RFShadowRead */ + + +void +PHY_RFShadowWrite( + PADAPTER Adapter, + u8 eRFPath, + u32 Offset, + u32 Data) +{ + RF_Shadow[eRFPath][Offset].Value = (Data & bRFRegOffsetMask); + RF_Shadow[eRFPath][Offset].Driver_Write = true; + +} /* PHY_RFShadowWrite */ + + +bool +PHY_RFShadowCompare( + PADAPTER Adapter, + u8 eRFPath, + u32 Offset) +{ + u32 reg; + /* Check if we need to check the register */ + if (RF_Shadow[eRFPath][Offset].Compare == true) { + reg = rtw_hal_read_rfreg(Adapter, eRFPath, Offset, bRFRegOffsetMask); + /* Compare shadow and real rf register for 20bits!! */ + if (RF_Shadow[eRFPath][Offset].Value != reg) { + /* Locate error position. */ + RF_Shadow[eRFPath][Offset].ErrorOrNot = true; + } + return RF_Shadow[eRFPath][Offset].ErrorOrNot ; + } + return false; +} /* PHY_RFShadowCompare */ + + +void +PHY_RFShadowRecorver( + PADAPTER Adapter, + u8 eRFPath, + u32 Offset) +{ + /* Check if the address is error */ + if (RF_Shadow[eRFPath][Offset].ErrorOrNot == true) { + /* Check if we need to recorver the register. */ + if (RF_Shadow[eRFPath][Offset].Recorver == true) { + rtw_hal_write_rfreg(Adapter, eRFPath, Offset, bRFRegOffsetMask, + RF_Shadow[eRFPath][Offset].Value); + } + } + +} /* PHY_RFShadowRecorver */ + + +void +PHY_RFShadowCompareAll( + PADAPTER Adapter) +{ + u8 eRFPath = 0 ; + u32 Offset = 0, maxReg = GET_RF6052_REAL_MAX_REG(Adapter); + + for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) { + for (Offset = 0; Offset < maxReg; Offset++) + PHY_RFShadowCompare(Adapter, eRFPath, Offset); + } + +} /* PHY_RFShadowCompareAll */ + + +void +PHY_RFShadowRecorverAll( + PADAPTER Adapter) +{ + u8 eRFPath = 0; + u32 Offset = 0, maxReg = GET_RF6052_REAL_MAX_REG(Adapter); + + for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) { + for (Offset = 0; Offset < maxReg; Offset++) + PHY_RFShadowRecorver(Adapter, eRFPath, Offset); + } + +} /* PHY_RFShadowRecorverAll */ + + +void +PHY_RFShadowCompareFlagSet( + PADAPTER Adapter, + u8 eRFPath, + u32 Offset, + u8 Type) +{ + /* Set True or False!!! */ + RF_Shadow[eRFPath][Offset].Compare = Type; + +} /* PHY_RFShadowCompareFlagSet */ + + +void +PHY_RFShadowRecorverFlagSet( + PADAPTER Adapter, + u8 eRFPath, + u32 Offset, + u8 Type) +{ + /* Set True or False!!! */ + RF_Shadow[eRFPath][Offset].Recorver = Type; + +} /* PHY_RFShadowRecorverFlagSet */ + + +void +PHY_RFShadowCompareFlagSetAll( + PADAPTER Adapter) +{ + u8 eRFPath = 0; + u32 Offset = 0, maxReg = GET_RF6052_REAL_MAX_REG(Adapter); + + for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) { + for (Offset = 0; Offset < maxReg; Offset++) { + /* 2008/11/20 MH For S3S4 test, we only check reg 26/27 now!!!! */ + if (Offset != 0x26 && Offset != 0x27) + PHY_RFShadowCompareFlagSet(Adapter, eRFPath, Offset, false); + else + PHY_RFShadowCompareFlagSet(Adapter, eRFPath, Offset, true); + } + } + +} /* PHY_RFShadowCompareFlagSetAll */ + + +void +PHY_RFShadowRecorverFlagSetAll( + PADAPTER Adapter) +{ + u8 eRFPath = 0; + u32 Offset = 0, maxReg = GET_RF6052_REAL_MAX_REG(Adapter); + + for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) { + for (Offset = 0; Offset < maxReg; Offset++) { + /* 2008/11/20 MH For S3S4 test, we only check reg 26/27 now!!!! */ + if (Offset != 0x26 && Offset != 0x27) + PHY_RFShadowRecorverFlagSet(Adapter, eRFPath, Offset, false); + else + PHY_RFShadowRecorverFlagSet(Adapter, eRFPath, Offset, true); + } + } + +} /* PHY_RFShadowCompareFlagSetAll */ + +void +PHY_RFShadowRefresh( + PADAPTER Adapter) +{ + u8 eRFPath = 0; + u32 Offset = 0, maxReg = GET_RF6052_REAL_MAX_REG(Adapter); + + for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) { + for (Offset = 0; Offset < maxReg; Offset++) { + RF_Shadow[eRFPath][Offset].Value = 0; + RF_Shadow[eRFPath][Offset].Compare = false; + RF_Shadow[eRFPath][Offset].Recorver = false; + RF_Shadow[eRFPath][Offset].ErrorOrNot = false; + RF_Shadow[eRFPath][Offset].Driver_Write = false; + } + } + +} /* PHY_RFShadowRead */ diff --git a/drivers/staging/rtl8188eu/hal/hal_usb.c b/drivers/staging/rtl8188eu/hal/hal_usb.c new file mode 100644 index 000000000000..db07579f52db --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal_usb.c @@ -0,0 +1,452 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#define _HAL_USB_C_ + +#include +#include + +int usb_init_recv_priv(_adapter *padapter, u16 ini_in_buf_sz) +{ + struct recv_priv *precvpriv = &padapter->recvpriv; + int i, res = _SUCCESS; + struct recv_buf *precvbuf; + + tasklet_init(&precvpriv->recv_tasklet, + (void(*)(unsigned long))usb_recv_tasklet, + (unsigned long)padapter); + +#ifdef CONFIG_USB_INTERRUPT_IN_PIPE + precvpriv->int_in_urb = usb_alloc_urb(0, GFP_KERNEL); + if (precvpriv->int_in_urb == NULL) { + res = _FAIL; + RTW_INFO("alloc_urb for interrupt in endpoint fail !!!!\n"); + goto exit; + } + precvpriv->int_in_buf = rtw_zmalloc(ini_in_buf_sz); + if (precvpriv->int_in_buf == NULL) { + res = _FAIL; + RTW_INFO("alloc_mem for interrupt in endpoint fail !!!!\n"); + goto exit; + } +#endif /* CONFIG_USB_INTERRUPT_IN_PIPE */ + + /* init recv_buf */ + _rtw_init_queue(&precvpriv->free_recv_buf_queue); + _rtw_init_queue(&precvpriv->recv_buf_pending_queue); +#ifndef CONFIG_USE_USB_BUFFER_ALLOC_RX + /* this is used only when RX_IOBUF is sk_buff */ + skb_queue_head_init(&precvpriv->free_recv_skb_queue); +#endif + + RTW_INFO("NR_RECVBUFF: %d\n", NR_RECVBUFF); + RTW_INFO("MAX_RECVBUF_SZ: %d\n", MAX_RECVBUF_SZ); + precvpriv->pallocated_recv_buf = rtw_zmalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4); + if (precvpriv->pallocated_recv_buf == NULL) { + res = _FAIL; + goto exit; + } + + precvpriv->precv_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4); + + precvbuf = (struct recv_buf *)precvpriv->precv_buf; + + for (i = 0; i < NR_RECVBUFF ; i++) { + INIT_LIST_HEAD(&precvbuf->list); + + spin_lock_init(&precvbuf->recvbuf_lock); + + precvbuf->alloc_sz = MAX_RECVBUF_SZ; + + res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf); + if (res == _FAIL) + break; + + precvbuf->ref_cnt = 0; + precvbuf->adapter = padapter; + + /* list_add_tail(&precvbuf->list, &(precvpriv->free_recv_buf_queue.queue)); */ + + precvbuf++; + } + + precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF; + + skb_queue_head_init(&precvpriv->rx_skb_queue); + +#ifdef CONFIG_RX_INDICATE_QUEUE + memset(&precvpriv->rx_indicate_queue, 0, sizeof(struct ifqueue)); + mtx_init(&precvpriv->rx_indicate_queue.ifq_mtx, "rx_indicate_queue", NULL, MTX_DEF); +#endif /* CONFIG_RX_INDICATE_QUEUE */ + +#ifdef CONFIG_PREALLOC_RECV_SKB + { + int i; + SIZE_PTR tmpaddr = 0; + SIZE_PTR alignment = 0; + struct sk_buff *pskb = NULL; + + RTW_INFO("NR_PREALLOC_RECV_SKB: %d\n", NR_PREALLOC_RECV_SKB); +#ifdef CONFIG_FIX_NR_BULKIN_BUFFER + RTW_INFO("Enable CONFIG_FIX_NR_BULKIN_BUFFER\n"); +#endif + + for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) { +#ifdef CONFIG_PREALLOC_RX_SKB_BUFFER + pskb = rtw_alloc_skb_premem(MAX_RECVBUF_SZ); +#else + pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); +#endif /* CONFIG_PREALLOC_RX_SKB_BUFFER */ + + if (pskb) { + pskb->dev = padapter->pnetdev; + +#ifndef CONFIG_PREALLOC_RX_SKB_BUFFER + tmpaddr = (SIZE_PTR)pskb->data; + alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1); + skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment)); +#endif + skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); + } + } + } +#endif /* CONFIG_PREALLOC_RECV_SKB */ + +exit: + + return res; +} + +void usb_free_recv_priv(_adapter *padapter, u16 ini_in_buf_sz) +{ + int i; + struct recv_buf *precvbuf; + struct recv_priv *precvpriv = &padapter->recvpriv; + + precvbuf = (struct recv_buf *)precvpriv->precv_buf; + + for (i = 0; i < NR_RECVBUFF ; i++) { + rtw_os_recvbuf_resource_free(padapter, precvbuf); + precvbuf++; + } + + if (precvpriv->pallocated_recv_buf) + rtw_mfree(precvpriv->pallocated_recv_buf, NR_RECVBUFF * sizeof(struct recv_buf) + 4); + +#ifdef CONFIG_USB_INTERRUPT_IN_PIPE + if (precvpriv->int_in_urb) + usb_free_urb(precvpriv->int_in_urb); + if (precvpriv->int_in_buf) + rtw_mfree(precvpriv->int_in_buf, ini_in_buf_sz); +#endif /* CONFIG_USB_INTERRUPT_IN_PIPE */ + + if (skb_queue_len(&precvpriv->rx_skb_queue)) + RTW_WARN("rx_skb_queue not empty\n"); + + rtw_skb_queue_purge(&precvpriv->rx_skb_queue); + + if (skb_queue_len(&precvpriv->free_recv_skb_queue)) + RTW_WARN("free_recv_skb_queue not empty, %d\n", skb_queue_len(&precvpriv->free_recv_skb_queue)); + +#if !defined(CONFIG_USE_USB_BUFFER_ALLOC_RX) +#if defined(CONFIG_PREALLOC_RECV_SKB) && defined(CONFIG_PREALLOC_RX_SKB_BUFFER) + { + struct sk_buff *skb; + + while ((skb = skb_dequeue(&precvpriv->free_recv_skb_queue)) != NULL) { + if (rtw_free_skb_premem(skb) != 0) + rtw_skb_free(skb); + } + } +#else + rtw_skb_queue_purge(&precvpriv->free_recv_skb_queue); +#endif /* defined(CONFIG_PREALLOC_RX_SKB_BUFFER) && defined(CONFIG_PREALLOC_RECV_SKB) */ +#endif /* !defined(CONFIG_USE_USB_BUFFER_ALLOC_RX) */ +} + +#ifdef CONFIG_FW_C2H_REG +void usb_c2h_hisr_hdl(_adapter *adapter, u8 *buf) +{ + u8 *c2h_evt = buf; + u8 id, seq, plen; + u8 *payload; + + if (rtw_hal_c2h_reg_hdr_parse(adapter, buf, &id, &seq, &plen, &payload) != _SUCCESS) + return; + + if (0) + RTW_PRINT("%s C2H == %d\n", __func__, id); + + if (rtw_hal_c2h_id_handle_directly(adapter, id, seq, plen, payload)) { + /* Handle directly */ + rtw_hal_c2h_handler(adapter, id, seq, plen, payload); + + /* Replace with special pointer to trigger c2h_evt_clear only */ + if (rtw_cbuf_push(adapter->evtpriv.c2h_queue, (void*)&adapter->evtpriv) != _SUCCESS) + RTW_ERR("%s rtw_cbuf_push fail\n", __func__); + } else { + c2h_evt = rtw_malloc(C2H_REG_LEN); + if (c2h_evt != NULL) { + memcpy(c2h_evt, buf, C2H_REG_LEN); + if (rtw_cbuf_push(adapter->evtpriv.c2h_queue, (void*)c2h_evt) != _SUCCESS) + RTW_ERR("%s rtw_cbuf_push fail\n", __func__); + } else { + /* Error handling for malloc fail */ + if (rtw_cbuf_push(adapter->evtpriv.c2h_queue, (void*)NULL) != _SUCCESS) + RTW_ERR("%s rtw_cbuf_push fail\n", __func__); + } + } + _set_workitem(&adapter->evtpriv.c2h_wk); +} +#endif + +#ifdef CONFIG_USB_SUPPORT_ASYNC_VDN_REQ +int usb_write_async(struct usb_device *udev, u32 addr, void *pdata, u16 len) +{ + u8 request; + u8 requesttype; + u16 wvalue; + u16 index; + int ret; + + requesttype = VENDOR_WRITE;/* write_out */ + request = REALTEK_USB_VENQT_CMD_REQ; + index = REALTEK_USB_VENQT_CMD_IDX;/* n/a */ + + wvalue = (u16)(addr & 0x0000ffff); + + ret = _usbctrl_vendorreq_async_write(udev, request, wvalue, index, pdata, len, requesttype); + + return ret; +} + +int usb_async_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val) +{ + u8 data; + int ret; + struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)pintfhdl->pintf_dev; + struct usb_device *udev = pdvobjpriv->pusbdev; + + data = val; + ret = usb_write_async(udev, addr, &data, 1); + + return ret; +} + +int usb_async_write16(struct intf_hdl *pintfhdl, u32 addr, __le16 val) +{ + __le16 data; + int ret; + struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)pintfhdl->pintf_dev; + struct usb_device *udev = pdvobjpriv->pusbdev; + + data = val; + ret = usb_write_async(udev, addr, &data, 2); + + return ret; +} + +int usb_async_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val) +{ + u32 data; + int ret; + struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)pintfhdl->pintf_dev; + struct usb_device *udev = pdvobjpriv->pusbdev; + + data = val; + ret = usb_write_async(udev, addr, &data, 4); + + return ret; +} +#endif /* CONFIG_USB_SUPPORT_ASYNC_VDN_REQ */ + +u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr) +{ + u8 request; + u8 requesttype; + u16 wvalue; + u16 index; + u16 len; + u8 data = 0; + + request = 0x05; + requesttype = 0x01;/* read_in */ + index = 0;/* n/a */ + + wvalue = (u16)(addr & 0x0000ffff); + len = 1; + usbctrl_vendorreq(pintfhdl, request, wvalue, index, + &data, len, requesttype); + + return data; +} + +u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr) +{ + u8 request; + u8 requesttype; + u16 wvalue; + u16 index; + u16 len; + __le16 data = 0; + + request = 0x05; + requesttype = 0x01;/* read_in */ + index = 0;/* n/a */ + + wvalue = (u16)(addr & 0x0000ffff); + len = 2; + usbctrl_vendorreq(pintfhdl, request, wvalue, index, + &data, len, requesttype); + + return le16_to_cpu(data); +} + +u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr) +{ + u8 request; + u8 requesttype; + u16 wvalue; + u16 index; + u16 len; + __le32 data = 0; + + request = 0x05; + requesttype = 0x01;/* read_in */ + index = 0;/* n/a */ + + wvalue = (u16)(addr & 0x0000ffff); + len = 4; + usbctrl_vendorreq(pintfhdl, request, wvalue, index, + &data, len, requesttype); + + return le32_to_cpu(data); +} + +int usb_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val) +{ + u8 request; + u8 requesttype; + u16 wvalue; + u16 index; + u16 len; + u8 data; + int ret; + + request = 0x05; + requesttype = 0x00;/* write_out */ + index = 0;/* n/a */ + + wvalue = (u16)(addr & 0x0000ffff); + len = 1; + + data = val; + ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, + &data, len, requesttype); + + return ret; +} + +int usb_write16(struct intf_hdl *pintfhdl, u32 addr, __le16 val) +{ + u8 request; + u8 requesttype; + u16 wvalue; + u16 index; + u16 len; + __le16 data; + int ret; + + request = 0x05; + requesttype = 0x00;/* write_out */ + index = 0;/* n/a */ + + wvalue = (u16)(addr & 0x0000ffff); + len = 2; + + data = val; + ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, + &data, len, requesttype); + + return ret; + +} + +int usb_write32(struct intf_hdl *pintfhdl, u32 addr, __le32 val) +{ + u8 request; + u8 requesttype; + u16 wvalue; + u16 index; + u16 len; + __le32 data; + int ret; + + request = 0x05; + requesttype = 0x00;/* write_out */ + index = 0;/* n/a */ + + wvalue = (u16)(addr & 0x0000ffff); + len = 4; + data = val; + ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, + &data, len, requesttype); + + return ret; + +} + +int usb_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata) +{ + u8 request; + u8 requesttype; + u16 wvalue; + u16 index; + u16 len; + u8 buf[VENDOR_CMD_MAX_DATA_LEN] = {0}; + int ret; + + request = 0x05; + requesttype = 0x00;/* write_out */ + index = 0;/* n/a */ + + wvalue = (u16)(addr & 0x0000ffff); + len = length; + memcpy(buf, pdata, len); + ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, + buf, len, requesttype); + + return ret; +} + +void usb_set_intf_ops(_adapter *padapter, struct _io_ops *pops) +{ + memset((u8 *)pops, 0, sizeof(struct _io_ops)); + + pops->_read8 = &usb_read8; + pops->_read16 = &usb_read16; + pops->_read32 = &usb_read32; + pops->_read_mem = &usb_read_mem; + pops->_read_port = &usb_read_port; + + pops->_write8 = &usb_write8; + pops->_write16 = &usb_write16; + pops->_write32 = &usb_write32; + pops->_writeN = &usb_writeN; + +#ifdef CONFIG_USB_SUPPORT_ASYNC_VDN_REQ + pops->_write8_async = &usb_async_write8; + pops->_write16_async = &usb_async_write16; + pops->_write32_async = &usb_async_write32; +#endif + pops->_write_mem = &usb_write_mem; + pops->_write_port = &usb_write_port; + + pops->_read_port_cancel = &usb_read_port_cancel; + pops->_write_port_cancel = &usb_write_port_cancel; + +#ifdef CONFIG_USB_INTERRUPT_IN_PIPE + pops->_read_interrupt = &usb_read_interrupt; +#endif + +} diff --git a/drivers/staging/rtl8188eu/hal/hal_usb_led.c b/drivers/staging/rtl8188eu/hal/hal_usb_led.c new file mode 100644 index 000000000000..d777aa501635 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/hal_usb_led.c @@ -0,0 +1,4235 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#include +#include + +/* + * Description: + * Implementation of LED blinking behavior. + * It toggle off LED and schedule corresponding timer if necessary. + * */ +static void +SwLedBlink( + PLED_USB pLed +) +{ + _adapter *padapter = pLed->padapter; + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + u8 bStopBlinking = false; + + /* Change LED according to BlinkingLedState specified. */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + SwLedOn(padapter, pLed); + } else { + SwLedOff(padapter, pLed); + } + + /* Determine if we shall change LED state again. */ + pLed->BlinkTimes--; + switch (pLed->CurrLedState) { + + case LED_BLINK_NORMAL: + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + break; + + case LED_BLINK_StartToBlink: + if (check_fwstate(pmlmepriv, _FW_LINKED) && check_fwstate(pmlmepriv, WIFI_STATION_STATE)) + bStopBlinking = true; + if (check_fwstate(pmlmepriv, _FW_LINKED) && + (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) + bStopBlinking = true; + else if (pLed->BlinkTimes == 0) + bStopBlinking = true; + break; + + case LED_BLINK_WPS: + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + break; + + + default: + bStopBlinking = true; + break; + + } + + if (bStopBlinking) { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on) + SwLedOff(padapter, pLed); + else if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) && (pLed->bLedOn == false)) + SwLedOn(padapter, pLed); + else if ((check_fwstate(pmlmepriv, _FW_LINKED) == false) && pLed->bLedOn == true) + SwLedOff(padapter, pLed); + + pLed->BlinkTimes = 0; + pLed->bLedBlinkInProgress = false; + } else { + /* Assign LED state to toggle. */ + if (pLed->BlinkingLedState == RTW_LED_ON) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + + /* Schedule a timer to toggle LED state. */ + switch (pLed->CurrLedState) { + case LED_BLINK_NORMAL: + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + break; + + case LED_BLINK_SLOWLY: + case LED_BLINK_StartToBlink: + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); + break; + + case LED_BLINK_WPS: { + if (pLed->BlinkingLedState == RTW_LED_ON) + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LONG_INTERVAL); + else + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LONG_INTERVAL); + } + break; + + default: + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); + break; + } + } +} + +static void +SwLedBlink1( + PLED_USB pLed +) +{ + _adapter *padapter = pLed->padapter; + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + struct led_priv *ledpriv = &(padapter->ledpriv); + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + PLED_USB pLed1 = &(ledpriv->SwLed1); + u8 bStopBlinking = false; + + u32 uLedBlinkNoLinkInterval = LED_BLINK_NO_LINK_INTERVAL_ALPHA; /* add by ylb 20121012 for customer led for alpha */ + if (pHalData->CustomerID == RT_CID_819x_ALPHA_Dlink) + uLedBlinkNoLinkInterval = LED_BLINK_NO_LINK_INTERVAL_ALPHA_500MS; + + if (pHalData->CustomerID == RT_CID_819x_CAMEO) + pLed = &(ledpriv->SwLed1); + + /* Change LED according to BlinkingLedState specified. */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + SwLedOn(padapter, pLed); + } else { + SwLedOff(padapter, pLed); + } + + + if (pHalData->CustomerID == RT_CID_DEFAULT) { + if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { + if (!pLed1->bSWLedCtrl) { + SwLedOn(padapter, pLed1); + pLed1->bSWLedCtrl = true; + } else if (!pLed1->bLedOn) + SwLedOn(padapter, pLed1); + } else { + if (!pLed1->bSWLedCtrl) { + SwLedOff(padapter, pLed1); + pLed1->bSWLedCtrl = true; + } else if (pLed1->bLedOn) + SwLedOff(padapter, pLed1); + } + } + + switch (pLed->CurrLedState) { + case LED_BLINK_SLOWLY: + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), uLedBlinkNoLinkInterval);/* change by ylb 20121012 for customer led for alpha */ + break; + + case LED_BLINK_NORMAL: + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA); + break; + + case LED_BLINK_SCAN: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + + if (bStopBlinking) { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on) + SwLedOff(padapter, pLed); + else if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { + pLed->bLedLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_NORMAL; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA); + + } else if (check_fwstate(pmlmepriv, _FW_LINKED) == false) { + pLed->bLedNoLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), uLedBlinkNoLinkInterval); + } + pLed->bLedScanBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on) + SwLedOff(padapter, pLed); + else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + } + } + break; + + case LED_BLINK_TXRX: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + if (bStopBlinking) { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on) + SwLedOff(padapter, pLed); + else if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { + pLed->bLedLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_NORMAL; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA); + } else if (check_fwstate(pmlmepriv, _FW_LINKED) == false) { + pLed->bLedNoLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), uLedBlinkNoLinkInterval); + } + pLed->BlinkTimes = 0; + pLed->bLedBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on) + SwLedOff(padapter, pLed); + else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + } + break; + + case LED_BLINK_WPS: + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + break; + + case LED_BLINK_WPS_STOP: /* WPS success */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA); + bStopBlinking = false; + } else + bStopBlinking = true; + + if (bStopBlinking) { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on) + SwLedOff(padapter, pLed); + else { + pLed->bLedLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_NORMAL; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA); + } + pLed->bLedWPSBlinkInProgress = false; + } + break; + + default: + break; + } + +} + +static void +SwLedBlink2( + PLED_USB pLed +) +{ + _adapter *padapter = pLed->padapter; + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + u8 bStopBlinking = false; + + /* Change LED according to BlinkingLedState specified. */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + SwLedOn(padapter, pLed); + } else { + SwLedOff(padapter, pLed); + } + + switch (pLed->CurrLedState) { + case LED_BLINK_SCAN: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + + if (bStopBlinking) { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on) + SwLedOff(padapter, pLed); + else if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + SwLedOn(padapter, pLed); + + } else if (check_fwstate(pmlmepriv, _FW_LINKED) == false) { + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + SwLedOff(padapter, pLed); + } + pLed->bLedScanBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on) + SwLedOff(padapter, pLed); + else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + } + } + break; + + case LED_BLINK_TXRX: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + if (bStopBlinking) { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on) + SwLedOff(padapter, pLed); + else if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + SwLedOn(padapter, pLed); + + } else if (check_fwstate(pmlmepriv, _FW_LINKED) == false) { + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + SwLedOff(padapter, pLed); + } + pLed->bLedBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on) + SwLedOff(padapter, pLed); + else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + } + break; + + default: + break; + } + +} + +static void +SwLedBlink3( + PLED_USB pLed +) +{ + _adapter *padapter = pLed->padapter; + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + u8 bStopBlinking = false; + + /* Change LED according to BlinkingLedState specified. */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + SwLedOn(padapter, pLed); + } else { + if (pLed->CurrLedState != LED_BLINK_WPS_STOP) + SwLedOff(padapter, pLed); + } + + switch (pLed->CurrLedState) { + case LED_BLINK_SCAN: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + + if (bStopBlinking) { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on) + SwLedOff(padapter, pLed); + else if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + if (!pLed->bLedOn) + SwLedOn(padapter, pLed); + + } else if (check_fwstate(pmlmepriv, _FW_LINKED) == false) { + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + if (pLed->bLedOn) + SwLedOff(padapter, pLed); + + } + pLed->bLedScanBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on) + SwLedOff(padapter, pLed); + else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + } + } + break; + + case LED_BLINK_TXRX: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + if (bStopBlinking) { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on) + SwLedOff(padapter, pLed); + else if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + + if (!pLed->bLedOn) + SwLedOn(padapter, pLed); + + } else if (check_fwstate(pmlmepriv, _FW_LINKED) == false) { + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + + if (pLed->bLedOn) + SwLedOff(padapter, pLed); + + + } + pLed->bLedBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on) + SwLedOff(padapter, pLed); + else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + } + break; + + case LED_BLINK_WPS: + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + break; + + case LED_BLINK_WPS_STOP: /* WPS success */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA); + bStopBlinking = false; + } else + bStopBlinking = true; + + if (bStopBlinking) { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on) + SwLedOff(padapter, pLed); + else { + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + SwLedOn(padapter, pLed); + } + pLed->bLedWPSBlinkInProgress = false; + } + break; + + + default: + break; + } + +} + + +static void +SwLedBlink4( + PLED_USB pLed +) +{ + _adapter *padapter = pLed->padapter; + struct led_priv *ledpriv = &(padapter->ledpriv); + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + PLED_USB pLed1 = &(ledpriv->SwLed1); + u8 bStopBlinking = false; + + /* Change LED according to BlinkingLedState specified. */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + SwLedOn(padapter, pLed); + } else { + SwLedOff(padapter, pLed); + } + + if (!pLed1->bLedWPSBlinkInProgress && pLed1->BlinkingLedState == LED_UNKNOWN) { + pLed1->BlinkingLedState = RTW_LED_OFF; + pLed1->CurrLedState = RTW_LED_OFF; + SwLedOff(padapter, pLed1); + } + + switch (pLed->CurrLedState) { + case LED_BLINK_SLOWLY: + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + break; + + case LED_BLINK_StartToBlink: + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + } + break; + + case LED_BLINK_SCAN: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = false; + + if (bStopBlinking) { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(padapter, pLed); + else { + pLed->bLedNoLinkBlinkInProgress = false; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + } + pLed->bLedScanBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(padapter, pLed); + else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + } + } + break; + + case LED_BLINK_TXRX: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + if (bStopBlinking) { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(padapter, pLed); + else { + pLed->bLedNoLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + } + pLed->bLedBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(padapter, pLed); + else { + + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + } + break; + + case LED_BLINK_WPS: + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + } + break; + + case LED_BLINK_WPS_STOP: /* WPS authentication fail */ + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + break; + + case LED_BLINK_WPS_STOP_OVERLAP: /* WPS session overlap */ + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) { + if (pLed->bLedOn) + pLed->BlinkTimes = 1; + else + bStopBlinking = true; + } + + if (bStopBlinking) { + pLed->BlinkTimes = 10; + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA); + } else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + } + break; + + case LED_BLINK_ALWAYS_ON: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + if (bStopBlinking) { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(padapter, pLed); + else { + pLed->bLedNoLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + } + pLed->bLedBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS) { + SwLedOff(padapter, pLed); + } else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + } + break; + + default: + break; + } + + + +} + +static void +SwLedBlink5( + PLED_USB pLed +) +{ + _adapter *padapter = pLed->padapter; + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + u8 bStopBlinking = false; + + /* Change LED according to BlinkingLedState specified. */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + SwLedOn(padapter, pLed); + } else { + SwLedOff(padapter, pLed); + } + + switch (pLed->CurrLedState) { + case LED_BLINK_SCAN: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + + if (bStopBlinking) { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS) { + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + if (pLed->bLedOn) + SwLedOff(padapter, pLed); + } else { + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + if (!pLed->bLedOn) + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + + pLed->bLedScanBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(padapter, pLed); + else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + } + } + break; + + + case LED_BLINK_TXRX: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + + if (bStopBlinking) { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS) { + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + if (pLed->bLedOn) + SwLedOff(padapter, pLed); + } else { + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + if (!pLed->bLedOn) + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + + pLed->bLedBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(padapter, pLed); + else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + } + break; + + default: + break; + } + + + +} + +static void +SwLedBlink6( + PLED_USB pLed +) +{ + _adapter *padapter = pLed->padapter; + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + u8 bStopBlinking = false; + + /* Change LED according to BlinkingLedState specified. */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + SwLedOn(padapter, pLed); + } else { + SwLedOff(padapter, pLed); + } + +} + +static void +SwLedBlink7( + PLED_USB pLed +) +{ + PADAPTER Adapter = pLed->padapter; + struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv); + bool bStopBlinking = false; + + /* Change LED according to BlinkingLedState specified. */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + SwLedOn(Adapter, pLed); + } else { + if (pLed->CurrLedState != LED_BLINK_WPS_STOP) + SwLedOff(Adapter, pLed); + } + + switch (pLed->CurrLedState) { + case LED_BLINK_SCAN: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + + if (bStopBlinking) { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on) + SwLedOff(Adapter, pLed); + else if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + if (!pLed->bLedOn) + SwLedOn(Adapter, pLed); + + } else if (check_fwstate(pmlmepriv, _FW_LINKED) == false) { + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + if (pLed->bLedOn) + SwLedOff(Adapter, pLed); + + } + pLed->bLedScanBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on) + SwLedOff(Adapter, pLed); + else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_NETGEAR); + } + } + break; + + case LED_BLINK_WPS: + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_NETGEAR); + break; + + case LED_BLINK_WPS_STOP: /* WPS success */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_NETGEAR); + bStopBlinking = false; + } else + bStopBlinking = true; + + if (bStopBlinking) { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on) + SwLedOff(Adapter, pLed); + else { + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + SwLedOn(Adapter, pLed); + } + pLed->bLedWPSBlinkInProgress = false; + } + break; + + + default: + break; + } + + +} + +static void +SwLedBlink8( + PLED_USB pLed +) +{ + PADAPTER Adapter = pLed->padapter; + + /* Change LED according to BlinkingLedState specified. */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + SwLedOn(Adapter, pLed); + } else { + SwLedOff(Adapter, pLed); + } + + +} + +/* page added for Belkin AC950. 20120813 */ +static void +SwLedBlink9( + PLED_USB pLed +) +{ + PADAPTER Adapter = pLed->padapter; + struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv); + bool bStopBlinking = false; + + /* Change LED according to BlinkingLedState specified. */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + SwLedOn(Adapter, pLed); + } else { + SwLedOff(Adapter, pLed); + } + /* RTW_INFO("%s, pLed->CurrLedState=%d, pLed->BlinkingLedState=%d\n", __func__, pLed->CurrLedState, pLed->BlinkingLedState); */ + + + switch (pLed->CurrLedState) { + case RTW_LED_ON: + SwLedOn(Adapter, pLed); + break; + + case RTW_LED_OFF: + SwLedOff(Adapter, pLed); + break; + + case LED_BLINK_SLOWLY: + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + break; + + case LED_BLINK_StartToBlink: + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + } + break; + + case LED_BLINK_SCAN: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + + if (bStopBlinking) { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on) + SwLedOff(Adapter, pLed); + else if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { + pLed->bLedLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA); + } else if (check_fwstate(pmlmepriv, _FW_LINKED) == false) { + pLed->bLedNoLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + } + pLed->BlinkTimes = 0; + pLed->bLedBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(Adapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(Adapter, pLed); + else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + } + } + break; + + case LED_BLINK_TXRX: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + if (bStopBlinking) { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(Adapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(Adapter, pLed); + else { + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + pLed->bLedBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(Adapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(Adapter, pLed); + else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + } + break; + + case LED_BLINK_WPS: + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + } + break; + + case LED_BLINK_WPS_STOP: /* WPS authentication fail */ + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + break; + + case LED_BLINK_WPS_STOP_OVERLAP: /* WPS session overlap */ + pLed->BlinkTimes--; + pLed->BlinkCounter--; + if (pLed->BlinkCounter == 0) { + pLed->BlinkingLedState = RTW_LED_OFF; + pLed->CurrLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + } else { + if (pLed->BlinkTimes == 0) { + if (pLed->bLedOn) + pLed->BlinkTimes = 1; + else + bStopBlinking = true; + } + + if (bStopBlinking) { + pLed->BlinkTimes = 10; + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA); + } else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + } + } + break; + + case LED_BLINK_ALWAYS_ON: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + if (bStopBlinking) { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(Adapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(Adapter, pLed); + else { + pLed->bLedNoLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + } + pLed->bLedBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(Adapter)->rfoff_reason > RF_CHANGE_BY_PS) { + SwLedOff(Adapter, pLed); + } else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + } + break; + + case LED_BLINK_LINK_IN_PROCESS: + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ON_BELKIN); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_OFF_BELKIN); + } + break; + + case LED_BLINK_AUTH_ERROR: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + if (bStopBlinking == false) { + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_ERROR_INTERVAL_BELKIN); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_ERROR_INTERVAL_BELKIN); + } + } else { + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_ERROR_INTERVAL_BELKIN); + } + break; + + default: + break; + } + +} + +/* page added for Netgear A6200V2. 20120827 */ +static void +SwLedBlink10( + PLED_USB pLed +) +{ + PADAPTER Adapter = pLed->padapter; + struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv); + bool bStopBlinking = false; + + /* Change LED according to BlinkingLedState specified. */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + SwLedOn(Adapter, pLed); + } else { + SwLedOff(Adapter, pLed); + } + + + switch (pLed->CurrLedState) { + case RTW_LED_ON: + SwLedOn(Adapter, pLed); + break; + + case RTW_LED_OFF: + SwLedOff(Adapter, pLed); + break; + + case LED_BLINK_SLOWLY: + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + break; + + case LED_BLINK_StartToBlink: + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + } + break; + + case LED_BLINK_SCAN: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + + if (bStopBlinking) { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on) + SwLedOff(Adapter, pLed); + else if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { + pLed->bLedNoLinkBlinkInProgress = false; + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + } + pLed->BlinkTimes = 0; + pLed->bLedBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(Adapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(Adapter, pLed); + else { + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_NETGEAR); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_SLOWLY_INTERVAL_NETGEAR + LED_BLINK_LINK_INTERVAL_NETGEAR); + } + } + } + break; + + case LED_BLINK_WPS: + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_NETGEAR); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL + LED_BLINK_LINK_INTERVAL_NETGEAR); + } + break; + + case LED_BLINK_WPS_STOP: /* WPS authentication fail */ + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + break; + + case LED_BLINK_WPS_STOP_OVERLAP: /* WPS session overlap */ + pLed->BlinkTimes--; + pLed->BlinkCounter--; + if (pLed->BlinkCounter == 0) { + pLed->BlinkingLedState = RTW_LED_OFF; + pLed->CurrLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + } else { + if (pLed->BlinkTimes == 0) { + if (pLed->bLedOn) + pLed->BlinkTimes = 1; + else + bStopBlinking = true; + } + + if (bStopBlinking) { + pLed->BlinkTimes = 10; + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA); + } else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + } + } + break; + + case LED_BLINK_ALWAYS_ON: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + if (bStopBlinking) { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(Adapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(Adapter, pLed); + else { + pLed->bLedNoLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + } + pLed->bLedBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(Adapter)->rfoff_reason > RF_CHANGE_BY_PS) { + SwLedOff(Adapter, pLed); + } else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + } + break; + + case LED_BLINK_LINK_IN_PROCESS: + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ON_BELKIN); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_OFF_BELKIN); + } + break; + + case LED_BLINK_AUTH_ERROR: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + if (bStopBlinking == false) { + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_ERROR_INTERVAL_BELKIN); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_ERROR_INTERVAL_BELKIN); + } + } else { + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_ERROR_INTERVAL_BELKIN); + } + break; + + default: + break; + } +} + +static void +SwLedBlink11( + PLED_USB pLed +) +{ + PADAPTER Adapter = pLed->padapter; + struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv); + bool bStopBlinking = false; + + /* Change LED according to BlinkingLedState specified. */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + SwLedOn(Adapter, pLed); + } else { + SwLedOff(Adapter, pLed); + } + + switch (pLed->CurrLedState) { + case LED_BLINK_TXRX: + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(Adapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(Adapter, pLed); + else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + } + + break; + + case LED_BLINK_WPS: + if (pLed->BlinkTimes == 5) { + SwLedOn(Adapter, pLed); + _set_timer(&(pLed->BlinkTimer), LED_CM11_LINK_ON_INTERVEL); + } else { + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_CM11_BLINK_INTERVAL); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_CM11_BLINK_INTERVAL); + } + } + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + if (bStopBlinking == true) + pLed->BlinkTimes = 5; + break; + + case LED_BLINK_WPS_STOP: /* WPS authentication fail */ + if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + } else { + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + SwLedOn(Adapter, pLed); + _set_timer(&(pLed->BlinkTimer), 0); + } + break; + + default: + break; + } + +} + +static void +SwLedBlink12( + PLED_USB pLed +) +{ + PADAPTER Adapter = pLed->padapter; + struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv); + bool bStopBlinking = false; + + /* Change LED according to BlinkingLedState specified. */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + SwLedOn(Adapter, pLed); + } else { + SwLedOff(Adapter, pLed); + } + + switch (pLed->CurrLedState) { + case LED_BLINK_SLOWLY: + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + break; + + case LED_BLINK_TXRX: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + + if (bStopBlinking) { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(Adapter)->rfoff_reason > RF_CHANGE_BY_PS) { + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + if (pLed->bLedOn) + SwLedOff(Adapter, pLed); + } else { + pLed->bLedNoLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + } + + pLed->bLedBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(Adapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(Adapter, pLed); + else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + } + break; + + default: + break; + } + + + +} + +static void +SwLedBlink13( + PLED_USB pLed +) +{ + PADAPTER Adapter = pLed->padapter; + struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv); + bool bStopBlinking = false; + static u8 LinkBlinkCnt = 0; + + /* Change LED according to BlinkingLedState specified. */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + SwLedOn(Adapter, pLed); + } else { + if (pLed->CurrLedState != LED_BLINK_WPS_STOP) + SwLedOff(Adapter, pLed); + } + switch (pLed->CurrLedState) { + case LED_BLINK_LINK_IN_PROCESS: + if (!pLed->bLedWPSBlinkInProgress) + LinkBlinkCnt++; + + if (LinkBlinkCnt > 15) { + LinkBlinkCnt = 0; + pLed->bLedBlinkInProgress = false; + break; + } + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), 500); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), 500); + } + + break; + + case LED_BLINK_WPS: + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_WPS_BLINK_ON_INTERVAL_NETGEAR); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_WPS_BLINK_OFF_INTERVAL_NETGEAR); + } + + break; + + case LED_BLINK_WPS_STOP: /* WPS success */ + SwLedOff(Adapter, pLed); + pLed->bLedWPSBlinkInProgress = false; + break; + + default: + LinkBlinkCnt = 0; + break; + } + + +} + +static void +SwLedBlink14( + PLED_USB pLed +) +{ + PADAPTER Adapter = pLed->padapter; + struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv); + bool bStopBlinking = false; + static u8 LinkBlinkCnt = 0; + + /* Change LED according to BlinkingLedState specified. */ + if (pLed->BlinkingLedState == RTW_LED_ON) { + SwLedOn(Adapter, pLed); + } else { + if (pLed->CurrLedState != LED_BLINK_WPS_STOP) + SwLedOff(Adapter, pLed); + } + switch (pLed->CurrLedState) { + case LED_BLINK_TXRX: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + if (bStopBlinking) { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(Adapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(Adapter, pLed); + else + SwLedOn(Adapter, pLed); + pLed->bLedBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(Adapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(Adapter, pLed); + else { + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + } + } + + break; + + default: + LinkBlinkCnt = 0; + break; + } + +} + +static void +SwLedBlink15( + PLED_USB pLed +) +{ + PADAPTER Adapter = pLed->padapter; + struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv); + bool bStopBlinking = false; + static u8 LinkBlinkCnt = 0; + /* Change LED according to BlinkingLedState specified. */ + + if (pLed->BlinkingLedState == RTW_LED_ON) { + SwLedOn(Adapter, pLed); + } else { + if (pLed->CurrLedState != LED_BLINK_WPS_STOP) + SwLedOff(Adapter, pLed); + } + switch (pLed->CurrLedState) { + case LED_BLINK_WPS: + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_WPS_BLINK_ON_INTERVAL_DLINK); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_WPS_BLINK_OFF_INTERVAL_DLINK); + } + break; + + case LED_BLINK_WPS_STOP: /* WPS success */ + + if (pLed->BlinkingLedState == RTW_LED_OFF) { + pLed->bLedWPSBlinkInProgress = false; + return; + } + + pLed->CurrLedState = LED_BLINK_WPS_STOP; + pLed->BlinkingLedState = RTW_LED_OFF; + + _set_timer(&(pLed->BlinkTimer), LED_WPS_BLINK_LINKED_ON_INTERVAL_DLINK); + break; + + case LED_BLINK_NO_LINK: { + static bool bLedOn = true; + if (bLedOn) { + bLedOn = false; + pLed->BlinkingLedState = RTW_LED_OFF; + } else { + bLedOn = true; + pLed->BlinkingLedState = RTW_LED_ON; + } + pLed->bLedBlinkInProgress = true; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL); + } + break; + + case LED_BLINK_LINK_IDEL: { + static bool bLedOn = true; + if (bLedOn) { + bLedOn = false; + pLed->BlinkingLedState = RTW_LED_OFF; + } else { + bLedOn = true; + pLed->BlinkingLedState = RTW_LED_ON; + + } + pLed->bLedBlinkInProgress = true; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_IDEL_INTERVAL); + } + break; + + case LED_BLINK_SCAN: { + static u8 BlinkTime = 0; + if (BlinkTime % 2 == 0) + pLed->BlinkingLedState = RTW_LED_ON; + else + pLed->BlinkingLedState = RTW_LED_OFF; + BlinkTime++; + + if (BlinkTime < 24) { + pLed->bLedBlinkInProgress = true; + + if (pLed->BlinkingLedState == RTW_LED_ON) + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_OFF_INTERVAL); + else + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_ON_INTERVAL); + } else { + /* if(pLed->OLDLedState ==LED_NO_LINK_BLINK) */ + if (check_fwstate(pmlmepriv, _FW_LINKED) == false) { + pLed->CurrLedState = LED_BLINK_NO_LINK; + pLed->BlinkingLedState = RTW_LED_ON; + + _set_timer(&(pLed->BlinkTimer), 100); + } + BlinkTime = 0; + } + } + break; + + case LED_BLINK_TXRX: + pLed->BlinkTimes--; + if (pLed->BlinkTimes == 0) + bStopBlinking = true; + if (bStopBlinking) { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(Adapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(Adapter, pLed); + else + SwLedOn(Adapter, pLed); + pLed->bLedBlinkInProgress = false; + } else { + if (adapter_to_pwrctl(Adapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(Adapter)->rfoff_reason > RF_CHANGE_BY_PS) + SwLedOff(Adapter, pLed); + else { + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + } + break; + + default: + LinkBlinkCnt = 0; + break; + } + +} + +/* + * Description: + * Handler function of LED Blinking. + * We dispatch acture LED blink action according to LedStrategy. + * */ +void BlinkHandler(PLED_USB pLed) +{ + _adapter *padapter = pLed->padapter; + struct led_priv *ledpriv = &(padapter->ledpriv); + + /* RTW_INFO("%s (%s:%d)\n",__func__, current->comm, current->pid); */ + + if (RTW_CANNOT_RUN(padapter) || (!rtw_is_hw_init_completed(padapter))) { + /*RTW_INFO("%s bDriverStopped:%s, bSurpriseRemoved:%s\n" + , __func__ + , rtw_is_drv_stopped(padapter)?"True":"False" + , rtw_is_surprise_removed(padapter)?"True":"False" );*/ + return; + } + + switch (ledpriv->LedStrategy) { + case SW_LED_MODE0: + SwLedBlink(pLed); + break; + + case SW_LED_MODE1: + SwLedBlink1(pLed); + break; + + case SW_LED_MODE2: + SwLedBlink2(pLed); + break; + + case SW_LED_MODE3: + SwLedBlink3(pLed); + break; + + case SW_LED_MODE4: + SwLedBlink4(pLed); + break; + + case SW_LED_MODE5: + SwLedBlink5(pLed); + break; + + case SW_LED_MODE6: + SwLedBlink6(pLed); + break; + + case SW_LED_MODE7: + SwLedBlink7(pLed); + break; + + case SW_LED_MODE8: + SwLedBlink8(pLed); + break; + + case SW_LED_MODE9: + SwLedBlink9(pLed); + break; + + case SW_LED_MODE10: + SwLedBlink10(pLed); + break; + + case SW_LED_MODE11: + SwLedBlink11(pLed); + break; + + case SW_LED_MODE12: + SwLedBlink12(pLed); + break; + + case SW_LED_MODE13: + SwLedBlink13(pLed); + break; + + case SW_LED_MODE14: + SwLedBlink14(pLed); + break; + + case SW_LED_MODE15: + SwLedBlink15(pLed); + break; + + default: + /* SwLedBlink(pLed); */ + break; + } +} + +/* + * Description: + * Callback function of LED BlinkTimer, + * it just schedules to corresponding BlinkWorkItem/led_blink_hdl + * */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) +void BlinkTimerCallback(void *data) +#else +void BlinkTimerCallback(struct timer_list *t) +#endif +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) + PLED_USB pLed = (PLED_USB)data; +#else + PLED_USB pLed = from_timer(pLed, t, BlinkTimer); +#endif + _adapter *padapter = pLed->padapter; + + /* RTW_INFO("%s\n", __func__); */ + + if (RTW_CANNOT_RUN(padapter) || (!rtw_is_hw_init_completed(padapter))) { + /*RTW_INFO("%s bDriverStopped:%s, bSurpriseRemoved:%s\n" + , __func__ + , rtw_is_drv_stopped(padapter)?"True":"False" + , rtw_is_surprise_removed(padapter)?"True":"False" );*/ + return; + } + +#ifdef CONFIG_LED_HANDLED_BY_CMD_THREAD + rtw_led_blink_cmd(padapter, (void *)pLed); +#else + _set_workitem(&(pLed->BlinkWorkItem)); +#endif +} + +/* + * Description: + * Callback function of LED BlinkWorkItem. + * We dispatch acture LED blink action according to LedStrategy. + * */ +void BlinkWorkItemCallback(_workitem *work) +{ + PLED_USB pLed = container_of(work, LED_USB, BlinkWorkItem); + BlinkHandler(pLed); +} + +static void +SwLedControlMode0( + _adapter *padapter, + LED_CTL_MODE LedAction +) +{ + struct led_priv *ledpriv = &(padapter->ledpriv); + PLED_USB pLed = &(ledpriv->SwLed1); + + /* Decide led state */ + switch (LedAction) { + case LED_CTL_TX: + case LED_CTL_RX: + if (pLed->bLedBlinkInProgress == false) { + pLed->bLedBlinkInProgress = true; + + pLed->CurrLedState = LED_BLINK_NORMAL; + pLed->BlinkTimes = 2; + + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + } + break; + + case LED_CTL_START_TO_LINK: + if (pLed->bLedBlinkInProgress == false) { + pLed->bLedBlinkInProgress = true; + + pLed->CurrLedState = LED_BLINK_StartToBlink; + pLed->BlinkTimes = 24; + + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); + } else + pLed->CurrLedState = LED_BLINK_StartToBlink; + break; + + case LED_CTL_LINK: + pLed->CurrLedState = RTW_LED_ON; + if (pLed->bLedBlinkInProgress == false) { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), 0); + } + break; + + case LED_CTL_NO_LINK: + pLed->CurrLedState = RTW_LED_OFF; + if (pLed->bLedBlinkInProgress == false) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), 0); + } + break; + + case LED_CTL_POWER_OFF: + pLed->CurrLedState = RTW_LED_OFF; + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + SwLedOff(padapter, pLed); + break; + + case LED_CTL_START_WPS: + if (pLed->bLedBlinkInProgress == false || pLed->CurrLedState == RTW_LED_ON) { + pLed->bLedBlinkInProgress = true; + + pLed->CurrLedState = LED_BLINK_WPS; + pLed->BlinkTimes = 20; + + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LONG_INTERVAL); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LONG_INTERVAL); + } + } + break; + + case LED_CTL_STOP_WPS: + if (pLed->bLedBlinkInProgress) { + pLed->CurrLedState = RTW_LED_OFF; + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + break; + + + default: + break; + } + + +} + +/* ALPHA, added by chiyoko, 20090106 */ +static void +SwLedControlMode1( + _adapter *padapter, + LED_CTL_MODE LedAction +) +{ + struct led_priv *ledpriv = &(padapter->ledpriv); + PLED_USB pLed = &(ledpriv->SwLed0); + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + + u32 uLedBlinkNoLinkInterval = LED_BLINK_NO_LINK_INTERVAL_ALPHA; /* add by ylb 20121012 for customer led for alpha */ + if (pHalData->CustomerID == RT_CID_819x_ALPHA_Dlink) + uLedBlinkNoLinkInterval = LED_BLINK_NO_LINK_INTERVAL_ALPHA_500MS; + + if (pHalData->CustomerID == RT_CID_819x_CAMEO) + pLed = &(ledpriv->SwLed1); + + switch (LedAction) { + case LED_CTL_POWER_ON: + case LED_CTL_START_TO_LINK: + case LED_CTL_NO_LINK: + if (pLed->bLedNoLinkBlinkInProgress == false) { + if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) + return; + if (pLed->bLedLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedLinkBlinkInProgress = false; + } + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + + pLed->bLedNoLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), uLedBlinkNoLinkInterval);/* change by ylb 20121012 for customer led for alpha */ + } + break; + + case LED_CTL_LINK: + if (pLed->bLedLinkBlinkInProgress == false) { + if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) + return; + if (pLed->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + pLed->bLedLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_NORMAL; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA); + } + break; + + case LED_CTL_SITE_SURVEY: + if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED) == true)) + ; + else if (pLed->bLedScanBlinkInProgress == false) { + if (IS_LED_WPS_BLINKING(pLed)) + return; + + if (pLed->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + if (pLed->bLedLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedLinkBlinkInProgress = false; + } + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + pLed->bLedScanBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SCAN; + pLed->BlinkTimes = 24; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason == RF_CHANGE_BY_IPS) + _set_timer(&(pLed->BlinkTimer), LED_INITIAL_INTERVAL); + else + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + + } + break; + + case LED_CTL_TX: + case LED_CTL_RX: + if (pLed->bLedBlinkInProgress == false) { + if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) + return; + if (pLed->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + if (pLed->bLedLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedLinkBlinkInProgress = false; + } + pLed->bLedBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_TXRX; + pLed->BlinkTimes = 2; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + break; + + case LED_CTL_START_WPS: /* wait until xinpin finish */ + case LED_CTL_START_WPS_BOTTON: + if (pLed->bLedWPSBlinkInProgress == false) { + if (pLed->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + if (pLed->bLedLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedLinkBlinkInProgress = false; + } + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + pLed->bLedWPSBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_WPS; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + } + break; + + + case LED_CTL_STOP_WPS: + if (pLed->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + if (pLed->bLedLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedLinkBlinkInProgress = false; + } + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + if (pLed->bLedWPSBlinkInProgress) + _cancel_timer_ex(&(pLed->BlinkTimer)); + else + pLed->bLedWPSBlinkInProgress = true; + + pLed->CurrLedState = LED_BLINK_WPS_STOP; + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), 0); + } + break; + + case LED_CTL_STOP_WPS_FAIL: + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } + + pLed->bLedNoLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), uLedBlinkNoLinkInterval);/* change by ylb 20121012 for customer led for alpha */ + break; + + case LED_CTL_POWER_OFF: + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + if (pLed->bLedNoLinkBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + if (pLed->bLedLinkBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedLinkBlinkInProgress = false; + } + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + + SwLedOff(padapter, pLed); + break; + + default: + break; + + } + +} + +/* Arcadyan/Sitecom , added by chiyoko, 20090216 */ +static void +SwLedControlMode2( + _adapter *padapter, + LED_CTL_MODE LedAction +) +{ + struct led_priv *ledpriv = &(padapter->ledpriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + PLED_USB pLed = &(ledpriv->SwLed0); + + switch (LedAction) { + case LED_CTL_SITE_SURVEY: + if (pmlmepriv->LinkDetectInfo.bBusyTraffic) + ; + else if (pLed->bLedScanBlinkInProgress == false) { + if (IS_LED_WPS_BLINKING(pLed)) + return; + + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + pLed->bLedScanBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SCAN; + pLed->BlinkTimes = 24; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + } + break; + + case LED_CTL_TX: + case LED_CTL_RX: + if ((pLed->bLedBlinkInProgress == false) && (check_fwstate(pmlmepriv, _FW_LINKED) == true)) { + if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) + return; + + pLed->bLedBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_TXRX; + pLed->BlinkTimes = 2; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + break; + + case LED_CTL_LINK: + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + + _set_timer(&(pLed->BlinkTimer), 0); + break; + + case LED_CTL_START_WPS: /* wait until xinpin finish */ + case LED_CTL_START_WPS_BOTTON: + if (pLed->bLedWPSBlinkInProgress == false) { + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + pLed->bLedWPSBlinkInProgress = true; + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), 0); + } + break; + + case LED_CTL_STOP_WPS: + pLed->bLedWPSBlinkInProgress = false; + if (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on) { + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), 0); + } else { + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), 0); + } + break; + + case LED_CTL_STOP_WPS_FAIL: + pLed->bLedWPSBlinkInProgress = false; + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), 0); + break; + + case LED_CTL_START_TO_LINK: + case LED_CTL_NO_LINK: + if (!IS_LED_BLINKING(pLed)) { + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), 0); + } + break; + + case LED_CTL_POWER_OFF: + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } + + SwLedOff(padapter, pLed); + break; + + default: + break; + + } + +} + +/* COREGA, added by chiyoko, 20090316 */ +static void +SwLedControlMode3( + _adapter *padapter, + LED_CTL_MODE LedAction +) +{ + struct led_priv *ledpriv = &(padapter->ledpriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + PLED_USB pLed = &(ledpriv->SwLed0); + + switch (LedAction) { + case LED_CTL_SITE_SURVEY: + if (pmlmepriv->LinkDetectInfo.bBusyTraffic) + ; + else if (pLed->bLedScanBlinkInProgress == false) { + if (IS_LED_WPS_BLINKING(pLed)) + return; + + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + pLed->bLedScanBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SCAN; + pLed->BlinkTimes = 24; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + } + break; + + case LED_CTL_TX: + case LED_CTL_RX: + if ((pLed->bLedBlinkInProgress == false) && (check_fwstate(pmlmepriv, _FW_LINKED) == true)) { + if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) + return; + + pLed->bLedBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_TXRX; + pLed->BlinkTimes = 2; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + break; + + case LED_CTL_LINK: + if (IS_LED_WPS_BLINKING(pLed)) + return; + + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + + _set_timer(&(pLed->BlinkTimer), 0); + break; + + case LED_CTL_START_WPS: /* wait until xinpin finish */ + case LED_CTL_START_WPS_BOTTON: + if (pLed->bLedWPSBlinkInProgress == false) { + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + pLed->bLedWPSBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_WPS; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + } + break; + + case LED_CTL_STOP_WPS: + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } else + pLed->bLedWPSBlinkInProgress = true; + + pLed->CurrLedState = LED_BLINK_WPS_STOP; + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), 0); + } + + break; + + case LED_CTL_STOP_WPS_FAIL: + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } + + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), 0); + break; + + case LED_CTL_START_TO_LINK: + case LED_CTL_NO_LINK: + if (!IS_LED_BLINKING(pLed)) { + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), 0); + } + break; + + case LED_CTL_POWER_OFF: + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } + + SwLedOff(padapter, pLed); + break; + + default: + break; + + } + +} + + +/* Edimax-Belkin, added by chiyoko, 20090413 */ +static void +SwLedControlMode4( + _adapter *padapter, + LED_CTL_MODE LedAction +) +{ + struct led_priv *ledpriv = &(padapter->ledpriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + PLED_USB pLed = &(ledpriv->SwLed0); + PLED_USB pLed1 = &(ledpriv->SwLed1); + + switch (LedAction) { + case LED_CTL_START_TO_LINK: + if (pLed1->bLedWPSBlinkInProgress) { + pLed1->bLedWPSBlinkInProgress = false; + _cancel_timer_ex(&(pLed1->BlinkTimer)); + + pLed1->BlinkingLedState = RTW_LED_OFF; + pLed1->CurrLedState = RTW_LED_OFF; + + if (pLed1->bLedOn) + _set_timer(&(pLed->BlinkTimer), 0); + } + + if (pLed->bLedStartToLinkBlinkInProgress == false) { + if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) + return; + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + + pLed->bLedStartToLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_StartToBlink; + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + } + } + break; + + case LED_CTL_LINK: + case LED_CTL_NO_LINK: + /* LED1 settings */ + if (LedAction == LED_CTL_LINK) { + if (pLed1->bLedWPSBlinkInProgress) { + pLed1->bLedWPSBlinkInProgress = false; + _cancel_timer_ex(&(pLed1->BlinkTimer)); + + pLed1->BlinkingLedState = RTW_LED_OFF; + pLed1->CurrLedState = RTW_LED_OFF; + + if (pLed1->bLedOn) + _set_timer(&(pLed->BlinkTimer), 0); + } + } + + if (pLed->bLedNoLinkBlinkInProgress == false) { + if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) + return; + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + + pLed->bLedNoLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + } + break; + + case LED_CTL_SITE_SURVEY: + if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED) == true)) + ; + else if (pLed->bLedScanBlinkInProgress == false) { + if (IS_LED_WPS_BLINKING(pLed)) + return; + + if (pLed->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + pLed->bLedScanBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SCAN; + pLed->BlinkTimes = 24; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + } + break; + + case LED_CTL_TX: + case LED_CTL_RX: + if (pLed->bLedBlinkInProgress == false) { + if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) + return; + if (pLed->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + pLed->bLedBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_TXRX; + pLed->BlinkTimes = 2; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + break; + + case LED_CTL_START_WPS: /* wait until xinpin finish */ + case LED_CTL_START_WPS_BOTTON: + if (pLed1->bLedWPSBlinkInProgress) { + pLed1->bLedWPSBlinkInProgress = false; + _cancel_timer_ex(&(pLed1->BlinkTimer)); + + pLed1->BlinkingLedState = RTW_LED_OFF; + pLed1->CurrLedState = RTW_LED_OFF; + + if (pLed1->bLedOn) + _set_timer(&(pLed->BlinkTimer), 0); + } + + if (pLed->bLedWPSBlinkInProgress == false) { + if (pLed->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + pLed->bLedWPSBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_WPS; + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + } + } + break; + + case LED_CTL_STOP_WPS: /* WPS connect success */ + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } + + pLed->bLedNoLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + + break; + + case LED_CTL_STOP_WPS_FAIL: /* WPS authentication fail */ + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } + + pLed->bLedNoLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + + /* LED1 settings */ + if (pLed1->bLedWPSBlinkInProgress) + _cancel_timer_ex(&(pLed1->BlinkTimer)); + else + pLed1->bLedWPSBlinkInProgress = true; + + pLed1->CurrLedState = LED_BLINK_WPS_STOP; + if (pLed1->bLedOn) + pLed1->BlinkingLedState = RTW_LED_OFF; + else + pLed1->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + + break; + + case LED_CTL_STOP_WPS_FAIL_OVERLAP: /* WPS session overlap */ + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } + + pLed->bLedNoLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + + /* LED1 settings */ + if (pLed1->bLedWPSBlinkInProgress) + _cancel_timer_ex(&(pLed1->BlinkTimer)); + else + pLed1->bLedWPSBlinkInProgress = true; + + pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP; + pLed1->BlinkTimes = 10; + if (pLed1->bLedOn) + pLed1->BlinkingLedState = RTW_LED_OFF; + else + pLed1->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); + + break; + + case LED_CTL_POWER_OFF: + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + + if (pLed->bLedNoLinkBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + if (pLed->bLedLinkBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedLinkBlinkInProgress = false; + } + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + if (pLed->bLedStartToLinkBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedStartToLinkBlinkInProgress = false; + } + + if (pLed1->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed1->BlinkTimer)); + pLed1->bLedWPSBlinkInProgress = false; + } + + pLed1->BlinkingLedState = LED_UNKNOWN; + SwLedOff(padapter, pLed); + SwLedOff(padapter, pLed1); + break; + + case LED_CTL_CONNECTION_NO_TRANSFER: + if (pLed->bLedBlinkInProgress == false) { + if (pLed->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + pLed->bLedBlinkInProgress = true; + + pLed->CurrLedState = LED_BLINK_ALWAYS_ON; + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + } + break; + + default: + break; + + } + +} + + + +/* Sercomm-Belkin, added by chiyoko, 20090415 */ +static void +SwLedControlMode5( + _adapter *padapter, + LED_CTL_MODE LedAction +) +{ + struct led_priv *ledpriv = &(padapter->ledpriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + PLED_USB pLed = &(ledpriv->SwLed0); + + if (pHalData->CustomerID == RT_CID_819x_CAMEO) + pLed = &(ledpriv->SwLed1); + + switch (LedAction) { + case LED_CTL_POWER_ON: + case LED_CTL_NO_LINK: + case LED_CTL_LINK: /* solid blue */ + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + + _set_timer(&(pLed->BlinkTimer), 0); + break; + + case LED_CTL_SITE_SURVEY: + if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED) == true)) + ; + else if (pLed->bLedScanBlinkInProgress == false) { + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + pLed->bLedScanBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SCAN; + pLed->BlinkTimes = 24; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + } + break; + + case LED_CTL_TX: + case LED_CTL_RX: + if (pLed->bLedBlinkInProgress == false) { + if (pLed->CurrLedState == LED_BLINK_SCAN) + return; + pLed->bLedBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_TXRX; + pLed->BlinkTimes = 2; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + break; + + case LED_CTL_POWER_OFF: + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + + SwLedOff(padapter, pLed); + break; + + default: + break; + + } + +} + +/* WNC-Corega, added by chiyoko, 20090902 */ +static void +SwLedControlMode6( + _adapter *padapter, + LED_CTL_MODE LedAction +) +{ + struct led_priv *ledpriv = &(padapter->ledpriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + PLED_USB pLed0 = &(ledpriv->SwLed0); + + switch (LedAction) { + case LED_CTL_POWER_ON: + case LED_CTL_LINK: + case LED_CTL_NO_LINK: + _cancel_timer_ex(&(pLed0->BlinkTimer)); + pLed0->CurrLedState = RTW_LED_ON; + pLed0->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed0->BlinkTimer), 0); + break; + + case LED_CTL_POWER_OFF: + SwLedOff(padapter, pLed0); + break; + + default: + break; + } + +} + +/* Netgear, added by sinda, 2011/11/11 */ +static void +SwLedControlMode7( + PADAPTER Adapter, + LED_CTL_MODE LedAction +) +{ + struct led_priv *ledpriv = &(Adapter->ledpriv); + struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; + PLED_USB pLed = &(ledpriv->SwLed0); + + switch (LedAction) { + case LED_CTL_SITE_SURVEY: + if (pmlmepriv->LinkDetectInfo.bBusyTraffic) + ; + else if (pLed->bLedScanBlinkInProgress == false) { + if (IS_LED_WPS_BLINKING(pLed)) + return; + + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + pLed->bLedScanBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SCAN; + pLed->BlinkTimes = 6; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_NETGEAR); + } + break; + + case LED_CTL_LINK: + if (IS_LED_WPS_BLINKING(pLed)) + return; + + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + + _set_timer(&(pLed->BlinkTimer), 0); + break; + + case LED_CTL_START_WPS: /* wait until xinpin finish */ + case LED_CTL_START_WPS_BOTTON: + if (pLed->bLedWPSBlinkInProgress == false) { + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + pLed->bLedWPSBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_WPS; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_NETGEAR); + } + break; + + case LED_CTL_STOP_WPS: + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } else + pLed->bLedWPSBlinkInProgress = true; + + pLed->CurrLedState = LED_BLINK_WPS_STOP; + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_NETGEAR); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), 0); + } + + break; + + + case LED_CTL_STOP_WPS_FAIL: + case LED_CTL_STOP_WPS_FAIL_OVERLAP: /* WPS session overlap */ + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } + + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), 0); + break; + + case LED_CTL_START_TO_LINK: + case LED_CTL_NO_LINK: + if (!IS_LED_BLINKING(pLed)) { + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), 0); + } + break; + + case LED_CTL_POWER_OFF: + case LED_CTL_POWER_ON: + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } + + _set_timer(&(pLed->BlinkTimer), 0); + break; + + default: + break; + + } + +} + +static void +SwLedControlMode8( + PADAPTER Adapter, + LED_CTL_MODE LedAction +) +{ + struct led_priv *ledpriv = &(Adapter->ledpriv); + struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; + PLED_USB pLed0 = &(ledpriv->SwLed0); + + switch (LedAction) { + case LED_CTL_LINK: + _cancel_timer_ex(&(pLed0->BlinkTimer)); + pLed0->CurrLedState = RTW_LED_ON; + pLed0->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed0->BlinkTimer), 0); + break; + + case LED_CTL_NO_LINK: + _cancel_timer_ex(&(pLed0->BlinkTimer)); + pLed0->CurrLedState = RTW_LED_OFF; + pLed0->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed0->BlinkTimer), 0); + break; + + case LED_CTL_POWER_OFF: + SwLedOff(Adapter, pLed0); + break; + + default: + break; + } + + +} + +/* page added for Belkin AC950, 20120813 */ +static void +SwLedControlMode9( + PADAPTER Adapter, + LED_CTL_MODE LedAction +) +{ + struct led_priv *ledpriv = &(Adapter->ledpriv); + struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; + PLED_USB pLed = &(ledpriv->SwLed0); + PLED_USB pLed1 = &(ledpriv->SwLed1); + PLED_USB pLed2 = &(ledpriv->SwLed2); + bool bWPSOverLap = false; + /* RTW_INFO("LedAction=%d\n", LedAction); */ + switch (LedAction) { + case LED_CTL_START_TO_LINK: + if (pLed2->bLedBlinkInProgress == false) { + pLed2->bLedBlinkInProgress = true; + pLed2->BlinkingLedState = RTW_LED_ON; + pLed2->CurrLedState = LED_BLINK_LINK_IN_PROCESS; + + _set_timer(&(pLed2->BlinkTimer), 0); + } + break; + + case LED_CTL_LINK: + case LED_CTL_NO_LINK: + /* LED1 settings */ + if (LedAction == LED_CTL_NO_LINK) { + /* if(pMgntInfo->AuthStatus == AUTH_STATUS_FAILED) */ + if (0) { + pLed1->CurrLedState = LED_BLINK_AUTH_ERROR; + if (pLed1->bLedOn) + pLed1->BlinkingLedState = RTW_LED_OFF; + else + pLed1->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed1->BlinkTimer), 0); + } else { + pLed1->CurrLedState = RTW_LED_OFF; + pLed1->BlinkingLedState = RTW_LED_OFF; + if (pLed1->bLedOn) + _set_timer(&(pLed1->BlinkTimer), 0); + } + } else { + pLed1->CurrLedState = RTW_LED_OFF; + pLed1->BlinkingLedState = RTW_LED_OFF; + if (pLed1->bLedOn) + _set_timer(&(pLed1->BlinkTimer), 0); + } + + /* LED2 settings */ + if (LedAction == LED_CTL_LINK) { + if (Adapter->securitypriv.dot11PrivacyAlgrthm != _NO_PRIVACY_) { + if (pLed2->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed2->BlinkTimer)); + pLed2->bLedBlinkInProgress = false; + } + pLed2->CurrLedState = RTW_LED_ON; + pLed2->bLedNoLinkBlinkInProgress = true; + if (!pLed2->bLedOn) + _set_timer(&(pLed2->BlinkTimer), 0); + } else { + if (pLed2->bLedWPSBlinkInProgress != true) { + pLed2->CurrLedState = RTW_LED_OFF; + pLed2->BlinkingLedState = RTW_LED_OFF; + if (pLed2->bLedOn) + _set_timer(&(pLed2->BlinkTimer), 0); + } + } + } else { /* NO_LINK */ + if (pLed2->bLedWPSBlinkInProgress == false) { + pLed2->CurrLedState = RTW_LED_OFF; + pLed2->BlinkingLedState = RTW_LED_OFF; + if (pLed2->bLedOn) + _set_timer(&(pLed2->BlinkTimer), 0); + } + } + + /* LED0 settings */ + if (pLed->bLedNoLinkBlinkInProgress == false) { + if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) + return; + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + + pLed->bLedNoLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + } + + break; + + case LED_CTL_SITE_SURVEY: + if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED) == true)) + ; + else { /* if(pLed->bLedScanBlinkInProgress ==false) */ + if (IS_LED_WPS_BLINKING(pLed)) + return; + + if (pLed->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + pLed->bLedScanBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SCAN; + pLed->BlinkTimes = 24; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + + } + break; + + case LED_CTL_TX: + case LED_CTL_RX: + if (pLed->bLedBlinkInProgress == false) { + if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) + return; + if (pLed->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + pLed->bLedBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_TXRX; + pLed->BlinkTimes = 2; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + break; + + case LED_CTL_START_WPS: /* wait until xinpin finish */ + case LED_CTL_START_WPS_BOTTON: + pLed2->bLedBlinkInProgress = true; + pLed2->BlinkingLedState = RTW_LED_ON; + pLed2->CurrLedState = LED_BLINK_LINK_IN_PROCESS; + pLed2->bLedWPSBlinkInProgress = true; + + _set_timer(&(pLed2->BlinkTimer), 500); + + break; + + case LED_CTL_STOP_WPS: /* WPS connect success */ + /* LED2 settings */ + if (pLed2->bLedWPSBlinkInProgress == true) { + _cancel_timer_ex(&(pLed2->BlinkTimer)); + pLed2->bLedBlinkInProgress = false; + pLed2->bLedWPSBlinkInProgress = false; + } + pLed2->CurrLedState = RTW_LED_ON; + pLed2->bLedNoLinkBlinkInProgress = true; + if (!pLed2->bLedOn) + _set_timer(&(pLed2->BlinkTimer), 0); + + /* LED1 settings */ + _cancel_timer_ex(&(pLed1->BlinkTimer)); + pLed1->CurrLedState = RTW_LED_OFF; + pLed1->BlinkingLedState = RTW_LED_OFF; + if (pLed1->bLedOn) + _set_timer(&(pLed1->BlinkTimer), 0); + + + break; + + case LED_CTL_STOP_WPS_FAIL: /* WPS authentication fail */ + /* LED1 settings */ + /* if(bWPSOverLap == false) */ + { + pLed1->CurrLedState = LED_BLINK_AUTH_ERROR; + pLed1->BlinkTimes = 50; + if (pLed1->bLedOn) + pLed1->BlinkingLedState = RTW_LED_OFF; + else + pLed1->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed1->BlinkTimer), 0); + } + /* else */ + /* { */ + /* bWPSOverLap = false; */ + /* pLed1->CurrLedState = RTW_LED_OFF; */ + /* pLed1->BlinkingLedState = RTW_LED_OFF; */ + /* _set_timer(&(pLed1->BlinkTimer), 0); */ + /* } */ + + /* LED2 settings */ + pLed2->CurrLedState = RTW_LED_OFF; + pLed2->BlinkingLedState = RTW_LED_OFF; + pLed2->bLedWPSBlinkInProgress = false; + if (pLed2->bLedOn) + _set_timer(&(pLed2->BlinkTimer), 0); + + break; + + case LED_CTL_STOP_WPS_FAIL_OVERLAP: /* WPS session overlap */ + /* LED1 settings */ + bWPSOverLap = true; + pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP; + pLed1->BlinkTimes = 10; + pLed1->BlinkCounter = 50; + if (pLed1->bLedOn) + pLed1->BlinkingLedState = RTW_LED_OFF; + else + pLed1->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed1->BlinkTimer), 0); + + /* LED2 settings */ + pLed2->CurrLedState = RTW_LED_OFF; + pLed2->BlinkingLedState = RTW_LED_OFF; + pLed2->bLedWPSBlinkInProgress = false; + if (pLed2->bLedOn) + _set_timer(&(pLed2->BlinkTimer), 0); + + break; + + case LED_CTL_POWER_OFF: + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + + if (pLed->bLedNoLinkBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + if (pLed->bLedLinkBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedLinkBlinkInProgress = false; + } + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + if (pLed->bLedStartToLinkBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedStartToLinkBlinkInProgress = false; + } + + if (pLed1->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed1->BlinkTimer)); + pLed1->bLedWPSBlinkInProgress = false; + } + + + pLed1->BlinkingLedState = LED_UNKNOWN; + SwLedOff(Adapter, pLed); + SwLedOff(Adapter, pLed1); + break; + + case LED_CTL_CONNECTION_NO_TRANSFER: + if (pLed->bLedBlinkInProgress == false) { + if (pLed->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + pLed->bLedBlinkInProgress = true; + + pLed->CurrLedState = LED_BLINK_ALWAYS_ON; + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + } + break; + + default: + break; + + } + +} + +/* page added for Netgear A6200V2, 20120827 */ +static void +SwLedControlMode10( + PADAPTER Adapter, + LED_CTL_MODE LedAction +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + struct led_priv *ledpriv = &(Adapter->ledpriv); + struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; + PLED_USB pLed = &(ledpriv->SwLed0); + PLED_USB pLed1 = &(ledpriv->SwLed1); + + switch (LedAction) { + case LED_CTL_START_TO_LINK: + if (pLed1->bLedBlinkInProgress == false) { + pLed1->bLedBlinkInProgress = true; + pLed1->BlinkingLedState = RTW_LED_ON; + pLed1->CurrLedState = LED_BLINK_LINK_IN_PROCESS; + + _set_timer(&(pLed1->BlinkTimer), 0); + } + break; + + case LED_CTL_LINK: + case LED_CTL_NO_LINK: + if (LedAction == LED_CTL_LINK) { + if (pLed->bLedWPSBlinkInProgress == true || pLed1->bLedWPSBlinkInProgress == true) + ; + else { + if (pHalData->current_band_type == BAND_ON_2_4G) + /* LED0 settings */ + { + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + _set_timer(&(pLed->BlinkTimer), 0); + + pLed1->CurrLedState = RTW_LED_OFF; + pLed1->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed1->BlinkTimer), 0); + } else if (pHalData->current_band_type == BAND_ON_5G) + /* LED1 settings */ + { + pLed1->CurrLedState = RTW_LED_ON; + pLed1->BlinkingLedState = RTW_LED_ON; + if (pLed1->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed1->BlinkTimer)); + pLed1->bLedBlinkInProgress = false; + } + _set_timer(&(pLed1->BlinkTimer), 0); + + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), 0); + } + } + } else if (LedAction == LED_CTL_NO_LINK) { /* TODO by page */ + if (pLed->bLedWPSBlinkInProgress == true || pLed1->bLedWPSBlinkInProgress == true) + ; + else { + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + if (pLed->bLedOn) + _set_timer(&(pLed->BlinkTimer), 0); + + pLed1->CurrLedState = RTW_LED_OFF; + pLed1->BlinkingLedState = RTW_LED_OFF; + if (pLed1->bLedOn) + _set_timer(&(pLed1->BlinkTimer), 0); + } + } + + break; + + case LED_CTL_SITE_SURVEY: + if (check_fwstate(pmlmepriv, _FW_LINKED) == true) + ; /* don't blink when media connect */ + else { /* if(pLed->bLedScanBlinkInProgress ==false) */ + if (IS_LED_WPS_BLINKING(pLed) || IS_LED_WPS_BLINKING(pLed1)) + return; + + if (pLed->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + pLed->bLedScanBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SCAN; + pLed->BlinkTimes = 12; + pLed->BlinkingLedState = LED_BLINK_SCAN; + _set_timer(&(pLed->BlinkTimer), 0); + + if (pLed1->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed1->BlinkTimer)); + pLed1->bLedNoLinkBlinkInProgress = false; + } + if (pLed1->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed1->BlinkTimer)); + pLed1->bLedBlinkInProgress = false; + } + pLed1->bLedScanBlinkInProgress = true; + pLed1->CurrLedState = LED_BLINK_SCAN; + pLed1->BlinkTimes = 12; + pLed1->BlinkingLedState = LED_BLINK_SCAN; + _set_timer(&(pLed1->BlinkTimer), LED_BLINK_LINK_SLOWLY_INTERVAL_NETGEAR); + + } + break; + + case LED_CTL_START_WPS: /* wait until xinpin finish */ + case LED_CTL_START_WPS_BOTTON: + /* LED0 settings */ + if (pLed->bLedBlinkInProgress == false) { + pLed->bLedBlinkInProgress = true; + pLed->bLedWPSBlinkInProgress = true; + pLed->BlinkingLedState = LED_BLINK_WPS; + pLed->CurrLedState = LED_BLINK_WPS; + _set_timer(&(pLed->BlinkTimer), 0); + } + + /* LED1 settings */ + if (pLed1->bLedBlinkInProgress == false) { + pLed1->bLedBlinkInProgress = true; + pLed1->bLedWPSBlinkInProgress = true; + pLed1->BlinkingLedState = LED_BLINK_WPS; + pLed1->CurrLedState = LED_BLINK_WPS; + _set_timer(&(pLed1->BlinkTimer), LED_BLINK_NORMAL_INTERVAL + LED_BLINK_LINK_INTERVAL_NETGEAR); + } + + + break; + + case LED_CTL_STOP_WPS: /* WPS connect success */ + if (pHalData->current_band_type == BAND_ON_2_4G) + /* LED0 settings */ + { + pLed->bLedWPSBlinkInProgress = false; + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + _set_timer(&(pLed->BlinkTimer), 0); + + pLed1->CurrLedState = RTW_LED_OFF; + pLed1->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed1->BlinkTimer), 0); + } else if (pHalData->current_band_type == BAND_ON_5G) + /* LED1 settings */ + { + pLed1->bLedWPSBlinkInProgress = false; + pLed1->CurrLedState = RTW_LED_ON; + pLed1->BlinkingLedState = RTW_LED_ON; + if (pLed1->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed1->BlinkTimer)); + pLed1->bLedBlinkInProgress = false; + } + _set_timer(&(pLed1->BlinkTimer), 0); + + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), 0); + } + + break; + + case LED_CTL_STOP_WPS_FAIL: /* WPS authentication fail */ + /* LED1 settings */ + pLed1->bLedWPSBlinkInProgress = false; + pLed1->CurrLedState = RTW_LED_OFF; + pLed1->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed1->BlinkTimer), 0); + + /* LED0 settings */ + pLed->bLedWPSBlinkInProgress = false; + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + if (pLed->bLedOn) + _set_timer(&(pLed->BlinkTimer), 0); + + break; + + + default: + break; + + } + +} + +/* Edimax-ASUS, added by Page, 20121221 */ +static void +SwLedControlMode11( + PADAPTER Adapter, + LED_CTL_MODE LedAction +) +{ + struct led_priv *ledpriv = &(Adapter->ledpriv); + struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; + PLED_USB pLed = &(ledpriv->SwLed0); + + switch (LedAction) { + case LED_CTL_POWER_ON: + case LED_CTL_START_TO_LINK: + case LED_CTL_NO_LINK: + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), 0); + break; + + case LED_CTL_LINK: + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + pLed->bLedBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_TXRX; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); + break; + + case LED_CTL_START_WPS: /* wait until xinpin finish */ + case LED_CTL_START_WPS_BOTTON: + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + pLed->bLedWPSBlinkInProgress = true; + pLed->bLedBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_WPS; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + pLed->BlinkTimes = 5; + _set_timer(&(pLed->BlinkTimer), 0); + + break; + + + case LED_CTL_STOP_WPS: + case LED_CTL_STOP_WPS_FAIL: + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + pLed->CurrLedState = LED_BLINK_WPS_STOP; + _set_timer(&(pLed->BlinkTimer), 0); + break; + + case LED_CTL_POWER_OFF: + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + + if (pLed->bLedNoLinkBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + if (pLed->bLedLinkBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedLinkBlinkInProgress = false; + } + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + + SwLedOff(Adapter, pLed); + break; + + default: + break; + + } + +} + +/* page added for NEC */ + +static void +SwLedControlMode12( + PADAPTER Adapter, + LED_CTL_MODE LedAction +) +{ + struct led_priv *ledpriv = &(Adapter->ledpriv); + struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; + PLED_USB pLed = &(ledpriv->SwLed0); + + switch (LedAction) { + case LED_CTL_POWER_ON: + case LED_CTL_NO_LINK: + case LED_CTL_LINK: + case LED_CTL_SITE_SURVEY: + + if (pLed->bLedNoLinkBlinkInProgress == false) { + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + + pLed->bLedNoLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); + } + break; + + case LED_CTL_TX: + case LED_CTL_RX: + if (pLed->bLedBlinkInProgress == false) { + if (pLed->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + pLed->bLedBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_TXRX; + pLed->BlinkTimes = 2; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + break; + + case LED_CTL_POWER_OFF: + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + + if (pLed->bLedScanBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + + if (pLed->bLedNoLinkBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedNoLinkBlinkInProgress = false; + } + + SwLedOff(Adapter, pLed); + break; + + default: + break; + + } + +} + +/* Maddest add for NETGEAR R6100 */ + +static void +SwLedControlMode13( + PADAPTER Adapter, + LED_CTL_MODE LedAction +) +{ + struct led_priv *ledpriv = &(Adapter->ledpriv); + struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; + PLED_USB pLed = &(ledpriv->SwLed0); + + switch (LedAction) { + case LED_CTL_LINK: + if (pLed->bLedWPSBlinkInProgress) + return; + + + pLed->CurrLedState = RTW_LED_ON; + pLed->BlinkingLedState = RTW_LED_ON; + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + + _set_timer(&(pLed->BlinkTimer), 0); + break; + + case LED_CTL_START_WPS: /* wait until xinpin finish */ + case LED_CTL_START_WPS_BOTTON: + if (pLed->bLedWPSBlinkInProgress == false) { + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + pLed->bLedWPSBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_WPS; + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_WPS_BLINK_OFF_INTERVAL_NETGEAR); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_WPS_BLINK_ON_INTERVAL_NETGEAR); + } + } + break; + + case LED_CTL_STOP_WPS: + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } else + pLed->bLedWPSBlinkInProgress = true; + + pLed->bLedWPSBlinkInProgress = false; + pLed->CurrLedState = LED_BLINK_WPS_STOP; + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + + _set_timer(&(pLed->BlinkTimer), 0); + } + + break; + + + case LED_CTL_STOP_WPS_FAIL: + case LED_CTL_STOP_WPS_FAIL_OVERLAP: /* WPS session overlap */ + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } + + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), 0); + break; + + case LED_CTL_START_TO_LINK: + if ((pLed->bLedBlinkInProgress == false) && (pLed->bLedWPSBlinkInProgress == false)) { + pLed->bLedBlinkInProgress = true; + pLed->BlinkingLedState = RTW_LED_ON; + pLed->CurrLedState = LED_BLINK_LINK_IN_PROCESS; + + _set_timer(&(pLed->BlinkTimer), 0); + } + break; + + case LED_CTL_NO_LINK: + + if (pLed->bLedWPSBlinkInProgress) + return; + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + /* if(!IS_LED_BLINKING(pLed)) */ + { + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), 0); + } + break; + + case LED_CTL_POWER_OFF: + case LED_CTL_POWER_ON: + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } + + if (LedAction == LED_CTL_POWER_ON) + _set_timer(&(pLed->BlinkTimer), 0); + else + SwLedOff(Adapter, pLed); + break; + + default: + break; + + } + + +} + +/* Maddest add for DNI Buffalo */ + +static void +SwLedControlMode14( + PADAPTER Adapter, + LED_CTL_MODE LedAction +) +{ + struct led_priv *ledpriv = &(Adapter->ledpriv); + PLED_USB pLed = &(ledpriv->SwLed0); + + switch (LedAction) { + case LED_CTL_POWER_OFF: + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + SwLedOff(Adapter, pLed); + break; + + case LED_CTL_POWER_ON: + SwLedOn(Adapter, pLed); + break; + + case LED_CTL_LINK: + case LED_CTL_NO_LINK: + break; + case LED_CTL_TX: + case LED_CTL_RX: + if (pLed->bLedBlinkInProgress == false) { + pLed->bLedBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_TXRX; + pLed->BlinkTimes = 2; + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + } + } + break; + + default: + break; + } +} + +/* Maddest add for Dlink */ + +static void +SwLedControlMode15( + PADAPTER Adapter, + LED_CTL_MODE LedAction +) +{ + struct led_priv *ledpriv = &(Adapter->ledpriv); + struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; + PLED_USB pLed = &(ledpriv->SwLed0); + + switch (LedAction) { + case LED_CTL_START_WPS: /* wait until xinpin finish */ + case LED_CTL_START_WPS_BOTTON: + if (pLed->bLedWPSBlinkInProgress == false) { + if (pLed->bLedBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress == true) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + pLed->bLedWPSBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_WPS; + if (pLed->bLedOn) { + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), LED_WPS_BLINK_OFF_INTERVAL_NETGEAR); + } else { + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_WPS_BLINK_ON_INTERVAL_NETGEAR); + } + } + break; + + case LED_CTL_STOP_WPS: + if (pLed->bLedWPSBlinkInProgress) + _cancel_timer_ex(&(pLed->BlinkTimer)); + + pLed->CurrLedState = LED_BLINK_WPS_STOP; + /* if(check_fwstate(pmlmepriv, _FW_LINKED)== true) */ + { + pLed->BlinkingLedState = RTW_LED_ON; + + _set_timer(&(pLed->BlinkTimer), 0); + } + + break; + + case LED_CTL_STOP_WPS_FAIL: + case LED_CTL_STOP_WPS_FAIL_OVERLAP: /* WPS session overlap */ + if (pLed->bLedWPSBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedWPSBlinkInProgress = false; + } + + pLed->CurrLedState = RTW_LED_OFF; + pLed->BlinkingLedState = RTW_LED_OFF; + _set_timer(&(pLed->BlinkTimer), 0); + break; + + case LED_CTL_NO_LINK: + if (pLed->bLedWPSBlinkInProgress) + return; + + /*if(Adapter->securitypriv.dot11PrivacyAlgrthm > _NO_PRIVACY_) + { + if(SecIsTxKeyInstalled(Adapter, pMgntInfo->Bssid)) + { + } + else + { + if(pMgntInfo->LEDAssocState ==LED_ASSOC_SECURITY_BEGIN) + return; + } + }*/ + + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + if (pLed->bLedScanBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedScanBlinkInProgress = false; + } + /* if(!IS_LED_BLINKING(pLed)) */ + { + pLed->CurrLedState = LED_BLINK_NO_LINK; + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), 30); + } + break; + + case LED_CTL_LINK: + + if (pLed->bLedWPSBlinkInProgress) + return; + + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + + pLed->CurrLedState = LED_BLINK_LINK_IDEL; + pLed->BlinkingLedState = RTW_LED_ON; + + _set_timer(&(pLed->BlinkTimer), 30); + break; + + case LED_CTL_SITE_SURVEY: + if (check_fwstate(pmlmepriv, _FW_LINKED) == true) + return; + + if (pLed->bLedWPSBlinkInProgress == true) + return; + + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + pLed->CurrLedState = LED_BLINK_SCAN; + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), 0); + break; + + case LED_CTL_TX: + case LED_CTL_RX: + if (pLed->bLedWPSBlinkInProgress) + return; + + if (pLed->bLedBlinkInProgress) { + _cancel_timer_ex(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + + pLed->bLedBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_TXRX; + pLed->BlinkTimes = 2; + if (pLed->bLedOn) + pLed->BlinkingLedState = RTW_LED_OFF; + else + pLed->BlinkingLedState = RTW_LED_ON; + _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); + break; + + default: + break; + } +} + +void +LedControlUSB( + _adapter *padapter, + LED_CTL_MODE LedAction +) +{ + struct led_priv *ledpriv = &(padapter->ledpriv); + +#if (MP_DRIVER == 1) + if (padapter->registrypriv.mp_mode == 1) + return; +#endif + + if (RTW_CANNOT_RUN(padapter) || (!rtw_is_hw_init_completed(padapter))) { + /*RTW_INFO("%s bDriverStopped:%s, bSurpriseRemoved:%s\n" + , __func__ + , rtw_is_drv_stopped(padapter)?"True":"False" + , rtw_is_surprise_removed(padapter)?"True":"False" );*/ + return; + } + + if (ledpriv->bRegUseLed == false) + return; + + /* if(priv->bInHctTest) */ + /* return; */ + +#ifdef CONFIG_CONCURRENT_MODE + /* Only do led action for PRIMARY_ADAPTER */ + if (padapter->adapter_type != PRIMARY_ADAPTER) + return; +#endif + + if ((adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && + adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS) && + (LedAction == LED_CTL_TX || LedAction == LED_CTL_RX || + LedAction == LED_CTL_SITE_SURVEY || + LedAction == LED_CTL_LINK || + LedAction == LED_CTL_NO_LINK || + LedAction == LED_CTL_POWER_ON)) + return; + + switch (ledpriv->LedStrategy) { + case SW_LED_MODE0: + SwLedControlMode0(padapter, LedAction); + break; + + case SW_LED_MODE1: + SwLedControlMode1(padapter, LedAction); + break; + + case SW_LED_MODE2: + SwLedControlMode2(padapter, LedAction); + break; + + case SW_LED_MODE3: + SwLedControlMode3(padapter, LedAction); + break; + + case SW_LED_MODE4: + SwLedControlMode4(padapter, LedAction); + break; + + case SW_LED_MODE5: + SwLedControlMode5(padapter, LedAction); + break; + + case SW_LED_MODE6: + SwLedControlMode6(padapter, LedAction); + break; + + case SW_LED_MODE7: + SwLedControlMode7(padapter, LedAction); + break; + + case SW_LED_MODE8: + SwLedControlMode8(padapter, LedAction); + break; + + case SW_LED_MODE9: + SwLedControlMode9(padapter, LedAction); + break; + + case SW_LED_MODE10: + SwLedControlMode10(padapter, LedAction); + break; + + case SW_LED_MODE11: + SwLedControlMode11(padapter, LedAction); + break; + + case SW_LED_MODE12: + SwLedControlMode12(padapter, LedAction); + break; + + case SW_LED_MODE13: + SwLedControlMode13(padapter, LedAction); + break; + + case SW_LED_MODE14: + SwLedControlMode14(padapter, LedAction); + break; + + case SW_LED_MODE15: + SwLedControlMode15(padapter, LedAction); + break; + + default: + break; + } + +} + +/* + * Description: + * Reset status of LED_871x object. + * */ +void ResetLedStatus(PLED_USB pLed) +{ + + pLed->CurrLedState = RTW_LED_OFF; /* Current LED state. */ + pLed->bLedOn = false; /* true if LED is ON, false if LED is OFF. */ + + pLed->bLedBlinkInProgress = false; /* true if it is blinking, false o.w.. */ + pLed->bLedWPSBlinkInProgress = false; + + pLed->BlinkTimes = 0; /* Number of times to toggle led state for blinking. */ + pLed->BlinkCounter = 0; + pLed->BlinkingLedState = LED_UNKNOWN; /* Next state for blinking, either RTW_LED_ON or RTW_LED_OFF are. */ + + pLed->bLedNoLinkBlinkInProgress = false; + pLed->bLedLinkBlinkInProgress = false; + pLed->bLedStartToLinkBlinkInProgress = false; + pLed->bLedScanBlinkInProgress = false; +} + +/* +* Description: +* Initialize an LED_871x object. +* */ +void +InitLed( + _adapter *padapter, + PLED_USB pLed, + LED_PIN LedPin +) +{ + pLed->padapter = padapter; + pLed->LedPin = LedPin; + + ResetLedStatus(pLed); +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) + _init_timer(&(pLed->BlinkTimer), padapter->pnetdev, BlinkTimerCallback, pLed); +#else + timer_setup(&pLed->BlinkTimer, BlinkTimerCallback, 0); +#endif + _init_workitem(&(pLed->BlinkWorkItem), BlinkWorkItemCallback, pLed); +} + + +/* + * Description: + * DeInitialize an LED_871x object. + * */ +void +DeInitLed( + PLED_USB pLed +) +{ + _cancel_workitem_sync(&(pLed->BlinkWorkItem)); + _cancel_timer_ex(&(pLed->BlinkTimer)); + ResetLedStatus(pLed); +} diff --git a/drivers/staging/rtl8188eu/hal/halcomtxbf.h b/drivers/staging/rtl8188eu/hal/halcomtxbf.h new file mode 100644 index 000000000000..a303e5404569 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/halcomtxbf.h @@ -0,0 +1,135 @@ +#ifndef __HAL_COM_TXBF_H__ +#define __HAL_COM_TXBF_H__ + +/* +typedef bool +(*TXBF_GET)( + void* p_adapter, + u8 get_type, + void* p_out_buf + ); + +typedef bool +(*TXBF_SET)( + void* p_adapter, + u8 set_type, + void* p_in_buf + ); +*/ + +enum txbf_set_type { + TXBF_SET_SOUNDING_ENTER, + TXBF_SET_SOUNDING_LEAVE, + TXBF_SET_SOUNDING_RATE, + TXBF_SET_SOUNDING_STATUS, + TXBF_SET_SOUNDING_FW_NDPA, + TXBF_SET_SOUNDING_CLK, + TXBF_SET_TX_PATH_RESET, + TXBF_SET_GET_TX_RATE +}; + + +enum txbf_get_type { + TXBF_GET_EXPLICIT_BEAMFORMEE, + TXBF_GET_EXPLICIT_BEAMFORMER, + TXBF_GET_MU_MIMO_STA, + TXBF_GET_MU_MIMO_AP +}; + + + +/* 2 HAL TXBF related */ +struct _HAL_TXBF_INFO { + u8 txbf_idx; + u8 ndpa_idx; + u8 BW; + u8 rate; + struct timer_list txbf_fw_ndpa_timer; +}; + +#if (BEAMFORMING_SUPPORT == 1) + +void +hal_com_txbf_beamform_init( + void *p_dm_void +); + +void +hal_com_txbf_config_gtab( + void *p_dm_void +); + +void +hal_com_txbf_enter_work_item_callback( + void *p_dm_void +); + +void +hal_com_txbf_leave_work_item_callback( + void *p_dm_void +); + +void +hal_com_txbf_fw_ndpa_work_item_callback( + void *p_dm_void +); + +void +hal_com_txbf_clk_work_item_callback( + void *p_dm_void +); + +void +hal_com_txbf_reset_tx_path_work_item_callback( + void *p_dm_void +); + +void +hal_com_txbf_get_tx_rate_work_item_callback( + void *p_dm_void +); + +void +hal_com_txbf_rate_work_item_callback( + void *p_dm_void +); + +void +hal_com_txbf_fw_ndpa_timer_callback( + struct timer_list *p_timer +); + +void +hal_com_txbf_status_work_item_callback( + void *p_dm_void +); + +bool +hal_com_txbf_set( + void *p_dm_void, + u8 set_type, + void *p_in_buf +); + +bool +hal_com_txbf_get( + struct _ADAPTER *adapter, + u8 get_type, + void *p_out_buf +); + +#else +#define hal_com_txbf_beamform_init(p_dm_void) NULL +#define hal_com_txbf_config_gtab(p_dm_void) NULL +#define hal_com_txbf_enter_work_item_callback(_adapter) NULL +#define hal_com_txbf_leave_work_item_callback(_adapter) NULL +#define hal_com_txbf_fw_ndpa_work_item_callback(_adapter) NULL +#define hal_com_txbf_clk_work_item_callback(_adapter) NULL +#define hal_com_txbf_rate_work_item_callback(_adapter) NULL +#define hal_com_txbf_fw_ndpa_timer_callback(_adapter) NULL +#define hal_com_txbf_status_work_item_callback(_adapter) NULL +#define hal_com_txbf_get(_adapter, _get_type, _pout_buf) + +#endif + +#endif /* #ifndef __HAL_COM_TXBF_H__ */ diff --git a/drivers/staging/rtl8188eu/hal/halhwimg.h b/drivers/staging/rtl8188eu/hal/halhwimg.h new file mode 100644 index 000000000000..3bb88565d9e8 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/halhwimg.h @@ -0,0 +1,78 @@ +#pragma once +#ifndef __INC_HW_IMG_H +#define __INC_HW_IMG_H + +/* + * 2011/03/15 MH Add for different IC HW image file selection. code size consideration. + * */ + #if (DEV_BUS_TYPE == RT_PCI_INTERFACE) + /* For 92C */ + #define RTL8192CE_HWIMG_SUPPORT 1 + #define RTL8192CE_TEST_HWIMG_SUPPORT 0 + #define RTL8192CU_HWIMG_SUPPORT 0 + #define RTL8192CU_TEST_HWIMG_SUPPORT 0 + + /* For 92D */ + #define RTL8192DE_HWIMG_SUPPORT 1 + #define RTL8192DE_TEST_HWIMG_SUPPORT 0 + #define RTL8192DU_HWIMG_SUPPORT 0 + #define RTL8192DU_TEST_HWIMG_SUPPORT 0 + + /* For 8723 */ + #define RTL8723E_HWIMG_SUPPORT 1 + #define RTL8723U_HWIMG_SUPPORT 0 + #define RTL8723S_HWIMG_SUPPORT 0 + + /* For 88E */ + #define RTL8188EE_HWIMG_SUPPORT 0 + #define RTL8188EU_HWIMG_SUPPORT 0 + #define RTL8188ES_HWIMG_SUPPORT 0 + + #elif (DEV_BUS_TYPE == RT_USB_INTERFACE) + /* For 92C */ + #define RTL8192CE_HWIMG_SUPPORT 0 + #define RTL8192CE_TEST_HWIMG_SUPPORT 0 + #define RTL8192CU_HWIMG_SUPPORT 1 + #define RTL8192CU_TEST_HWIMG_SUPPORT 0 + + /* For 92D */ + #define RTL8192DE_HWIMG_SUPPORT 0 + #define RTL8192DE_TEST_HWIMG_SUPPORT 0 + #define RTL8192DU_HWIMG_SUPPORT 1 + #define RTL8192DU_TEST_HWIMG_SUPPORT 0 + + /* For 8723 */ + #define RTL8723E_HWIMG_SUPPORT 0 + #define RTL8723U_HWIMG_SUPPORT 1 + #define RTL8723S_HWIMG_SUPPORT 0 + + /* For 88E */ + #define RTL8188EE_HWIMG_SUPPORT 0 + #define RTL8188EU_HWIMG_SUPPORT 0 + #define RTL8188ES_HWIMG_SUPPORT 0 + + #elif (DEV_BUS_TYPE == RT_SDIO_INTERFACE) + /* For 92C */ + #define RTL8192CE_HWIMG_SUPPORT 0 + #define RTL8192CE_TEST_HWIMG_SUPPORT 0 + #define RTL8192CU_HWIMG_SUPPORT 1 + #define RTL8192CU_TEST_HWIMG_SUPPORT 0 + + /* For 92D */ + #define RTL8192DE_HWIMG_SUPPORT 0 + #define RTL8192DE_TEST_HWIMG_SUPPORT 0 + #define RTL8192DU_HWIMG_SUPPORT 1 + #define RTL8192DU_TEST_HWIMG_SUPPORT 0 + + /* For 8723 */ + #define RTL8723E_HWIMG_SUPPORT 0 + #define RTL8723U_HWIMG_SUPPORT 0 + #define RTL8723S_HWIMG_SUPPORT 1 + + /* For 88E */ + #define RTL8188EE_HWIMG_SUPPORT 0 + #define RTL8188EU_HWIMG_SUPPORT 0 + #define RTL8188ES_HWIMG_SUPPORT 0 + #endif + +#endif /* __INC_HW_IMG_H */ diff --git a/drivers/staging/rtl8188eu/hal/halhwimg8188e_bb.c b/drivers/staging/rtl8188eu/hal/halhwimg8188e_bb.c new file mode 100644 index 000000000000..5f7c6add8b51 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/halhwimg8188e_bb.c @@ -0,0 +1,1730 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/*Image2HeaderVersion: 2.18*/ +#include "mp_precomp.h" +#include "phydm_precomp.h" + +static bool +check_positive( + struct PHY_DM_STRUCT *p_dm_odm, + const u32 condition1, + const u32 condition2, + const u32 condition3, + const u32 condition4 +) +{ + u8 _board_type = ((p_dm_odm->board_type & BIT(4)) >> 4) << 0 | /* _GLNA*/ + ((p_dm_odm->board_type & BIT(3)) >> 3) << 1 | /* _GPA*/ + ((p_dm_odm->board_type & BIT(7)) >> 7) << 2 | /* _ALNA*/ + ((p_dm_odm->board_type & BIT(6)) >> 6) << 3 | /* _APA */ + ((p_dm_odm->board_type & BIT(2)) >> 2) << 4; /* _BT*/ + + u32 cond1 = condition1, cond2 = condition2, cond3 = condition3, cond4 = condition4; + u32 driver1 = p_dm_odm->cut_version << 24 | + (p_dm_odm->support_interface & 0xF0) << 16 | + p_dm_odm->support_platform << 16 | + p_dm_odm->package_type << 12 | + (p_dm_odm->support_interface & 0x0F) << 8 | + _board_type; + + u32 driver2 = (p_dm_odm->type_glna & 0xFF) << 0 | + (p_dm_odm->type_gpa & 0xFF) << 8 | + (p_dm_odm->type_alna & 0xFF) << 16 | + (p_dm_odm->type_apa & 0xFF) << 24; + + u32 driver3 = 0; + + u32 driver4 = (p_dm_odm->type_glna & 0xFF00) >> 8 | + (p_dm_odm->type_gpa & 0xFF00) | + (p_dm_odm->type_alna & 0xFF00) << 8 | + (p_dm_odm->type_apa & 0xFF00) << 16; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, + ("===> check_positive (cond1, cond2, cond3, cond4) = (0x%X 0x%X 0x%X 0x%X)\n", cond1, cond2, cond3, cond4)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, + ("===> check_positive (driver1, driver2, driver3, driver4) = (0x%X 0x%X 0x%X 0x%X)\n", driver1, driver2, driver3, driver4)); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, + (" (Platform, Interface) = (0x%X, 0x%X)\n", p_dm_odm->support_platform, p_dm_odm->support_interface)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, + (" (Board, Package) = (0x%X, 0x%X)\n", p_dm_odm->board_type, p_dm_odm->package_type)); + + + /*============== value Defined Check ===============*/ + /*QFN type [15:12] and cut version [27:24] need to do value check*/ + + if (((cond1 & 0x0000F000) != 0) && ((cond1 & 0x0000F000) != (driver1 & 0x0000F000))) + return false; + if (((cond1 & 0x0F000000) != 0) && ((cond1 & 0x0F000000) != (driver1 & 0x0F000000))) + return false; + + /*=============== Bit Defined Check ================*/ + /* We don't care [31:28] */ + + cond1 &= 0x00FF0FFF; + driver1 &= 0x00FF0FFF; + + if ((cond1 & driver1) == cond1) { + u32 bit_mask = 0; + + if ((cond1 & 0x0F) == 0) /* board_type is DONTCARE*/ + return true; + + if ((cond1 & BIT(0)) != 0) /*GLNA*/ + bit_mask |= 0x000000FF; + if ((cond1 & BIT(1)) != 0) /*GPA*/ + bit_mask |= 0x0000FF00; + if ((cond1 & BIT(2)) != 0) /*ALNA*/ + bit_mask |= 0x00FF0000; + if ((cond1 & BIT(3)) != 0) /*APA*/ + bit_mask |= 0xFF000000; + + if (((cond2 & bit_mask) == (driver2 & bit_mask)) && ((cond4 & bit_mask) == (driver4 & bit_mask))) /* board_type of each RF path is matched*/ + return true; + else + return false; + } else + return false; +} +static bool +check_negative( + struct PHY_DM_STRUCT *p_dm_odm, + const u32 condition1, + const u32 condition2 +) +{ + return true; +} + +/****************************************************************************** +* AGC_TAB.TXT +******************************************************************************/ + +static u32 array_mp_8188e_agc_tab[] = { + 0x88000001, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0xF6000001, + 0xC78, 0xF5010001, + 0xC78, 0xF4020001, + 0xC78, 0xF3030001, + 0xC78, 0xF2040001, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0xF7000001, + 0xC78, 0xF6010001, + 0xC78, 0xF5020001, + 0xC78, 0xF4030001, + 0xC78, 0xF3040001, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0xC78, 0xF9000001, + 0xC78, 0xF8010001, + 0xC78, 0xF7020001, + 0xC78, 0xF6030001, + 0xC78, 0xF5040001, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0xFB000001, + 0xC78, 0xFB010001, + 0xC78, 0xFA020001, + 0xC78, 0xF9030001, + 0xC78, 0xF8040001, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0xFF000001, + 0xC78, 0xFF010001, + 0xC78, 0xFE020001, + 0xC78, 0xFD030001, + 0xC78, 0xFC040001, + 0xA0000000, 0x00000000, + 0xC78, 0xFB000001, + 0xC78, 0xFB010001, + 0xC78, 0xFB020001, + 0xC78, 0xFB030001, + 0xC78, 0xFB040001, + 0xB0000000, 0x00000000, + 0x88000001, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0xF1050001, + 0xC78, 0xF0060001, + 0xC78, 0xEF070001, + 0xC78, 0xEE080001, + 0xC78, 0xED090001, + 0xC78, 0xEC0A0001, + 0xC78, 0xEB0B0001, + 0xC78, 0xEA0C0001, + 0xC78, 0xE90D0001, + 0xC78, 0xE80E0001, + 0xC78, 0xE70F0001, + 0xC78, 0xE6100001, + 0xC78, 0xE5110001, + 0xC78, 0xE4120001, + 0xC78, 0xE3130001, + 0xC78, 0xE2140001, + 0xC78, 0xC5150001, + 0xC78, 0xC4160001, + 0xC78, 0xC3170001, + 0xC78, 0xC2180001, + 0xC78, 0x88190001, + 0xC78, 0x871A0001, + 0xC78, 0x861B0001, + 0xC78, 0x851C0001, + 0xC78, 0x841D0001, + 0xC78, 0x831E0001, + 0xC78, 0x821F0001, + 0xC78, 0x81200001, + 0xC78, 0x80210001, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0xF2050001, + 0xC78, 0xF1060001, + 0xC78, 0xF0070001, + 0xC78, 0xEF080001, + 0xC78, 0xEE090001, + 0xC78, 0xED0A0001, + 0xC78, 0xEC0B0001, + 0xC78, 0xEB0C0001, + 0xC78, 0xEA0D0001, + 0xC78, 0xE90E0001, + 0xC78, 0xE80F0001, + 0xC78, 0xE7100001, + 0xC78, 0xE6110001, + 0xC78, 0xE5120001, + 0xC78, 0xE4130001, + 0xC78, 0xE3140001, + 0xC78, 0xE2150001, + 0xC78, 0xE1160001, + 0xC78, 0x89170001, + 0xC78, 0x88180001, + 0xC78, 0x87190001, + 0xC78, 0x861A0001, + 0xC78, 0x851B0001, + 0xC78, 0x841C0001, + 0xC78, 0x831D0001, + 0xC78, 0x821E0001, + 0xC78, 0x811F0001, + 0xC78, 0x6B200001, + 0xC78, 0x6A210001, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0xC78, 0xF4050001, + 0xC78, 0xF3060001, + 0xC78, 0xF2070001, + 0xC78, 0xF1080001, + 0xC78, 0xF0090001, + 0xC78, 0xEF0A0001, + 0xC78, 0xEE0B0001, + 0xC78, 0xED0C0001, + 0xC78, 0xEC0D0001, + 0xC78, 0xEB0E0001, + 0xC78, 0xEA0F0001, + 0xC78, 0xE9100001, + 0xC78, 0xE8110001, + 0xC78, 0xE7120001, + 0xC78, 0xE6130001, + 0xC78, 0xE5140001, + 0xC78, 0xE4150001, + 0xC78, 0xE3160001, + 0xC78, 0xE2170001, + 0xC78, 0xE1180001, + 0xC78, 0x8A190001, + 0xC78, 0x891A0001, + 0xC78, 0x881B0001, + 0xC78, 0x871C0001, + 0xC78, 0x861D0001, + 0xC78, 0x851E0001, + 0xC78, 0x841F0001, + 0xC78, 0x83200001, + 0xC78, 0x82210001, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0xF7050001, + 0xC78, 0xF6060001, + 0xC78, 0xF5070001, + 0xC78, 0xF4080001, + 0xC78, 0xF3090001, + 0xC78, 0xF20A0001, + 0xC78, 0xF10B0001, + 0xC78, 0xF00C0001, + 0xC78, 0xEF0D0001, + 0xC78, 0xEE0E0001, + 0xC78, 0xED0F0001, + 0xC78, 0xEC100001, + 0xC78, 0xEB110001, + 0xC78, 0xEA120001, + 0xC78, 0xE9130001, + 0xC78, 0xE8140001, + 0xC78, 0xE7150001, + 0xC78, 0xE6160001, + 0xC78, 0xE5170001, + 0xC78, 0xE4180001, + 0xC78, 0xC7190001, + 0xC78, 0xC61A0001, + 0xC78, 0xC51B0001, + 0xC78, 0xC41C0001, + 0xC78, 0xC31D0001, + 0xC78, 0xC21E0001, + 0xC78, 0x871F0001, + 0xC78, 0x86200001, + 0xC78, 0x85210001, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0xFB050001, + 0xC78, 0xFA060001, + 0xC78, 0xF9070001, + 0xC78, 0xF8080001, + 0xC78, 0xF7090001, + 0xC78, 0xF60A0001, + 0xC78, 0xF50B0001, + 0xC78, 0xF40C0001, + 0xC78, 0xF30D0001, + 0xC78, 0xF20E0001, + 0xC78, 0xF10F0001, + 0xC78, 0xF0100001, + 0xC78, 0xEF110001, + 0xC78, 0xEE120001, + 0xC78, 0xED130001, + 0xC78, 0xEC140001, + 0xC78, 0xEB150001, + 0xC78, 0xEA160001, + 0xC78, 0xE9170001, + 0xC78, 0xE8180001, + 0xC78, 0xE7190001, + 0xC78, 0xE61A0001, + 0xC78, 0xC51B0001, + 0xC78, 0xC41C0001, + 0xC78, 0xC31D0001, + 0xC78, 0xC21E0001, + 0xC78, 0x881F0001, + 0xC78, 0x87200001, + 0xC78, 0x86210001, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0xFA050001, + 0xC78, 0xF9060001, + 0xC78, 0xF8070001, + 0xC78, 0xF7080001, + 0xC78, 0xF6090001, + 0xC78, 0xF50A0001, + 0xC78, 0xF40B0001, + 0xC78, 0xF30C0001, + 0xC78, 0xF20D0001, + 0xC78, 0xF10E0001, + 0xC78, 0xF00F0001, + 0xC78, 0xEF100001, + 0xC78, 0xEE110001, + 0xC78, 0xED120001, + 0xC78, 0xEC130001, + 0xC78, 0xEB140001, + 0xC78, 0xEA150001, + 0xC78, 0xE9160001, + 0xC78, 0xE8170001, + 0xC78, 0xE7180001, + 0xC78, 0xE6190001, + 0xC78, 0xE51A0001, + 0xC78, 0xE41B0001, + 0xC78, 0xC71C0001, + 0xC78, 0xC61D0001, + 0xC78, 0xC51E0001, + 0xC78, 0xC41F0001, + 0xC78, 0xC3200001, + 0xC78, 0xC2210001, + 0xA0000000, 0x00000000, + 0xC78, 0xFB050001, + 0xC78, 0xFA060001, + 0xC78, 0xF9070001, + 0xC78, 0xF8080001, + 0xC78, 0xF7090001, + 0xC78, 0xF60A0001, + 0xC78, 0xF50B0001, + 0xC78, 0xF40C0001, + 0xC78, 0xF30D0001, + 0xC78, 0xF20E0001, + 0xC78, 0xF10F0001, + 0xC78, 0xF0100001, + 0xC78, 0xEF110001, + 0xC78, 0xEE120001, + 0xC78, 0xED130001, + 0xC78, 0xEC140001, + 0xC78, 0xEB150001, + 0xC78, 0xEA160001, + 0xC78, 0xE9170001, + 0xC78, 0xE8180001, + 0xC78, 0xE7190001, + 0xC78, 0xE61A0001, + 0xC78, 0xE51B0001, + 0xC78, 0xE41C0001, + 0xC78, 0xE31D0001, + 0xC78, 0xE21E0001, + 0xC78, 0xE11F0001, + 0xC78, 0x8A200001, + 0xC78, 0x89210001, + 0xB0000000, 0x00000000, + 0x88000001, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0x66220001, + 0xC78, 0x65230001, + 0xC78, 0x64240001, + 0xC78, 0x63250001, + 0xC78, 0x62260001, + 0xC78, 0x61270001, + 0xC78, 0x60280001, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0x69220001, + 0xC78, 0x68230001, + 0xC78, 0x67240001, + 0xC78, 0x66250001, + 0xC78, 0x65260001, + 0xC78, 0x64270001, + 0xC78, 0x63280001, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0xC78, 0x6B220001, + 0xC78, 0x6A230001, + 0xC78, 0x69240001, + 0xC78, 0x68250001, + 0xC78, 0x67260001, + 0xC78, 0x66270001, + 0xC78, 0x65280001, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0x84220001, + 0xC78, 0x83230001, + 0xC78, 0x82240001, + 0xC78, 0x81250001, + 0xC78, 0x67260001, + 0xC78, 0x66270001, + 0xC78, 0x65280001, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0x85220001, + 0xC78, 0x84230001, + 0xC78, 0x83240001, + 0xC78, 0x82250001, + 0xC78, 0x6A260001, + 0xC78, 0x69270001, + 0xC78, 0x68280001, + 0xA0000000, 0x00000000, + 0xC78, 0x88220001, + 0xC78, 0x87230001, + 0xC78, 0x86240001, + 0xC78, 0x85250001, + 0xC78, 0x84260001, + 0xC78, 0x83270001, + 0xC78, 0x82280001, + 0xB0000000, 0x00000000, + 0x88000001, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0x4A290001, + 0xC78, 0x492A0001, + 0xC78, 0x482B0001, + 0xC78, 0x472C0001, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0x62290001, + 0xC78, 0x612A0001, + 0xC78, 0x462B0001, + 0xC78, 0x452C0001, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0xC78, 0x64290001, + 0xC78, 0x632A0001, + 0xC78, 0x622B0001, + 0xC78, 0x612C0001, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0x64290001, + 0xC78, 0x632A0001, + 0xC78, 0x622B0001, + 0xC78, 0x612C0001, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0x67290001, + 0xC78, 0x662A0001, + 0xC78, 0x652B0001, + 0xC78, 0x642C0001, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0x81290001, + 0xC78, 0x242A0001, + 0xC78, 0x232B0001, + 0xC78, 0x222C0001, + 0xA0000000, 0x00000000, + 0xC78, 0x6B290001, + 0xC78, 0x6A2A0001, + 0xC78, 0x692B0001, + 0xC78, 0x682C0001, + 0xB0000000, 0x00000000, + 0x88000001, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0x462D0001, + 0xC78, 0x452E0001, + 0xC78, 0x442F0001, + 0xC78, 0x43300001, + 0xC78, 0x42310001, + 0xC78, 0x41320001, + 0xC78, 0x40330001, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0x442D0001, + 0xC78, 0x432E0001, + 0xC78, 0x422F0001, + 0xC78, 0x41300001, + 0xC78, 0x40310001, + 0xC78, 0x40320001, + 0xC78, 0x40330001, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0xC78, 0x462D0001, + 0xC78, 0x452E0001, + 0xC78, 0x442F0001, + 0xC78, 0x43300001, + 0xC78, 0x42310001, + 0xC78, 0x41320001, + 0xC78, 0x40330001, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0x4B2D0001, + 0xC78, 0x4A2E0001, + 0xC78, 0x492F0001, + 0xC78, 0x48300001, + 0xC78, 0x47310001, + 0xC78, 0x46320001, + 0xC78, 0x45330001, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0x4A2D0001, + 0xC78, 0x492E0001, + 0xC78, 0x482F0001, + 0xC78, 0x47300001, + 0xC78, 0x46310001, + 0xC78, 0x45320001, + 0xC78, 0x44330001, + 0xA0000000, 0x00000000, + 0xC78, 0x672D0001, + 0xC78, 0x662E0001, + 0xC78, 0x652F0001, + 0xC78, 0x64300001, + 0xC78, 0x63310001, + 0xC78, 0x62320001, + 0xC78, 0x61330001, + 0xB0000000, 0x00000000, + 0x88000001, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0x40340001, + 0xC78, 0x40350001, + 0xC78, 0x40360001, + 0xC78, 0x40370001, + 0xC78, 0x40380001, + 0xC78, 0x40390001, + 0xC78, 0x403A0001, + 0xC78, 0x403B0001, + 0xC78, 0x403C0001, + 0xC78, 0x403D0001, + 0xC78, 0x403E0001, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0x40340001, + 0xC78, 0x40350001, + 0xC78, 0x40360001, + 0xC78, 0x40370001, + 0xC78, 0x40380001, + 0xC78, 0x40390001, + 0xC78, 0x403A0001, + 0xC78, 0x403B0001, + 0xC78, 0x403C0001, + 0xC78, 0x403D0001, + 0xC78, 0x403E0001, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0xC78, 0x40340001, + 0xC78, 0x40350001, + 0xC78, 0x40360001, + 0xC78, 0x40370001, + 0xC78, 0x40380001, + 0xC78, 0x40390001, + 0xC78, 0x403A0001, + 0xC78, 0x403B0001, + 0xC78, 0x403C0001, + 0xC78, 0x403D0001, + 0xC78, 0x403E0001, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0x44340001, + 0xC78, 0x43350001, + 0xC78, 0x42360001, + 0xC78, 0x41370001, + 0xC78, 0x40380001, + 0xC78, 0x40390001, + 0xC78, 0x403A0001, + 0xC78, 0x403B0001, + 0xC78, 0x403C0001, + 0xC78, 0x403D0001, + 0xC78, 0x403E0001, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0x43340001, + 0xC78, 0x42350001, + 0xC78, 0x41360001, + 0xC78, 0x40370001, + 0xC78, 0x40380001, + 0xC78, 0x40390001, + 0xC78, 0x403A0001, + 0xC78, 0x403B0001, + 0xC78, 0x403C0001, + 0xC78, 0x403D0001, + 0xC78, 0x403E0001, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0x60340001, + 0xC78, 0x4A350001, + 0xC78, 0x49360001, + 0xC78, 0x48370001, + 0xC78, 0x47380001, + 0xC78, 0x46390001, + 0xC78, 0x453A0001, + 0xC78, 0x443B0001, + 0xC78, 0x433C0001, + 0xC78, 0x423D0001, + 0xC78, 0x413E0001, + 0xA0000000, 0x00000000, + 0xC78, 0x46340001, + 0xC78, 0x45350001, + 0xC78, 0x44360001, + 0xC78, 0x43370001, + 0xC78, 0x42380001, + 0xC78, 0x41390001, + 0xC78, 0x403A0001, + 0xC78, 0x403B0001, + 0xC78, 0x403C0001, + 0xC78, 0x403D0001, + 0xC78, 0x403E0001, + 0xB0000000, 0x00000000, + 0x80000001, 0x00000001, 0x40000000, 0x00000000, + 0xC78, 0x403F0001, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0x403F0001, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0x403F0001, + 0xA0000000, 0x00000000, + 0xC78, 0x403F0001, + 0xB0000000, 0x00000000, + 0x88000001, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0xFB400001, + 0xC78, 0xFA410001, + 0xC78, 0xF9420001, + 0xC78, 0xF8430001, + 0xC78, 0xF7440001, + 0xC78, 0xF6450001, + 0xC78, 0xF5460001, + 0xC78, 0xF4470001, + 0xC78, 0xF3480001, + 0xC78, 0xF2490001, + 0xC78, 0xF14A0001, + 0xC78, 0xF04B0001, + 0xC78, 0xEF4C0001, + 0xC78, 0xEE4D0001, + 0xC78, 0xED4E0001, + 0xC78, 0xEC4F0001, + 0xC78, 0xEB500001, + 0xC78, 0xEA510001, + 0xC78, 0xE9520001, + 0xC78, 0xE8530001, + 0xC78, 0xE7540001, + 0xC78, 0xE6550001, + 0xC78, 0xE5560001, + 0xC78, 0xC6570001, + 0xC78, 0xC5580001, + 0xC78, 0xC4590001, + 0xC78, 0xC35A0001, + 0xC78, 0xC25B0001, + 0xC78, 0xC15C0001, + 0xC78, 0xC05D0001, + 0xC78, 0xA35E0001, + 0xC78, 0xA25F0001, + 0xC78, 0xA1600001, + 0xC78, 0x88610001, + 0xC78, 0x87620001, + 0xC78, 0x86630001, + 0xC78, 0x85640001, + 0xC78, 0x84650001, + 0xC78, 0x83660001, + 0xC78, 0x82670001, + 0xC78, 0x66680001, + 0xC78, 0x65690001, + 0xC78, 0x646A0001, + 0xC78, 0x636B0001, + 0xC78, 0x626C0001, + 0xC78, 0x616D0001, + 0xC78, 0x486E0001, + 0xC78, 0x476F0001, + 0xC78, 0x46700001, + 0xC78, 0x45710001, + 0xC78, 0x44720001, + 0xC78, 0x43730001, + 0xC78, 0x42740001, + 0xC78, 0x41750001, + 0xC78, 0x40760001, + 0xC78, 0x40770001, + 0xC78, 0x40780001, + 0xC78, 0x40790001, + 0xC78, 0x407A0001, + 0xC78, 0x407B0001, + 0xC78, 0x407C0001, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0xFB400001, + 0xC78, 0xFA410001, + 0xC78, 0xF9420001, + 0xC78, 0xF8430001, + 0xC78, 0xF7440001, + 0xC78, 0xF6450001, + 0xC78, 0xF5460001, + 0xC78, 0xF4470001, + 0xC78, 0xF3480001, + 0xC78, 0xF2490001, + 0xC78, 0xF14A0001, + 0xC78, 0xF04B0001, + 0xC78, 0xEF4C0001, + 0xC78, 0xEE4D0001, + 0xC78, 0xED4E0001, + 0xC78, 0xEC4F0001, + 0xC78, 0xEB500001, + 0xC78, 0xEA510001, + 0xC78, 0xE9520001, + 0xC78, 0xE8530001, + 0xC78, 0xE7540001, + 0xC78, 0xE6550001, + 0xC78, 0xE5560001, + 0xC78, 0xE4570001, + 0xC78, 0xE3580001, + 0xC78, 0xE2590001, + 0xC78, 0xC35A0001, + 0xC78, 0xC25B0001, + 0xC78, 0xC15C0001, + 0xC78, 0x8B5D0001, + 0xC78, 0x8A5E0001, + 0xC78, 0x895F0001, + 0xC78, 0x88600001, + 0xC78, 0x87610001, + 0xC78, 0x86620001, + 0xC78, 0x85630001, + 0xC78, 0x84640001, + 0xC78, 0x67650001, + 0xC78, 0x66660001, + 0xC78, 0x65670001, + 0xC78, 0x64680001, + 0xC78, 0x63690001, + 0xC78, 0x626A0001, + 0xC78, 0x616B0001, + 0xC78, 0x606C0001, + 0xC78, 0x466D0001, + 0xC78, 0x456E0001, + 0xC78, 0x446F0001, + 0xC78, 0x43700001, + 0xC78, 0x42710001, + 0xC78, 0x41720001, + 0xC78, 0x40730001, + 0xC78, 0x40740001, + 0xC78, 0x40750001, + 0xC78, 0x40760001, + 0xC78, 0x40770001, + 0xC78, 0x40780001, + 0xC78, 0x40790001, + 0xC78, 0x407A0001, + 0xC78, 0x407B0001, + 0xC78, 0x407C0001, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0xC78, 0xFB400001, + 0xC78, 0xFB410001, + 0xC78, 0xFB420001, + 0xC78, 0xFB430001, + 0xC78, 0xFB440001, + 0xC78, 0xFB450001, + 0xC78, 0xFA460001, + 0xC78, 0xF9470001, + 0xC78, 0xF8480001, + 0xC78, 0xF7490001, + 0xC78, 0xF64A0001, + 0xC78, 0xF54B0001, + 0xC78, 0xF44C0001, + 0xC78, 0xF34D0001, + 0xC78, 0xF24E0001, + 0xC78, 0xF14F0001, + 0xC78, 0xF0500001, + 0xC78, 0xEF510001, + 0xC78, 0xEE520001, + 0xC78, 0xED530001, + 0xC78, 0xEC540001, + 0xC78, 0xEB550001, + 0xC78, 0xEA560001, + 0xC78, 0xE9570001, + 0xC78, 0xE8580001, + 0xC78, 0xE7590001, + 0xC78, 0xE65A0001, + 0xC78, 0xE55B0001, + 0xC78, 0xC65C0001, + 0xC78, 0xC55D0001, + 0xC78, 0xC45E0001, + 0xC78, 0xC35F0001, + 0xC78, 0xC2600001, + 0xC78, 0xC1610001, + 0xC78, 0xC0620001, + 0xC78, 0xA3630001, + 0xC78, 0xA2640001, + 0xC78, 0xA1650001, + 0xC78, 0x88660001, + 0xC78, 0x87670001, + 0xC78, 0x86680001, + 0xC78, 0x85690001, + 0xC78, 0x846A0001, + 0xC78, 0x836B0001, + 0xC78, 0x826C0001, + 0xC78, 0x666D0001, + 0xC78, 0x656E0001, + 0xC78, 0x646F0001, + 0xC78, 0x63700001, + 0xC78, 0x62710001, + 0xC78, 0x61720001, + 0xC78, 0x48730001, + 0xC78, 0x47740001, + 0xC78, 0x46750001, + 0xC78, 0x45760001, + 0xC78, 0x44770001, + 0xC78, 0x43780001, + 0xC78, 0x42790001, + 0xC78, 0x417A0001, + 0xC78, 0x407B0001, + 0xC78, 0x407C0001, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0xFB400001, + 0xC78, 0xFB410001, + 0xC78, 0xFB420001, + 0xC78, 0xFB430001, + 0xC78, 0xFB440001, + 0xC78, 0xFB450001, + 0xC78, 0xFB460001, + 0xC78, 0xFB470001, + 0xC78, 0xFB480001, + 0xC78, 0xFA490001, + 0xC78, 0xF94A0001, + 0xC78, 0xF84B0001, + 0xC78, 0xF74C0001, + 0xC78, 0xF64D0001, + 0xC78, 0xF54E0001, + 0xC78, 0xF44F0001, + 0xC78, 0xF3500001, + 0xC78, 0xF2510001, + 0xC78, 0xF1520001, + 0xC78, 0xF0530001, + 0xC78, 0xEF540001, + 0xC78, 0xEE550001, + 0xC78, 0xED560001, + 0xC78, 0xEC570001, + 0xC78, 0xEB580001, + 0xC78, 0xEA590001, + 0xC78, 0xE95A0001, + 0xC78, 0xE85B0001, + 0xC78, 0xE75C0001, + 0xC78, 0xE65D0001, + 0xC78, 0xE55E0001, + 0xC78, 0xE45F0001, + 0xC78, 0xE3600001, + 0xC78, 0xE2610001, + 0xC78, 0xC3620001, + 0xC78, 0xC2630001, + 0xC78, 0xC1640001, + 0xC78, 0x8B650001, + 0xC78, 0x8A660001, + 0xC78, 0x89670001, + 0xC78, 0x88680001, + 0xC78, 0x87690001, + 0xC78, 0x866A0001, + 0xC78, 0x856B0001, + 0xC78, 0x846C0001, + 0xC78, 0x676D0001, + 0xC78, 0x666E0001, + 0xC78, 0x656F0001, + 0xC78, 0x64700001, + 0xC78, 0x63710001, + 0xC78, 0x62720001, + 0xC78, 0x61730001, + 0xC78, 0x60740001, + 0xC78, 0x46750001, + 0xC78, 0x45760001, + 0xC78, 0x44770001, + 0xC78, 0x43780001, + 0xC78, 0x42790001, + 0xC78, 0x417A0001, + 0xC78, 0x407B0001, + 0xC78, 0x407C0001, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0xFB400001, + 0xC78, 0xFB410001, + 0xC78, 0xFB420001, + 0xC78, 0xFB430001, + 0xC78, 0xFB440001, + 0xC78, 0xFB450001, + 0xC78, 0xFB460001, + 0xC78, 0xFB470001, + 0xC78, 0xFB480001, + 0xC78, 0xFA490001, + 0xC78, 0xF94A0001, + 0xC78, 0xF84B0001, + 0xC78, 0xF74C0001, + 0xC78, 0xF64D0001, + 0xC78, 0xF54E0001, + 0xC78, 0xF44F0001, + 0xC78, 0xF3500001, + 0xC78, 0xF2510001, + 0xC78, 0xF1520001, + 0xC78, 0xF0530001, + 0xC78, 0xEF540001, + 0xC78, 0xEE550001, + 0xC78, 0xED560001, + 0xC78, 0xEC570001, + 0xC78, 0xEB580001, + 0xC78, 0xEA590001, + 0xC78, 0xE95A0001, + 0xC78, 0xE85B0001, + 0xC78, 0xE75C0001, + 0xC78, 0xE65D0001, + 0xC78, 0xE55E0001, + 0xC78, 0xE45F0001, + 0xC78, 0xE3600001, + 0xC78, 0xE2610001, + 0xC78, 0xC3620001, + 0xC78, 0xC2630001, + 0xC78, 0xC1640001, + 0xC78, 0x8B650001, + 0xC78, 0x8A660001, + 0xC78, 0x89670001, + 0xC78, 0x88680001, + 0xC78, 0x87690001, + 0xC78, 0x866A0001, + 0xC78, 0x856B0001, + 0xC78, 0x846C0001, + 0xC78, 0x676D0001, + 0xC78, 0x666E0001, + 0xC78, 0x656F0001, + 0xC78, 0x64700001, + 0xC78, 0x63710001, + 0xC78, 0x62720001, + 0xC78, 0x61730001, + 0xC78, 0x60740001, + 0xC78, 0x46750001, + 0xC78, 0x45760001, + 0xC78, 0x44770001, + 0xC78, 0x43780001, + 0xC78, 0x42790001, + 0xC78, 0x417A0001, + 0xC78, 0x407B0001, + 0xC78, 0x407C0001, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0xC78, 0xFF400001, + 0xC78, 0xFF410001, + 0xC78, 0xFE420001, + 0xC78, 0xFD430001, + 0xC78, 0xFC440001, + 0xC78, 0xFB450001, + 0xC78, 0xFA460001, + 0xC78, 0xF9470001, + 0xC78, 0xF8480001, + 0xC78, 0xF7490001, + 0xC78, 0xF64A0001, + 0xC78, 0xF54B0001, + 0xC78, 0xF44C0001, + 0xC78, 0xF34D0001, + 0xC78, 0xF24E0001, + 0xC78, 0xF14F0001, + 0xC78, 0xF0500001, + 0xC78, 0xEF510001, + 0xC78, 0xEE520001, + 0xC78, 0xED530001, + 0xC78, 0xEC540001, + 0xC78, 0xEB550001, + 0xC78, 0xEA560001, + 0xC78, 0xE9570001, + 0xC78, 0xE8580001, + 0xC78, 0xE7590001, + 0xC78, 0xE65A0001, + 0xC78, 0xE55B0001, + 0xC78, 0xE45C0001, + 0xC78, 0xA85D0001, + 0xC78, 0xA75E0001, + 0xC78, 0xA65F0001, + 0xC78, 0xA5600001, + 0xC78, 0xA4610001, + 0xC78, 0xA3620001, + 0xC78, 0xA2630001, + 0xC78, 0xA1640001, + 0xC78, 0x28650001, + 0xC78, 0x27660001, + 0xC78, 0x26670001, + 0xC78, 0x07680001, + 0xC78, 0x06690001, + 0xC78, 0x056A0001, + 0xC78, 0x046B0001, + 0xC78, 0x036C0001, + 0xC78, 0x026D0001, + 0xC78, 0x016E0001, + 0xC78, 0x646F0001, + 0xC78, 0x63700001, + 0xC78, 0x62710001, + 0xC78, 0x61720001, + 0xC78, 0x47730001, + 0xC78, 0x46740001, + 0xC78, 0x45750001, + 0xC78, 0x44760001, + 0xC78, 0x43770001, + 0xC78, 0x42780001, + 0xC78, 0x41790001, + 0xC78, 0x407A0001, + 0xC78, 0x407B0001, + 0xC78, 0x407C0001, + 0xA0000000, 0x00000000, + 0xC78, 0xFB400001, + 0xC78, 0xFB410001, + 0xC78, 0xFB420001, + 0xC78, 0xFB430001, + 0xC78, 0xFB440001, + 0xC78, 0xFB450001, + 0xC78, 0xFB460001, + 0xC78, 0xFB470001, + 0xC78, 0xFB480001, + 0xC78, 0xFA490001, + 0xC78, 0xF94A0001, + 0xC78, 0xF84B0001, + 0xC78, 0xF74C0001, + 0xC78, 0xF64D0001, + 0xC78, 0xF54E0001, + 0xC78, 0xF44F0001, + 0xC78, 0xF3500001, + 0xC78, 0xF2510001, + 0xC78, 0xF1520001, + 0xC78, 0xF0530001, + 0xC78, 0xEF540001, + 0xC78, 0xEE550001, + 0xC78, 0xED560001, + 0xC78, 0xEC570001, + 0xC78, 0xEB580001, + 0xC78, 0xEA590001, + 0xC78, 0xE95A0001, + 0xC78, 0xE85B0001, + 0xC78, 0xE75C0001, + 0xC78, 0xE65D0001, + 0xC78, 0xE55E0001, + 0xC78, 0xE45F0001, + 0xC78, 0xE3600001, + 0xC78, 0xE2610001, + 0xC78, 0xC3620001, + 0xC78, 0xC2630001, + 0xC78, 0xC1640001, + 0xC78, 0x8B650001, + 0xC78, 0x8A660001, + 0xC78, 0x89670001, + 0xC78, 0x88680001, + 0xC78, 0x87690001, + 0xC78, 0x866A0001, + 0xC78, 0x856B0001, + 0xC78, 0x846C0001, + 0xC78, 0x676D0001, + 0xC78, 0x666E0001, + 0xC78, 0x656F0001, + 0xC78, 0x64700001, + 0xC78, 0x63710001, + 0xC78, 0x62720001, + 0xC78, 0x61730001, + 0xC78, 0x60740001, + 0xC78, 0x46750001, + 0xC78, 0x45760001, + 0xC78, 0x44770001, + 0xC78, 0x43780001, + 0xC78, 0x42790001, + 0xC78, 0x417A0001, + 0xC78, 0x407B0001, + 0xC78, 0x407C0001, + 0xB0000000, 0x00000000, + 0x80000001, 0x00000001, 0x40000000, 0x00000000, + 0xC78, 0x407D0001, + 0xC78, 0x407E0001, + 0xC78, 0x407F0001, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0x407D0001, + 0xC78, 0x407E0001, + 0xC78, 0x407F0001, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xC78, 0x407D0001, + 0xC78, 0x407E0001, + 0xC78, 0x407F0001, + 0xA0000000, 0x00000000, + 0xC78, 0x407D0001, + 0xC78, 0x407E0001, + 0xC78, 0x407F0001, + 0xB0000000, 0x00000000, + 0xC50, 0x69553422, + 0xC50, 0x69553420, + +}; + +void +odm_read_and_config_mp_8188e_agc_tab( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u32 i = 0; + u8 c_cond; + bool is_matched = true, is_skipped = false; + u32 array_len = sizeof(array_mp_8188e_agc_tab) / sizeof(u32); + u32 *array = array_mp_8188e_agc_tab; + + u32 v1 = 0, v2 = 0, pre_v1 = 0, pre_v2 = 0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("===> odm_read_and_config_mp_8188e_agc_tab\n")); + + while ((i + 1) < array_len) { + v1 = array[i]; + v2 = array[i + 1]; + + if (v1 & (BIT(31) | BIT30)) {/*positive & negative condition*/ + if (v1 & BIT(31)) {/* positive condition*/ + c_cond = (u8)((v1 & (BIT(29) | BIT(28))) >> 28); + if (c_cond == COND_ENDIF) {/*end*/ + is_matched = true; + is_skipped = false; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("ENDIF\n")); + } else if (c_cond == COND_ELSE) { /*else*/ + is_matched = is_skipped ? false : true; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("ELSE\n")); + } else {/*if , else if*/ + pre_v1 = v1; + pre_v2 = v2; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("IF or ELSE IF\n")); + } + } else if (v1 & BIT(30)) { /*negative condition*/ + if (is_skipped == false) { + if (check_positive(p_dm_odm, pre_v1, pre_v2, v1, v2)) { + is_matched = true; + is_skipped = true; + } else { + is_matched = false; + is_skipped = false; + } + } else + is_matched = false; + } + } else { + if (is_matched) + odm_config_bb_agc_8188e(p_dm_odm, v1, MASKDWORD, v2); + } + i = i + 2; + } +} + +u32 +odm_get_version_mp_8188e_agc_tab(void) +{ + return 70; +} + +/****************************************************************************** +* PHY_REG.TXT +******************************************************************************/ + +static u32 array_mp_8188e_phy_reg[] = { + 0x800, 0x80040000, + 0x804, 0x00000003, + 0x808, 0x0000FC00, + 0x80C, 0x0000000A, + 0x810, 0x10001331, + 0x814, 0x020C3D10, + 0x818, 0x02200385, + 0x81C, 0x00000000, + 0x820, 0x01000100, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0x824, 0x00390204, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0x824, 0x00390204, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0x824, 0x00390204, + 0x98000001, 0x00000000, 0x40000000, 0x00000000, + 0x824, 0x00390204, + 0x98000001, 0x00000001, 0x40000000, 0x00000000, + 0x824, 0x00390204, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0x824, 0x00390204, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0x824, 0x00390004, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x824, 0x00390204, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x824, 0x00390204, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0x824, 0x00390204, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0x824, 0x00390004, + 0x98000400, 0x00000000, 0x40000000, 0x00000000, + 0x824, 0x00390204, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0x824, 0x00390004, + 0xA0000000, 0x00000000, + 0x824, 0x00390204, + 0xB0000000, 0x00000000, + 0x828, 0x00000000, + 0x82C, 0x00000000, + 0x830, 0x00000000, + 0x834, 0x00000000, + 0x838, 0x00000000, + 0x83C, 0x00000000, + 0x840, 0x00010000, + 0x844, 0x00000000, + 0x848, 0x00000000, + 0x84C, 0x00000000, + 0x850, 0x00000000, + 0x854, 0x00000000, + 0x858, 0x569A11A9, + 0x85C, 0x01000014, + 0x860, 0x66F60110, + 0x864, 0x061F0649, + 0x868, 0x00000000, + 0x86C, 0x27272700, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0x870, 0x07000300, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0x870, 0x07000300, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0x870, 0x07000300, + 0x98000001, 0x00000000, 0x40000000, 0x00000000, + 0x870, 0x07000300, + 0x98000001, 0x00000001, 0x40000000, 0x00000000, + 0x870, 0x07000300, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0x870, 0x07000300, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0x870, 0x07000300, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x870, 0x07000300, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x870, 0x07000300, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0x870, 0x07000300, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0x870, 0x07000300, + 0x98000400, 0x00000000, 0x40000000, 0x00000000, + 0x870, 0x07000760, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0x870, 0x07000760, + 0xA0000000, 0x00000000, + 0x870, 0x07000760, + 0xB0000000, 0x00000000, + 0x874, 0x25004000, + 0x878, 0x00000808, + 0x87C, 0x00000000, + 0x880, 0xB0000C1C, + 0x884, 0x00000001, + 0x888, 0x00000000, + 0x88C, 0xCCC000C0, + 0x890, 0x00000800, + 0x894, 0xFFFFFFFE, + 0x898, 0x40302010, + 0x89C, 0x00706050, + 0x900, 0x00000000, + 0x904, 0x00000023, + 0x908, 0x00000000, + 0x90C, 0x81121111, + 0x910, 0x00000002, + 0x914, 0x00000201, + 0xA00, 0x00D047C8, + 0xA04, 0x80FF800C, + 0xA08, 0x8C838300, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0xA0C, 0x2E7F120F, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0xA0C, 0x2E7F120F, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0xA0C, 0x2E7F120F, + 0x98000001, 0x00000000, 0x40000000, 0x00000000, + 0xA0C, 0x2E7F120F, + 0x98000001, 0x00000001, 0x40000000, 0x00000000, + 0xA0C, 0x2E7F120F, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xA0C, 0x2E7F120F, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0xA0C, 0x2D38120F, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0xA0C, 0x2E7F120F, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0xA0C, 0x2E7F120F, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0xA0C, 0x2E7F120F, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xA0C, 0x2D38120F, + 0x98000400, 0x00000000, 0x40000000, 0x00000000, + 0xA0C, 0x2E7F120F, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0xA0C, 0x2E34120F, + 0xA0000000, 0x00000000, + 0xA0C, 0x2E7F120F, + 0xB0000000, 0x00000000, + 0xA10, 0x9500BB7E, + 0xA14, 0x1114D028, + 0xA18, 0x00881117, + 0xA1C, 0x89140F00, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0xA20, 0x13130000, + 0xA24, 0x060A0D10, + 0xA28, 0x00000103, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0xA20, 0x13130000, + 0xA24, 0x060A0D10, + 0xA28, 0x00000103, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0xA20, 0x13130000, + 0xA24, 0x060A0D10, + 0xA28, 0x00000103, + 0x98000001, 0x00000000, 0x40000000, 0x00000000, + 0xA20, 0x1A1B0000, + 0xA24, 0x090E1317, + 0xA28, 0x00000204, + 0x98000001, 0x00000001, 0x40000000, 0x00000000, + 0xA20, 0x1A1B0000, + 0xA24, 0x090E1317, + 0xA28, 0x00000204, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xA20, 0x1A1B0000, + 0xA24, 0x090E1317, + 0xA28, 0x00000204, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0xA20, 0x13130000, + 0xA24, 0x060A0D10, + 0xA28, 0x00000103, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0xA20, 0x13130000, + 0xA24, 0x060A0D10, + 0xA28, 0x00000103, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0xA20, 0x1A1B0000, + 0xA24, 0x090E1317, + 0xA28, 0x00000204, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0xA20, 0x1A1B0000, + 0xA24, 0x090E1317, + 0xA28, 0x00000204, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xA20, 0x1A1B0000, + 0xA24, 0x090E1317, + 0xA28, 0x00000204, + 0x98000400, 0x00000000, 0x40000000, 0x00000000, + 0xA20, 0x1A1B0000, + 0xA24, 0x090E1317, + 0xA28, 0x00000204, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0xA20, 0x1A1B0000, + 0xA24, 0x090E1317, + 0xA28, 0x00000204, + 0xA0000000, 0x00000000, + 0xA20, 0x1A1B0000, + 0xA24, 0x090E1317, + 0xA28, 0x00000204, + 0xB0000000, 0x00000000, + 0xA2C, 0x00D30000, + 0xA70, 0x101FBF00, + 0xA74, 0x00000007, + 0xA78, 0x00000900, + 0xA7C, 0x225B0606, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0xA80, 0x218075B1, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0xA80, 0x218075B1, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0xA80, 0x218075B1, + 0x98000001, 0x00000000, 0x40000000, 0x00000000, + 0xA80, 0x218075B1, + 0x98000001, 0x00000001, 0x40000000, 0x00000000, + 0xA80, 0x218075B1, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xA80, 0x218075B1, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0xA80, 0x21807530, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0xA80, 0x218075B1, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0xA80, 0x218075B1, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0xA80, 0x218075B1, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xA80, 0x21807530, + 0x98000400, 0x00000000, 0x40000000, 0x00000000, + 0xA80, 0x218075B1, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0xA80, 0x21807531, + 0xA0000000, 0x00000000, + 0xA80, 0x218075B1, + 0xB0000000, 0x00000000, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0xB2C, 0x00000000, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0xB2C, 0x00000000, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0xB2C, 0x00000000, + 0x98000001, 0x00000000, 0x40000000, 0x00000000, + 0xB2C, 0x00000000, + 0x98000001, 0x00000001, 0x40000000, 0x00000000, + 0xB2C, 0x00000000, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xB2C, 0x00000000, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0xB2C, 0x00000000, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0xB2C, 0x00000000, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0xB2C, 0x00000000, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0xB2C, 0x00000000, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xB2C, 0x00000000, + 0x98000400, 0x00000000, 0x40000000, 0x00000000, + 0xB2C, 0x80000000, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0xB2C, 0x80000000, + 0xA0000000, 0x00000000, + 0xB2C, 0x80000000, + 0xB0000000, 0x00000000, + 0xC00, 0x48071D40, + 0xC04, 0x03A05611, + 0xC08, 0x000000E4, + 0xC0C, 0x6C6C6C6C, + 0xC10, 0x08800000, + 0xC14, 0x40000100, + 0xC18, 0x08800000, + 0xC1C, 0x40000100, + 0xC20, 0x00000000, + 0xC24, 0x00000000, + 0xC28, 0x00000000, + 0xC2C, 0x00000000, + 0xC30, 0x69E9AC47, + 0xC34, 0x469652AF, + 0xC38, 0x49795994, + 0xC3C, 0x0A97971C, + 0xC40, 0x1F7C403F, + 0xC44, 0x000100B7, + 0xC48, 0xEC020107, + 0xC4C, 0x007F037F, + 0xC50, 0x69553420, + 0xC54, 0x43BC0094, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0xC58, 0x00013159, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0xC58, 0x00013159, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0xC58, 0x00013959, + 0x98000001, 0x00000000, 0x40000000, 0x00000000, + 0xC58, 0x00013159, + 0x98000001, 0x00000001, 0x40000000, 0x00000000, + 0xC58, 0x00013159, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xC58, 0x00013959, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0xC58, 0x00013169, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0xC58, 0x00013169, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0xC58, 0x00013169, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0xC58, 0x00013169, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xC58, 0x00013169, + 0x98000400, 0x00000000, 0x40000000, 0x00000000, + 0xC58, 0x00013159, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0xC58, 0x00013159, + 0xA0000000, 0x00000000, + 0xC58, 0x00013169, + 0xB0000000, 0x00000000, + 0xC5C, 0x00250492, + 0xC60, 0x00000000, + 0xC64, 0x7112848B, + 0xC68, 0x47C00BFF, + 0xC6C, 0x00000036, + 0xC70, 0x2C7F000D, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0xC74, 0x028610DB, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0xC74, 0x028610DB, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0xC74, 0x028610DB, + 0x98000001, 0x00000000, 0x40000000, 0x00000000, + 0xC74, 0x028610DB, + 0x98000001, 0x00000001, 0x40000000, 0x00000000, + 0xC74, 0x028610DB, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xC74, 0x028610DB, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0xC74, 0x020610DB, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0xC74, 0x020610DB, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0xC74, 0x020610DB, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0xC74, 0x020610DB, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xC74, 0x020610DB, + 0x98000400, 0x00000000, 0x40000000, 0x00000000, + 0xC74, 0x028610DB, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0xC74, 0x028610DB, + 0xA0000000, 0x00000000, + 0xC74, 0x020610DB, + 0xB0000000, 0x00000000, + 0xC78, 0x0000001F, + 0xC7C, 0x00B91612, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0xC80, 0x2D4000B5, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0xC80, 0x2D4000B5, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0xC80, 0x2D4000B5, + 0x98000001, 0x00000000, 0x40000000, 0x00000000, + 0xC80, 0x390000E4, + 0x98000001, 0x00000001, 0x40000000, 0x00000000, + 0xC80, 0x390000E4, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xC80, 0x390000E4, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0xC80, 0x2D4000B5, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0xC80, 0x2D4000B5, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0xC80, 0x390000E4, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0xC80, 0x390000E4, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xC80, 0x390000E4, + 0x98000400, 0x00000000, 0x40000000, 0x00000000, + 0xC80, 0x390000E4, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0xC80, 0x390000E4, + 0xA0000000, 0x00000000, + 0xC80, 0x390000E4, + 0xB0000000, 0x00000000, + 0xC84, 0x21F60000, + 0xC88, 0x40000100, + 0xC8C, 0x20200000, + 0xC90, 0x00091521, + 0xC94, 0x00000000, + 0xC98, 0x00121820, + 0xC9C, 0x00007F7F, + 0xCA0, 0x00000000, + 0xCA4, 0x000300A0, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0xCA8, 0xFFFF0000, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0xCA8, 0xFFFF0000, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0xCA8, 0xFFFF0000, + 0x98000001, 0x00000000, 0x40000000, 0x00000000, + 0xCA8, 0xFFFF0000, + 0x98000001, 0x00000001, 0x40000000, 0x00000000, + 0xCA8, 0xFFFF0000, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xCA8, 0xFFFF0000, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0xCA8, 0x00000000, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0xCA8, 0x00000000, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0xCA8, 0x00000000, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0xCA8, 0x00000000, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xCA8, 0x00000000, + 0x98000400, 0x00000000, 0x40000000, 0x00000000, + 0xCA8, 0xFFFF0000, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0xCA8, 0xFFFF0000, + 0xA0000000, 0x00000000, + 0xCA8, 0x00000000, + 0xB0000000, 0x00000000, + 0xCAC, 0x00000000, + 0xCB0, 0x00000000, + 0xCB4, 0x00000000, + 0xCB8, 0x00000000, + 0xCBC, 0x28000000, + 0xCC0, 0x00000000, + 0xCC4, 0x00000000, + 0xCC8, 0x00000000, + 0xCCC, 0x00000000, + 0xCD0, 0x00000000, + 0xCD4, 0x00000000, + 0xCD8, 0x64B22427, + 0xCDC, 0x00766932, + 0xCE0, 0x00222222, + 0xCE4, 0x00000000, + 0xCE8, 0x37644302, + 0xCEC, 0x2F97D40C, + 0xD00, 0x00000740, + 0xD04, 0x00020401, + 0xD08, 0x0000907F, + 0xD0C, 0x20010201, + 0xD10, 0xA0633333, + 0xD14, 0x3333BC43, + 0xD18, 0x7A8F5B6F, + 0xD2C, 0xCC979975, + 0xD30, 0x00000000, + 0xD34, 0x80608000, + 0xD38, 0x00000000, + 0xD3C, 0x00127353, + 0xD40, 0x00000000, + 0xD44, 0x00000000, + 0xD48, 0x00000000, + 0xD4C, 0x00000000, + 0xD50, 0x6437140A, + 0xD54, 0x00000000, + 0xD58, 0x00000282, + 0xD5C, 0x30032064, + 0xD60, 0x4653DE68, + 0xD64, 0x04518A3C, + 0xD68, 0x00002101, + 0xD6C, 0x2A201C16, + 0xD70, 0x1812362E, + 0xD74, 0x322C2220, + 0xD78, 0x000E3C24, + 0xE00, 0x2D2D2D2D, + 0xE04, 0x2D2D2D2D, + 0xE08, 0x0390272D, + 0xE10, 0x2D2D2D2D, + 0xE14, 0x2D2D2D2D, + 0xE18, 0x2D2D2D2D, + 0xE1C, 0x2D2D2D2D, + 0xE28, 0x00000000, + 0xE30, 0x1000DC1F, + 0xE34, 0x10008C1F, + 0xE38, 0x02140102, + 0xE3C, 0x681604C2, + 0xE40, 0x01007C00, + 0xE44, 0x01004800, + 0xE48, 0xFB000000, + 0xE4C, 0x000028D1, + 0xE50, 0x1000DC1F, + 0xE54, 0x10008C1F, + 0xE58, 0x02140102, + 0xE5C, 0x28160D05, + 0xE60, 0x00000048, + 0xE68, 0x001B25A4, + 0xE6C, 0x00C00014, + 0xE70, 0x00C00014, + 0xE74, 0x01000014, + 0xE78, 0x01000014, + 0xE7C, 0x01000014, + 0xE80, 0x01000014, + 0xE84, 0x00C00014, + 0xE88, 0x01000014, + 0xE8C, 0x00C00014, + 0xED0, 0x00C00014, + 0xED4, 0x00C00014, + 0xED8, 0x00C00014, + 0xEDC, 0x00000014, + 0xEE0, 0x00000014, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0xEE8, 0x32555448, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0xEE8, 0x32555448, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0xEE8, 0x32555448, + 0x98000001, 0x00000000, 0x40000000, 0x00000000, + 0xEE8, 0x32555448, + 0x98000001, 0x00000001, 0x40000000, 0x00000000, + 0xEE8, 0x32555448, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0xEE8, 0x32555448, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0xEE8, 0x32555448, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0xEE8, 0x32555448, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0xEE8, 0x32555448, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0xEE8, 0x32555448, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0xEE8, 0x32555448, + 0x98000400, 0x00000000, 0x40000000, 0x00000000, + 0xEE8, 0x21555448, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0xEE8, 0x21555448, + 0xA0000000, 0x00000000, + 0xEE8, 0x21555448, + 0xB0000000, 0x00000000, + 0xEEC, 0x01C00014, + 0xF14, 0x00000003, + 0xF4C, 0x00000000, + 0xF00, 0x00000300, + +}; + +void +odm_read_and_config_mp_8188e_phy_reg( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u32 i = 0; + u8 c_cond; + bool is_matched = true, is_skipped = false; + u32 array_len = sizeof(array_mp_8188e_phy_reg) / sizeof(u32); + u32 *array = array_mp_8188e_phy_reg; + + u32 v1 = 0, v2 = 0, pre_v1 = 0, pre_v2 = 0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("===> odm_read_and_config_mp_8188e_phy_reg\n")); + + while ((i + 1) < array_len) { + v1 = array[i]; + v2 = array[i + 1]; + + if (v1 & (BIT(31) | BIT30)) {/*positive & negative condition*/ + if (v1 & BIT(31)) {/* positive condition*/ + c_cond = (u8)((v1 & (BIT(29) | BIT(28))) >> 28); + if (c_cond == COND_ENDIF) {/*end*/ + is_matched = true; + is_skipped = false; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("ENDIF\n")); + } else if (c_cond == COND_ELSE) { /*else*/ + is_matched = is_skipped ? false : true; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("ELSE\n")); + } else {/*if , else if*/ + pre_v1 = v1; + pre_v2 = v2; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("IF or ELSE IF\n")); + } + } else if (v1 & BIT(30)) { /*negative condition*/ + if (is_skipped == false) { + if (check_positive(p_dm_odm, pre_v1, pre_v2, v1, v2)) { + is_matched = true; + is_skipped = true; + } else { + is_matched = false; + is_skipped = false; + } + } else + is_matched = false; + } + } else { + if (is_matched) + odm_config_bb_phy_8188e(p_dm_odm, v1, MASKDWORD, v2); + } + i = i + 2; + } +} + +u32 +odm_get_version_mp_8188e_phy_reg(void) +{ + return 70; +} + +/****************************************************************************** +* PHY_REG_PG.TXT +******************************************************************************/ + +static u32 array_mp_8188e_phy_reg_pg[] = { + 0, 0, 0, 0x00000e08, 0x0000ff00, 0x00003800, + 0, 0, 0, 0x0000086c, 0xffffff00, 0x32343600, + 0, 0, 0, 0x00000e00, 0xffffffff, 0x40424446, + 0, 0, 0, 0x00000e04, 0xffffffff, 0x28323638, + 0, 0, 0, 0x00000e10, 0xffffffff, 0x38404244, + 0, 0, 0, 0x00000e14, 0xffffffff, 0x26303436 +}; + +void +odm_read_and_config_mp_8188e_phy_reg_pg( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u32 i = 0; + u32 array_len = sizeof(array_mp_8188e_phy_reg_pg) / sizeof(u32); + u32 *array = array_mp_8188e_phy_reg_pg; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("===> odm_read_and_config_mp_8188e_phy_reg_pg\n")); + + p_dm_odm->phy_reg_pg_version = 1; + p_dm_odm->phy_reg_pg_value_type = PHY_REG_PG_EXACT_VALUE; + + for (i = 0; i < array_len; i += 6) { + u32 v1 = array[i]; + u32 v2 = array[i + 1]; + u32 v3 = array[i + 2]; + u32 v4 = array[i + 3]; + u32 v5 = array[i + 4]; + u32 v6 = array[i + 5]; + + odm_config_bb_phy_reg_pg_8188e(p_dm_odm, v1, v2, v3, v4, v5, v6); + } +} diff --git a/drivers/staging/rtl8188eu/hal/halhwimg8188e_bb.h b/drivers/staging/rtl8188eu/hal/halhwimg8188e_bb.h new file mode 100644 index 000000000000..a0ad19bb56ed --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/halhwimg8188e_bb.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/*Image2HeaderVersion: 2.18*/ +#if (RTL8188E_SUPPORT == 1) +#ifndef __INC_MP_BB_HW_IMG_8188E_H +#define __INC_MP_BB_HW_IMG_8188E_H + + +/****************************************************************************** +* AGC_TAB.TXT +******************************************************************************/ + +void +odm_read_and_config_mp_8188e_agc_tab(/* TC: Test Chip, MP: MP Chip*/ + struct PHY_DM_STRUCT *p_dm_odm +); +u32 odm_get_version_mp_8188e_agc_tab(void); + +/****************************************************************************** +* PHY_REG.TXT +******************************************************************************/ + +void +odm_read_and_config_mp_8188e_phy_reg(/* TC: Test Chip, MP: MP Chip*/ + struct PHY_DM_STRUCT *p_dm_odm +); +u32 odm_get_version_mp_8188e_phy_reg(void); + +/****************************************************************************** +* PHY_REG_PG.TXT +******************************************************************************/ + +void +odm_read_and_config_mp_8188e_phy_reg_pg(/* TC: Test Chip, MP: MP Chip*/ + struct PHY_DM_STRUCT *p_dm_odm +); +u32 odm_get_version_mp_8188e_phy_reg_pg(void); + +#endif +#endif /* end of HWIMG_SUPPORT*/ diff --git a/drivers/staging/rtl8188eu/hal/halhwimg8188e_mac.c b/drivers/staging/rtl8188eu/hal/halhwimg8188e_mac.c new file mode 100644 index 000000000000..e9d3837c6233 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/halhwimg8188e_mac.c @@ -0,0 +1,272 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/*Image2HeaderVersion: 2.18*/ +#include "mp_precomp.h" +#include "phydm_precomp.h" + +#if (RTL8188E_SUPPORT == 1) +static bool +check_positive( + struct PHY_DM_STRUCT *p_dm_odm, + const u32 condition1, + const u32 condition2, + const u32 condition3, + const u32 condition4 +) +{ + u8 _board_type = ((p_dm_odm->board_type & BIT(4)) >> 4) << 0 | /* _GLNA*/ + ((p_dm_odm->board_type & BIT(3)) >> 3) << 1 | /* _GPA*/ + ((p_dm_odm->board_type & BIT(7)) >> 7) << 2 | /* _ALNA*/ + ((p_dm_odm->board_type & BIT(6)) >> 6) << 3 | /* _APA */ + ((p_dm_odm->board_type & BIT(2)) >> 2) << 4; /* _BT*/ + + u32 cond1 = condition1, cond2 = condition2, cond3 = condition3, cond4 = condition4; + u32 driver1 = p_dm_odm->cut_version << 24 | + (p_dm_odm->support_interface & 0xF0) << 16 | + p_dm_odm->support_platform << 16 | + p_dm_odm->package_type << 12 | + (p_dm_odm->support_interface & 0x0F) << 8 | + _board_type; + + u32 driver2 = (p_dm_odm->type_glna & 0xFF) << 0 | + (p_dm_odm->type_gpa & 0xFF) << 8 | + (p_dm_odm->type_alna & 0xFF) << 16 | + (p_dm_odm->type_apa & 0xFF) << 24; + + u32 driver3 = 0; + + u32 driver4 = (p_dm_odm->type_glna & 0xFF00) >> 8 | + (p_dm_odm->type_gpa & 0xFF00) | + (p_dm_odm->type_alna & 0xFF00) << 8 | + (p_dm_odm->type_apa & 0xFF00) << 16; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, + ("===> check_positive (cond1, cond2, cond3, cond4) = (0x%X 0x%X 0x%X 0x%X)\n", cond1, cond2, cond3, cond4)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, + ("===> check_positive (driver1, driver2, driver3, driver4) = (0x%X 0x%X 0x%X 0x%X)\n", driver1, driver2, driver3, driver4)); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, + (" (Platform, Interface) = (0x%X, 0x%X)\n", p_dm_odm->support_platform, p_dm_odm->support_interface)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, + (" (Board, Package) = (0x%X, 0x%X)\n", p_dm_odm->board_type, p_dm_odm->package_type)); + + + /*============== value Defined Check ===============*/ + /*QFN type [15:12] and cut version [27:24] need to do value check*/ + + if (((cond1 & 0x0000F000) != 0) && ((cond1 & 0x0000F000) != (driver1 & 0x0000F000))) + return false; + if (((cond1 & 0x0F000000) != 0) && ((cond1 & 0x0F000000) != (driver1 & 0x0F000000))) + return false; + + /*=============== Bit Defined Check ================*/ + /* We don't care [31:28] */ + + cond1 &= 0x00FF0FFF; + driver1 &= 0x00FF0FFF; + + if ((cond1 & driver1) == cond1) { + u32 bit_mask = 0; + + if ((cond1 & 0x0F) == 0) /* board_type is DONTCARE*/ + return true; + + if ((cond1 & BIT(0)) != 0) /*GLNA*/ + bit_mask |= 0x000000FF; + if ((cond1 & BIT(1)) != 0) /*GPA*/ + bit_mask |= 0x0000FF00; + if ((cond1 & BIT(2)) != 0) /*ALNA*/ + bit_mask |= 0x00FF0000; + if ((cond1 & BIT(3)) != 0) /*APA*/ + bit_mask |= 0xFF000000; + + if (((cond2 & bit_mask) == (driver2 & bit_mask)) && ((cond4 & bit_mask) == (driver4 & bit_mask))) /* board_type of each RF path is matched*/ + return true; + else + return false; + } else + return false; +} +static bool +check_negative( + struct PHY_DM_STRUCT *p_dm_odm, + const u32 condition1, + const u32 condition2 +) +{ + return true; +} + +/****************************************************************************** +* MAC_REG.TXT +******************************************************************************/ + +static u32 array_mp_8188e_mac_reg[] = { + 0x026, 0x00000041, + 0x027, 0x00000035, + 0x80000002, 0x00000000, 0x40000000, 0x00000000, + 0x040, 0x0000000C, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x040, 0x0000000C, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0x040, 0x0000000C, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0x040, 0x0000000C, + 0xA0000000, 0x00000000, + 0x040, 0x00000000, + 0xB0000000, 0x00000000, + 0x421, 0x0000000F, + 0x428, 0x0000000A, + 0x429, 0x00000010, + 0x430, 0x00000000, + 0x431, 0x00000001, + 0x432, 0x00000002, + 0x433, 0x00000004, + 0x434, 0x00000005, + 0x435, 0x00000006, + 0x436, 0x00000007, + 0x437, 0x00000008, + 0x438, 0x00000000, + 0x439, 0x00000000, + 0x43A, 0x00000001, + 0x43B, 0x00000002, + 0x43C, 0x00000004, + 0x43D, 0x00000005, + 0x43E, 0x00000006, + 0x43F, 0x00000007, + 0x440, 0x0000005D, + 0x441, 0x00000001, + 0x442, 0x00000000, + 0x444, 0x00000015, + 0x445, 0x000000F0, + 0x446, 0x0000000F, + 0x447, 0x00000000, + 0x458, 0x00000041, + 0x459, 0x000000A8, + 0x45A, 0x00000072, + 0x45B, 0x000000B9, + 0x460, 0x00000066, + 0x461, 0x00000066, + 0x480, 0x00000008, + 0x4C8, 0x000000FF, + 0x4C9, 0x00000008, + 0x4CC, 0x000000FF, + 0x4CD, 0x000000FF, + 0x4CE, 0x00000001, + 0x4D3, 0x00000001, + 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, + 0x525, 0x0000004F, + 0x550, 0x00000010, + 0x551, 0x00000010, + 0x559, 0x00000002, + 0x55D, 0x000000FF, + 0x605, 0x00000030, + 0x608, 0x0000000E, + 0x609, 0x0000002A, + 0x620, 0x000000FF, + 0x621, 0x000000FF, + 0x622, 0x000000FF, + 0x623, 0x000000FF, + 0x624, 0x000000FF, + 0x625, 0x000000FF, + 0x626, 0x000000FF, + 0x627, 0x000000FF, + 0x63C, 0x00000008, + 0x63D, 0x00000008, + 0x63E, 0x0000000C, + 0x63F, 0x0000000C, + 0x640, 0x00000040, + 0x652, 0x00000020, + 0x66E, 0x00000005, + 0x700, 0x00000021, + 0x701, 0x00000043, + 0x702, 0x00000065, + 0x703, 0x00000087, + 0x708, 0x00000021, + 0x709, 0x00000043, + 0x70A, 0x00000065, + 0x70B, 0x00000087, + +}; + +void +odm_read_and_config_mp_8188e_mac_reg( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u32 i = 0; + u8 c_cond; + bool is_matched = true, is_skipped = false; + u32 array_len = sizeof(array_mp_8188e_mac_reg) / sizeof(u32); + u32 *array = array_mp_8188e_mac_reg; + + u32 v1 = 0, v2 = 0, pre_v1 = 0, pre_v2 = 0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("===> odm_read_and_config_mp_8188e_mac_reg\n")); + + while ((i + 1) < array_len) { + v1 = array[i]; + v2 = array[i + 1]; + + if (v1 & (BIT(31) | BIT30)) {/*positive & negative condition*/ + if (v1 & BIT(31)) {/* positive condition*/ + c_cond = (u8)((v1 & (BIT(29) | BIT(28))) >> 28); + if (c_cond == COND_ENDIF) {/*end*/ + is_matched = true; + is_skipped = false; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("ENDIF\n")); + } else if (c_cond == COND_ELSE) { /*else*/ + is_matched = is_skipped ? false : true; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("ELSE\n")); + } else {/*if , else if*/ + pre_v1 = v1; + pre_v2 = v2; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("IF or ELSE IF\n")); + } + } else if (v1 & BIT(30)) { /*negative condition*/ + if (is_skipped == false) { + if (check_positive(p_dm_odm, pre_v1, pre_v2, v1, v2)) { + is_matched = true; + is_skipped = true; + } else { + is_matched = false; + is_skipped = false; + } + } else + is_matched = false; + } + } else { + if (is_matched) + odm_config_mac_8188e(p_dm_odm, v1, (u8)v2); + } + i = i + 2; + } +} + +u32 +odm_get_version_mp_8188e_mac_reg(void) +{ + return 70; +} + +#endif /* end of HWIMG_SUPPORT*/ diff --git a/drivers/staging/rtl8188eu/hal/halhwimg8188e_mac.h b/drivers/staging/rtl8188eu/hal/halhwimg8188e_mac.h new file mode 100644 index 000000000000..40f5ab8073bf --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/halhwimg8188e_mac.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/*Image2HeaderVersion: 2.18*/ +#if (RTL8188E_SUPPORT == 1) +#ifndef __INC_MP_MAC_HW_IMG_8188E_H +#define __INC_MP_MAC_HW_IMG_8188E_H + + +/****************************************************************************** +* MAC_REG.TXT +******************************************************************************/ + +void +odm_read_and_config_mp_8188e_mac_reg(/* TC: Test Chip, MP: MP Chip*/ + struct PHY_DM_STRUCT *p_dm_odm +); +u32 odm_get_version_mp_8188e_mac_reg(void); + +#endif +#endif /* end of HWIMG_SUPPORT*/ diff --git a/drivers/staging/rtl8188eu/hal/halhwimg8188e_rf.c b/drivers/staging/rtl8188eu/hal/halhwimg8188e_rf.c new file mode 100644 index 000000000000..da5af62eed12 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/halhwimg8188e_rf.c @@ -0,0 +1,2183 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/*Image2HeaderVersion: 2.18*/ +#include "mp_precomp.h" +#include "phydm_precomp.h" + +static bool +check_positive( + struct PHY_DM_STRUCT *p_dm_odm, + const u32 condition1, + const u32 condition2, + const u32 condition3, + const u32 condition4 +) +{ + u8 _board_type = ((p_dm_odm->board_type & BIT(4)) >> 4) << 0 | /* _GLNA*/ + ((p_dm_odm->board_type & BIT(3)) >> 3) << 1 | /* _GPA*/ + ((p_dm_odm->board_type & BIT(7)) >> 7) << 2 | /* _ALNA*/ + ((p_dm_odm->board_type & BIT(6)) >> 6) << 3 | /* _APA */ + ((p_dm_odm->board_type & BIT(2)) >> 2) << 4; /* _BT*/ + + u32 cond1 = condition1, cond2 = condition2, cond3 = condition3, cond4 = condition4; + u32 driver1 = p_dm_odm->cut_version << 24 | + (p_dm_odm->support_interface & 0xF0) << 16 | + p_dm_odm->support_platform << 16 | + p_dm_odm->package_type << 12 | + (p_dm_odm->support_interface & 0x0F) << 8 | + _board_type; + + u32 driver2 = (p_dm_odm->type_glna & 0xFF) << 0 | + (p_dm_odm->type_gpa & 0xFF) << 8 | + (p_dm_odm->type_alna & 0xFF) << 16 | + (p_dm_odm->type_apa & 0xFF) << 24; + + u32 driver3 = 0; + + u32 driver4 = (p_dm_odm->type_glna & 0xFF00) >> 8 | + (p_dm_odm->type_gpa & 0xFF00) | + (p_dm_odm->type_alna & 0xFF00) << 8 | + (p_dm_odm->type_apa & 0xFF00) << 16; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, + ("===> check_positive (cond1, cond2, cond3, cond4) = (0x%X 0x%X 0x%X 0x%X)\n", cond1, cond2, cond3, cond4)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, + ("===> check_positive (driver1, driver2, driver3, driver4) = (0x%X 0x%X 0x%X 0x%X)\n", driver1, driver2, driver3, driver4)); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, + (" (Platform, Interface) = (0x%X, 0x%X)\n", p_dm_odm->support_platform, p_dm_odm->support_interface)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, + (" (Board, Package) = (0x%X, 0x%X)\n", p_dm_odm->board_type, p_dm_odm->package_type)); + + + /*============== value Defined Check ===============*/ + /*QFN type [15:12] and cut version [27:24] need to do value check*/ + + if (((cond1 & 0x0000F000) != 0) && ((cond1 & 0x0000F000) != (driver1 & 0x0000F000))) + return false; + if (((cond1 & 0x0F000000) != 0) && ((cond1 & 0x0F000000) != (driver1 & 0x0F000000))) + return false; + + /*=============== Bit Defined Check ================*/ + /* We don't care [31:28] */ + + cond1 &= 0x00FF0FFF; + driver1 &= 0x00FF0FFF; + + if ((cond1 & driver1) == cond1) { + u32 bit_mask = 0; + + if ((cond1 & 0x0F) == 0) /* board_type is DONTCARE*/ + return true; + + if ((cond1 & BIT(0)) != 0) /*GLNA*/ + bit_mask |= 0x000000FF; + if ((cond1 & BIT(1)) != 0) /*GPA*/ + bit_mask |= 0x0000FF00; + if ((cond1 & BIT(2)) != 0) /*ALNA*/ + bit_mask |= 0x00FF0000; + if ((cond1 & BIT(3)) != 0) /*APA*/ + bit_mask |= 0xFF000000; + + if (((cond2 & bit_mask) == (driver2 & bit_mask)) && ((cond4 & bit_mask) == (driver4 & bit_mask))) /* board_type of each RF path is matched*/ + return true; + else + return false; + } else + return false; +} +static bool +check_negative( + struct PHY_DM_STRUCT *p_dm_odm, + const u32 condition1, + const u32 condition2 +) +{ + return true; +} + +/****************************************************************************** +* RadioA.TXT +******************************************************************************/ + +static u32 array_mp_8188e_radioa[] = { + 0x000, 0x00030000, + 0x008, 0x00084000, + 0x018, 0x00000407, + 0x019, 0x00000012, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0x01B, 0x00000084, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0x01B, 0x00000084, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0x01B, 0x00000084, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0x98000001, 0x00000000, 0x40000000, 0x00000000, + 0x01B, 0x00000084, + 0x98000001, 0x00000001, 0x40000000, 0x00000000, + 0x01B, 0x00000084, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0x01B, 0x00000084, + 0x98000400, 0x00000000, 0x40000000, 0x00000000, + 0x01B, 0x00000084, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0x01B, 0x00000084, + 0x90000400, 0x00000000, 0x40000000, 0x00000000, + 0xA0000000, 0x00000000, + 0xB0000000, 0x00000000, + 0x01E, 0x00080009, + 0x01F, 0x00000880, + 0x02F, 0x0001A060, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0000, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0x03F, 0x000C0000, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0x03F, 0x000C0000, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x98000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0000, + 0x98000001, 0x00000001, 0x40000000, 0x00000000, + 0x03F, 0x000C0000, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0x03F, 0x000C0000, + 0x98000400, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0000, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x000C0000, + 0x90000400, 0x00000000, 0x40000000, 0x00000000, + 0x03F, 0x00000000, + 0xA0000000, 0x00000000, + 0x03F, 0x00000000, + 0xB0000000, 0x00000000, + 0x042, 0x000060C0, + 0x057, 0x000D0000, + 0x058, 0x000BE180, + 0x067, 0x00001552, + 0x083, 0x00000000, + 0x0B0, 0x000FF8FC, + 0x0B1, 0x00054400, + 0x0B2, 0x000CCC19, + 0x0B4, 0x00043003, + 0x0B6, 0x0004953E, + 0x0B7, 0x0001C718, + 0x0B8, 0x000060FF, + 0x0B9, 0x00080001, + 0x0BA, 0x00040000, + 0x0BB, 0x00000400, + 0x0BF, 0x000C0000, + 0x0C2, 0x00002400, + 0x0C3, 0x00000009, + 0x0C4, 0x00040C91, + 0x0C5, 0x00099999, + 0x0C6, 0x000000A3, + 0x0C7, 0x00088820, + 0x0C8, 0x00076C06, + 0x0C9, 0x00000000, + 0x0CA, 0x00080000, + 0x0DF, 0x00000180, + 0x0EF, 0x000001A0, + 0x051, 0x0006B27D, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x0007E49D, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0x052, 0x0007E49D, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0x052, 0x0007E49D, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0x052, 0x0007E49D, + 0x98000001, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x0007E49D, + 0x98000001, 0x00000001, 0x40000000, 0x00000000, + 0x052, 0x0007E49D, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0x052, 0x0007E49D, + 0x98000400, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x0007E4DD, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x0007E49D, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x0007E49D, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0x052, 0x0007E49D, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0x052, 0x0007E49D, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x0007E49D, + 0x90000400, 0x00000000, 0x40000000, 0x00000000, + 0x052, 0x0007E4DD, + 0xA0000000, 0x00000000, + 0x052, 0x0007E49D, + 0xB0000000, 0x00000000, + 0x053, 0x00000073, + 0x056, 0x00051FF3, + 0x035, 0x00000086, + 0x035, 0x00000186, + 0x035, 0x00000286, + 0x036, 0x00001C25, + 0x036, 0x00009C25, + 0x036, 0x00011C25, + 0x036, 0x00019C25, + 0x0B6, 0x00048538, + 0x018, 0x00000C07, + 0x05A, 0x0004BD00, + 0x019, 0x000739D0, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x0000A095, + 0x034, 0x00009092, + 0x034, 0x0000808E, + 0x034, 0x0000704F, + 0x034, 0x0000604C, + 0x034, 0x00005049, + 0x034, 0x0000400C, + 0x034, 0x00003009, + 0x034, 0x00002006, + 0x034, 0x00001003, + 0x034, 0x00000000, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0x034, 0x0000A095, + 0x034, 0x00009092, + 0x034, 0x0000808E, + 0x034, 0x0000704F, + 0x034, 0x0000604C, + 0x034, 0x00005049, + 0x034, 0x0000400C, + 0x034, 0x00003009, + 0x034, 0x00002006, + 0x034, 0x00001003, + 0x034, 0x00000000, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0x034, 0x0000A095, + 0x034, 0x00009092, + 0x034, 0x0000808E, + 0x034, 0x0000704F, + 0x034, 0x0000604C, + 0x034, 0x00005049, + 0x034, 0x0000400C, + 0x034, 0x00003009, + 0x034, 0x00002006, + 0x034, 0x00001003, + 0x034, 0x00000000, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0x034, 0x0000A095, + 0x034, 0x00009092, + 0x034, 0x0000808E, + 0x034, 0x0000704F, + 0x034, 0x0000604C, + 0x034, 0x00005049, + 0x034, 0x0000400C, + 0x034, 0x00003009, + 0x034, 0x00002006, + 0x034, 0x00001003, + 0x034, 0x00000000, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x034, 0x0000A095, + 0x034, 0x00009092, + 0x034, 0x0000808E, + 0x034, 0x0000704F, + 0x034, 0x0000604C, + 0x034, 0x00005049, + 0x034, 0x0000400C, + 0x034, 0x00003009, + 0x034, 0x00002006, + 0x034, 0x00001003, + 0x034, 0x00000000, + 0xA0000000, 0x00000000, + 0x034, 0x0000ADF3, + 0x034, 0x00009DF0, + 0x034, 0x00008DED, + 0x034, 0x00007DEA, + 0x034, 0x00006DE7, + 0x034, 0x000054EE, + 0x034, 0x000044EB, + 0x034, 0x000034E8, + 0x034, 0x0000246B, + 0x034, 0x00001468, + 0x034, 0x0000006D, + 0xB0000000, 0x00000000, + 0x000, 0x00030159, + 0x084, 0x00068200, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0x086, 0x000000CE, + 0x087, 0x00048A00, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0x086, 0x000000CE, + 0x087, 0x00048A00, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0x086, 0x000000CE, + 0x087, 0x00048A00, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0x086, 0x000000CE, + 0x087, 0x00079F80, + 0x98000001, 0x00000000, 0x40000000, 0x00000000, + 0x086, 0x000000CE, + 0x087, 0x00048A00, + 0x98000001, 0x00000001, 0x40000000, 0x00000000, + 0x086, 0x000000CE, + 0x087, 0x00048A00, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0x086, 0x000000CE, + 0x087, 0x00048A00, + 0x98000400, 0x00000000, 0x40000000, 0x00000000, + 0x086, 0x000000CE, + 0x087, 0x00048A00, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x086, 0x000000CE, + 0x087, 0x00048A00, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x086, 0x000000CE, + 0x087, 0x00048A00, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0x086, 0x000000CE, + 0x087, 0x00048A00, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0x086, 0x000000CE, + 0x087, 0x00079F80, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0x086, 0x0008014E, + 0x087, 0x0004DF80, + 0x90000400, 0x00000000, 0x40000000, 0x00000000, + 0x086, 0x000000CE, + 0x087, 0x00048A00, + 0xA0000000, 0x00000000, + 0x086, 0x000000CE, + 0x087, 0x00048A00, + 0xB0000000, 0x00000000, + 0x08E, 0x00065540, + 0x08F, 0x00088000, + 0x0EF, 0x000020A0, + 0x88000003, 0x00000000, 0x40000000, 0x00000000, + 0x03B, 0x000F02B0, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D4FB0, + 0x03B, 0x000CF060, + 0x03B, 0x000B0090, + 0x03B, 0x000A0080, + 0x03B, 0x00090080, + 0x03B, 0x0008F780, + 0x03B, 0x000722B0, + 0x03B, 0x0006F7B0, + 0x03B, 0x00054FB0, + 0x03B, 0x0004F060, + 0x03B, 0x00030090, + 0x03B, 0x00020080, + 0x03B, 0x00010080, + 0x03B, 0x0000F780, + 0x0EF, 0x000000A0, + 0x98000003, 0x00000001, 0x40000000, 0x00000000, + 0x03B, 0x000F02B0, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D4FB0, + 0x03B, 0x000CF060, + 0x03B, 0x000B0090, + 0x03B, 0x000A0080, + 0x03B, 0x00090080, + 0x03B, 0x0008F780, + 0x03B, 0x000722B0, + 0x03B, 0x0006F7B0, + 0x03B, 0x00054FB0, + 0x03B, 0x0004F060, + 0x03B, 0x00030090, + 0x03B, 0x00020080, + 0x03B, 0x00010080, + 0x03B, 0x0000F780, + 0x0EF, 0x000000A0, + 0x98000003, 0x00000002, 0x40000000, 0x00000000, + 0x03B, 0x000F02B0, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D4FB0, + 0x03B, 0x000CF060, + 0x03B, 0x000B0090, + 0x03B, 0x000A0080, + 0x03B, 0x00090080, + 0x03B, 0x0008F780, + 0x03B, 0x000722B0, + 0x03B, 0x0006F7B0, + 0x03B, 0x00054FB0, + 0x03B, 0x0004F060, + 0x03B, 0x00030090, + 0x03B, 0x00020080, + 0x03B, 0x00010080, + 0x03B, 0x0000F780, + 0x0EF, 0x000000A0, + 0x90000003, 0x00000002, 0x40000000, 0x00000000, + 0x03B, 0x000F07B0, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D0020, + 0x03B, 0x000CF060, + 0x03B, 0x000B07E0, + 0x03B, 0x000A0010, + 0x03B, 0x00090000, + 0x03B, 0x0008F780, + 0x03B, 0x000727B0, + 0x03B, 0x0006F7B0, + 0x03B, 0x00054FB0, + 0x03B, 0x0004F060, + 0x03B, 0x00030090, + 0x03B, 0x00020080, + 0x03B, 0x00010080, + 0x03B, 0x0000F780, + 0x0EF, 0x000000A0, + 0x98000001, 0x00000000, 0x40000000, 0x00000000, + 0x03B, 0x000F02B0, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D4FB0, + 0x03B, 0x000CF060, + 0x03B, 0x000B0090, + 0x03B, 0x000A0080, + 0x03B, 0x00090080, + 0x03B, 0x0008F780, + 0x03B, 0x000722B0, + 0x03B, 0x0006F7B0, + 0x03B, 0x00054FB0, + 0x03B, 0x0004F060, + 0x03B, 0x00030090, + 0x03B, 0x00020080, + 0x03B, 0x00010080, + 0x03B, 0x0000F780, + 0x0EF, 0x000000A0, + 0x98000001, 0x00000001, 0x40000000, 0x00000000, + 0x03B, 0x000F02B0, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D4FB0, + 0x03B, 0x000CF060, + 0x03B, 0x000B0090, + 0x03B, 0x000A0080, + 0x03B, 0x00090080, + 0x03B, 0x0008F780, + 0x03B, 0x000722B0, + 0x03B, 0x0006F7B0, + 0x03B, 0x00054FB0, + 0x03B, 0x0004F060, + 0x03B, 0x00030090, + 0x03B, 0x00020080, + 0x03B, 0x00010080, + 0x03B, 0x0000F780, + 0x0EF, 0x000000A0, + 0x98000001, 0x00000002, 0x40000000, 0x00000000, + 0x03B, 0x000F02B0, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D4FB0, + 0x03B, 0x000CF060, + 0x03B, 0x000B0090, + 0x03B, 0x000A0080, + 0x03B, 0x00090080, + 0x03B, 0x0008F780, + 0x03B, 0x000722B0, + 0x03B, 0x0006F7B0, + 0x03B, 0x00054FB0, + 0x03B, 0x0004F060, + 0x03B, 0x00030090, + 0x03B, 0x00020080, + 0x03B, 0x00010080, + 0x03B, 0x0000F780, + 0x0EF, 0x000000A0, + 0x98000400, 0x00000000, 0x40000000, 0x00000000, + 0x03B, 0x000F02B0, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D4FB0, + 0x03B, 0x000CF060, + 0x03B, 0x000B0090, + 0x03B, 0x000A0080, + 0x03B, 0x00090080, + 0x03B, 0x0008F780, + 0x03B, 0x000722B0, + 0x03B, 0x0006F7B0, + 0x03B, 0x00054FB0, + 0x03B, 0x0004F060, + 0x03B, 0x00030090, + 0x03B, 0x00020080, + 0x03B, 0x00010080, + 0x03B, 0x0000F780, + 0x0EF, 0x000000A0, + 0x90000002, 0x00000000, 0x40000000, 0x00000000, + 0x03B, 0x000F02B0, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D4FB0, + 0x03B, 0x000CF060, + 0x03B, 0x000B0090, + 0x03B, 0x000A0080, + 0x03B, 0x00090080, + 0x03B, 0x0008F780, + 0x03B, 0x000722B0, + 0x03B, 0x0006F7B0, + 0x03B, 0x00054FB0, + 0x03B, 0x0004F060, + 0x03B, 0x00030090, + 0x03B, 0x00020080, + 0x03B, 0x00010080, + 0x03B, 0x0000F780, + 0x0EF, 0x000000A0, + 0x90000001, 0x00000000, 0x40000000, 0x00000000, + 0x03B, 0x000F02B0, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D4FB0, + 0x03B, 0x000CF060, + 0x03B, 0x000B0090, + 0x03B, 0x000A0080, + 0x03B, 0x00090080, + 0x03B, 0x0008F780, + 0x03B, 0x000722B0, + 0x03B, 0x0006F7B0, + 0x03B, 0x00054FB0, + 0x03B, 0x0004F060, + 0x03B, 0x00030090, + 0x03B, 0x00020080, + 0x03B, 0x00010080, + 0x03B, 0x0000F780, + 0x0EF, 0x000000A0, + 0x90000001, 0x00000001, 0x40000000, 0x00000000, + 0x03B, 0x000F02B0, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D4FB0, + 0x03B, 0x000CF060, + 0x03B, 0x000B0090, + 0x03B, 0x000A0080, + 0x03B, 0x00090080, + 0x03B, 0x0008F780, + 0x03B, 0x000722B0, + 0x03B, 0x0006F7B0, + 0x03B, 0x00054FB0, + 0x03B, 0x0004F060, + 0x03B, 0x00030090, + 0x03B, 0x00020080, + 0x03B, 0x00010080, + 0x03B, 0x0000F780, + 0x0EF, 0x000000A0, + 0x90000001, 0x00000002, 0x40000000, 0x00000000, + 0x03B, 0x000F07B0, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D0020, + 0x03B, 0x000CF060, + 0x03B, 0x000B07E0, + 0x03B, 0x000A0010, + 0x03B, 0x00090000, + 0x03B, 0x0008F780, + 0x03B, 0x000727B0, + 0x03B, 0x0006F7B0, + 0x03B, 0x00054FB0, + 0x03B, 0x0004F060, + 0x03B, 0x00030090, + 0x03B, 0x00020080, + 0x03B, 0x00010080, + 0x03B, 0x0000F780, + 0x0EF, 0x000000A0, + 0x98000000, 0x00000000, 0x40000000, 0x00000000, + 0x03B, 0x000F6030, + 0x03B, 0x000E6030, + 0x03B, 0x000D6030, + 0x03B, 0x000C6030, + 0x03B, 0x000BF030, + 0x03B, 0x000A0020, + 0x03B, 0x00090090, + 0x03B, 0x0008F080, + 0x03B, 0x0007A730, + 0x03B, 0x000607B0, + 0x03B, 0x0005F770, + 0x03B, 0x00040060, + 0x03B, 0x00030090, + 0x03B, 0x00020780, + 0x03B, 0x000107A0, + 0x03B, 0x0000F760, + 0x0EF, 0x000000A0, + 0x90000400, 0x00000000, 0x40000000, 0x00000000, + 0x03B, 0x000F02B0, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D4FB0, + 0x03B, 0x000CF060, + 0x03B, 0x000B0090, + 0x03B, 0x000A0080, + 0x03B, 0x00090080, + 0x03B, 0x0008F780, + 0x03B, 0x000722B0, + 0x03B, 0x0006F7B0, + 0x03B, 0x00054FB0, + 0x03B, 0x0004F060, + 0x03B, 0x00030090, + 0x03B, 0x00020080, + 0x03B, 0x00010080, + 0x03B, 0x0000F780, + 0x0EF, 0x000000A0, + 0xA0000000, 0x00000000, + 0x03B, 0x000F02B0, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D4FB0, + 0x03B, 0x000CF060, + 0x03B, 0x000B0090, + 0x03B, 0x000A0080, + 0x03B, 0x00090080, + 0x03B, 0x0008F780, + 0x03B, 0x000722B0, + 0x03B, 0x0006F7B0, + 0x03B, 0x00054FB0, + 0x03B, 0x0004F060, + 0x03B, 0x00030090, + 0x03B, 0x00020080, + 0x03B, 0x00010080, + 0x03B, 0x0000F780, + 0x0EF, 0x000000A0, + 0xB0000000, 0x00000000, + 0x000, 0x00010159, + 0x018, 0x0000F407, + 0xFFE, 0x00000000, + 0xFFE, 0x00000000, + 0x01F, 0x00080003, + 0xFFE, 0x00000000, + 0xFFE, 0x00000000, + 0x01E, 0x00000001, + 0x01F, 0x00080000, + 0x000, 0x00033E60, + +}; + +void +odm_read_and_config_mp_8188e_radioa( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u32 i = 0; + u8 c_cond; + bool is_matched = true, is_skipped = false; + u32 array_len = sizeof(array_mp_8188e_radioa) / sizeof(u32); + u32 *array = array_mp_8188e_radioa; + + u32 v1 = 0, v2 = 0, pre_v1 = 0, pre_v2 = 0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("===> odm_read_and_config_mp_8188e_radioa\n")); + + while ((i + 1) < array_len) { + v1 = array[i]; + v2 = array[i + 1]; + + if (v1 & (BIT(31) | BIT30)) {/*positive & negative condition*/ + if (v1 & BIT(31)) {/* positive condition*/ + c_cond = (u8)((v1 & (BIT(29) | BIT(28))) >> 28); + if (c_cond == COND_ENDIF) {/*end*/ + is_matched = true; + is_skipped = false; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("ENDIF\n")); + } else if (c_cond == COND_ELSE) { /*else*/ + is_matched = is_skipped ? false : true; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("ELSE\n")); + } else {/*if , else if*/ + pre_v1 = v1; + pre_v2 = v2; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("IF or ELSE IF\n")); + } + } else if (v1 & BIT(30)) { /*negative condition*/ + if (is_skipped == false) { + if (check_positive(p_dm_odm, pre_v1, pre_v2, v1, v2)) { + is_matched = true; + is_skipped = true; + } else { + is_matched = false; + is_skipped = false; + } + } else + is_matched = false; + } + } else { + if (is_matched) + odm_config_rf_radio_a_8188e(p_dm_odm, v1, v2); + } + i = i + 2; + } +} + +u32 +odm_get_version_mp_8188e_radioa(void) +{ + return 70; +} + +/****************************************************************************** +* TxPowerTrack_AP.TXT +******************************************************************************/ + +void +odm_read_and_config_mp_8188e_txpowertrack_ap( + struct PHY_DM_STRUCT *p_dm_odm +) +{ +} + +/****************************************************************************** +* TxPowerTrack_PCIE.TXT +******************************************************************************/ + +void +odm_read_and_config_mp_8188e_txpowertrack_pcie( + struct PHY_DM_STRUCT *p_dm_odm +) +{ +} + +/****************************************************************************** +* TxPowerTrack_PCIE_ICUT.TXT +******************************************************************************/ + +static u8 g_delta_swing_table_idx_mp_5gb_n_txpowertrack_pcie_icut_8188e[][DELTA_SWINGIDX_SIZE] = { + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 17, 17, 17, 17, 18, 18, 18}, + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18}, + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18}, +}; +static u8 g_delta_swing_table_idx_mp_5gb_p_txpowertrack_pcie_icut_8188e[][DELTA_SWINGIDX_SIZE] = { + {0, 1, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, +}; +static u8 g_delta_swing_table_idx_mp_5ga_n_txpowertrack_pcie_icut_8188e[][DELTA_SWINGIDX_SIZE] = { + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 17, 17, 17, 17, 18, 18, 18}, + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18}, + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18}, +}; +static u8 g_delta_swing_table_idx_mp_5ga_p_txpowertrack_pcie_icut_8188e[][DELTA_SWINGIDX_SIZE] = { + {0, 1, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, +}; +static u8 g_delta_swing_table_idx_mp_2gb_n_txpowertrack_pcie_icut_8188e[] = {0, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}; +static u8 g_delta_swing_table_idx_mp_2gb_p_txpowertrack_pcie_icut_8188e[] = {0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 9, 9, 10, 11, 11, 11, 11, 11}; +static u8 g_delta_swing_table_idx_mp_2ga_n_txpowertrack_pcie_icut_8188e[] = {0, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}; +static u8 g_delta_swing_table_idx_mp_2ga_p_txpowertrack_pcie_icut_8188e[] = {0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 9, 9, 10, 11, 11, 11, 11, 11}; +static u8 g_delta_swing_table_idx_mp_2g_cck_b_n_txpowertrack_pcie_icut_8188e[] = {0, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; +static u8 g_delta_swing_table_idx_mp_2g_cck_b_p_txpowertrack_pcie_icut_8188e[] = {0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 8, 8, 9, 9, 10, 10, 11, 12, 12, 12, 12}; +static u8 g_delta_swing_table_idx_mp_2g_cck_a_n_txpowertrack_pcie_icut_8188e[] = {0, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; +static u8 g_delta_swing_table_idx_mp_2g_cck_a_p_txpowertrack_pcie_icut_8188e[] = {0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 8, 8, 9, 9, 10, 10, 11, 12, 12, 12, 12}; + +void +odm_read_and_config_mp_8188e_txpowertrack_pcie_icut( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + struct odm_rf_calibration_structure *p_rf_calibrate_info = &(p_dm_odm->rf_calibrate_info); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("===> ODM_ReadAndConfig_MP_MP_8188E\n")); + + + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2ga_p, g_delta_swing_table_idx_mp_2ga_p_txpowertrack_pcie_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2ga_n, g_delta_swing_table_idx_mp_2ga_n_txpowertrack_pcie_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2gb_p, g_delta_swing_table_idx_mp_2gb_p_txpowertrack_pcie_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2gb_n, g_delta_swing_table_idx_mp_2gb_n_txpowertrack_pcie_icut_8188e, DELTA_SWINGIDX_SIZE); + + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2g_cck_a_p, g_delta_swing_table_idx_mp_2g_cck_a_p_txpowertrack_pcie_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2g_cck_a_n, g_delta_swing_table_idx_mp_2g_cck_a_n_txpowertrack_pcie_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2g_cck_b_p, g_delta_swing_table_idx_mp_2g_cck_b_p_txpowertrack_pcie_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2g_cck_b_n, g_delta_swing_table_idx_mp_2g_cck_b_n_txpowertrack_pcie_icut_8188e, DELTA_SWINGIDX_SIZE); + + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_5ga_p, g_delta_swing_table_idx_mp_5ga_p_txpowertrack_pcie_icut_8188e, DELTA_SWINGIDX_SIZE * 3); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_5ga_n, g_delta_swing_table_idx_mp_5ga_n_txpowertrack_pcie_icut_8188e, DELTA_SWINGIDX_SIZE * 3); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_5gb_p, g_delta_swing_table_idx_mp_5gb_p_txpowertrack_pcie_icut_8188e, DELTA_SWINGIDX_SIZE * 3); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_5gb_n, g_delta_swing_table_idx_mp_5gb_n_txpowertrack_pcie_icut_8188e, DELTA_SWINGIDX_SIZE * 3); +} + +void +odm_read_and_config_mp_8188e_txpowertrack_sdio( + struct PHY_DM_STRUCT *p_dm_odm +) +{ +} + +/****************************************************************************** +* TxPowerTrack_SDIO_ICUT.TXT +******************************************************************************/ + +static u8 g_delta_swing_table_idx_mp_5gb_n_txpowertrack_sdio_icut_8188e[][DELTA_SWINGIDX_SIZE] = { + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 17, 17, 17, 17, 18, 18, 18}, + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18}, + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18}, +}; +static u8 g_delta_swing_table_idx_mp_5gb_p_txpowertrack_sdio_icut_8188e[][DELTA_SWINGIDX_SIZE] = { + {0, 1, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, +}; +static u8 g_delta_swing_table_idx_mp_5ga_n_txpowertrack_sdio_icut_8188e[][DELTA_SWINGIDX_SIZE] = { + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 17, 17, 17, 17, 18, 18, 18}, + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18}, + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18}, +}; +static u8 g_delta_swing_table_idx_mp_5ga_p_txpowertrack_sdio_icut_8188e[][DELTA_SWINGIDX_SIZE] = { + {0, 1, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, +}; +static u8 g_delta_swing_table_idx_mp_2gb_n_txpowertrack_sdio_icut_8188e[] = {0, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}; +static u8 g_delta_swing_table_idx_mp_2gb_p_txpowertrack_sdio_icut_8188e[] = {0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 9, 9, 10, 11, 11, 11, 11, 11}; +static u8 g_delta_swing_table_idx_mp_2ga_n_txpowertrack_sdio_icut_8188e[] = {0, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}; +static u8 g_delta_swing_table_idx_mp_2ga_p_txpowertrack_sdio_icut_8188e[] = {0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 9, 9, 10, 11, 11, 11, 11, 11}; +static u8 g_delta_swing_table_idx_mp_2g_cck_b_n_txpowertrack_sdio_icut_8188e[] = {0, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; +static u8 g_delta_swing_table_idx_mp_2g_cck_b_p_txpowertrack_sdio_icut_8188e[] = {0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 8, 8, 9, 9, 10, 10, 11, 12, 12, 12, 12}; +static u8 g_delta_swing_table_idx_mp_2g_cck_a_n_txpowertrack_sdio_icut_8188e[] = {0, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; +static u8 g_delta_swing_table_idx_mp_2g_cck_a_p_txpowertrack_sdio_icut_8188e[] = {0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 8, 8, 9, 9, 10, 10, 11, 12, 12, 12, 12}; + +void +odm_read_and_config_mp_8188e_txpowertrack_sdio_icut( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + struct odm_rf_calibration_structure *p_rf_calibrate_info = &(p_dm_odm->rf_calibrate_info); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("===> ODM_ReadAndConfig_MP_MP_8188E\n")); + + + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2ga_p, g_delta_swing_table_idx_mp_2ga_p_txpowertrack_sdio_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2ga_n, g_delta_swing_table_idx_mp_2ga_n_txpowertrack_sdio_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2gb_p, g_delta_swing_table_idx_mp_2gb_p_txpowertrack_sdio_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2gb_n, g_delta_swing_table_idx_mp_2gb_n_txpowertrack_sdio_icut_8188e, DELTA_SWINGIDX_SIZE); + + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2g_cck_a_p, g_delta_swing_table_idx_mp_2g_cck_a_p_txpowertrack_sdio_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2g_cck_a_n, g_delta_swing_table_idx_mp_2g_cck_a_n_txpowertrack_sdio_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2g_cck_b_p, g_delta_swing_table_idx_mp_2g_cck_b_p_txpowertrack_sdio_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2g_cck_b_n, g_delta_swing_table_idx_mp_2g_cck_b_n_txpowertrack_sdio_icut_8188e, DELTA_SWINGIDX_SIZE); + + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_5ga_p, g_delta_swing_table_idx_mp_5ga_p_txpowertrack_sdio_icut_8188e, DELTA_SWINGIDX_SIZE * 3); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_5ga_n, g_delta_swing_table_idx_mp_5ga_n_txpowertrack_sdio_icut_8188e, DELTA_SWINGIDX_SIZE * 3); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_5gb_p, g_delta_swing_table_idx_mp_5gb_p_txpowertrack_sdio_icut_8188e, DELTA_SWINGIDX_SIZE * 3); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_5gb_n, g_delta_swing_table_idx_mp_5gb_n_txpowertrack_sdio_icut_8188e, DELTA_SWINGIDX_SIZE * 3); +} + +/****************************************************************************** +* TxPowerTrack_USB.TXT +******************************************************************************/ + +static u8 g_delta_swing_table_idx_mp_5gb_n_txpowertrack_usb_8188e[][DELTA_SWINGIDX_SIZE] = { + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 17, 17, 17, 17, 18, 18, 18}, + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18}, + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18}, +}; +static u8 g_delta_swing_table_idx_mp_5gb_p_txpowertrack_usb_8188e[][DELTA_SWINGIDX_SIZE] = { + {0, 1, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, +}; +static u8 g_delta_swing_table_idx_mp_5ga_n_txpowertrack_usb_8188e[][DELTA_SWINGIDX_SIZE] = { + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 17, 17, 17, 17, 18, 18, 18}, + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18}, + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18}, +}; +static u8 g_delta_swing_table_idx_mp_5ga_p_txpowertrack_usb_8188e[][DELTA_SWINGIDX_SIZE] = { + {0, 1, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, +}; +static u8 g_delta_swing_table_idx_mp_2gb_n_txpowertrack_usb_8188e[] = {0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9}; +static u8 g_delta_swing_table_idx_mp_2gb_p_txpowertrack_usb_8188e[] = {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 7, 8, 8, 8, 8}; +static u8 g_delta_swing_table_idx_mp_2ga_n_txpowertrack_usb_8188e[] = {0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9}; +static u8 g_delta_swing_table_idx_mp_2ga_p_txpowertrack_usb_8188e[] = {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 7, 8, 8, 8, 8}; +static u8 g_delta_swing_table_idx_mp_2g_cck_b_n_txpowertrack_usb_8188e[] = {0, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9}; +static u8 g_delta_swing_table_idx_mp_2g_cck_b_p_txpowertrack_usb_8188e[] = {0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 6, 6, 6, 6, 7, 7}; +static u8 g_delta_swing_table_idx_mp_2g_cck_a_n_txpowertrack_usb_8188e[] = {0, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9}; +static u8 g_delta_swing_table_idx_mp_2g_cck_a_p_txpowertrack_usb_8188e[] = {0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 6, 6, 6, 6, 7, 7}; + +void +odm_read_and_config_mp_8188e_txpowertrack_usb( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + struct odm_rf_calibration_structure *p_rf_calibrate_info = &(p_dm_odm->rf_calibrate_info); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("===> ODM_ReadAndConfig_MP_MP_8188E\n")); + + + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2ga_p, g_delta_swing_table_idx_mp_2ga_p_txpowertrack_usb_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2ga_n, g_delta_swing_table_idx_mp_2ga_n_txpowertrack_usb_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2gb_p, g_delta_swing_table_idx_mp_2gb_p_txpowertrack_usb_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2gb_n, g_delta_swing_table_idx_mp_2gb_n_txpowertrack_usb_8188e, DELTA_SWINGIDX_SIZE); + + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2g_cck_a_p, g_delta_swing_table_idx_mp_2g_cck_a_p_txpowertrack_usb_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2g_cck_a_n, g_delta_swing_table_idx_mp_2g_cck_a_n_txpowertrack_usb_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2g_cck_b_p, g_delta_swing_table_idx_mp_2g_cck_b_p_txpowertrack_usb_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2g_cck_b_n, g_delta_swing_table_idx_mp_2g_cck_b_n_txpowertrack_usb_8188e, DELTA_SWINGIDX_SIZE); + + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_5ga_p, g_delta_swing_table_idx_mp_5ga_p_txpowertrack_usb_8188e, DELTA_SWINGIDX_SIZE * 3); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_5ga_n, g_delta_swing_table_idx_mp_5ga_n_txpowertrack_usb_8188e, DELTA_SWINGIDX_SIZE * 3); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_5gb_p, g_delta_swing_table_idx_mp_5gb_p_txpowertrack_usb_8188e, DELTA_SWINGIDX_SIZE * 3); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_5gb_n, g_delta_swing_table_idx_mp_5gb_n_txpowertrack_usb_8188e, DELTA_SWINGIDX_SIZE * 3); +} + +/****************************************************************************** +* TxPowerTrack_USB_ICUT.TXT +******************************************************************************/ + +static u8 g_delta_swing_table_idx_mp_5gb_n_txpowertrack_usb_icut_8188e[][DELTA_SWINGIDX_SIZE] = { + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 17, 17, 17, 17, 18, 18, 18}, + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18}, + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18}, +}; +static u8 g_delta_swing_table_idx_mp_5gb_p_txpowertrack_usb_icut_8188e[][DELTA_SWINGIDX_SIZE] = { + {0, 1, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, +}; +static u8 g_delta_swing_table_idx_mp_5ga_n_txpowertrack_usb_icut_8188e[][DELTA_SWINGIDX_SIZE] = { + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 17, 17, 17, 17, 18, 18, 18}, + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18}, + {0, 1, 2, 3, 3, 5, 5, 6, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 18}, +}; +static u8 g_delta_swing_table_idx_mp_5ga_p_txpowertrack_usb_icut_8188e[][DELTA_SWINGIDX_SIZE] = { + {0, 1, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, +}; +static u8 g_delta_swing_table_idx_mp_2gb_n_txpowertrack_usb_icut_8188e[] = { + 0, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9}; +static u8 g_delta_swing_table_idx_mp_2gb_p_txpowertrack_usb_icut_8188e[] = { + 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 9, + 9, 10, 11, 11, 11, 11, 11}; +static u8 g_delta_swing_table_idx_mp_2ga_n_txpowertrack_usb_icut_8188e[] = { + 0, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9}; +static u8 g_delta_swing_table_idx_mp_2ga_p_txpowertrack_usb_icut_8188e[] = { + 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 9, + 9, 10, 11, 11, 11, 11, 11}; +static u8 g_delta_swing_table_idx_mp_2g_cck_b_n_txpowertrack_usb_icut_8188e[] = { + 0, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8}; +static u8 g_delta_swing_table_idx_mp_2g_cck_b_p_txpowertrack_usb_icut_8188e[] = { + 0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 8, 8, 9, 9, + 10, 10, 11, 12, 12, 12, 12}; +static u8 g_delta_swing_table_idx_mp_2g_cck_a_n_txpowertrack_usb_icut_8188e[] = { + 0, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8}; +static u8 g_delta_swing_table_idx_mp_2g_cck_a_p_txpowertrack_usb_icut_8188e[] = { + 0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 8, 8, 9, 9, + 10, 10, 11, 12, 12, 12, 12 +}; + +void +odm_read_and_config_mp_8188e_txpowertrack_usb_icut( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + struct odm_rf_calibration_structure *p_rf_calibrate_info = &(p_dm_odm->rf_calibrate_info); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("===> ODM_ReadAndConfig_MP_MP_8188E\n")); + + + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2ga_p, g_delta_swing_table_idx_mp_2ga_p_txpowertrack_usb_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2ga_n, g_delta_swing_table_idx_mp_2ga_n_txpowertrack_usb_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2gb_p, g_delta_swing_table_idx_mp_2gb_p_txpowertrack_usb_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2gb_n, g_delta_swing_table_idx_mp_2gb_n_txpowertrack_usb_icut_8188e, DELTA_SWINGIDX_SIZE); + + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2g_cck_a_p, g_delta_swing_table_idx_mp_2g_cck_a_p_txpowertrack_usb_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2g_cck_a_n, g_delta_swing_table_idx_mp_2g_cck_a_n_txpowertrack_usb_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2g_cck_b_p, g_delta_swing_table_idx_mp_2g_cck_b_p_txpowertrack_usb_icut_8188e, DELTA_SWINGIDX_SIZE); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_2g_cck_b_n, g_delta_swing_table_idx_mp_2g_cck_b_n_txpowertrack_usb_icut_8188e, DELTA_SWINGIDX_SIZE); + + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_5ga_p, g_delta_swing_table_idx_mp_5ga_p_txpowertrack_usb_icut_8188e, DELTA_SWINGIDX_SIZE * 3); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_5ga_n, g_delta_swing_table_idx_mp_5ga_n_txpowertrack_usb_icut_8188e, DELTA_SWINGIDX_SIZE * 3); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_5gb_p, g_delta_swing_table_idx_mp_5gb_p_txpowertrack_usb_icut_8188e, DELTA_SWINGIDX_SIZE * 3); + odm_move_memory(p_dm_odm, p_rf_calibrate_info->delta_swing_table_idx_5gb_n, g_delta_swing_table_idx_mp_5gb_n_txpowertrack_usb_icut_8188e, DELTA_SWINGIDX_SIZE * 3); +} + +/****************************************************************************** +* TXPWR_LMT.TXT +******************************************************************************/ + +static const char *array_mp_8188e_txpwr_lmt[] = { + "FCC", "2.4G", "20M", "CCK", "1T", "01", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "01", "26", + "MKK", "2.4G", "20M", "CCK", "1T", "01", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "02", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "02", "26", + "MKK", "2.4G", "20M", "CCK", "1T", "02", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "03", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "03", "26", + "MKK", "2.4G", "20M", "CCK", "1T", "03", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "04", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "04", "26", + "MKK", "2.4G", "20M", "CCK", "1T", "04", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "05", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "05", "26", + "MKK", "2.4G", "20M", "CCK", "1T", "05", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "06", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "06", "26", + "MKK", "2.4G", "20M", "CCK", "1T", "06", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "07", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "07", "26", + "MKK", "2.4G", "20M", "CCK", "1T", "07", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "08", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "08", "26", + "MKK", "2.4G", "20M", "CCK", "1T", "08", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "09", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "09", "26", + "MKK", "2.4G", "20M", "CCK", "1T", "09", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "10", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "10", "26", + "MKK", "2.4G", "20M", "CCK", "1T", "10", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "11", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "11", "26", + "MKK", "2.4G", "20M", "CCK", "1T", "11", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "12", "63", + "ETSI", "2.4G", "20M", "CCK", "1T", "12", "26", + "MKK", "2.4G", "20M", "CCK", "1T", "12", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "13", "63", + "ETSI", "2.4G", "20M", "CCK", "1T", "13", "26", + "MKK", "2.4G", "20M", "CCK", "1T", "13", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "14", "63", + "ETSI", "2.4G", "20M", "CCK", "1T", "14", "63", + "MKK", "2.4G", "20M", "CCK", "1T", "14", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "01", "28", + "ETSI", "2.4G", "20M", "OFDM", "1T", "01", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "01", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "02", "28", + "ETSI", "2.4G", "20M", "OFDM", "1T", "02", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "02", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "03", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "03", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "03", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "04", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "04", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "04", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "05", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "05", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "05", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "06", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "06", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "06", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "07", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "07", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "07", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "08", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "08", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "08", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "09", "28", + "ETSI", "2.4G", "20M", "OFDM", "1T", "09", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "09", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "10", "28", + "ETSI", "2.4G", "20M", "OFDM", "1T", "10", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "10", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "11", "28", + "ETSI", "2.4G", "20M", "OFDM", "1T", "11", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "11", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "12", "63", + "ETSI", "2.4G", "20M", "OFDM", "1T", "12", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "12", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "13", "63", + "ETSI", "2.4G", "20M", "OFDM", "1T", "13", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "13", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "14", "63", + "ETSI", "2.4G", "20M", "OFDM", "1T", "14", "63", + "MKK", "2.4G", "20M", "OFDM", "1T", "14", "63", + "FCC", "2.4G", "20M", "HT", "1T", "01", "28", + "ETSI", "2.4G", "20M", "HT", "1T", "01", "30", + "MKK", "2.4G", "20M", "HT", "1T", "01", "30", + "FCC", "2.4G", "20M", "HT", "1T", "02", "28", + "ETSI", "2.4G", "20M", "HT", "1T", "02", "30", + "MKK", "2.4G", "20M", "HT", "1T", "02", "30", + "FCC", "2.4G", "20M", "HT", "1T", "03", "30", + "ETSI", "2.4G", "20M", "HT", "1T", "03", "30", + "MKK", "2.4G", "20M", "HT", "1T", "03", "30", + "FCC", "2.4G", "20M", "HT", "1T", "04", "30", + "ETSI", "2.4G", "20M", "HT", "1T", "04", "30", + "MKK", "2.4G", "20M", "HT", "1T", "04", "30", + "FCC", "2.4G", "20M", "HT", "1T", "05", "30", + "ETSI", "2.4G", "20M", "HT", "1T", "05", "30", + "MKK", "2.4G", "20M", "HT", "1T", "05", "30", + "FCC", "2.4G", "20M", "HT", "1T", "06", "30", + "ETSI", "2.4G", "20M", "HT", "1T", "06", "30", + "MKK", "2.4G", "20M", "HT", "1T", "06", "30", + "FCC", "2.4G", "20M", "HT", "1T", "07", "30", + "ETSI", "2.4G", "20M", "HT", "1T", "07", "30", + "MKK", "2.4G", "20M", "HT", "1T", "07", "30", + "FCC", "2.4G", "20M", "HT", "1T", "08", "30", + "ETSI", "2.4G", "20M", "HT", "1T", "08", "30", + "MKK", "2.4G", "20M", "HT", "1T", "08", "30", + "FCC", "2.4G", "20M", "HT", "1T", "09", "28", + "ETSI", "2.4G", "20M", "HT", "1T", "09", "30", + "MKK", "2.4G", "20M", "HT", "1T", "09", "30", + "FCC", "2.4G", "20M", "HT", "1T", "10", "28", + "ETSI", "2.4G", "20M", "HT", "1T", "10", "30", + "MKK", "2.4G", "20M", "HT", "1T", "10", "30", + "FCC", "2.4G", "20M", "HT", "1T", "11", "28", + "ETSI", "2.4G", "20M", "HT", "1T", "11", "30", + "MKK", "2.4G", "20M", "HT", "1T", "11", "30", + "FCC", "2.4G", "20M", "HT", "1T", "12", "63", + "ETSI", "2.4G", "20M", "HT", "1T", "12", "30", + "MKK", "2.4G", "20M", "HT", "1T", "12", "30", + "FCC", "2.4G", "20M", "HT", "1T", "13", "63", + "ETSI", "2.4G", "20M", "HT", "1T", "13", "30", + "MKK", "2.4G", "20M", "HT", "1T", "13", "30", + "FCC", "2.4G", "20M", "HT", "1T", "14", "63", + "ETSI", "2.4G", "20M", "HT", "1T", "14", "63", + "MKK", "2.4G", "20M", "HT", "1T", "14", "63", + "FCC", "2.4G", "20M", "HT", "2T", "01", "28", + "ETSI", "2.4G", "20M", "HT", "2T", "01", "30", + "MKK", "2.4G", "20M", "HT", "2T", "01", "30", + "FCC", "2.4G", "20M", "HT", "2T", "02", "28", + "ETSI", "2.4G", "20M", "HT", "2T", "02", "30", + "MKK", "2.4G", "20M", "HT", "2T", "02", "30", + "FCC", "2.4G", "20M", "HT", "2T", "03", "30", + "ETSI", "2.4G", "20M", "HT", "2T", "03", "30", + "MKK", "2.4G", "20M", "HT", "2T", "03", "30", + "FCC", "2.4G", "20M", "HT", "2T", "04", "30", + "ETSI", "2.4G", "20M", "HT", "2T", "04", "30", + "MKK", "2.4G", "20M", "HT", "2T", "04", "30", + "FCC", "2.4G", "20M", "HT", "2T", "05", "30", + "ETSI", "2.4G", "20M", "HT", "2T", "05", "30", + "MKK", "2.4G", "20M", "HT", "2T", "05", "30", + "FCC", "2.4G", "20M", "HT", "2T", "06", "30", + "ETSI", "2.4G", "20M", "HT", "2T", "06", "30", + "MKK", "2.4G", "20M", "HT", "2T", "06", "30", + "FCC", "2.4G", "20M", "HT", "2T", "07", "30", + "ETSI", "2.4G", "20M", "HT", "2T", "07", "30", + "MKK", "2.4G", "20M", "HT", "2T", "07", "30", + "FCC", "2.4G", "20M", "HT", "2T", "08", "30", + "ETSI", "2.4G", "20M", "HT", "2T", "08", "30", + "MKK", "2.4G", "20M", "HT", "2T", "08", "30", + "FCC", "2.4G", "20M", "HT", "2T", "09", "28", + "ETSI", "2.4G", "20M", "HT", "2T", "09", "30", + "MKK", "2.4G", "20M", "HT", "2T", "09", "30", + "FCC", "2.4G", "20M", "HT", "2T", "10", "28", + "ETSI", "2.4G", "20M", "HT", "2T", "10", "30", + "MKK", "2.4G", "20M", "HT", "2T", "10", "30", + "FCC", "2.4G", "20M", "HT", "2T", "11", "28", + "ETSI", "2.4G", "20M", "HT", "2T", "11", "30", + "MKK", "2.4G", "20M", "HT", "2T", "11", "30", + "FCC", "2.4G", "20M", "HT", "2T", "12", "63", + "ETSI", "2.4G", "20M", "HT", "2T", "12", "30", + "MKK", "2.4G", "20M", "HT", "2T", "12", "30", + "FCC", "2.4G", "20M", "HT", "2T", "13", "63", + "ETSI", "2.4G", "20M", "HT", "2T", "13", "30", + "MKK", "2.4G", "20M", "HT", "2T", "13", "30", + "FCC", "2.4G", "20M", "HT", "2T", "14", "63", + "ETSI", "2.4G", "20M", "HT", "2T", "14", "63", + "MKK", "2.4G", "20M", "HT", "2T", "14", "63", + "FCC", "2.4G", "40M", "HT", "1T", "01", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "01", "63", + "MKK", "2.4G", "40M", "HT", "1T", "01", "63", + "FCC", "2.4G", "40M", "HT", "1T", "02", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "02", "63", + "MKK", "2.4G", "40M", "HT", "1T", "02", "63", + "FCC", "2.4G", "40M", "HT", "1T", "03", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "03", "26", + "MKK", "2.4G", "40M", "HT", "1T", "03", "26", + "FCC", "2.4G", "40M", "HT", "1T", "04", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "04", "26", + "MKK", "2.4G", "40M", "HT", "1T", "04", "26", + "FCC", "2.4G", "40M", "HT", "1T", "05", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "05", "26", + "MKK", "2.4G", "40M", "HT", "1T", "05", "26", + "FCC", "2.4G", "40M", "HT", "1T", "06", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "06", "26", + "MKK", "2.4G", "40M", "HT", "1T", "06", "26", + "FCC", "2.4G", "40M", "HT", "1T", "07", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "07", "26", + "MKK", "2.4G", "40M", "HT", "1T", "07", "26", + "FCC", "2.4G", "40M", "HT", "1T", "08", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "08", "26", + "MKK", "2.4G", "40M", "HT", "1T", "08", "26", + "FCC", "2.4G", "40M", "HT", "1T", "09", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "09", "26", + "MKK", "2.4G", "40M", "HT", "1T", "09", "26", + "FCC", "2.4G", "40M", "HT", "1T", "10", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "10", "26", + "MKK", "2.4G", "40M", "HT", "1T", "10", "26", + "FCC", "2.4G", "40M", "HT", "1T", "11", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "11", "26", + "MKK", "2.4G", "40M", "HT", "1T", "11", "26", + "FCC", "2.4G", "40M", "HT", "1T", "12", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "12", "26", + "MKK", "2.4G", "40M", "HT", "1T", "12", "26", + "FCC", "2.4G", "40M", "HT", "1T", "13", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "13", "26", + "MKK", "2.4G", "40M", "HT", "1T", "13", "26", + "FCC", "2.4G", "40M", "HT", "1T", "14", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "14", "63", + "MKK", "2.4G", "40M", "HT", "1T", "14", "63", + "FCC", "2.4G", "40M", "HT", "2T", "01", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "01", "63", + "MKK", "2.4G", "40M", "HT", "2T", "01", "63", + "FCC", "2.4G", "40M", "HT", "2T", "02", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "02", "63", + "MKK", "2.4G", "40M", "HT", "2T", "02", "63", + "FCC", "2.4G", "40M", "HT", "2T", "03", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "03", "26", + "MKK", "2.4G", "40M", "HT", "2T", "03", "26", + "FCC", "2.4G", "40M", "HT", "2T", "04", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "04", "26", + "MKK", "2.4G", "40M", "HT", "2T", "04", "26", + "FCC", "2.4G", "40M", "HT", "2T", "05", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "05", "26", + "MKK", "2.4G", "40M", "HT", "2T", "05", "26", + "FCC", "2.4G", "40M", "HT", "2T", "06", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "06", "26", + "MKK", "2.4G", "40M", "HT", "2T", "06", "26", + "FCC", "2.4G", "40M", "HT", "2T", "07", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "07", "26", + "MKK", "2.4G", "40M", "HT", "2T", "07", "26", + "FCC", "2.4G", "40M", "HT", "2T", "08", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "08", "26", + "MKK", "2.4G", "40M", "HT", "2T", "08", "26", + "FCC", "2.4G", "40M", "HT", "2T", "09", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "09", "26", + "MKK", "2.4G", "40M", "HT", "2T", "09", "26", + "FCC", "2.4G", "40M", "HT", "2T", "10", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "10", "26", + "MKK", "2.4G", "40M", "HT", "2T", "10", "26", + "FCC", "2.4G", "40M", "HT", "2T", "11", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "11", "26", + "MKK", "2.4G", "40M", "HT", "2T", "11", "26", + "FCC", "2.4G", "40M", "HT", "2T", "12", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "12", "26", + "MKK", "2.4G", "40M", "HT", "2T", "12", "26", + "FCC", "2.4G", "40M", "HT", "2T", "13", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "13", "26", + "MKK", "2.4G", "40M", "HT", "2T", "13", "26", + "FCC", "2.4G", "40M", "HT", "2T", "14", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "14", "63", + "MKK", "2.4G", "40M", "HT", "2T", "14", "63", + "FCC", "5G", "20M", "OFDM", "1T", "36", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "36", "32", + "MKK", "5G", "20M", "OFDM", "1T", "36", "32", + "FCC", "5G", "20M", "OFDM", "1T", "40", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "40", "32", + "MKK", "5G", "20M", "OFDM", "1T", "40", "32", + "FCC", "5G", "20M", "OFDM", "1T", "44", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "44", "32", + "MKK", "5G", "20M", "OFDM", "1T", "44", "32", + "FCC", "5G", "20M", "OFDM", "1T", "48", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "48", "32", + "MKK", "5G", "20M", "OFDM", "1T", "48", "32", + "FCC", "5G", "20M", "OFDM", "1T", "52", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "52", "32", + "MKK", "5G", "20M", "OFDM", "1T", "52", "32", + "FCC", "5G", "20M", "OFDM", "1T", "56", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "56", "32", + "MKK", "5G", "20M", "OFDM", "1T", "56", "32", + "FCC", "5G", "20M", "OFDM", "1T", "60", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "60", "32", + "MKK", "5G", "20M", "OFDM", "1T", "60", "32", + "FCC", "5G", "20M", "OFDM", "1T", "64", "28", + "ETSI", "5G", "20M", "OFDM", "1T", "64", "32", + "MKK", "5G", "20M", "OFDM", "1T", "64", "32", + "FCC", "5G", "20M", "OFDM", "1T", "100", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "100", "32", + "MKK", "5G", "20M", "OFDM", "1T", "100", "32", + "FCC", "5G", "20M", "OFDM", "1T", "114", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "114", "32", + "MKK", "5G", "20M", "OFDM", "1T", "114", "32", + "FCC", "5G", "20M", "OFDM", "1T", "108", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "108", "32", + "MKK", "5G", "20M", "OFDM", "1T", "108", "32", + "FCC", "5G", "20M", "OFDM", "1T", "112", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "112", "32", + "MKK", "5G", "20M", "OFDM", "1T", "112", "32", + "FCC", "5G", "20M", "OFDM", "1T", "116", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "116", "32", + "MKK", "5G", "20M", "OFDM", "1T", "116", "32", + "FCC", "5G", "20M", "OFDM", "1T", "120", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "120", "32", + "MKK", "5G", "20M", "OFDM", "1T", "120", "32", + "FCC", "5G", "20M", "OFDM", "1T", "124", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "124", "32", + "MKK", "5G", "20M", "OFDM", "1T", "124", "32", + "FCC", "5G", "20M", "OFDM", "1T", "128", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "128", "32", + "MKK", "5G", "20M", "OFDM", "1T", "128", "32", + "FCC", "5G", "20M", "OFDM", "1T", "132", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "132", "32", + "MKK", "5G", "20M", "OFDM", "1T", "132", "32", + "FCC", "5G", "20M", "OFDM", "1T", "136", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "136", "32", + "MKK", "5G", "20M", "OFDM", "1T", "136", "32", + "FCC", "5G", "20M", "OFDM", "1T", "140", "28", + "ETSI", "5G", "20M", "OFDM", "1T", "140", "32", + "MKK", "5G", "20M", "OFDM", "1T", "140", "32", + "FCC", "5G", "20M", "OFDM", "1T", "149", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "149", "32", + "MKK", "5G", "20M", "OFDM", "1T", "149", "63", + "FCC", "5G", "20M", "OFDM", "1T", "153", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "153", "32", + "MKK", "5G", "20M", "OFDM", "1T", "153", "63", + "FCC", "5G", "20M", "OFDM", "1T", "157", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "157", "32", + "MKK", "5G", "20M", "OFDM", "1T", "157", "63", + "FCC", "5G", "20M", "OFDM", "1T", "161", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "161", "32", + "MKK", "5G", "20M", "OFDM", "1T", "161", "63", + "FCC", "5G", "20M", "OFDM", "1T", "165", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "165", "32", + "MKK", "5G", "20M", "OFDM", "1T", "165", "63", + "FCC", "5G", "20M", "HT", "1T", "36", "30", + "ETSI", "5G", "20M", "HT", "1T", "36", "32", + "MKK", "5G", "20M", "HT", "1T", "36", "32", + "FCC", "5G", "20M", "HT", "1T", "40", "30", + "ETSI", "5G", "20M", "HT", "1T", "40", "32", + "MKK", "5G", "20M", "HT", "1T", "40", "32", + "FCC", "5G", "20M", "HT", "1T", "44", "30", + "ETSI", "5G", "20M", "HT", "1T", "44", "32", + "MKK", "5G", "20M", "HT", "1T", "44", "32", + "FCC", "5G", "20M", "HT", "1T", "48", "30", + "ETSI", "5G", "20M", "HT", "1T", "48", "32", + "MKK", "5G", "20M", "HT", "1T", "48", "32", + "FCC", "5G", "20M", "HT", "1T", "52", "34", + "ETSI", "5G", "20M", "HT", "1T", "52", "32", + "MKK", "5G", "20M", "HT", "1T", "52", "32", + "FCC", "5G", "20M", "HT", "1T", "56", "34", + "ETSI", "5G", "20M", "HT", "1T", "56", "32", + "MKK", "5G", "20M", "HT", "1T", "56", "32", + "FCC", "5G", "20M", "HT", "1T", "60", "32", + "ETSI", "5G", "20M", "HT", "1T", "60", "32", + "MKK", "5G", "20M", "HT", "1T", "60", "32", + "FCC", "5G", "20M", "HT", "1T", "64", "28", + "ETSI", "5G", "20M", "HT", "1T", "64", "32", + "MKK", "5G", "20M", "HT", "1T", "64", "32", + "FCC", "5G", "20M", "HT", "1T", "100", "30", + "ETSI", "5G", "20M", "HT", "1T", "100", "32", + "MKK", "5G", "20M", "HT", "1T", "100", "32", + "FCC", "5G", "20M", "HT", "1T", "114", "30", + "ETSI", "5G", "20M", "HT", "1T", "114", "32", + "MKK", "5G", "20M", "HT", "1T", "114", "32", + "FCC", "5G", "20M", "HT", "1T", "108", "32", + "ETSI", "5G", "20M", "HT", "1T", "108", "32", + "MKK", "5G", "20M", "HT", "1T", "108", "32", + "FCC", "5G", "20M", "HT", "1T", "112", "34", + "ETSI", "5G", "20M", "HT", "1T", "112", "32", + "MKK", "5G", "20M", "HT", "1T", "112", "32", + "FCC", "5G", "20M", "HT", "1T", "116", "34", + "ETSI", "5G", "20M", "HT", "1T", "116", "32", + "MKK", "5G", "20M", "HT", "1T", "116", "32", + "FCC", "5G", "20M", "HT", "1T", "120", "34", + "ETSI", "5G", "20M", "HT", "1T", "120", "32", + "MKK", "5G", "20M", "HT", "1T", "120", "32", + "FCC", "5G", "20M", "HT", "1T", "124", "34", + "ETSI", "5G", "20M", "HT", "1T", "124", "32", + "MKK", "5G", "20M", "HT", "1T", "124", "32", + "FCC", "5G", "20M", "HT", "1T", "128", "32", + "ETSI", "5G", "20M", "HT", "1T", "128", "32", + "MKK", "5G", "20M", "HT", "1T", "128", "32", + "FCC", "5G", "20M", "HT", "1T", "132", "30", + "ETSI", "5G", "20M", "HT", "1T", "132", "32", + "MKK", "5G", "20M", "HT", "1T", "132", "32", + "FCC", "5G", "20M", "HT", "1T", "136", "30", + "ETSI", "5G", "20M", "HT", "1T", "136", "32", + "MKK", "5G", "20M", "HT", "1T", "136", "32", + "FCC", "5G", "20M", "HT", "1T", "140", "28", + "ETSI", "5G", "20M", "HT", "1T", "140", "32", + "MKK", "5G", "20M", "HT", "1T", "140", "32", + "FCC", "5G", "20M", "HT", "1T", "149", "34", + "ETSI", "5G", "20M", "HT", "1T", "149", "32", + "MKK", "5G", "20M", "HT", "1T", "149", "63", + "FCC", "5G", "20M", "HT", "1T", "153", "34", + "ETSI", "5G", "20M", "HT", "1T", "153", "32", + "MKK", "5G", "20M", "HT", "1T", "153", "63", + "FCC", "5G", "20M", "HT", "1T", "157", "34", + "ETSI", "5G", "20M", "HT", "1T", "157", "32", + "MKK", "5G", "20M", "HT", "1T", "157", "63", + "FCC", "5G", "20M", "HT", "1T", "161", "34", + "ETSI", "5G", "20M", "HT", "1T", "161", "32", + "MKK", "5G", "20M", "HT", "1T", "161", "63", + "FCC", "5G", "20M", "HT", "1T", "165", "34", + "ETSI", "5G", "20M", "HT", "1T", "165", "32", + "MKK", "5G", "20M", "HT", "1T", "165", "63", + "FCC", "5G", "20M", "HT", "2T", "36", "28", + "ETSI", "5G", "20M", "HT", "2T", "36", "30", + "MKK", "5G", "20M", "HT", "2T", "36", "30", + "FCC", "5G", "20M", "HT", "2T", "40", "28", + "ETSI", "5G", "20M", "HT", "2T", "40", "30", + "MKK", "5G", "20M", "HT", "2T", "40", "30", + "FCC", "5G", "20M", "HT", "2T", "44", "28", + "ETSI", "5G", "20M", "HT", "2T", "44", "30", + "MKK", "5G", "20M", "HT", "2T", "44", "30", + "FCC", "5G", "20M", "HT", "2T", "48", "28", + "ETSI", "5G", "20M", "HT", "2T", "48", "30", + "MKK", "5G", "20M", "HT", "2T", "48", "30", + "FCC", "5G", "20M", "HT", "2T", "52", "34", + "ETSI", "5G", "20M", "HT", "2T", "52", "30", + "MKK", "5G", "20M", "HT", "2T", "52", "30", + "FCC", "5G", "20M", "HT", "2T", "56", "32", + "ETSI", "5G", "20M", "HT", "2T", "56", "30", + "MKK", "5G", "20M", "HT", "2T", "56", "30", + "FCC", "5G", "20M", "HT", "2T", "60", "30", + "ETSI", "5G", "20M", "HT", "2T", "60", "30", + "MKK", "5G", "20M", "HT", "2T", "60", "30", + "FCC", "5G", "20M", "HT", "2T", "64", "26", + "ETSI", "5G", "20M", "HT", "2T", "64", "30", + "MKK", "5G", "20M", "HT", "2T", "64", "30", + "FCC", "5G", "20M", "HT", "2T", "100", "28", + "ETSI", "5G", "20M", "HT", "2T", "100", "30", + "MKK", "5G", "20M", "HT", "2T", "100", "30", + "FCC", "5G", "20M", "HT", "2T", "114", "28", + "ETSI", "5G", "20M", "HT", "2T", "114", "30", + "MKK", "5G", "20M", "HT", "2T", "114", "30", + "FCC", "5G", "20M", "HT", "2T", "108", "30", + "ETSI", "5G", "20M", "HT", "2T", "108", "30", + "MKK", "5G", "20M", "HT", "2T", "108", "30", + "FCC", "5G", "20M", "HT", "2T", "112", "32", + "ETSI", "5G", "20M", "HT", "2T", "112", "30", + "MKK", "5G", "20M", "HT", "2T", "112", "30", + "FCC", "5G", "20M", "HT", "2T", "116", "32", + "ETSI", "5G", "20M", "HT", "2T", "116", "30", + "MKK", "5G", "20M", "HT", "2T", "116", "30", + "FCC", "5G", "20M", "HT", "2T", "120", "34", + "ETSI", "5G", "20M", "HT", "2T", "120", "30", + "MKK", "5G", "20M", "HT", "2T", "120", "30", + "FCC", "5G", "20M", "HT", "2T", "124", "32", + "ETSI", "5G", "20M", "HT", "2T", "124", "30", + "MKK", "5G", "20M", "HT", "2T", "124", "30", + "FCC", "5G", "20M", "HT", "2T", "128", "30", + "ETSI", "5G", "20M", "HT", "2T", "128", "30", + "MKK", "5G", "20M", "HT", "2T", "128", "30", + "FCC", "5G", "20M", "HT", "2T", "132", "28", + "ETSI", "5G", "20M", "HT", "2T", "132", "30", + "MKK", "5G", "20M", "HT", "2T", "132", "30", + "FCC", "5G", "20M", "HT", "2T", "136", "28", + "ETSI", "5G", "20M", "HT", "2T", "136", "30", + "MKK", "5G", "20M", "HT", "2T", "136", "30", + "FCC", "5G", "20M", "HT", "2T", "140", "26", + "ETSI", "5G", "20M", "HT", "2T", "140", "30", + "MKK", "5G", "20M", "HT", "2T", "140", "30", + "FCC", "5G", "20M", "HT", "2T", "149", "34", + "ETSI", "5G", "20M", "HT", "2T", "149", "30", + "MKK", "5G", "20M", "HT", "2T", "149", "63", + "FCC", "5G", "20M", "HT", "2T", "153", "34", + "ETSI", "5G", "20M", "HT", "2T", "153", "30", + "MKK", "5G", "20M", "HT", "2T", "153", "63", + "FCC", "5G", "20M", "HT", "2T", "157", "34", + "ETSI", "5G", "20M", "HT", "2T", "157", "30", + "MKK", "5G", "20M", "HT", "2T", "157", "63", + "FCC", "5G", "20M", "HT", "2T", "161", "34", + "ETSI", "5G", "20M", "HT", "2T", "161", "30", + "MKK", "5G", "20M", "HT", "2T", "161", "63", + "FCC", "5G", "20M", "HT", "2T", "165", "34", + "ETSI", "5G", "20M", "HT", "2T", "165", "30", + "MKK", "5G", "20M", "HT", "2T", "165", "63", + "FCC", "5G", "40M", "HT", "1T", "38", "30", + "ETSI", "5G", "40M", "HT", "1T", "38", "32", + "MKK", "5G", "40M", "HT", "1T", "38", "32", + "FCC", "5G", "40M", "HT", "1T", "46", "30", + "ETSI", "5G", "40M", "HT", "1T", "46", "32", + "MKK", "5G", "40M", "HT", "1T", "46", "32", + "FCC", "5G", "40M", "HT", "1T", "54", "32", + "ETSI", "5G", "40M", "HT", "1T", "54", "32", + "MKK", "5G", "40M", "HT", "1T", "54", "32", + "FCC", "5G", "40M", "HT", "1T", "62", "32", + "ETSI", "5G", "40M", "HT", "1T", "62", "32", + "MKK", "5G", "40M", "HT", "1T", "62", "32", + "FCC", "5G", "40M", "HT", "1T", "102", "28", + "ETSI", "5G", "40M", "HT", "1T", "102", "32", + "MKK", "5G", "40M", "HT", "1T", "102", "32", + "FCC", "5G", "40M", "HT", "1T", "110", "32", + "ETSI", "5G", "40M", "HT", "1T", "110", "32", + "MKK", "5G", "40M", "HT", "1T", "110", "32", + "FCC", "5G", "40M", "HT", "1T", "118", "34", + "ETSI", "5G", "40M", "HT", "1T", "118", "32", + "MKK", "5G", "40M", "HT", "1T", "118", "32", + "FCC", "5G", "40M", "HT", "1T", "126", "34", + "ETSI", "5G", "40M", "HT", "1T", "126", "32", + "MKK", "5G", "40M", "HT", "1T", "126", "32", + "FCC", "5G", "40M", "HT", "1T", "134", "32", + "ETSI", "5G", "40M", "HT", "1T", "134", "32", + "MKK", "5G", "40M", "HT", "1T", "134", "32", + "FCC", "5G", "40M", "HT", "1T", "151", "34", + "ETSI", "5G", "40M", "HT", "1T", "151", "32", + "MKK", "5G", "40M", "HT", "1T", "151", "63", + "FCC", "5G", "40M", "HT", "1T", "159", "34", + "ETSI", "5G", "40M", "HT", "1T", "159", "32", + "MKK", "5G", "40M", "HT", "1T", "159", "63", + "FCC", "5G", "40M", "HT", "2T", "38", "28", + "ETSI", "5G", "40M", "HT", "2T", "38", "30", + "MKK", "5G", "40M", "HT", "2T", "38", "30", + "FCC", "5G", "40M", "HT", "2T", "46", "28", + "ETSI", "5G", "40M", "HT", "2T", "46", "30", + "MKK", "5G", "40M", "HT", "2T", "46", "30", + "FCC", "5G", "40M", "HT", "2T", "54", "30", + "ETSI", "5G", "40M", "HT", "2T", "54", "30", + "MKK", "5G", "40M", "HT", "2T", "54", "30", + "FCC", "5G", "40M", "HT", "2T", "62", "30", + "ETSI", "5G", "40M", "HT", "2T", "62", "30", + "MKK", "5G", "40M", "HT", "2T", "62", "30", + "FCC", "5G", "40M", "HT", "2T", "102", "26", + "ETSI", "5G", "40M", "HT", "2T", "102", "30", + "MKK", "5G", "40M", "HT", "2T", "102", "30", + "FCC", "5G", "40M", "HT", "2T", "110", "30", + "ETSI", "5G", "40M", "HT", "2T", "110", "30", + "MKK", "5G", "40M", "HT", "2T", "110", "30", + "FCC", "5G", "40M", "HT", "2T", "118", "34", + "ETSI", "5G", "40M", "HT", "2T", "118", "30", + "MKK", "5G", "40M", "HT", "2T", "118", "30", + "FCC", "5G", "40M", "HT", "2T", "126", "32", + "ETSI", "5G", "40M", "HT", "2T", "126", "30", + "MKK", "5G", "40M", "HT", "2T", "126", "30", + "FCC", "5G", "40M", "HT", "2T", "134", "30", + "ETSI", "5G", "40M", "HT", "2T", "134", "30", + "MKK", "5G", "40M", "HT", "2T", "134", "30", + "FCC", "5G", "40M", "HT", "2T", "151", "34", + "ETSI", "5G", "40M", "HT", "2T", "151", "30", + "MKK", "5G", "40M", "HT", "2T", "151", "63", + "FCC", "5G", "40M", "HT", "2T", "159", "34", + "ETSI", "5G", "40M", "HT", "2T", "159", "30", + "MKK", "5G", "40M", "HT", "2T", "159", "63", + "FCC", "5G", "80M", "VHT", "1T", "42", "30", + "ETSI", "5G", "80M", "VHT", "1T", "42", "32", + "MKK", "5G", "80M", "VHT", "1T", "42", "32", + "FCC", "5G", "80M", "VHT", "1T", "58", "28", + "ETSI", "5G", "80M", "VHT", "1T", "58", "32", + "MKK", "5G", "80M", "VHT", "1T", "58", "32", + "FCC", "5G", "80M", "VHT", "1T", "106", "30", + "ETSI", "5G", "80M", "VHT", "1T", "106", "32", + "MKK", "5G", "80M", "VHT", "1T", "106", "32", + "FCC", "5G", "80M", "VHT", "1T", "122", "34", + "ETSI", "5G", "80M", "VHT", "1T", "122", "32", + "MKK", "5G", "80M", "VHT", "1T", "122", "32", + "FCC", "5G", "80M", "VHT", "1T", "155", "34", + "ETSI", "5G", "80M", "VHT", "1T", "155", "32", + "MKK", "5G", "80M", "VHT", "1T", "155", "63", + "FCC", "5G", "80M", "VHT", "2T", "42", "28", + "ETSI", "5G", "80M", "VHT", "2T", "42", "30", + "MKK", "5G", "80M", "VHT", "2T", "42", "30", + "FCC", "5G", "80M", "VHT", "2T", "58", "26", + "ETSI", "5G", "80M", "VHT", "2T", "58", "30", + "MKK", "5G", "80M", "VHT", "2T", "58", "30", + "FCC", "5G", "80M", "VHT", "2T", "106", "28", + "ETSI", "5G", "80M", "VHT", "2T", "106", "30", + "MKK", "5G", "80M", "VHT", "2T", "106", "30", + "FCC", "5G", "80M", "VHT", "2T", "122", "32", + "ETSI", "5G", "80M", "VHT", "2T", "122", "30", + "MKK", "5G", "80M", "VHT", "2T", "122", "30", + "FCC", "5G", "80M", "VHT", "2T", "155", "34", + "ETSI", "5G", "80M", "VHT", "2T", "155", "30", + "MKK", "5G", "80M", "VHT", "2T", "155", "63" +}; + +void +odm_read_and_config_mp_8188e_txpwr_lmt( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u32 i = 0; + u32 array_len = sizeof(array_mp_8188e_txpwr_lmt) / sizeof(u8 *); + u8 **array = (u8 **)array_mp_8188e_txpwr_lmt; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("===> odm_read_and_config_mp_8188e_txpwr_lmt\n")); + + for (i = 0; i < array_len; i += 7) { + u8 *regulation = array[i]; + u8 *band = array[i + 1]; + u8 *bandwidth = array[i + 2]; + u8 *rate = array[i + 3]; + u8 *rf_path = array[i + 4]; + u8 *chnl = array[i + 5]; + u8 *val = array[i + 6]; + + odm_config_bb_txpwr_lmt_8188e(p_dm_odm, regulation, band, bandwidth, rate, rf_path, chnl, val); + } + +} + +/****************************************************************************** +* TXPWR_LMT_88EE_M2_for_MSI.TXT +******************************************************************************/ + +static const char *array_mp_8188e_txpwr_lmt_88ee_m2_for_msi[] = { + "FCC", "2.4G", "20M", "CCK", "1T", "01", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "01", "28", + "MKK", "2.4G", "20M", "CCK", "1T", "01", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "02", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "02", "28", + "MKK", "2.4G", "20M", "CCK", "1T", "02", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "03", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "03", "28", + "MKK", "2.4G", "20M", "CCK", "1T", "03", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "04", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "04", "28", + "MKK", "2.4G", "20M", "CCK", "1T", "04", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "05", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "05", "28", + "MKK", "2.4G", "20M", "CCK", "1T", "05", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "06", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "06", "28", + "MKK", "2.4G", "20M", "CCK", "1T", "06", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "07", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "07", "28", + "MKK", "2.4G", "20M", "CCK", "1T", "07", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "08", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "08", "28", + "MKK", "2.4G", "20M", "CCK", "1T", "08", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "09", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "09", "28", + "MKK", "2.4G", "20M", "CCK", "1T", "09", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "10", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "10", "28", + "MKK", "2.4G", "20M", "CCK", "1T", "10", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "11", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "11", "28", + "MKK", "2.4G", "20M", "CCK", "1T", "11", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "12", "63", + "ETSI", "2.4G", "20M", "CCK", "1T", "12", "28", + "MKK", "2.4G", "20M", "CCK", "1T", "12", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "13", "63", + "ETSI", "2.4G", "20M", "CCK", "1T", "13", "28", + "MKK", "2.4G", "20M", "CCK", "1T", "13", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "14", "63", + "ETSI", "2.4G", "20M", "CCK", "1T", "14", "63", + "MKK", "2.4G", "20M", "CCK", "1T", "14", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "01", "28", + "ETSI", "2.4G", "20M", "OFDM", "1T", "01", "28", + "MKK", "2.4G", "20M", "OFDM", "1T", "01", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "02", "28", + "ETSI", "2.4G", "20M", "OFDM", "1T", "02", "28", + "MKK", "2.4G", "20M", "OFDM", "1T", "02", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "03", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "03", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "03", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "04", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "04", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "04", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "05", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "05", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "05", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "06", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "06", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "06", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "07", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "07", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "07", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "08", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "08", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "08", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "09", "28", + "ETSI", "2.4G", "20M", "OFDM", "1T", "09", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "09", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "10", "28", + "ETSI", "2.4G", "20M", "OFDM", "1T", "10", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "10", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "11", "28", + "ETSI", "2.4G", "20M", "OFDM", "1T", "11", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "11", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "12", "63", + "ETSI", "2.4G", "20M", "OFDM", "1T", "12", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "12", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "13", "63", + "ETSI", "2.4G", "20M", "OFDM", "1T", "13", "30", + "MKK", "2.4G", "20M", "OFDM", "1T", "13", "30", + "FCC", "2.4G", "20M", "OFDM", "1T", "14", "63", + "ETSI", "2.4G", "20M", "OFDM", "1T", "14", "63", + "MKK", "2.4G", "20M", "OFDM", "1T", "14", "63", + "FCC", "2.4G", "20M", "HT", "1T", "01", "28", + "ETSI", "2.4G", "20M", "HT", "1T", "01", "30", + "MKK", "2.4G", "20M", "HT", "1T", "01", "30", + "FCC", "2.4G", "20M", "HT", "1T", "02", "28", + "ETSI", "2.4G", "20M", "HT", "1T", "02", "30", + "MKK", "2.4G", "20M", "HT", "1T", "02", "30", + "FCC", "2.4G", "20M", "HT", "1T", "03", "30", + "ETSI", "2.4G", "20M", "HT", "1T", "03", "30", + "MKK", "2.4G", "20M", "HT", "1T", "03", "30", + "FCC", "2.4G", "20M", "HT", "1T", "04", "30", + "ETSI", "2.4G", "20M", "HT", "1T", "04", "30", + "MKK", "2.4G", "20M", "HT", "1T", "04", "30", + "FCC", "2.4G", "20M", "HT", "1T", "05", "30", + "ETSI", "2.4G", "20M", "HT", "1T", "05", "30", + "MKK", "2.4G", "20M", "HT", "1T", "05", "30", + "FCC", "2.4G", "20M", "HT", "1T", "06", "30", + "ETSI", "2.4G", "20M", "HT", "1T", "06", "30", + "MKK", "2.4G", "20M", "HT", "1T", "06", "30", + "FCC", "2.4G", "20M", "HT", "1T", "07", "30", + "ETSI", "2.4G", "20M", "HT", "1T", "07", "30", + "MKK", "2.4G", "20M", "HT", "1T", "07", "30", + "FCC", "2.4G", "20M", "HT", "1T", "08", "30", + "ETSI", "2.4G", "20M", "HT", "1T", "08", "30", + "MKK", "2.4G", "20M", "HT", "1T", "08", "30", + "FCC", "2.4G", "20M", "HT", "1T", "09", "28", + "ETSI", "2.4G", "20M", "HT", "1T", "09", "30", + "MKK", "2.4G", "20M", "HT", "1T", "09", "30", + "FCC", "2.4G", "20M", "HT", "1T", "10", "28", + "ETSI", "2.4G", "20M", "HT", "1T", "10", "30", + "MKK", "2.4G", "20M", "HT", "1T", "10", "30", + "FCC", "2.4G", "20M", "HT", "1T", "11", "28", + "ETSI", "2.4G", "20M", "HT", "1T", "11", "30", + "MKK", "2.4G", "20M", "HT", "1T", "11", "30", + "FCC", "2.4G", "20M", "HT", "1T", "12", "63", + "ETSI", "2.4G", "20M", "HT", "1T", "12", "30", + "MKK", "2.4G", "20M", "HT", "1T", "12", "30", + "FCC", "2.4G", "20M", "HT", "1T", "13", "63", + "ETSI", "2.4G", "20M", "HT", "1T", "13", "30", + "MKK", "2.4G", "20M", "HT", "1T", "13", "30", + "FCC", "2.4G", "20M", "HT", "1T", "14", "63", + "ETSI", "2.4G", "20M", "HT", "1T", "14", "63", + "MKK", "2.4G", "20M", "HT", "1T", "14", "63", + "FCC", "2.4G", "20M", "HT", "2T", "01", "28", + "ETSI", "2.4G", "20M", "HT", "2T", "01", "30", + "MKK", "2.4G", "20M", "HT", "2T", "01", "30", + "FCC", "2.4G", "20M", "HT", "2T", "02", "28", + "ETSI", "2.4G", "20M", "HT", "2T", "02", "30", + "MKK", "2.4G", "20M", "HT", "2T", "02", "30", + "FCC", "2.4G", "20M", "HT", "2T", "03", "30", + "ETSI", "2.4G", "20M", "HT", "2T", "03", "30", + "MKK", "2.4G", "20M", "HT", "2T", "03", "30", + "FCC", "2.4G", "20M", "HT", "2T", "04", "30", + "ETSI", "2.4G", "20M", "HT", "2T", "04", "30", + "MKK", "2.4G", "20M", "HT", "2T", "04", "30", + "FCC", "2.4G", "20M", "HT", "2T", "05", "30", + "ETSI", "2.4G", "20M", "HT", "2T", "05", "30", + "MKK", "2.4G", "20M", "HT", "2T", "05", "30", + "FCC", "2.4G", "20M", "HT", "2T", "06", "30", + "ETSI", "2.4G", "20M", "HT", "2T", "06", "30", + "MKK", "2.4G", "20M", "HT", "2T", "06", "30", + "FCC", "2.4G", "20M", "HT", "2T", "07", "30", + "ETSI", "2.4G", "20M", "HT", "2T", "07", "30", + "MKK", "2.4G", "20M", "HT", "2T", "07", "30", + "FCC", "2.4G", "20M", "HT", "2T", "08", "30", + "ETSI", "2.4G", "20M", "HT", "2T", "08", "30", + "MKK", "2.4G", "20M", "HT", "2T", "08", "30", + "FCC", "2.4G", "20M", "HT", "2T", "09", "28", + "ETSI", "2.4G", "20M", "HT", "2T", "09", "30", + "MKK", "2.4G", "20M", "HT", "2T", "09", "30", + "FCC", "2.4G", "20M", "HT", "2T", "10", "28", + "ETSI", "2.4G", "20M", "HT", "2T", "10", "30", + "MKK", "2.4G", "20M", "HT", "2T", "10", "30", + "FCC", "2.4G", "20M", "HT", "2T", "11", "28", + "ETSI", "2.4G", "20M", "HT", "2T", "11", "30", + "MKK", "2.4G", "20M", "HT", "2T", "11", "30", + "FCC", "2.4G", "20M", "HT", "2T", "12", "63", + "ETSI", "2.4G", "20M", "HT", "2T", "12", "30", + "MKK", "2.4G", "20M", "HT", "2T", "12", "30", + "FCC", "2.4G", "20M", "HT", "2T", "13", "63", + "ETSI", "2.4G", "20M", "HT", "2T", "13", "30", + "MKK", "2.4G", "20M", "HT", "2T", "13", "30", + "FCC", "2.4G", "20M", "HT", "2T", "14", "63", + "ETSI", "2.4G", "20M", "HT", "2T", "14", "63", + "MKK", "2.4G", "20M", "HT", "2T", "14", "63", + "FCC", "2.4G", "40M", "HT", "1T", "01", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "01", "63", + "MKK", "2.4G", "40M", "HT", "1T", "01", "63", + "FCC", "2.4G", "40M", "HT", "1T", "02", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "02", "63", + "MKK", "2.4G", "40M", "HT", "1T", "02", "63", + "FCC", "2.4G", "40M", "HT", "1T", "03", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "03", "26", + "MKK", "2.4G", "40M", "HT", "1T", "03", "26", + "FCC", "2.4G", "40M", "HT", "1T", "04", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "04", "26", + "MKK", "2.4G", "40M", "HT", "1T", "04", "26", + "FCC", "2.4G", "40M", "HT", "1T", "05", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "05", "26", + "MKK", "2.4G", "40M", "HT", "1T", "05", "26", + "FCC", "2.4G", "40M", "HT", "1T", "06", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "06", "26", + "MKK", "2.4G", "40M", "HT", "1T", "06", "26", + "FCC", "2.4G", "40M", "HT", "1T", "07", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "07", "26", + "MKK", "2.4G", "40M", "HT", "1T", "07", "26", + "FCC", "2.4G", "40M", "HT", "1T", "08", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "08", "26", + "MKK", "2.4G", "40M", "HT", "1T", "08", "26", + "FCC", "2.4G", "40M", "HT", "1T", "09", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "09", "26", + "MKK", "2.4G", "40M", "HT", "1T", "09", "26", + "FCC", "2.4G", "40M", "HT", "1T", "10", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "10", "26", + "MKK", "2.4G", "40M", "HT", "1T", "10", "26", + "FCC", "2.4G", "40M", "HT", "1T", "11", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "11", "26", + "MKK", "2.4G", "40M", "HT", "1T", "11", "26", + "FCC", "2.4G", "40M", "HT", "1T", "12", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "12", "26", + "MKK", "2.4G", "40M", "HT", "1T", "12", "26", + "FCC", "2.4G", "40M", "HT", "1T", "13", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "13", "26", + "MKK", "2.4G", "40M", "HT", "1T", "13", "26", + "FCC", "2.4G", "40M", "HT", "1T", "14", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "14", "63", + "MKK", "2.4G", "40M", "HT", "1T", "14", "63", + "FCC", "2.4G", "40M", "HT", "2T", "01", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "01", "63", + "MKK", "2.4G", "40M", "HT", "2T", "01", "63", + "FCC", "2.4G", "40M", "HT", "2T", "02", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "02", "63", + "MKK", "2.4G", "40M", "HT", "2T", "02", "63", + "FCC", "2.4G", "40M", "HT", "2T", "03", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "03", "26", + "MKK", "2.4G", "40M", "HT", "2T", "03", "26", + "FCC", "2.4G", "40M", "HT", "2T", "04", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "04", "26", + "MKK", "2.4G", "40M", "HT", "2T", "04", "26", + "FCC", "2.4G", "40M", "HT", "2T", "05", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "05", "26", + "MKK", "2.4G", "40M", "HT", "2T", "05", "26", + "FCC", "2.4G", "40M", "HT", "2T", "06", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "06", "26", + "MKK", "2.4G", "40M", "HT", "2T", "06", "26", + "FCC", "2.4G", "40M", "HT", "2T", "07", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "07", "26", + "MKK", "2.4G", "40M", "HT", "2T", "07", "26", + "FCC", "2.4G", "40M", "HT", "2T", "08", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "08", "26", + "MKK", "2.4G", "40M", "HT", "2T", "08", "26", + "FCC", "2.4G", "40M", "HT", "2T", "09", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "09", "26", + "MKK", "2.4G", "40M", "HT", "2T", "09", "26", + "FCC", "2.4G", "40M", "HT", "2T", "10", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "10", "26", + "MKK", "2.4G", "40M", "HT", "2T", "10", "26", + "FCC", "2.4G", "40M", "HT", "2T", "11", "26", + "ETSI", "2.4G", "40M", "HT", "2T", "11", "26", + "MKK", "2.4G", "40M", "HT", "2T", "11", "26", + "FCC", "2.4G", "40M", "HT", "2T", "12", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "12", "26", + "MKK", "2.4G", "40M", "HT", "2T", "12", "26", + "FCC", "2.4G", "40M", "HT", "2T", "13", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "13", "26", + "MKK", "2.4G", "40M", "HT", "2T", "13", "26", + "FCC", "2.4G", "40M", "HT", "2T", "14", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "14", "63", + "MKK", "2.4G", "40M", "HT", "2T", "14", "63", + "FCC", "5G", "20M", "OFDM", "1T", "36", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "36", "32", + "MKK", "5G", "20M", "OFDM", "1T", "36", "32", + "FCC", "5G", "20M", "OFDM", "1T", "40", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "40", "32", + "MKK", "5G", "20M", "OFDM", "1T", "40", "32", + "FCC", "5G", "20M", "OFDM", "1T", "44", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "44", "32", + "MKK", "5G", "20M", "OFDM", "1T", "44", "32", + "FCC", "5G", "20M", "OFDM", "1T", "48", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "48", "32", + "MKK", "5G", "20M", "OFDM", "1T", "48", "32", + "FCC", "5G", "20M", "OFDM", "1T", "52", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "52", "32", + "MKK", "5G", "20M", "OFDM", "1T", "52", "32", + "FCC", "5G", "20M", "OFDM", "1T", "56", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "56", "32", + "MKK", "5G", "20M", "OFDM", "1T", "56", "32", + "FCC", "5G", "20M", "OFDM", "1T", "60", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "60", "32", + "MKK", "5G", "20M", "OFDM", "1T", "60", "32", + "FCC", "5G", "20M", "OFDM", "1T", "64", "28", + "ETSI", "5G", "20M", "OFDM", "1T", "64", "32", + "MKK", "5G", "20M", "OFDM", "1T", "64", "32", + "FCC", "5G", "20M", "OFDM", "1T", "100", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "100", "32", + "MKK", "5G", "20M", "OFDM", "1T", "100", "32", + "FCC", "5G", "20M", "OFDM", "1T", "114", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "114", "32", + "MKK", "5G", "20M", "OFDM", "1T", "114", "32", + "FCC", "5G", "20M", "OFDM", "1T", "108", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "108", "32", + "MKK", "5G", "20M", "OFDM", "1T", "108", "32", + "FCC", "5G", "20M", "OFDM", "1T", "112", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "112", "32", + "MKK", "5G", "20M", "OFDM", "1T", "112", "32", + "FCC", "5G", "20M", "OFDM", "1T", "116", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "116", "32", + "MKK", "5G", "20M", "OFDM", "1T", "116", "32", + "FCC", "5G", "20M", "OFDM", "1T", "120", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "120", "32", + "MKK", "5G", "20M", "OFDM", "1T", "120", "32", + "FCC", "5G", "20M", "OFDM", "1T", "124", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "124", "32", + "MKK", "5G", "20M", "OFDM", "1T", "124", "32", + "FCC", "5G", "20M", "OFDM", "1T", "128", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "128", "32", + "MKK", "5G", "20M", "OFDM", "1T", "128", "32", + "FCC", "5G", "20M", "OFDM", "1T", "132", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "132", "32", + "MKK", "5G", "20M", "OFDM", "1T", "132", "32", + "FCC", "5G", "20M", "OFDM", "1T", "136", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "136", "32", + "MKK", "5G", "20M", "OFDM", "1T", "136", "32", + "FCC", "5G", "20M", "OFDM", "1T", "140", "28", + "ETSI", "5G", "20M", "OFDM", "1T", "140", "32", + "MKK", "5G", "20M", "OFDM", "1T", "140", "32", + "FCC", "5G", "20M", "OFDM", "1T", "149", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "149", "32", + "MKK", "5G", "20M", "OFDM", "1T", "149", "63", + "FCC", "5G", "20M", "OFDM", "1T", "153", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "153", "32", + "MKK", "5G", "20M", "OFDM", "1T", "153", "63", + "FCC", "5G", "20M", "OFDM", "1T", "157", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "157", "32", + "MKK", "5G", "20M", "OFDM", "1T", "157", "63", + "FCC", "5G", "20M", "OFDM", "1T", "161", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "161", "32", + "MKK", "5G", "20M", "OFDM", "1T", "161", "63", + "FCC", "5G", "20M", "OFDM", "1T", "165", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "165", "32", + "MKK", "5G", "20M", "OFDM", "1T", "165", "63", + "FCC", "5G", "20M", "HT", "1T", "36", "30", + "ETSI", "5G", "20M", "HT", "1T", "36", "32", + "MKK", "5G", "20M", "HT", "1T", "36", "32", + "FCC", "5G", "20M", "HT", "1T", "40", "30", + "ETSI", "5G", "20M", "HT", "1T", "40", "32", + "MKK", "5G", "20M", "HT", "1T", "40", "32", + "FCC", "5G", "20M", "HT", "1T", "44", "30", + "ETSI", "5G", "20M", "HT", "1T", "44", "32", + "MKK", "5G", "20M", "HT", "1T", "44", "32", + "FCC", "5G", "20M", "HT", "1T", "48", "30", + "ETSI", "5G", "20M", "HT", "1T", "48", "32", + "MKK", "5G", "20M", "HT", "1T", "48", "32", + "FCC", "5G", "20M", "HT", "1T", "52", "34", + "ETSI", "5G", "20M", "HT", "1T", "52", "32", + "MKK", "5G", "20M", "HT", "1T", "52", "32", + "FCC", "5G", "20M", "HT", "1T", "56", "34", + "ETSI", "5G", "20M", "HT", "1T", "56", "32", + "MKK", "5G", "20M", "HT", "1T", "56", "32", + "FCC", "5G", "20M", "HT", "1T", "60", "32", + "ETSI", "5G", "20M", "HT", "1T", "60", "32", + "MKK", "5G", "20M", "HT", "1T", "60", "32", + "FCC", "5G", "20M", "HT", "1T", "64", "28", + "ETSI", "5G", "20M", "HT", "1T", "64", "32", + "MKK", "5G", "20M", "HT", "1T", "64", "32", + "FCC", "5G", "20M", "HT", "1T", "100", "30", + "ETSI", "5G", "20M", "HT", "1T", "100", "32", + "MKK", "5G", "20M", "HT", "1T", "100", "32", + "FCC", "5G", "20M", "HT", "1T", "114", "30", + "ETSI", "5G", "20M", "HT", "1T", "114", "32", + "MKK", "5G", "20M", "HT", "1T", "114", "32", + "FCC", "5G", "20M", "HT", "1T", "108", "32", + "ETSI", "5G", "20M", "HT", "1T", "108", "32", + "MKK", "5G", "20M", "HT", "1T", "108", "32", + "FCC", "5G", "20M", "HT", "1T", "112", "34", + "ETSI", "5G", "20M", "HT", "1T", "112", "32", + "MKK", "5G", "20M", "HT", "1T", "112", "32", + "FCC", "5G", "20M", "HT", "1T", "116", "34", + "ETSI", "5G", "20M", "HT", "1T", "116", "32", + "MKK", "5G", "20M", "HT", "1T", "116", "32", + "FCC", "5G", "20M", "HT", "1T", "120", "34", + "ETSI", "5G", "20M", "HT", "1T", "120", "32", + "MKK", "5G", "20M", "HT", "1T", "120", "32", + "FCC", "5G", "20M", "HT", "1T", "124", "34", + "ETSI", "5G", "20M", "HT", "1T", "124", "32", + "MKK", "5G", "20M", "HT", "1T", "124", "32", + "FCC", "5G", "20M", "HT", "1T", "128", "32", + "ETSI", "5G", "20M", "HT", "1T", "128", "32", + "MKK", "5G", "20M", "HT", "1T", "128", "32", + "FCC", "5G", "20M", "HT", "1T", "132", "30", + "ETSI", "5G", "20M", "HT", "1T", "132", "32", + "MKK", "5G", "20M", "HT", "1T", "132", "32", + "FCC", "5G", "20M", "HT", "1T", "136", "30", + "ETSI", "5G", "20M", "HT", "1T", "136", "32", + "MKK", "5G", "20M", "HT", "1T", "136", "32", + "FCC", "5G", "20M", "HT", "1T", "140", "28", + "ETSI", "5G", "20M", "HT", "1T", "140", "32", + "MKK", "5G", "20M", "HT", "1T", "140", "32", + "FCC", "5G", "20M", "HT", "1T", "149", "34", + "ETSI", "5G", "20M", "HT", "1T", "149", "32", + "MKK", "5G", "20M", "HT", "1T", "149", "63", + "FCC", "5G", "20M", "HT", "1T", "153", "34", + "ETSI", "5G", "20M", "HT", "1T", "153", "32", + "MKK", "5G", "20M", "HT", "1T", "153", "63", + "FCC", "5G", "20M", "HT", "1T", "157", "34", + "ETSI", "5G", "20M", "HT", "1T", "157", "32", + "MKK", "5G", "20M", "HT", "1T", "157", "63", + "FCC", "5G", "20M", "HT", "1T", "161", "34", + "ETSI", "5G", "20M", "HT", "1T", "161", "32", + "MKK", "5G", "20M", "HT", "1T", "161", "63", + "FCC", "5G", "20M", "HT", "1T", "165", "34", + "ETSI", "5G", "20M", "HT", "1T", "165", "32", + "MKK", "5G", "20M", "HT", "1T", "165", "63", + "FCC", "5G", "20M", "HT", "2T", "36", "28", + "ETSI", "5G", "20M", "HT", "2T", "36", "30", + "MKK", "5G", "20M", "HT", "2T", "36", "30", + "FCC", "5G", "20M", "HT", "2T", "40", "28", + "ETSI", "5G", "20M", "HT", "2T", "40", "30", + "MKK", "5G", "20M", "HT", "2T", "40", "30", + "FCC", "5G", "20M", "HT", "2T", "44", "28", + "ETSI", "5G", "20M", "HT", "2T", "44", "30", + "MKK", "5G", "20M", "HT", "2T", "44", "30", + "FCC", "5G", "20M", "HT", "2T", "48", "28", + "ETSI", "5G", "20M", "HT", "2T", "48", "30", + "MKK", "5G", "20M", "HT", "2T", "48", "30", + "FCC", "5G", "20M", "HT", "2T", "52", "34", + "ETSI", "5G", "20M", "HT", "2T", "52", "30", + "MKK", "5G", "20M", "HT", "2T", "52", "30", + "FCC", "5G", "20M", "HT", "2T", "56", "32", + "ETSI", "5G", "20M", "HT", "2T", "56", "30", + "MKK", "5G", "20M", "HT", "2T", "56", "30", + "FCC", "5G", "20M", "HT", "2T", "60", "30", + "ETSI", "5G", "20M", "HT", "2T", "60", "30", + "MKK", "5G", "20M", "HT", "2T", "60", "30", + "FCC", "5G", "20M", "HT", "2T", "64", "26", + "ETSI", "5G", "20M", "HT", "2T", "64", "30", + "MKK", "5G", "20M", "HT", "2T", "64", "30", + "FCC", "5G", "20M", "HT", "2T", "100", "28", + "ETSI", "5G", "20M", "HT", "2T", "100", "30", + "MKK", "5G", "20M", "HT", "2T", "100", "30", + "FCC", "5G", "20M", "HT", "2T", "114", "28", + "ETSI", "5G", "20M", "HT", "2T", "114", "30", + "MKK", "5G", "20M", "HT", "2T", "114", "30", + "FCC", "5G", "20M", "HT", "2T", "108", "30", + "ETSI", "5G", "20M", "HT", "2T", "108", "30", + "MKK", "5G", "20M", "HT", "2T", "108", "30", + "FCC", "5G", "20M", "HT", "2T", "112", "32", + "ETSI", "5G", "20M", "HT", "2T", "112", "30", + "MKK", "5G", "20M", "HT", "2T", "112", "30", + "FCC", "5G", "20M", "HT", "2T", "116", "32", + "ETSI", "5G", "20M", "HT", "2T", "116", "30", + "MKK", "5G", "20M", "HT", "2T", "116", "30", + "FCC", "5G", "20M", "HT", "2T", "120", "34", + "ETSI", "5G", "20M", "HT", "2T", "120", "30", + "MKK", "5G", "20M", "HT", "2T", "120", "30", + "FCC", "5G", "20M", "HT", "2T", "124", "32", + "ETSI", "5G", "20M", "HT", "2T", "124", "30", + "MKK", "5G", "20M", "HT", "2T", "124", "30", + "FCC", "5G", "20M", "HT", "2T", "128", "30", + "ETSI", "5G", "20M", "HT", "2T", "128", "30", + "MKK", "5G", "20M", "HT", "2T", "128", "30", + "FCC", "5G", "20M", "HT", "2T", "132", "28", + "ETSI", "5G", "20M", "HT", "2T", "132", "30", + "MKK", "5G", "20M", "HT", "2T", "132", "30", + "FCC", "5G", "20M", "HT", "2T", "136", "28", + "ETSI", "5G", "20M", "HT", "2T", "136", "30", + "MKK", "5G", "20M", "HT", "2T", "136", "30", + "FCC", "5G", "20M", "HT", "2T", "140", "26", + "ETSI", "5G", "20M", "HT", "2T", "140", "30", + "MKK", "5G", "20M", "HT", "2T", "140", "30", + "FCC", "5G", "20M", "HT", "2T", "149", "34", + "ETSI", "5G", "20M", "HT", "2T", "149", "30", + "MKK", "5G", "20M", "HT", "2T", "149", "63", + "FCC", "5G", "20M", "HT", "2T", "153", "34", + "ETSI", "5G", "20M", "HT", "2T", "153", "30", + "MKK", "5G", "20M", "HT", "2T", "153", "63", + "FCC", "5G", "20M", "HT", "2T", "157", "34", + "ETSI", "5G", "20M", "HT", "2T", "157", "30", + "MKK", "5G", "20M", "HT", "2T", "157", "63", + "FCC", "5G", "20M", "HT", "2T", "161", "34", + "ETSI", "5G", "20M", "HT", "2T", "161", "30", + "MKK", "5G", "20M", "HT", "2T", "161", "63", + "FCC", "5G", "20M", "HT", "2T", "165", "34", + "ETSI", "5G", "20M", "HT", "2T", "165", "30", + "MKK", "5G", "20M", "HT", "2T", "165", "63", + "FCC", "5G", "40M", "HT", "1T", "38", "30", + "ETSI", "5G", "40M", "HT", "1T", "38", "32", + "MKK", "5G", "40M", "HT", "1T", "38", "32", + "FCC", "5G", "40M", "HT", "1T", "46", "30", + "ETSI", "5G", "40M", "HT", "1T", "46", "32", + "MKK", "5G", "40M", "HT", "1T", "46", "32", + "FCC", "5G", "40M", "HT", "1T", "54", "32", + "ETSI", "5G", "40M", "HT", "1T", "54", "32", + "MKK", "5G", "40M", "HT", "1T", "54", "32", + "FCC", "5G", "40M", "HT", "1T", "62", "32", + "ETSI", "5G", "40M", "HT", "1T", "62", "32", + "MKK", "5G", "40M", "HT", "1T", "62", "32", + "FCC", "5G", "40M", "HT", "1T", "102", "28", + "ETSI", "5G", "40M", "HT", "1T", "102", "32", + "MKK", "5G", "40M", "HT", "1T", "102", "32", + "FCC", "5G", "40M", "HT", "1T", "110", "32", + "ETSI", "5G", "40M", "HT", "1T", "110", "32", + "MKK", "5G", "40M", "HT", "1T", "110", "32", + "FCC", "5G", "40M", "HT", "1T", "118", "34", + "ETSI", "5G", "40M", "HT", "1T", "118", "32", + "MKK", "5G", "40M", "HT", "1T", "118", "32", + "FCC", "5G", "40M", "HT", "1T", "126", "34", + "ETSI", "5G", "40M", "HT", "1T", "126", "32", + "MKK", "5G", "40M", "HT", "1T", "126", "32", + "FCC", "5G", "40M", "HT", "1T", "134", "32", + "ETSI", "5G", "40M", "HT", "1T", "134", "32", + "MKK", "5G", "40M", "HT", "1T", "134", "32", + "FCC", "5G", "40M", "HT", "1T", "151", "34", + "ETSI", "5G", "40M", "HT", "1T", "151", "32", + "MKK", "5G", "40M", "HT", "1T", "151", "63", + "FCC", "5G", "40M", "HT", "1T", "159", "34", + "ETSI", "5G", "40M", "HT", "1T", "159", "32", + "MKK", "5G", "40M", "HT", "1T", "159", "63", + "FCC", "5G", "40M", "HT", "2T", "38", "28", + "ETSI", "5G", "40M", "HT", "2T", "38", "30", + "MKK", "5G", "40M", "HT", "2T", "38", "30", + "FCC", "5G", "40M", "HT", "2T", "46", "28", + "ETSI", "5G", "40M", "HT", "2T", "46", "30", + "MKK", "5G", "40M", "HT", "2T", "46", "30", + "FCC", "5G", "40M", "HT", "2T", "54", "30", + "ETSI", "5G", "40M", "HT", "2T", "54", "30", + "MKK", "5G", "40M", "HT", "2T", "54", "30", + "FCC", "5G", "40M", "HT", "2T", "62", "30", + "ETSI", "5G", "40M", "HT", "2T", "62", "30", + "MKK", "5G", "40M", "HT", "2T", "62", "30", + "FCC", "5G", "40M", "HT", "2T", "102", "26", + "ETSI", "5G", "40M", "HT", "2T", "102", "30", + "MKK", "5G", "40M", "HT", "2T", "102", "30", + "FCC", "5G", "40M", "HT", "2T", "110", "30", + "ETSI", "5G", "40M", "HT", "2T", "110", "30", + "MKK", "5G", "40M", "HT", "2T", "110", "30", + "FCC", "5G", "40M", "HT", "2T", "118", "34", + "ETSI", "5G", "40M", "HT", "2T", "118", "30", + "MKK", "5G", "40M", "HT", "2T", "118", "30", + "FCC", "5G", "40M", "HT", "2T", "126", "32", + "ETSI", "5G", "40M", "HT", "2T", "126", "30", + "MKK", "5G", "40M", "HT", "2T", "126", "30", + "FCC", "5G", "40M", "HT", "2T", "134", "30", + "ETSI", "5G", "40M", "HT", "2T", "134", "30", + "MKK", "5G", "40M", "HT", "2T", "134", "30", + "FCC", "5G", "40M", "HT", "2T", "151", "34", + "ETSI", "5G", "40M", "HT", "2T", "151", "30", + "MKK", "5G", "40M", "HT", "2T", "151", "63", + "FCC", "5G", "40M", "HT", "2T", "159", "34", + "ETSI", "5G", "40M", "HT", "2T", "159", "30", + "MKK", "5G", "40M", "HT", "2T", "159", "63", + "FCC", "5G", "80M", "VHT", "1T", "42", "30", + "ETSI", "5G", "80M", "VHT", "1T", "42", "32", + "MKK", "5G", "80M", "VHT", "1T", "42", "32", + "FCC", "5G", "80M", "VHT", "1T", "58", "28", + "ETSI", "5G", "80M", "VHT", "1T", "58", "32", + "MKK", "5G", "80M", "VHT", "1T", "58", "32", + "FCC", "5G", "80M", "VHT", "1T", "106", "30", + "ETSI", "5G", "80M", "VHT", "1T", "106", "32", + "MKK", "5G", "80M", "VHT", "1T", "106", "32", + "FCC", "5G", "80M", "VHT", "1T", "122", "34", + "ETSI", "5G", "80M", "VHT", "1T", "122", "32", + "MKK", "5G", "80M", "VHT", "1T", "122", "32", + "FCC", "5G", "80M", "VHT", "1T", "155", "34", + "ETSI", "5G", "80M", "VHT", "1T", "155", "32", + "MKK", "5G", "80M", "VHT", "1T", "155", "63", + "FCC", "5G", "80M", "VHT", "2T", "42", "28", + "ETSI", "5G", "80M", "VHT", "2T", "42", "30", + "MKK", "5G", "80M", "VHT", "2T", "42", "30", + "FCC", "5G", "80M", "VHT", "2T", "58", "26", + "ETSI", "5G", "80M", "VHT", "2T", "58", "30", + "MKK", "5G", "80M", "VHT", "2T", "58", "30", + "FCC", "5G", "80M", "VHT", "2T", "106", "28", + "ETSI", "5G", "80M", "VHT", "2T", "106", "30", + "MKK", "5G", "80M", "VHT", "2T", "106", "30", + "FCC", "5G", "80M", "VHT", "2T", "122", "32", + "ETSI", "5G", "80M", "VHT", "2T", "122", "30", + "MKK", "5G", "80M", "VHT", "2T", "122", "30", + "FCC", "5G", "80M", "VHT", "2T", "155", "34", + "ETSI", "5G", "80M", "VHT", "2T", "155", "30", + "MKK", "5G", "80M", "VHT", "2T", "155", "63" +}; + +void +odm_read_and_config_mp_8188e_txpwr_lmt_88e_e_m2_for_msi( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u32 i = 0; + u32 array_len = sizeof(array_mp_8188e_txpwr_lmt_88ee_m2_for_msi) / sizeof(u8 *); + u8 **array = (u8 **)array_mp_8188e_txpwr_lmt_88ee_m2_for_msi; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("===> odm_read_and_config_mp_8188e_txpwr_lmt_88e_e_m2_for_msi\n")); + + for (i = 0; i < array_len; i += 7) { + u8 *regulation = array[i]; + u8 *band = array[i + 1]; + u8 *bandwidth = array[i + 2]; + u8 *rate = array[i + 3]; + u8 *rf_path = array[i + 4]; + u8 *chnl = array[i + 5]; + u8 *val = array[i + 6]; + + odm_config_bb_txpwr_lmt_8188e(p_dm_odm, regulation, band, bandwidth, rate, rf_path, chnl, val); + } + +} diff --git a/drivers/staging/rtl8188eu/hal/halhwimg8188e_rf.h b/drivers/staging/rtl8188eu/hal/halhwimg8188e_rf.h new file mode 100644 index 000000000000..470d594d6c9e --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/halhwimg8188e_rf.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/*Image2HeaderVersion: 2.18*/ +#if (RTL8188E_SUPPORT == 1) +#ifndef __INC_MP_RF_HW_IMG_8188E_H +#define __INC_MP_RF_HW_IMG_8188E_H + + +/****************************************************************************** +* RadioA.TXT +******************************************************************************/ + +void +odm_read_and_config_mp_8188e_radioa(/* TC: Test Chip, MP: MP Chip*/ + struct PHY_DM_STRUCT *p_dm_odm +); +u32 odm_get_version_mp_8188e_radioa(void); + +/****************************************************************************** +* TxPowerTrack_AP.TXT +******************************************************************************/ + +void +odm_read_and_config_mp_8188e_txpowertrack_ap(/* TC: Test Chip, MP: MP Chip*/ + struct PHY_DM_STRUCT *p_dm_odm +); +u32 odm_get_version_mp_8188e_txpowertrack_ap(void); + +/****************************************************************************** +* TxPowerTrack_PCIE.TXT +******************************************************************************/ + +void +odm_read_and_config_mp_8188e_txpowertrack_pcie(/* TC: Test Chip, MP: MP Chip*/ + struct PHY_DM_STRUCT *p_dm_odm +); +u32 odm_get_version_mp_8188e_txpowertrack_pcie(void); + +/****************************************************************************** +* TxPowerTrack_PCIE_ICUT.TXT +******************************************************************************/ + +void +odm_read_and_config_mp_8188e_txpowertrack_pcie_icut(/* TC: Test Chip, MP: MP Chip*/ + struct PHY_DM_STRUCT *p_dm_odm +); +u32 odm_get_version_mp_8188e_txpowertrack_pcie_icut(void); + +/****************************************************************************** +* TxPowerTrack_SDIO.TXT +******************************************************************************/ + +void +odm_read_and_config_mp_8188e_txpowertrack_sdio(/* TC: Test Chip, MP: MP Chip*/ + struct PHY_DM_STRUCT *p_dm_odm +); +u32 odm_get_version_mp_8188e_txpowertrack_sdio(void); + +/****************************************************************************** +* TxPowerTrack_SDIO_ICUT.TXT +******************************************************************************/ + +void +odm_read_and_config_mp_8188e_txpowertrack_sdio_icut(/* TC: Test Chip, MP: MP Chip*/ + struct PHY_DM_STRUCT *p_dm_odm +); +u32 odm_get_version_mp_8188e_txpowertrack_sdio_icut(void); + +/****************************************************************************** +* TxPowerTrack_USB.TXT +******************************************************************************/ + +void +odm_read_and_config_mp_8188e_txpowertrack_usb(/* TC: Test Chip, MP: MP Chip*/ + struct PHY_DM_STRUCT *p_dm_odm +); +u32 odm_get_version_mp_8188e_txpowertrack_usb(void); + +/****************************************************************************** +* TxPowerTrack_USB_ICUT.TXT +******************************************************************************/ + +void +odm_read_and_config_mp_8188e_txpowertrack_usb_icut(/* TC: Test Chip, MP: MP Chip*/ + struct PHY_DM_STRUCT *p_dm_odm +); +u32 odm_get_version_mp_8188e_txpowertrack_usb_icut(void); + +/****************************************************************************** +* TXPWR_LMT.TXT +******************************************************************************/ + +void +odm_read_and_config_mp_8188e_txpwr_lmt(/* TC: Test Chip, MP: MP Chip*/ + struct PHY_DM_STRUCT *p_dm_odm +); +u32 odm_get_version_mp_8188e_txpwr_lmt(void); + +/****************************************************************************** +* TXPWR_LMT_88EE_M2_for_MSI.TXT +******************************************************************************/ + +void +odm_read_and_config_mp_8188e_txpwr_lmt_88e_e_m2_for_msi(/* TC: Test Chip, MP: MP Chip*/ + struct PHY_DM_STRUCT *p_dm_odm +); +u32 odm_get_version_mp_8188e_txpwr_lmt_88ee_m2_for_msi(void); + +#endif +#endif /* end of HWIMG_SUPPORT*/ diff --git a/drivers/staging/rtl8188eu/hal/halphyrf_8188e_ce.c b/drivers/staging/rtl8188eu/hal/halphyrf_8188e_ce.c new file mode 100644 index 000000000000..326d9762a15e --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/halphyrf_8188e_ce.c @@ -0,0 +1,1973 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#include "mp_precomp.h" +#include "phydm_precomp.h" + +/*---------------------------Define Local Constant---------------------------*/ +/* 2010/04/25 MH Define the max tx power tracking tx agc power. */ +#define ODM_TXPWRTRACK_MAX_IDX_88E 6 + +/*---------------------------Define Local Constant---------------------------*/ + +/* 3============================================================ + * 3 Tx Power Tracking + * 3============================================================ */ + +static void set_iqk_matrix_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u8 OFDM_index, + u8 rf_path, + s32 iqk_result_x, + s32 iqk_result_y +) +{ + s32 ele_A = 0, ele_D, ele_C = 0, value32; + + ele_D = (ofdm_swing_table_new[OFDM_index] & 0xFFC00000) >> 22; + + /* new element A = element D x X */ + if ((iqk_result_x != 0) && (*(p_dm_odm->p_band_type) == ODM_BAND_2_4G)) { + if ((iqk_result_x & 0x00000200) != 0) /* consider minus */ + iqk_result_x = iqk_result_x | 0xFFFFFC00; + ele_A = ((iqk_result_x * ele_D) >> 8) & 0x000003FF; + + /* new element C = element D x Y */ + if ((iqk_result_y & 0x00000200) != 0) + iqk_result_y = iqk_result_y | 0xFFFFFC00; + ele_C = ((iqk_result_y * ele_D) >> 8) & 0x000003FF; + + /* if (rf_path == ODM_RF_PATH_A) */ + switch (rf_path) { + case ODM_RF_PATH_A: + /* wirte new elements A, C, D to regC80 and regC94, element B is always 0 */ + value32 = (ele_D << 22) | ((ele_C & 0x3F) << 16) | ele_A; + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XA_TX_IQ_IMBALANCE, MASKDWORD, value32); + + value32 = (ele_C & 0x000003C0) >> 6; + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XC_TX_AFE, MASKH4BITS, value32); + + value32 = ((iqk_result_x * ele_D) >> 7) & 0x01; + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_ECCA_THRESHOLD, BIT(24), value32); + break; + case ODM_RF_PATH_B: + /* wirte new elements A, C, D to regC88 and regC9C, element B is always 0 */ + value32 = (ele_D << 22) | ((ele_C & 0x3F) << 16) | ele_A; + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XB_TX_IQ_IMBALANCE, MASKDWORD, value32); + + value32 = (ele_C & 0x000003C0) >> 6; + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XD_TX_AFE, MASKH4BITS, value32); + + value32 = ((iqk_result_x * ele_D) >> 7) & 0x01; + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_ECCA_THRESHOLD, BIT(28), value32); + + break; + default: + break; + } + } else { + switch (rf_path) { + case ODM_RF_PATH_A: + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XA_TX_IQ_IMBALANCE, MASKDWORD, ofdm_swing_table_new[OFDM_index]); + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XC_TX_AFE, MASKH4BITS, 0x00); + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_ECCA_THRESHOLD, BIT(24), 0x00); + break; + + case ODM_RF_PATH_B: + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XB_TX_IQ_IMBALANCE, MASKDWORD, ofdm_swing_table_new[OFDM_index]); + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XD_TX_AFE, MASKH4BITS, 0x00); + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_ECCA_THRESHOLD, BIT(28), 0x00); + break; + + default: + break; + } + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("TxPwrTracking path B: X = 0x%x, Y = 0x%x ele_A = 0x%x ele_C = 0x%x ele_D = 0x%x 0xeb4 = 0x%x 0xebc = 0x%x\n", + (u32)iqk_result_x, (u32)iqk_result_y, (u32)ele_A, (u32)ele_C, (u32)ele_D, (u32)iqk_result_x, (u32)iqk_result_y)); +} + +void do_iqk_8188e( + void *p_dm_void, + u8 delta_thermal_index, + u8 thermal_value, + u8 threshold +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTER *adapter = p_dm_odm->adapter; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(adapter); + + odm_reset_iqk_result(p_dm_odm); + + p_dm_odm->rf_calibrate_info.thermal_value_iqk = thermal_value; + phy_iq_calibrate_8188e(adapter, false); +} + +/*----------------------------------------------------------------------------- + * Function: odm_TxPwrTrackSetPwr88E() + * + * Overview: 88E change all channel tx power accordign to flag. + * OFDM & CCK are all different. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 04/23/2012 MHC Create version 0. + * + *---------------------------------------------------------------------------*/ +void +odm_tx_pwr_track_set_pwr88_e( + void *p_dm_void, + enum pwrtrack_method method, + u8 rf_path, + u8 channel_mapped_index +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTER *adapter = p_dm_odm->adapter; + PHAL_DATA_TYPE p_hal_data = GET_HAL_DATA(adapter); + u8 pwr_tracking_limit_ofdm = 30; /* +0dB */ + u8 pwr_tracking_limit_cck = 28; /* -2dB */ + u8 tx_rate = 0xFF; + u8 final_ofdm_swing_index = 0; + u8 final_cck_swing_index = 0; + u8 i = 0; + struct odm_rf_calibration_structure *p_rf_calibrate_info = &(p_dm_odm->rf_calibrate_info); + + if (p_dm_odm->mp_mode == true) { + PMPT_CONTEXT p_mpt_ctx = &(adapter->mppriv.mpt_ctx); + + tx_rate = mpt_to_mgnt_rate(p_mpt_ctx->mpt_rate_index); + } else { + u16 rate = *(p_dm_odm->p_forced_data_rate); + + if (!rate) { /*auto rate*/ + if (rate != 0xFF) { + if (p_dm_odm->number_linked_client != 0) + tx_rate = hw_rate_to_m_rate(p_dm_odm->tx_rate); + } + } else /*force rate*/ + tx_rate = (u8)rate; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("Power Tracking tx_rate=0x%X\n", tx_rate)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("===>ODM_TxPwrTrackSetPwr8188E\n")); + + if (tx_rate != 0xFF) { + /* 2 CCK */ + if (((tx_rate >= MGN_1M) && (tx_rate <= MGN_5_5M)) || (tx_rate == MGN_11M)) + pwr_tracking_limit_cck = 28; /* -2dB */ + /* 2 OFDM */ + else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M)) + pwr_tracking_limit_ofdm = 36; /* +3dB */ + else if (tx_rate == MGN_54M) + pwr_tracking_limit_ofdm = 34; /* +2dB */ + + /* 2 HT */ + else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2)) /* QPSK/BPSK */ + pwr_tracking_limit_ofdm = 38; /* +4dB */ + else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4)) /* 16QAM */ + pwr_tracking_limit_ofdm = 36; /* +3dB */ + else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7)) /* 64QAM */ + pwr_tracking_limit_ofdm = 34; /* +2dB */ + + else + pwr_tracking_limit_ofdm = p_rf_calibrate_info->default_ofdm_index; /*Default OFDM index = 30*/ + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("tx_rate=0x%x, pwr_tracking_limit=%d\n", tx_rate, pwr_tracking_limit_ofdm)); + + if (method == TXAGC) { + u32 pwr = 0, tx_agc = 0; + struct _ADAPTER *adapter = p_dm_odm->adapter; + + p_rf_calibrate_info->remnant_ofdm_swing_idx[rf_path] = p_rf_calibrate_info->absolute_ofdm_swing_idx[rf_path]; /*Remnant index equal to aboslute compensate value.*/ + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("odm_TxPwrTrackSetPwr88E CH=%d\n", *(p_dm_odm->p_channel))); + + if (p_dm_odm->mp_mode == true) { + pwr = phy_query_bb_reg(adapter, REG_TX_AGC_A_RATE18_06, 0xFF); + pwr += p_dm_odm->rf_calibrate_info.power_index_offset[ODM_RF_PATH_A]; + phy_set_bb_reg(adapter, REG_TX_AGC_A_CCK_1_MCS32, MASKBYTE1, pwr); + tx_agc = (pwr << 16) | (pwr << 8) | (pwr); + phy_set_bb_reg(adapter, REG_TX_AGC_B_CCK_11_A_CCK_2_11, MASKH3BYTES, tx_agc); + /* RT_DISP(FPHY, PHY_TXPWR, ("odm_tx_pwr_track_set_pwr88_e: CCK Tx-rf(A) Power = 0x%x\n", tx_agc)); */ + + pwr = phy_query_bb_reg(adapter, REG_TX_AGC_A_RATE18_06, 0xFF); + pwr += (p_rf_calibrate_info->bb_swing_idx_ofdm[ODM_RF_PATH_A] - p_rf_calibrate_info->bb_swing_idx_ofdm_base[RF_PATH_A]); + tx_agc |= ((pwr << 24) | (pwr << 16) | (pwr << 8) | pwr); + phy_set_bb_reg(adapter, REG_TX_AGC_A_RATE18_06, MASKDWORD, tx_agc); + phy_set_bb_reg(adapter, REG_TX_AGC_A_RATE54_24, MASKDWORD, tx_agc); + phy_set_bb_reg(adapter, REG_TX_AGC_A_MCS03_MCS00, MASKDWORD, tx_agc); + phy_set_bb_reg(adapter, REG_TX_AGC_A_MCS07_MCS04, MASKDWORD, tx_agc); + phy_set_bb_reg(adapter, REG_TX_AGC_A_MCS11_MCS08, MASKDWORD, tx_agc); + phy_set_bb_reg(adapter, REG_TX_AGC_A_MCS15_MCS12, MASKDWORD, tx_agc); + /* RT_DISP(FPHY, PHY_TXPWR, ("odm_tx_pwr_track_set_pwr88_e: OFDM Tx-rf(A) Power = 0x%x\n", tx_agc)); */ + } else { + /* phy_set_tx_power_level8188e(p_dm_odm->adapter, *p_dm_odm->p_channel); */ + p_rf_calibrate_info->modify_tx_agc_flag_path_a = true; + p_rf_calibrate_info->modify_tx_agc_flag_path_a_cck = true; + + if (rf_path == ODM_RF_PATH_A) { + phy_set_tx_power_index_by_rate_section(adapter, ODM_RF_PATH_A, *p_dm_odm->p_channel, CCK); + phy_set_tx_power_index_by_rate_section(adapter, ODM_RF_PATH_A, *p_dm_odm->p_channel, OFDM); + phy_set_tx_power_index_by_rate_section(adapter, ODM_RF_PATH_A, *p_dm_odm->p_channel, HT_MCS0_MCS7); + } + } + } else if (method == BBSWING) { + final_ofdm_swing_index = p_rf_calibrate_info->default_ofdm_index + p_rf_calibrate_info->absolute_ofdm_swing_idx[rf_path]; + final_cck_swing_index = p_rf_calibrate_info->default_cck_index + p_rf_calibrate_info->absolute_ofdm_swing_idx[rf_path]; + + if (final_ofdm_swing_index >= pwr_tracking_limit_ofdm) + final_ofdm_swing_index = pwr_tracking_limit_ofdm; + else if (final_ofdm_swing_index <= 0) + final_ofdm_swing_index = 0; + + if (final_cck_swing_index >= CCK_TABLE_SIZE) + final_cck_swing_index = CCK_TABLE_SIZE - 1; + else if (p_rf_calibrate_info->bb_swing_idx_cck <= 0) + final_cck_swing_index = 0; + + /* Adjust BB swing by OFDM IQ matrix */ + if (rf_path == ODM_RF_PATH_A) { + set_iqk_matrix_8188e(p_dm_odm, final_ofdm_swing_index, ODM_RF_PATH_A, + p_dm_odm->rf_calibrate_info.iqk_matrix_reg_setting[channel_mapped_index].value[0][0], + p_dm_odm->rf_calibrate_info.iqk_matrix_reg_setting[channel_mapped_index].value[0][1]); + /* Adjust BB swing by CCK filter coefficient */ + if (!p_dm_odm->rf_calibrate_info.is_cck_in_ch14) { + odm_write_1byte(p_dm_odm, 0xa22, cck_swing_table_ch1_ch13_new[final_cck_swing_index][0]); + odm_write_1byte(p_dm_odm, 0xa23, cck_swing_table_ch1_ch13_new[final_cck_swing_index][1]); + odm_write_1byte(p_dm_odm, 0xa24, cck_swing_table_ch1_ch13_new[final_cck_swing_index][2]); + odm_write_1byte(p_dm_odm, 0xa25, cck_swing_table_ch1_ch13_new[final_cck_swing_index][3]); + odm_write_1byte(p_dm_odm, 0xa26, cck_swing_table_ch1_ch13_new[final_cck_swing_index][4]); + odm_write_1byte(p_dm_odm, 0xa27, cck_swing_table_ch1_ch13_new[final_cck_swing_index][5]); + odm_write_1byte(p_dm_odm, 0xa28, cck_swing_table_ch1_ch13_new[final_cck_swing_index][6]); + odm_write_1byte(p_dm_odm, 0xa29, cck_swing_table_ch1_ch13_new[final_cck_swing_index][7]); + } else { + odm_write_1byte(p_dm_odm, 0xa22, cck_swing_table_ch14_new[final_cck_swing_index][0]); + odm_write_1byte(p_dm_odm, 0xa23, cck_swing_table_ch14_new[final_cck_swing_index][1]); + odm_write_1byte(p_dm_odm, 0xa24, cck_swing_table_ch14_new[final_cck_swing_index][2]); + odm_write_1byte(p_dm_odm, 0xa25, cck_swing_table_ch14_new[final_cck_swing_index][3]); + odm_write_1byte(p_dm_odm, 0xa26, cck_swing_table_ch14_new[final_cck_swing_index][4]); + odm_write_1byte(p_dm_odm, 0xa27, cck_swing_table_ch14_new[final_cck_swing_index][5]); + odm_write_1byte(p_dm_odm, 0xa28, cck_swing_table_ch14_new[final_cck_swing_index][6]); + odm_write_1byte(p_dm_odm, 0xa29, cck_swing_table_ch14_new[final_cck_swing_index][7]); + } + } + } else if (method == MIX_MODE) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("p_rf_calibrate_info->default_ofdm_index=%d, p_dm_odm->DefaultCCKIndex=%d, p_rf_calibrate_info->absolute_ofdm_swing_idx[rf_path]=%d, rf_path = %d\n", + p_rf_calibrate_info->default_ofdm_index, p_rf_calibrate_info->default_cck_index, p_rf_calibrate_info->absolute_ofdm_swing_idx[rf_path], rf_path)); + + final_cck_swing_index = p_rf_calibrate_info->default_cck_index + p_rf_calibrate_info->absolute_ofdm_swing_idx[rf_path]; + final_ofdm_swing_index = p_rf_calibrate_info->default_ofdm_index + p_rf_calibrate_info->absolute_ofdm_swing_idx[rf_path]; + + if (final_ofdm_swing_index > pwr_tracking_limit_ofdm) { /* BBSwing higher then Limit */ + p_rf_calibrate_info->remnant_ofdm_swing_idx[rf_path] = final_ofdm_swing_index - pwr_tracking_limit_ofdm; + + set_iqk_matrix_8188e(p_dm_odm, pwr_tracking_limit_ofdm, ODM_RF_PATH_A, + p_dm_odm->rf_calibrate_info.iqk_matrix_reg_setting[channel_mapped_index].value[0][0], + p_dm_odm->rf_calibrate_info.iqk_matrix_reg_setting[channel_mapped_index].value[0][1]); + + p_rf_calibrate_info->modify_tx_agc_flag_path_a = true; + + phy_set_tx_power_index_by_rate_section(adapter, ODM_RF_PATH_A, *p_dm_odm->p_channel, OFDM); + phy_set_tx_power_index_by_rate_section(adapter, ODM_RF_PATH_A, *p_dm_odm->p_channel, HT_MCS0_MCS7); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("******Path_A Over BBSwing Limit, pwr_tracking_limit = %d, Remnant tx_agc value = %d\n", pwr_tracking_limit_ofdm, p_rf_calibrate_info->remnant_ofdm_swing_idx[rf_path])); + } else if (final_ofdm_swing_index <= 0) { + p_rf_calibrate_info->remnant_ofdm_swing_idx[rf_path] = final_ofdm_swing_index; + + set_iqk_matrix_8188e(p_dm_odm, 0, ODM_RF_PATH_A, + p_dm_odm->rf_calibrate_info.iqk_matrix_reg_setting[channel_mapped_index].value[0][0], + p_dm_odm->rf_calibrate_info.iqk_matrix_reg_setting[channel_mapped_index].value[0][1]); + + p_rf_calibrate_info->modify_tx_agc_flag_path_a = true; + + phy_set_tx_power_index_by_rate_section(adapter, ODM_RF_PATH_A, *p_dm_odm->p_channel, OFDM); + phy_set_tx_power_index_by_rate_section(adapter, ODM_RF_PATH_A, *p_dm_odm->p_channel, HT_MCS0_MCS7); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("******Path_A Lower then BBSwing lower bound 0, Remnant tx_agc value = %d\n", p_rf_calibrate_info->remnant_ofdm_swing_idx[rf_path])); + } else { + set_iqk_matrix_8188e(p_dm_odm, final_ofdm_swing_index, ODM_RF_PATH_A, + p_dm_odm->rf_calibrate_info.iqk_matrix_reg_setting[channel_mapped_index].value[0][0], + p_dm_odm->rf_calibrate_info.iqk_matrix_reg_setting[channel_mapped_index].value[0][1]); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("******Path_A Compensate with BBSwing, final_ofdm_swing_index = %d\n", final_ofdm_swing_index)); + + if (p_rf_calibrate_info->modify_tx_agc_flag_path_a) { /*If tx_agc has changed, reset tx_agc again*/ + p_rf_calibrate_info->remnant_ofdm_swing_idx[rf_path] = 0; + + phy_set_tx_power_index_by_rate_section(adapter, ODM_RF_PATH_A, *p_dm_odm->p_channel, OFDM); + phy_set_tx_power_index_by_rate_section(adapter, ODM_RF_PATH_A, *p_dm_odm->p_channel, HT_MCS0_MCS7); + + p_rf_calibrate_info->modify_tx_agc_flag_path_a = false; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("******Path_A p_dm_odm->Modify_TxAGC_Flag = false\n")); + } + } + + if (final_cck_swing_index > pwr_tracking_limit_cck) { + p_rf_calibrate_info->remnant_cck_swing_idx = final_cck_swing_index - pwr_tracking_limit_cck; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("******Path_A CCK Over Limit, pwr_tracking_limit_cck = %d, p_rf_calibrate_info->remnant_cck_swing_idx = %d\n", pwr_tracking_limit_cck, p_rf_calibrate_info->remnant_cck_swing_idx)); + + /* Adjust BB swing by CCK filter coefficient */ + + if (!p_dm_odm->rf_calibrate_info.is_cck_in_ch14) { + odm_write_1byte(p_dm_odm, 0xa22, cck_swing_table_ch1_ch13_new[pwr_tracking_limit_cck][0]); + odm_write_1byte(p_dm_odm, 0xa23, cck_swing_table_ch1_ch13_new[pwr_tracking_limit_cck][1]); + odm_write_1byte(p_dm_odm, 0xa24, cck_swing_table_ch1_ch13_new[pwr_tracking_limit_cck][2]); + odm_write_1byte(p_dm_odm, 0xa25, cck_swing_table_ch1_ch13_new[pwr_tracking_limit_cck][3]); + odm_write_1byte(p_dm_odm, 0xa26, cck_swing_table_ch1_ch13_new[pwr_tracking_limit_cck][4]); + odm_write_1byte(p_dm_odm, 0xa27, cck_swing_table_ch1_ch13_new[pwr_tracking_limit_cck][5]); + odm_write_1byte(p_dm_odm, 0xa28, cck_swing_table_ch1_ch13_new[pwr_tracking_limit_cck][6]); + odm_write_1byte(p_dm_odm, 0xa29, cck_swing_table_ch1_ch13_new[pwr_tracking_limit_cck][7]); + } else { + odm_write_1byte(p_dm_odm, 0xa22, cck_swing_table_ch14_new[pwr_tracking_limit_cck][0]); + odm_write_1byte(p_dm_odm, 0xa23, cck_swing_table_ch14_new[pwr_tracking_limit_cck][1]); + odm_write_1byte(p_dm_odm, 0xa24, cck_swing_table_ch14_new[pwr_tracking_limit_cck][2]); + odm_write_1byte(p_dm_odm, 0xa25, cck_swing_table_ch14_new[pwr_tracking_limit_cck][3]); + odm_write_1byte(p_dm_odm, 0xa26, cck_swing_table_ch14_new[pwr_tracking_limit_cck][4]); + odm_write_1byte(p_dm_odm, 0xa27, cck_swing_table_ch14_new[pwr_tracking_limit_cck][5]); + odm_write_1byte(p_dm_odm, 0xa28, cck_swing_table_ch14_new[pwr_tracking_limit_cck][6]); + odm_write_1byte(p_dm_odm, 0xa29, cck_swing_table_ch14_new[pwr_tracking_limit_cck][7]); + } + + p_rf_calibrate_info->modify_tx_agc_flag_path_a_cck = true; + + phy_set_tx_power_index_by_rate_section(adapter, ODM_RF_PATH_A, *p_dm_odm->p_channel, CCK); + + } else if (final_cck_swing_index <= 0) { /* Lowest CCK index = 0 */ + p_rf_calibrate_info->remnant_cck_swing_idx = final_cck_swing_index; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("******Path_A CCK Under Limit, pwr_tracking_limit_cck = %d, p_rf_calibrate_info->remnant_cck_swing_idx = %d\n", 0, p_rf_calibrate_info->remnant_cck_swing_idx)); + + if (!p_dm_odm->rf_calibrate_info.is_cck_in_ch14) { + odm_write_1byte(p_dm_odm, 0xa22, cck_swing_table_ch1_ch13_new[0][0]); + odm_write_1byte(p_dm_odm, 0xa23, cck_swing_table_ch1_ch13_new[0][1]); + odm_write_1byte(p_dm_odm, 0xa24, cck_swing_table_ch1_ch13_new[0][2]); + odm_write_1byte(p_dm_odm, 0xa25, cck_swing_table_ch1_ch13_new[0][3]); + odm_write_1byte(p_dm_odm, 0xa26, cck_swing_table_ch1_ch13_new[0][4]); + odm_write_1byte(p_dm_odm, 0xa27, cck_swing_table_ch1_ch13_new[0][5]); + odm_write_1byte(p_dm_odm, 0xa28, cck_swing_table_ch1_ch13_new[0][6]); + odm_write_1byte(p_dm_odm, 0xa29, cck_swing_table_ch1_ch13_new[0][7]); + } else { + odm_write_1byte(p_dm_odm, 0xa22, cck_swing_table_ch14_new[0][0]); + odm_write_1byte(p_dm_odm, 0xa23, cck_swing_table_ch14_new[0][1]); + odm_write_1byte(p_dm_odm, 0xa24, cck_swing_table_ch14_new[0][2]); + odm_write_1byte(p_dm_odm, 0xa25, cck_swing_table_ch14_new[0][3]); + odm_write_1byte(p_dm_odm, 0xa26, cck_swing_table_ch14_new[0][4]); + odm_write_1byte(p_dm_odm, 0xa27, cck_swing_table_ch14_new[0][5]); + odm_write_1byte(p_dm_odm, 0xa28, cck_swing_table_ch14_new[0][6]); + odm_write_1byte(p_dm_odm, 0xa29, cck_swing_table_ch14_new[0][7]); + } + + p_rf_calibrate_info->modify_tx_agc_flag_path_a_cck = true; + + phy_set_tx_power_index_by_rate_section(adapter, ODM_RF_PATH_A, *p_dm_odm->p_channel, CCK); + + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("******Path_A CCK Compensate with BBSwing, final_cck_swing_index = %d\n", final_cck_swing_index)); + + if (!p_dm_odm->rf_calibrate_info.is_cck_in_ch14) { + odm_write_1byte(p_dm_odm, 0xa22, cck_swing_table_ch1_ch13_new[final_cck_swing_index][0]); + odm_write_1byte(p_dm_odm, 0xa23, cck_swing_table_ch1_ch13_new[final_cck_swing_index][1]); + odm_write_1byte(p_dm_odm, 0xa24, cck_swing_table_ch1_ch13_new[final_cck_swing_index][2]); + odm_write_1byte(p_dm_odm, 0xa25, cck_swing_table_ch1_ch13_new[final_cck_swing_index][3]); + odm_write_1byte(p_dm_odm, 0xa26, cck_swing_table_ch1_ch13_new[final_cck_swing_index][4]); + odm_write_1byte(p_dm_odm, 0xa27, cck_swing_table_ch1_ch13_new[final_cck_swing_index][5]); + odm_write_1byte(p_dm_odm, 0xa28, cck_swing_table_ch1_ch13_new[final_cck_swing_index][6]); + odm_write_1byte(p_dm_odm, 0xa29, cck_swing_table_ch1_ch13_new[final_cck_swing_index][7]); + } else { + odm_write_1byte(p_dm_odm, 0xa22, cck_swing_table_ch14_new[final_cck_swing_index][0]); + odm_write_1byte(p_dm_odm, 0xa23, cck_swing_table_ch14_new[final_cck_swing_index][1]); + odm_write_1byte(p_dm_odm, 0xa24, cck_swing_table_ch14_new[final_cck_swing_index][2]); + odm_write_1byte(p_dm_odm, 0xa25, cck_swing_table_ch14_new[final_cck_swing_index][3]); + odm_write_1byte(p_dm_odm, 0xa26, cck_swing_table_ch14_new[final_cck_swing_index][4]); + odm_write_1byte(p_dm_odm, 0xa27, cck_swing_table_ch14_new[final_cck_swing_index][5]); + odm_write_1byte(p_dm_odm, 0xa28, cck_swing_table_ch14_new[final_cck_swing_index][6]); + odm_write_1byte(p_dm_odm, 0xa29, cck_swing_table_ch14_new[final_cck_swing_index][7]); + } + + if (p_rf_calibrate_info->modify_tx_agc_flag_path_a_cck) { /*If tx_agc has changed, reset tx_agc again*/ + p_rf_calibrate_info->remnant_cck_swing_idx = 0; + phy_set_tx_power_index_by_rate_section(adapter, ODM_RF_PATH_A, *p_dm_odm->p_channel, CCK); + p_rf_calibrate_info->modify_tx_agc_flag_path_a_cck = false; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("******Path_A p_dm_odm->Modify_TxAGC_Flag_CCK = false\n")); + } + } + } else + return; +} /* odm_TxPwrTrackSetPwr88E */ + +void +get_delta_swing_table_8188e( + void *p_dm_void, + u8 **temperature_up_a, + u8 **temperature_down_a, + u8 **temperature_up_b, + u8 **temperature_down_b +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTER *adapter = p_dm_odm->adapter; + PHAL_DATA_TYPE p_hal_data = GET_HAL_DATA(adapter); + struct odm_rf_calibration_structure *p_rf_calibrate_info = &(p_dm_odm->rf_calibrate_info); + + u8 tx_rate = 0xFF; + u8 channel = *p_dm_odm->p_channel; + + if (p_dm_odm->mp_mode == true) { + PMPT_CONTEXT p_mpt_ctx = &(adapter->mppriv.mpt_ctx); + + tx_rate = mpt_to_mgnt_rate(p_mpt_ctx->mpt_rate_index); + } else { + u16 rate = *(p_dm_odm->p_forced_data_rate); + + if (!rate) { /*auto rate*/ + if (rate != 0xFF) { + if (p_dm_odm->number_linked_client != 0) + tx_rate = hw_rate_to_m_rate(p_dm_odm->tx_rate); + } + } else /*force rate*/ + tx_rate = (u8)rate; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("Power Tracking tx_rate=0x%X\n", tx_rate)); + + if (1 <= channel && channel <= 14) { + if (IS_CCK_RATE(tx_rate)) { + *temperature_up_a = p_rf_calibrate_info->delta_swing_table_idx_2g_cck_a_p; + *temperature_down_a = p_rf_calibrate_info->delta_swing_table_idx_2g_cck_a_n; + } else { + *temperature_up_a = p_rf_calibrate_info->delta_swing_table_idx_2ga_p; + *temperature_down_a = p_rf_calibrate_info->delta_swing_table_idx_2ga_n; + } + } else { + *temperature_up_a = (u8 *)delta_swing_table_idx_2ga_p_8188e; + *temperature_down_a = (u8 *)delta_swing_table_idx_2ga_n_8188e; + } + +} + +void configure_txpower_track_8188e( + struct _TXPWRTRACK_CFG *p_config +) +{ + p_config->swing_table_size_cck = CCK_TABLE_SIZE; + p_config->swing_table_size_ofdm = OFDM_TABLE_SIZE; + p_config->threshold_iqk = IQK_THRESHOLD; + p_config->average_thermal_num = AVG_THERMAL_NUM_88E; + p_config->rf_path_count = MAX_PATH_NUM_8188E; + p_config->thermal_reg_addr = RF_T_METER_88E; + + p_config->odm_tx_pwr_track_set_pwr = odm_tx_pwr_track_set_pwr88_e; + p_config->do_iqk = do_iqk_8188e; + p_config->phy_lc_calibrate = phy_lc_calibrate_8188e; + p_config->get_delta_swing_table = get_delta_swing_table_8188e; +} + +/* 1 7. IQK */ +#define MAX_TOLERANCE 5 +#define IQK_DELAY_TIME 1 /* ms */ + +static u8 /* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ +phy_path_a_iqk_8188e( + struct _ADAPTER *p_adapter, + bool config_path_b +) +{ + u32 reg_eac, reg_e94, reg_e9c, reg_ea4; + u8 result = 0x00; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path A IQK!\n")); + + /* 1 Tx IQK */ + /* path-A IQK setting */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path-A IQK setting!\n")); + odm_set_bb_reg(p_dm_odm, REG_TX_IQK_TONE_A, MASKDWORD, 0x10008c1c); + odm_set_bb_reg(p_dm_odm, REG_RX_IQK_TONE_A, MASKDWORD, 0x30008c1c); + odm_set_bb_reg(p_dm_odm, REG_TX_IQK_PI_A, MASKDWORD, 0x8214032a); + odm_set_bb_reg(p_dm_odm, REG_RX_IQK_PI_A, MASKDWORD, 0x28160000); + + /* LO calibration setting */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LO calibration setting!\n")); + odm_set_bb_reg(p_dm_odm, REG_IQK_AGC_RSP, MASKDWORD, 0x00462911); + + /* One shot, path A LOK & IQK */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("One shot, path A LOK & IQK!\n")); + odm_set_bb_reg(p_dm_odm, REG_IQK_AGC_PTS, MASKDWORD, 0xf9000000); + odm_set_bb_reg(p_dm_odm, REG_IQK_AGC_PTS, MASKDWORD, 0xf8000000); + + /* delay x ms */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_88E)); + /* platform_stall_execution(IQK_DELAY_TIME_88E*1000); */ + ODM_delay_ms(IQK_DELAY_TIME_88E); + + /* Check failed */ + reg_eac = odm_get_bb_reg(p_dm_odm, REG_RX_POWER_AFTER_IQK_A_2, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeac = 0x%x\n", reg_eac)); + reg_e94 = odm_get_bb_reg(p_dm_odm, REG_TX_POWER_BEFORE_IQK_A, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe94 = 0x%x\n", reg_e94)); + reg_e9c = odm_get_bb_reg(p_dm_odm, REG_TX_POWER_AFTER_IQK_A, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe9c = 0x%x\n", reg_e9c)); + reg_ea4 = odm_get_bb_reg(p_dm_odm, REG_RX_POWER_BEFORE_IQK_A_2, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xea4 = 0x%x\n", reg_ea4)); + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && + (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else /* if Tx not OK, ignore Rx */ + return result; + return result; +} + +static u8 /* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ +phy_path_a_rx_iqk( + struct _ADAPTER *p_adapter, + bool config_path_b +) +{ + u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u4tmp; + u8 result = 0x00; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path A Rx IQK!\n")); + + /* 1 Get TXIMR setting */ + /* modify RXIQK mode table */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path-A Rx IQK modify RXIQK mode table!\n")); + odm_set_bb_reg(p_dm_odm, REG_FPGA0_IQK, MASKH3BYTES, 0x000000); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_WE_LUT, RFREGOFFSETMASK, 0x800a0); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_RCK_OS, RFREGOFFSETMASK, 0x30000); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_TXPA_G1, RFREGOFFSETMASK, 0x0000f); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_TXPA_G2, RFREGOFFSETMASK, 0xf117B); + odm_set_bb_reg(p_dm_odm, REG_FPGA0_IQK, MASKH3BYTES, 0x808000); + + /* IQK setting */ + odm_set_bb_reg(p_dm_odm, REG_TX_IQK, MASKDWORD, 0x01007c00); + odm_set_bb_reg(p_dm_odm, REG_RX_IQK, MASKDWORD, 0x81004800); + + /* path-A IQK setting */ + odm_set_bb_reg(p_dm_odm, REG_TX_IQK_TONE_A, MASKDWORD, 0x10008c1c); + odm_set_bb_reg(p_dm_odm, REG_RX_IQK_TONE_A, MASKDWORD, 0x30008c1c); + odm_set_bb_reg(p_dm_odm, REG_TX_IQK_PI_A, MASKDWORD, 0x82160804); + odm_set_bb_reg(p_dm_odm, REG_RX_IQK_PI_A, MASKDWORD, 0x28160000); + + /* LO calibration setting */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LO calibration setting!\n")); + odm_set_bb_reg(p_dm_odm, REG_IQK_AGC_RSP, MASKDWORD, 0x0046a911); + + /* One shot, path A LOK & IQK */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("One shot, path A LOK & IQK!\n")); + odm_set_bb_reg(p_dm_odm, REG_IQK_AGC_PTS, MASKDWORD, 0xf9000000); + odm_set_bb_reg(p_dm_odm, REG_IQK_AGC_PTS, MASKDWORD, 0xf8000000); + + /* delay x ms */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_88E)); + /* platform_stall_execution(IQK_DELAY_TIME_88E*1000); */ + ODM_delay_ms(IQK_DELAY_TIME_88E); + + /* Check failed */ + reg_eac = odm_get_bb_reg(p_dm_odm, REG_RX_POWER_AFTER_IQK_A_2, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeac = 0x%x\n", reg_eac)); + reg_e94 = odm_get_bb_reg(p_dm_odm, REG_TX_POWER_BEFORE_IQK_A, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe94 = 0x%x\n", reg_e94)); + reg_e9c = odm_get_bb_reg(p_dm_odm, REG_TX_POWER_AFTER_IQK_A, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe9c = 0x%x\n", reg_e9c)); + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && + (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else /* if Tx not OK, ignore Rx */ + return result; + + u4tmp = 0x80007C00 | (reg_e94 & 0x3FF0000) | ((reg_e9c & 0x3FF0000) >> 16); + odm_set_bb_reg(p_dm_odm, REG_TX_IQK, MASKDWORD, u4tmp); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe40 = 0x%x u4tmp = 0x%x\n", odm_get_bb_reg(p_dm_odm, REG_TX_IQK, MASKDWORD), u4tmp)); + + /* 1 RX IQK */ + /* modify RXIQK mode table */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path-A Rx IQK modify RXIQK mode table 2!\n")); + odm_set_bb_reg(p_dm_odm, REG_FPGA0_IQK, MASKH3BYTES, 0x000000); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_WE_LUT, RFREGOFFSETMASK, 0x800a0); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_RCK_OS, RFREGOFFSETMASK, 0x30000); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_TXPA_G1, RFREGOFFSETMASK, 0x0000f); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_TXPA_G2, RFREGOFFSETMASK, 0xf7ffa); + odm_set_bb_reg(p_dm_odm, REG_FPGA0_IQK, MASKH3BYTES, 0x808000); + + /* IQK setting */ + odm_set_bb_reg(p_dm_odm, REG_RX_IQK, MASKDWORD, 0x01004800); + + /* path-A IQK setting */ + odm_set_bb_reg(p_dm_odm, REG_TX_IQK_TONE_A, MASKDWORD, 0x30008c1c); + odm_set_bb_reg(p_dm_odm, REG_RX_IQK_TONE_A, MASKDWORD, 0x10008c1c); + odm_set_bb_reg(p_dm_odm, REG_TX_IQK_PI_A, MASKDWORD, 0x82160c05); + odm_set_bb_reg(p_dm_odm, REG_RX_IQK_PI_A, MASKDWORD, 0x28160c05); + + /* LO calibration setting */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LO calibration setting!\n")); + odm_set_bb_reg(p_dm_odm, REG_IQK_AGC_RSP, MASKDWORD, 0x0046a911); + + /* One shot, path A LOK & IQK */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("One shot, path A LOK & IQK!\n")); + odm_set_bb_reg(p_dm_odm, REG_IQK_AGC_PTS, MASKDWORD, 0xf9000000); + odm_set_bb_reg(p_dm_odm, REG_IQK_AGC_PTS, MASKDWORD, 0xf8000000); + + /* delay x ms */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_88E)); + /* platform_stall_execution(IQK_DELAY_TIME_88E*1000); */ + ODM_delay_ms(IQK_DELAY_TIME_88E); + + /* Check failed */ + reg_eac = odm_get_bb_reg(p_dm_odm, REG_RX_POWER_AFTER_IQK_A_2, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeac = 0x%x\n", reg_eac)); + reg_e94 = odm_get_bb_reg(p_dm_odm, REG_TX_POWER_BEFORE_IQK_A, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe94 = 0x%x\n", reg_e94)); + reg_e9c = odm_get_bb_reg(p_dm_odm, REG_TX_POWER_AFTER_IQK_A, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe9c = 0x%x\n", reg_e9c)); + reg_ea4 = odm_get_bb_reg(p_dm_odm, REG_RX_POWER_BEFORE_IQK_A_2, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xea4 = 0x%x\n", reg_ea4)); + + if (!(reg_eac & BIT(27)) && /* if Tx is OK, check whether Rx is OK */ + (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && + (((reg_eac & 0x03FF0000) >> 16) != 0x36)) + result |= 0x02; + else + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path A Rx IQK fail!!\n")); + + return result; +} + +static u8 /* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ +phy_path_b_iqk_8188e( + struct _ADAPTER *p_adapter +) +{ + u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc; + u8 result = 0x00; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path B IQK!\n")); + + /* One shot, path B LOK & IQK */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("One shot, path A LOK & IQK!\n")); + odm_set_bb_reg(p_dm_odm, REG_IQK_AGC_CONT, MASKDWORD, 0x00000002); + odm_set_bb_reg(p_dm_odm, REG_IQK_AGC_CONT, MASKDWORD, 0x00000000); + + /* delay x ms */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("delay %d ms for One shot, path B LOK & IQK.\n", IQK_DELAY_TIME_88E)); + /* platform_stall_execution(IQK_DELAY_TIME_88E*1000); */ + ODM_delay_ms(IQK_DELAY_TIME_88E); + + /* Check failed */ + reg_eac = odm_get_bb_reg(p_dm_odm, REG_RX_POWER_AFTER_IQK_A_2, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeac = 0x%x\n", reg_eac)); + reg_eb4 = odm_get_bb_reg(p_dm_odm, REG_TX_POWER_BEFORE_IQK_B, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeb4 = 0x%x\n", reg_eb4)); + reg_ebc = odm_get_bb_reg(p_dm_odm, REG_TX_POWER_AFTER_IQK_B, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xebc = 0x%x\n", reg_ebc)); + reg_ec4 = odm_get_bb_reg(p_dm_odm, REG_RX_POWER_BEFORE_IQK_B_2, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xec4 = 0x%x\n", reg_ec4)); + reg_ecc = odm_get_bb_reg(p_dm_odm, REG_RX_POWER_AFTER_IQK_B_2, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xecc = 0x%x\n", reg_ecc)); + + if (!(reg_eac & BIT(31)) && + (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && + (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else + return result; + + if (!(reg_eac & BIT(30)) && + (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && + (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) + result |= 0x02; + else + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path B Rx IQK fail!!\n")); + + return result; + +} + +static void _phy_path_a_fill_iqk_matrix( + struct _ADAPTER *p_adapter, + bool is_iqk_ok, + s32 result[][8], + u8 final_candidate, + bool is_tx_only +) +{ + u32 oldval_0, X, TX0_A, reg; + s32 Y, TX0_C; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path A IQ Calibration %s !\n", (is_iqk_ok) ? "Success" : "Failed")); + + if (final_candidate == 0xFF) + return; + + else if (is_iqk_ok) { + oldval_0 = (odm_get_bb_reg(p_dm_odm, REG_OFDM_0_XA_TX_IQ_IMBALANCE, MASKDWORD) >> 22) & 0x3FF; + + X = result[final_candidate][0]; + if ((X & 0x00000200) != 0) + X = X | 0xFFFFFC00; + TX0_A = (X * oldval_0) >> 8; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("X = 0x%x, TX0_A = 0x%x, oldval_0 0x%x\n", X, TX0_A, oldval_0)); + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XA_TX_IQ_IMBALANCE, 0x3FF, TX0_A); + + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_ECCA_THRESHOLD, BIT(31), ((X * oldval_0 >> 7) & 0x1)); + + Y = result[final_candidate][1]; + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + + TX0_C = (Y * oldval_0) >> 8; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Y = 0x%x, TX = 0x%x\n", Y, TX0_C)); + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XC_TX_AFE, 0xF0000000, ((TX0_C & 0x3C0) >> 6)); + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XA_TX_IQ_IMBALANCE, 0x003F0000, (TX0_C & 0x3F)); + + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_ECCA_THRESHOLD, BIT(29), ((Y * oldval_0 >> 7) & 0x1)); + + if (is_tx_only) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_path_a_fill_iqk_matrix only Tx OK\n")); + return; + } + + reg = result[final_candidate][2]; + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XA_RX_IQ_IMBALANCE, 0x3FF, reg); + + reg = result[final_candidate][3] & 0x3F; + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XA_RX_IQ_IMBALANCE, 0xFC00, reg); + + reg = (result[final_candidate][3] >> 6) & 0xF; + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_RX_IQ_EXT_ANTA, 0xF0000000, reg); + } +} + +static void _phy_path_b_fill_iqk_matrix( + struct _ADAPTER *p_adapter, + bool is_iqk_ok, + s32 result[][8], + u8 final_candidate, + bool is_tx_only /* do Tx only */ +) +{ + u32 oldval_1, X, TX1_A, reg; + s32 Y, TX1_C; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path B IQ Calibration %s !\n", (is_iqk_ok) ? "Success" : "Failed")); + + if (final_candidate == 0xFF) + return; + + else if (is_iqk_ok) { + oldval_1 = (odm_get_bb_reg(p_dm_odm, REG_OFDM_0_XB_TX_IQ_IMBALANCE, MASKDWORD) >> 22) & 0x3FF; + + X = result[final_candidate][4]; + if ((X & 0x00000200) != 0) + X = X | 0xFFFFFC00; + TX1_A = (X * oldval_1) >> 8; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("X = 0x%x, TX1_A = 0x%x\n", X, TX1_A)); + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XB_TX_IQ_IMBALANCE, 0x3FF, TX1_A); + + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_ECCA_THRESHOLD, BIT(27), ((X * oldval_1 >> 7) & 0x1)); + + Y = result[final_candidate][5]; + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + + TX1_C = (Y * oldval_1) >> 8; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Y = 0x%x, TX1_C = 0x%x\n", Y, TX1_C)); + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XD_TX_AFE, 0xF0000000, ((TX1_C & 0x3C0) >> 6)); + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XB_TX_IQ_IMBALANCE, 0x003F0000, (TX1_C & 0x3F)); + + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_ECCA_THRESHOLD, BIT(25), ((Y * oldval_1 >> 7) & 0x1)); + + if (is_tx_only) + return; + + reg = result[final_candidate][6]; + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XB_RX_IQ_IMBALANCE, 0x3FF, reg); + + reg = result[final_candidate][7] & 0x3F; + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XB_RX_IQ_IMBALANCE, 0xFC00, reg); + + reg = (result[final_candidate][7] >> 6) & 0xF; + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_AGC_RSSI_TABLE, 0x0000F000, reg); + } +} + +/* + * 2011/07/26 MH Add an API for testing IQK fail case. + * + * MP Already declare in odm.c */ +static bool odm_check_power_status( + struct _ADAPTER *adapter) +{ + return true; +} + +void +_phy_save_adda_registers( + struct _ADAPTER *p_adapter, + u32 *adda_reg, + u32 *adda_backup, + u32 register_num +) +{ + u32 i; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + + if (odm_check_power_status(p_adapter) == false) + return; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Save ADDA parameters.\n")); + for (i = 0 ; i < register_num ; i++) + adda_backup[i] = odm_get_bb_reg(p_dm_odm, adda_reg[i], MASKDWORD); +} + +static void _phy_save_mac_registers( + struct _ADAPTER *p_adapter, + u32 *mac_reg, + u32 *mac_backup +) +{ + u32 i; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Save MAC parameters.\n")); + for (i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++) + mac_backup[i] = odm_read_1byte(p_dm_odm, mac_reg[i]); + mac_backup[i] = odm_read_4byte(p_dm_odm, mac_reg[i]); + +} + +static void _phy_reload_adda_registers( + struct _ADAPTER *p_adapter, + u32 *adda_reg, + u32 *adda_backup, + u32 regiester_num +) +{ + u32 i; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Reload ADDA power saving parameters !\n")); + for (i = 0 ; i < regiester_num; i++) + odm_set_bb_reg(p_dm_odm, adda_reg[i], MASKDWORD, adda_backup[i]); +} + +static void _phy_reload_mac_registers( + struct _ADAPTER *p_adapter, + u32 *mac_reg, + u32 *mac_backup +) +{ + u32 i; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Reload MAC parameters !\n")); + for (i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++) + odm_write_1byte(p_dm_odm, mac_reg[i], (u8)mac_backup[i]); + odm_write_4byte(p_dm_odm, mac_reg[i], mac_backup[i]); +} + +void +_phy_path_adda_on( + struct _ADAPTER *p_adapter, + u32 *adda_reg, + bool is_path_a_on, + bool is2T +) +{ + u32 path_on; + u32 i; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("ADDA ON.\n")); + + path_on = is_path_a_on ? 0x04db25a4 : 0x0b1b25a4; + if (false == is2T) { + path_on = 0x0bdb25a0; + odm_set_bb_reg(p_dm_odm, adda_reg[0], MASKDWORD, 0x0b1b25a0); + } else + odm_set_bb_reg(p_dm_odm, adda_reg[0], MASKDWORD, path_on); + + for (i = 1 ; i < IQK_ADDA_REG_NUM ; i++) + odm_set_bb_reg(p_dm_odm, adda_reg[i], MASKDWORD, path_on); + +} + +void +_phy_mac_setting_calibration( + struct _ADAPTER *p_adapter, + u32 *mac_reg, + u32 *mac_backup +) +{ + u32 i = 0; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("MAC settings for Calibration.\n")); + + odm_write_1byte(p_dm_odm, mac_reg[i], 0x3F); + + for (i = 1 ; i < (IQK_MAC_REG_NUM - 1); i++) + odm_write_1byte(p_dm_odm, mac_reg[i], (u8)(mac_backup[i] & (~BIT(3)))); + odm_write_1byte(p_dm_odm, mac_reg[i], (u8)(mac_backup[i] & (~BIT(5)))); + +} + +void _phy_path_a_stand_by(struct _ADAPTER *p_adapter) +{ + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path-A standby mode!\n")); + + odm_set_bb_reg(p_dm_odm, REG_FPGA0_IQK, MASKH3BYTES, 0x0); + odm_set_bb_reg(p_dm_odm, 0x840, MASKDWORD, 0x00010000); + odm_set_bb_reg(p_dm_odm, REG_FPGA0_IQK, MASKH3BYTES, 0x808000); +} + +static void _phy_pi_mode_switch( + struct _ADAPTER *p_adapter, + bool pi_mode +) +{ + u32 mode; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("BB Switch to %s mode!\n", (pi_mode ? "PI" : "SI"))); + + mode = pi_mode ? 0x01000100 : 0x01000000; + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XA_HSSI_PARAMETER1, MASKDWORD, mode); + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XB_HSSI_PARAMETER1, MASKDWORD, mode); +} + +static bool phy_simularity_compare_8188e( + struct _ADAPTER *p_adapter, + s32 result[][8], + u8 c1, + u8 c2 +) +{ + u32 i, j, diff, simularity_bit_map, bound; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */ + bool is_result = true; + bool is2T = IS_2T2R(p_hal_data->version_id); + + if (is2T) + bound = 8; + else + bound = 4; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("===> IQK:phy_simularity_compare_8188e c1 %d c2 %d!!!\n", c1, c2)); + + simularity_bit_map = 0; + + for (i = 0; i < bound; i++) { + diff = (result[c1][i] > result[c2][i]) ? (result[c1][i] - result[c2][i]) : (result[c2][i] - result[c1][i]); + if (diff > MAX_TOLERANCE) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK:phy_simularity_compare_8188e differnece overflow index %d compare1 0x%x compare2 0x%x!!!\n", i, result[c1][i], result[c2][i])); + + if ((i == 2 || i == 6) && !simularity_bit_map) { + if (result[c1][i] + result[c1][i + 1] == 0) + final_candidate[(i / 4)] = c2; + else if (result[c2][i] + result[c2][i + 1] == 0) + final_candidate[(i / 4)] = c1; + else + simularity_bit_map = simularity_bit_map | (1 << i); + } else + simularity_bit_map = simularity_bit_map | (1 << i); + } + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK:phy_simularity_compare_8188e simularity_bit_map %d !!!\n", simularity_bit_map)); + + if (simularity_bit_map == 0) { + for (i = 0; i < (bound / 4); i++) { + if (final_candidate[i] != 0xFF) { + for (j = i * 4; j < (i + 1) * 4 - 2; j++) + result[3][j] = result[final_candidate[i]][j]; + is_result = false; + } + } + return is_result; + } else if (!(simularity_bit_map & 0x0F)) { /* path A OK */ + for (i = 0; i < 4; i++) + result[3][i] = result[c1][i]; + return false; + } else if (!(simularity_bit_map & 0xF0) && is2T) { /* path B OK */ + for (i = 4; i < 8; i++) + result[3][i] = result[c1][i]; + return false; + } else + return false; + +} + +static void _phy_iq_calibrate_8188e( + struct _ADAPTER *p_adapter, + s32 result[][8], + u8 t, + bool is2T +) +{ + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + u32 i; + u8 path_aok = 0, path_bok = 0; + u32 ADDA_REG[IQK_ADDA_REG_NUM] = { + REG_FPGA0_XCD_SWITCH_CONTROL, REG_BLUE_TOOTH, + REG_RX_WAIT_CCA, REG_TX_CCK_RFON, + REG_TX_CCK_BBON, REG_TX_OFDM_RFON, + REG_TX_OFDM_BBON, REG_TX_TO_RX, + REG_TX_TO_TX, REG_RX_CCK, + REG_RX_OFDM, REG_RX_WAIT_RIFS, + REG_RX_TO_RX, REG_STANDBY, + REG_SLEEP, REG_PMPD_ANAEN + }; + u32 IQK_MAC_REG[IQK_MAC_REG_NUM] = { + REG_TXPAUSE, REG_BCN_CTRL, + REG_BCN_CTRL_1, REG_GPIO_MUXCFG + }; + + /* since 92C & 92D have the different define in IQK_BB_REG */ + u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = { + REG_OFDM_0_TRX_PATH_ENABLE, REG_OFDM_0_TR_MUX_PAR, + REG_FPGA0_XCD_RF_INTERFACE_SW, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B, + REG_FPGA0_XAB_RF_INTERFACE_SW, REG_FPGA0_XA_RF_INTERFACE_OE, + REG_FPGA0_XB_RF_INTERFACE_OE, REG_CCK_0_AFE_SETTING + }; + + u32 retry_count = 2; + + if (p_dm_odm->mp_mode == true) + retry_count = 9; + + /* Note: IQ calibration must be performed after loading */ + /* PHY_REG.txt , and radio_a, radio_b.txt */ + + /* u32 bbvalue; */ + + if (t == 0) { + /* bbvalue = odm_get_bb_reg(p_dm_odm, REG_FPGA0_RFMOD, MASKDWORD); + * RT_DISP(FINIT, INIT_IQK, ("_phy_iq_calibrate_8188e()==>0x%08x\n",bbvalue)); */ + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQ Calibration for %s for %d times\n", (is2T ? "2T2R" : "1T1R"), t)); + + /* Save ADDA parameters, turn path A ADDA on */ + _phy_save_adda_registers(p_adapter, ADDA_REG, p_dm_odm->rf_calibrate_info.ADDA_backup, IQK_ADDA_REG_NUM); + _phy_save_mac_registers(p_adapter, IQK_MAC_REG, p_dm_odm->rf_calibrate_info.IQK_MAC_backup); + _phy_save_adda_registers(p_adapter, IQK_BB_REG_92C, p_dm_odm->rf_calibrate_info.IQK_BB_backup, IQK_BB_REG_NUM); + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQ Calibration for %s for %d times\n", (is2T ? "2T2R" : "1T1R"), t)); + + _phy_path_adda_on(p_adapter, ADDA_REG, true, is2T); + + if (t == 0) + p_dm_odm->rf_calibrate_info.is_rf_pi_enable = (u8)odm_get_bb_reg(p_dm_odm, REG_FPGA0_XA_HSSI_PARAMETER1, BIT(8)); + + if (!p_dm_odm->rf_calibrate_info.is_rf_pi_enable) { + /* Switch BB to PI mode to do IQ Calibration. */ + _phy_pi_mode_switch(p_adapter, true); + } + + /* MAC settings */ + _phy_mac_setting_calibration(p_adapter, IQK_MAC_REG, p_dm_odm->rf_calibrate_info.IQK_MAC_backup); + + /* BB setting */ + /* odm_set_bb_reg(p_dm_odm, REG_FPGA0_RFMOD, BIT24, 0x00); */ + odm_set_bb_reg(p_dm_odm, REG_CCK_0_AFE_SETTING, 0x0f000000, 0xf); + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_TRX_PATH_ENABLE, MASKDWORD, 0x03a05600); + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_TR_MUX_PAR, MASKDWORD, 0x000800e4); + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XCD_RF_INTERFACE_SW, MASKDWORD, 0x22204000); + + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XAB_RF_INTERFACE_SW, BIT(10), 0x01); + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XAB_RF_INTERFACE_SW, BIT(26), 0x01); + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XA_RF_INTERFACE_OE, BIT(10), 0x00); + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XB_RF_INTERFACE_OE, BIT(10), 0x00); + + if (is2T) { + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XA_LSSI_PARAMETER, MASKDWORD, 0x00010000); + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XB_LSSI_PARAMETER, MASKDWORD, 0x00010000); + } + + /* Page B init */ + /* AP or IQK */ + odm_set_bb_reg(p_dm_odm, REG_CONFIG_ANT_A, MASKDWORD, 0x0f600000); + + if (is2T) + odm_set_bb_reg(p_dm_odm, REG_CONFIG_ANT_B, MASKDWORD, 0x0f600000); + + /* IQ calibration setting */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK setting!\n")); + odm_set_bb_reg(p_dm_odm, REG_FPGA0_IQK, MASKH3BYTES, 0x808000); + odm_set_bb_reg(p_dm_odm, REG_TX_IQK, MASKDWORD, 0x01007c00); + odm_set_bb_reg(p_dm_odm, REG_RX_IQK, MASKDWORD, 0x81004800); + + for (i = 0 ; i < retry_count ; i++) { + path_aok = phy_path_a_iqk_8188e(p_adapter, is2T); + /* if(path_aok == 0x03){ */ + if (path_aok == 0x01) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path A Tx IQK Success!!\n")); + result[t][0] = (odm_get_bb_reg(p_dm_odm, REG_TX_POWER_BEFORE_IQK_A, MASKDWORD) & 0x3FF0000) >> 16; + result[t][1] = (odm_get_bb_reg(p_dm_odm, REG_TX_POWER_AFTER_IQK_A, MASKDWORD) & 0x3FF0000) >> 16; + break; + } + } + + for (i = 0 ; i < retry_count ; i++) { + path_aok = phy_path_a_rx_iqk(p_adapter, is2T); + if (path_aok == 0x03) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path A Rx IQK Success!!\n")); + /* result[t][0] = (odm_get_bb_reg(p_dm_odm, REG_TX_POWER_BEFORE_IQK_A, MASKDWORD)&0x3FF0000)>>16; + * result[t][1] = (odm_get_bb_reg(p_dm_odm, REG_TX_POWER_AFTER_IQK_A, MASKDWORD)&0x3FF0000)>>16; */ + result[t][2] = (odm_get_bb_reg(p_dm_odm, REG_RX_POWER_BEFORE_IQK_A_2, MASKDWORD) & 0x3FF0000) >> 16; + result[t][3] = (odm_get_bb_reg(p_dm_odm, REG_RX_POWER_AFTER_IQK_A_2, MASKDWORD) & 0x3FF0000) >> 16; + break; + } else + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path A Rx IQK Fail!!\n")); + } + + if (0x00 == path_aok) + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path A IQK failed!!\n")); + + if (is2T) { + _phy_path_a_stand_by(p_adapter); + + /* Turn path B ADDA on */ + _phy_path_adda_on(p_adapter, ADDA_REG, false, is2T); + + for (i = 0 ; i < retry_count ; i++) { + path_bok = phy_path_b_iqk_8188e(p_adapter); + if (path_bok == 0x03) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path B IQK Success!!\n")); + result[t][4] = (odm_get_bb_reg(p_dm_odm, REG_TX_POWER_BEFORE_IQK_B, MASKDWORD) & 0x3FF0000) >> 16; + result[t][5] = (odm_get_bb_reg(p_dm_odm, REG_TX_POWER_AFTER_IQK_B, MASKDWORD) & 0x3FF0000) >> 16; + result[t][6] = (odm_get_bb_reg(p_dm_odm, REG_RX_POWER_BEFORE_IQK_B_2, MASKDWORD) & 0x3FF0000) >> 16; + result[t][7] = (odm_get_bb_reg(p_dm_odm, REG_RX_POWER_AFTER_IQK_B_2, MASKDWORD) & 0x3FF0000) >> 16; + break; + } else if (i == (retry_count - 1) && path_bok == 0x01) { /* Tx IQK OK */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path B Only Tx IQK Success!!\n")); + result[t][4] = (odm_get_bb_reg(p_dm_odm, REG_TX_POWER_BEFORE_IQK_B, MASKDWORD) & 0x3FF0000) >> 16; + result[t][5] = (odm_get_bb_reg(p_dm_odm, REG_TX_POWER_AFTER_IQK_B, MASKDWORD) & 0x3FF0000) >> 16; + } + } + + if (0x00 == path_bok) + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("path B IQK failed!!\n")); + } + + /* Back to BB mode, load original value */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK:Back to BB mode, load original value!\n")); + odm_set_bb_reg(p_dm_odm, REG_FPGA0_IQK, MASKH3BYTES, 0); + + if (t != 0) { + if (!p_dm_odm->rf_calibrate_info.is_rf_pi_enable) { + /* Switch back BB to SI mode after finish IQ Calibration. */ + _phy_pi_mode_switch(p_adapter, false); + } + + /* Reload ADDA power saving parameters */ + _phy_reload_adda_registers(p_adapter, ADDA_REG, p_dm_odm->rf_calibrate_info.ADDA_backup, IQK_ADDA_REG_NUM); + + /* Reload MAC parameters */ + _phy_reload_mac_registers(p_adapter, IQK_MAC_REG, p_dm_odm->rf_calibrate_info.IQK_MAC_backup); + + _phy_reload_adda_registers(p_adapter, IQK_BB_REG_92C, p_dm_odm->rf_calibrate_info.IQK_BB_backup, IQK_BB_REG_NUM); + + /* Restore RX initial gain */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XA_LSSI_PARAMETER, MASKDWORD, 0x00032ed3); + if (is2T) + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XB_LSSI_PARAMETER, MASKDWORD, 0x00032ed3); + + /* load 0xe30 IQC default value */ + odm_set_bb_reg(p_dm_odm, REG_TX_IQK_TONE_A, MASKDWORD, 0x01008c00); + odm_set_bb_reg(p_dm_odm, REG_RX_IQK_TONE_A, MASKDWORD, 0x01008c00); + + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_iq_calibrate_8188e() <==\n")); + +} + +static void _phy_lc_calibrate_8188e(struct PHY_DM_STRUCT *p_dm_odm, bool is2T) +{ + u8 tmp_reg; + u32 rf_amode = 0, rf_bmode = 0, lc_cal; + struct _ADAPTER *p_adapter = p_dm_odm->adapter; + /* Check continuous TX and Packet TX */ + tmp_reg = odm_read_1byte(p_dm_odm, 0xd03); + + if ((tmp_reg & 0x70) != 0) /* Deal with contisuous TX case */ + odm_write_1byte(p_dm_odm, 0xd03, tmp_reg & 0x8F); /* disable all continuous TX */ + else /* Deal with Packet TX case */ + odm_write_1byte(p_dm_odm, REG_TXPAUSE, 0xFF); /* block all queues */ + + if ((tmp_reg & 0x70) != 0) { + /* 1. Read original RF mode */ + /* path-A */ + rf_amode = phy_query_rf_reg(p_adapter, ODM_RF_PATH_A, RF_AC, MASK12BITS); + + /* path-B */ + if (is2T) + rf_bmode = phy_query_rf_reg(p_adapter, ODM_RF_PATH_B, RF_AC, MASK12BITS); + + /* 2. Set RF mode = standby mode */ + /* path-A */ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_AC, MASK12BITS, (rf_amode & 0x8FFFF) | 0x10000); + + /* path-B */ + if (is2T) + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, RF_AC, MASK12BITS, (rf_bmode & 0x8FFFF) | 0x10000); + } + + /* 3. Read RF reg18 */ + lc_cal = phy_query_rf_reg(p_adapter, ODM_RF_PATH_A, RF_CHNLBW, MASK12BITS); + + /* 4. Set LC calibration begin bit15 */ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_CHNLBW, MASK12BITS, lc_cal | 0x08000); + + ODM_delay_ms(100); + + /* Restore original situation */ + if ((tmp_reg & 0x70) != 0) { /* Deal with contisuous TX case */ + /* path-A */ + odm_write_1byte(p_dm_odm, 0xd03, tmp_reg); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_AC, MASK12BITS, rf_amode); + + /* path-B */ + if (is2T) + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, RF_AC, MASK12BITS, rf_bmode); + } else /* Deal with Packet TX case */ + odm_write_1byte(p_dm_odm, REG_TXPAUSE, 0x00); +} + +/* Analog Pre-distortion calibration */ +#define APK_BB_REG_NUM 8 +#define APK_CURVE_REG_NUM 4 +#define PATH_NUM 2 + +static void _phy_ap_calibrate_8188e( + struct _ADAPTER *p_adapter, + s8 delta, + bool is2T +) +{ + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + u32 reg_d[PATH_NUM]; + u32 tmp_reg, index, offset, apkbound; + u8 path, i, pathbound = PATH_NUM; + u32 BB_backup[APK_BB_REG_NUM]; + u32 BB_REG[APK_BB_REG_NUM] = { + REG_FPGA1_TX_BLOCK, REG_OFDM_0_TRX_PATH_ENABLE, + REG_FPGA0_RFMOD, REG_OFDM_0_TR_MUX_PAR, + REG_FPGA0_XCD_RF_INTERFACE_SW, REG_FPGA0_XAB_RF_INTERFACE_SW, + REG_FPGA0_XA_RF_INTERFACE_OE, REG_FPGA0_XB_RF_INTERFACE_OE + }; + u32 BB_AP_MODE[APK_BB_REG_NUM] = { + 0x00000020, 0x00a05430, 0x02040000, + 0x000800e4, 0x00204000 + }; + u32 BB_normal_AP_MODE[APK_BB_REG_NUM] = { + 0x00000020, 0x00a05430, 0x02040000, + 0x000800e4, 0x22204000 + }; + + u32 AFE_backup[IQK_ADDA_REG_NUM]; + u32 AFE_REG[IQK_ADDA_REG_NUM] = { + REG_FPGA0_XCD_SWITCH_CONTROL, REG_BLUE_TOOTH, + REG_RX_WAIT_CCA, REG_TX_CCK_RFON, + REG_TX_CCK_BBON, REG_TX_OFDM_RFON, + REG_TX_OFDM_BBON, REG_TX_TO_RX, + REG_TX_TO_TX, REG_RX_CCK, + REG_RX_OFDM, REG_RX_WAIT_RIFS, + REG_RX_TO_RX, REG_STANDBY, + REG_SLEEP, REG_PMPD_ANAEN + }; + + u32 MAC_backup[IQK_MAC_REG_NUM]; + u32 MAC_REG[IQK_MAC_REG_NUM] = { + REG_TXPAUSE, REG_BCN_CTRL, + REG_BCN_CTRL_1, REG_GPIO_MUXCFG + }; + + u32 APK_RF_init_value[PATH_NUM][APK_BB_REG_NUM] = { + {0x0852c, 0x1852c, 0x5852c, 0x1852c, 0x5852c}, + {0x2852e, 0x0852e, 0x3852e, 0x0852e, 0x0852e} + }; + + u32 APK_normal_RF_init_value[PATH_NUM][APK_BB_REG_NUM] = { + {0x0852c, 0x0a52c, 0x3a52c, 0x5a52c, 0x5a52c}, /* path settings equal to path b settings */ + {0x0852c, 0x0a52c, 0x5a52c, 0x5a52c, 0x5a52c} + }; + + u32 APK_RF_value_0[PATH_NUM][APK_BB_REG_NUM] = { + {0x52019, 0x52014, 0x52013, 0x5200f, 0x5208d}, + {0x5201a, 0x52019, 0x52016, 0x52033, 0x52050} + }; + + u32 APK_normal_RF_value_0[PATH_NUM][APK_BB_REG_NUM] = { + {0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a}, /* path settings equal to path b settings */ + {0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a} + }; + + u32 AFE_on_off[PATH_NUM] = { + 0x04db25a4, 0x0b1b25a4 + }; /* path A on path B off / path A off path B on */ + + u32 APK_offset[PATH_NUM] = { + REG_CONFIG_ANT_A, REG_CONFIG_ANT_B + }; + + u32 APK_normal_offset[PATH_NUM] = { + REG_CONFIG_PMPD_ANT_A, REG_CONFIG_PMPD_ANT_B + }; + + u32 APK_value[PATH_NUM] = { + 0x92fc0000, 0x12fc0000 + }; + + u32 APK_normal_value[PATH_NUM] = { + 0x92680000, 0x12680000 + }; + + s8 APK_delta_mapping[APK_BB_REG_NUM][13] = { + {-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6}, + {-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6}, + {-6, -4, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6}, + {-1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6}, + {-11, -9, -7, -5, -3, -1, 0, 0, 0, 0, 0, 0, 0} + }; + + u32 APK_normal_setting_value_1[13] = { + 0x01017018, 0xf7ed8f84, 0x1b1a1816, 0x2522201e, 0x322e2b28, + 0x433f3a36, 0x5b544e49, 0x7b726a62, 0xa69a8f84, 0xdfcfc0b3, + 0x12680000, 0x00880000, 0x00880000 + }; + + u32 APK_normal_setting_value_2[16] = { + 0x01c7021d, 0x01670183, 0x01000123, 0x00bf00e2, 0x008d00a3, + 0x0068007b, 0x004d0059, 0x003a0042, 0x002b0031, 0x001f0025, + 0x0017001b, 0x00110014, 0x000c000f, 0x0009000b, 0x00070008, + 0x00050006 + }; + + u32 APK_result[PATH_NUM][APK_BB_REG_NUM]; /* val_1_1a, val_1_2a, val_2a, val_3a, val_4a + * u32 AP_curve[PATH_NUM][APK_CURVE_REG_NUM]; */ + + s32 BB_offset, delta_V, delta_offset; + +#if MP_DRIVER == 1 + PMPT_CONTEXT p_mpt_ctx = &(p_adapter->mppriv.mpt_ctx); + + if (p_dm_odm->mp_mode == true) { + p_mpt_ctx->APK_bound[0] = 45; + p_mpt_ctx->APK_bound[1] = 52; + } +#endif + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("==>_phy_ap_calibrate_8188e() delta %d\n", delta)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("AP Calibration for %s\n", (is2T ? "2T2R" : "1T1R"))); + if (!is2T) + pathbound = 1; + + /* 2 FOR NORMAL CHIP SETTINGS */ + + /* Temporarily do not allow normal driver to do the following settings because these offset + * and value will cause RF internal PA to be unpredictably disabled by HW, such that RF Tx signal + * will disappear after disable/enable card many times on 88CU. RF SD and DD have not find the + * root cause, so we remove these actions temporarily. Added by tynli and SD3 Allen. 2010.05.31. + * #if MP_DRIVER != 1 */ + if (p_dm_odm->mp_mode == false) + return; + /* #endif */ + /* settings adjust for normal chip */ + for (index = 0; index < PATH_NUM; index++) { + APK_offset[index] = APK_normal_offset[index]; + APK_value[index] = APK_normal_value[index]; + AFE_on_off[index] = 0x6fdb25a4; + } + + for (index = 0; index < APK_BB_REG_NUM; index++) { + for (path = 0; path < pathbound; path++) { + APK_RF_init_value[path][index] = APK_normal_RF_init_value[path][index]; + APK_RF_value_0[path][index] = APK_normal_RF_value_0[path][index]; + } + BB_AP_MODE[index] = BB_normal_AP_MODE[index]; + } + + apkbound = 6; + + /* save BB default value */ + for (index = 0; index < APK_BB_REG_NUM ; index++) { + if (index == 0) /* skip */ + continue; + BB_backup[index] = odm_get_bb_reg(p_dm_odm, BB_REG[index], MASKDWORD); + } + + /* save MAC default value */ + _phy_save_mac_registers(p_adapter, MAC_REG, MAC_backup); + + /* save AFE default value */ + _phy_save_adda_registers(p_adapter, AFE_REG, AFE_backup, IQK_ADDA_REG_NUM); + + for (path = 0; path < pathbound; path++) { + if (path == ODM_RF_PATH_A) { + /* path A APK */ + /* load APK setting */ + /* path-A */ + offset = REG_PDP_ANT_A; + for (index = 0; index < 11; index++) { + odm_set_bb_reg(p_dm_odm, offset, MASKDWORD, APK_normal_setting_value_1[index]); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_ap_calibrate_8188e() offset 0x%x value 0x%x\n", offset, odm_get_bb_reg(p_dm_odm, offset, MASKDWORD))); + + offset += 0x04; + } + + odm_set_bb_reg(p_dm_odm, REG_CONFIG_PMPD_ANT_B, MASKDWORD, 0x12680000); + + offset = REG_CONFIG_ANT_A; + for (; index < 13; index++) { + odm_set_bb_reg(p_dm_odm, offset, MASKDWORD, APK_normal_setting_value_1[index]); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_ap_calibrate_8188e() offset 0x%x value 0x%x\n", offset, odm_get_bb_reg(p_dm_odm, offset, MASKDWORD))); + + offset += 0x04; + } + + /* page-B1 */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_IQK, MASKH3BYTES, 0x400000); + + /* path A */ + offset = REG_PDP_ANT_A; + for (index = 0; index < 16; index++) { + odm_set_bb_reg(p_dm_odm, offset, MASKDWORD, APK_normal_setting_value_2[index]); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_ap_calibrate_8188e() offset 0x%x value 0x%x\n", offset, odm_get_bb_reg(p_dm_odm, offset, MASKDWORD))); + + offset += 0x04; + } + odm_set_bb_reg(p_dm_odm, REG_FPGA0_IQK, MASKH3BYTES, 0x000000); + } else if (path == ODM_RF_PATH_B) { + /* path B APK */ + /* load APK setting */ + /* path-B */ + offset = REG_PDP_ANT_B; + for (index = 0; index < 10; index++) { + odm_set_bb_reg(p_dm_odm, offset, MASKDWORD, APK_normal_setting_value_1[index]); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_ap_calibrate_8188e() offset 0x%x value 0x%x\n", offset, odm_get_bb_reg(p_dm_odm, offset, MASKDWORD))); + + offset += 0x04; + } + odm_set_bb_reg(p_dm_odm, REG_CONFIG_PMPD_ANT_A, MASKDWORD, 0x12680000); + phy_set_bb_reg(p_adapter, REG_CONFIG_PMPD_ANT_B, MASKDWORD, 0x12680000); + + offset = REG_CONFIG_ANT_A; + index = 11; + for (; index < 13; index++) { /* offset 0xb68, 0xb6c */ + odm_set_bb_reg(p_dm_odm, offset, MASKDWORD, APK_normal_setting_value_1[index]); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_ap_calibrate_8188e() offset 0x%x value 0x%x\n", offset, odm_get_bb_reg(p_dm_odm, offset, MASKDWORD))); + + offset += 0x04; + } + + /* page-B1 */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_IQK, MASKH3BYTES, 0x400000); + + /* path B */ + offset = 0xb60; + for (index = 0; index < 16; index++) { + odm_set_bb_reg(p_dm_odm, offset, MASKDWORD, APK_normal_setting_value_2[index]); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_ap_calibrate_8188e() offset 0x%x value 0x%x\n", offset, odm_get_bb_reg(p_dm_odm, offset, MASKDWORD))); + + offset += 0x04; + } + odm_set_bb_reg(p_dm_odm, REG_FPGA0_IQK, MASKH3BYTES, 0); + } + + /* save RF default value */ + reg_d[path] = phy_query_rf_reg(p_adapter, path, RF_TXBIAS_A, MASKDWORD); + + /* path A AFE all on, path B AFE All off or vise versa */ + for (index = 0; index < IQK_ADDA_REG_NUM ; index++) + odm_set_bb_reg(p_dm_odm, AFE_REG[index], MASKDWORD, AFE_on_off[path]); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_ap_calibrate_8188e() offset 0xe70 %x\n", odm_get_bb_reg(p_dm_odm, REG_RX_WAIT_CCA, MASKDWORD))); + + /* BB to AP mode */ + if (path == 0) { + for (index = 0; index < APK_BB_REG_NUM ; index++) { + + if (index == 0) /* skip */ + continue; + else if (index < 5) + odm_set_bb_reg(p_dm_odm, BB_REG[index], MASKDWORD, BB_AP_MODE[index]); + else if (BB_REG[index] == 0x870) + odm_set_bb_reg(p_dm_odm, BB_REG[index], MASKDWORD, BB_backup[index] | BIT(10) | BIT(26)); + else + odm_set_bb_reg(p_dm_odm, BB_REG[index], BIT(10), 0x0); + } + + odm_set_bb_reg(p_dm_odm, REG_TX_IQK_TONE_A, MASKDWORD, 0x01008c00); + odm_set_bb_reg(p_dm_odm, REG_RX_IQK_TONE_A, MASKDWORD, 0x01008c00); + } else { /* path B */ + odm_set_bb_reg(p_dm_odm, REG_TX_IQK_TONE_B, MASKDWORD, 0x01008c00); + odm_set_bb_reg(p_dm_odm, REG_RX_IQK_TONE_B, MASKDWORD, 0x01008c00); + + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_ap_calibrate_8188e() offset 0x800 %x\n", odm_get_bb_reg(p_dm_odm, 0x800, MASKDWORD))); + + /* MAC settings */ + _phy_mac_setting_calibration(p_adapter, MAC_REG, MAC_backup); + + if (path == ODM_RF_PATH_A) /* path B to standby mode */ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, RF_AC, MASKDWORD, 0x10000); + else { /* path A to standby mode */ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_AC, MASKDWORD, 0x10000); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_MODE1, MASKDWORD, 0x1000f); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_MODE2, MASKDWORD, 0x20103); + } + + delta_offset = ((delta + 14) / 2); + if (delta_offset < 0) + delta_offset = 0; + else if (delta_offset > 12) + delta_offset = 12; + + /* AP calibration */ + for (index = 0; index < APK_BB_REG_NUM; index++) { + if (index != 1) /* only DO PA11+PAD01001, AP RF setting */ + continue; + + tmp_reg = APK_RF_init_value[path][index]; + if (!p_dm_odm->rf_calibrate_info.is_apk_thermal_meter_ignore) { + BB_offset = (tmp_reg & 0xF0000) >> 16; + + if (!(tmp_reg & BIT(15))) /* sign bit 0 */ + BB_offset = -BB_offset; + + delta_V = APK_delta_mapping[index][delta_offset]; + + BB_offset += delta_V; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_ap_calibrate_8188e() APK index %d tmp_reg 0x%x delta_V %d delta_offset %d\n", index, tmp_reg, delta_V, delta_offset)); + + if (BB_offset < 0) { + tmp_reg = tmp_reg & (~BIT(15)); + BB_offset = -BB_offset; + } else + tmp_reg = tmp_reg | BIT(15); + tmp_reg = (tmp_reg & 0xFFF0FFFF) | (BB_offset << 16); + } + odm_set_rf_reg(p_dm_odm, (enum odm_rf_radio_path_e)path, RF_IPA_A, MASKDWORD, 0x8992e); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_ap_calibrate_8188e() offset 0xc %x\n", phy_query_rf_reg(p_adapter, path, RF_IPA_A, MASKDWORD))); + odm_set_rf_reg(p_dm_odm, (enum odm_rf_radio_path_e)path, RF_AC, MASKDWORD, APK_RF_value_0[path][index]); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_ap_calibrate_8188e() offset 0x0 %x\n", phy_query_rf_reg(p_adapter, path, RF_AC, MASKDWORD))); + odm_set_rf_reg(p_dm_odm, (enum odm_rf_radio_path_e)path, RF_TXBIAS_A, MASKDWORD, tmp_reg); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_ap_calibrate_8188e() offset 0xd %x\n", phy_query_rf_reg(p_adapter, path, RF_TXBIAS_A, MASKDWORD))); + + /* PA11+PAD01111, one shot */ + i = 0; + do { + odm_set_bb_reg(p_dm_odm, REG_FPGA0_IQK, MASKH3BYTES, 0x800000); + { + odm_set_bb_reg(p_dm_odm, APK_offset[path], MASKDWORD, APK_value[0]); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_ap_calibrate_8188e() offset 0x%x value 0x%x\n", APK_offset[path], odm_get_bb_reg(p_dm_odm, APK_offset[path], MASKDWORD))); + ODM_delay_ms(3); + odm_set_bb_reg(p_dm_odm, APK_offset[path], MASKDWORD, APK_value[1]); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_ap_calibrate_8188e() offset 0x%x value 0x%x\n", APK_offset[path], odm_get_bb_reg(p_dm_odm, APK_offset[path], MASKDWORD))); + + ODM_delay_ms(20); + } + odm_set_bb_reg(p_dm_odm, REG_FPGA0_IQK, MASKH3BYTES, 0x000000); + + if (path == ODM_RF_PATH_A) + tmp_reg = odm_get_bb_reg(p_dm_odm, REG_APK, 0x03E00000); + else + tmp_reg = odm_get_bb_reg(p_dm_odm, REG_APK, 0xF8000000); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_phy_ap_calibrate_8188e() offset 0xbd8[25:21] %x\n", tmp_reg)); + + i++; + } while (tmp_reg > apkbound && i < 4); + + APK_result[path][index] = tmp_reg; + } + } + + /* reload MAC default value */ + _phy_reload_mac_registers(p_adapter, MAC_REG, MAC_backup); + + /* reload BB default value */ + for (index = 0; index < APK_BB_REG_NUM ; index++) { + + if (index == 0) /* skip */ + continue; + odm_set_bb_reg(p_dm_odm, BB_REG[index], MASKDWORD, BB_backup[index]); + } + + /* reload AFE default value */ + _phy_reload_adda_registers(p_adapter, AFE_REG, AFE_backup, IQK_ADDA_REG_NUM); + + /* reload RF path default value */ + for (path = 0; path < pathbound; path++) { + odm_set_rf_reg(p_dm_odm, (enum odm_rf_radio_path_e)path, 0xd, MASKDWORD, reg_d[path]); + if (path == ODM_RF_PATH_B) { + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_MODE1, MASKDWORD, 0x1000f); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_MODE2, MASKDWORD, 0x20101); + } + + /* note no index == 0 */ + if (APK_result[path][1] > 6) + APK_result[path][1] = 6; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("apk path %d result %d 0x%x \t", path, 1, APK_result[path][1])); + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("\n")); + + for (path = 0; path < pathbound; path++) { + odm_set_rf_reg(p_dm_odm, (enum odm_rf_radio_path_e)path, 0x3, MASKDWORD, + ((APK_result[path][1] << 15) | (APK_result[path][1] << 10) | (APK_result[path][1] << 5) | APK_result[path][1])); + if (path == ODM_RF_PATH_A) + odm_set_rf_reg(p_dm_odm, (enum odm_rf_radio_path_e)path, 0x4, MASKDWORD, + ((APK_result[path][1] << 15) | (APK_result[path][1] << 10) | (0x00 << 5) | 0x05)); + else + odm_set_rf_reg(p_dm_odm, (enum odm_rf_radio_path_e)path, 0x4, MASKDWORD, + ((APK_result[path][1] << 15) | (APK_result[path][1] << 10) | (0x02 << 5) | 0x05)); + odm_set_rf_reg(p_dm_odm, (enum odm_rf_radio_path_e)path, RF_BS_PA_APSET_G9_G11, MASKDWORD, + ((0x08 << 15) | (0x08 << 10) | (0x08 << 5) | 0x08)); + } + + p_dm_odm->rf_calibrate_info.is_ap_kdone = true; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("<==_phy_ap_calibrate_8188e()\n")); +} + +#define DP_BB_REG_NUM 7 +#define DP_RF_REG_NUM 1 +#define DP_RETRY_LIMIT 10 +#define DP_PATH_NUM 2 +#define DP_DPK_NUM 3 +#define DP_DPK_VALUE_NUM 2 + +void +phy_iq_calibrate_8188e( + struct _ADAPTER *p_adapter, + bool is_recovery +) +{ + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + +#if (MP_DRIVER == 1) + PMPT_CONTEXT p_mpt_ctx = &(p_adapter->mppriv.mpt_ctx); +#endif/* (MP_DRIVER == 1) */ + + s32 result[4][8]; /* last is final result */ + u8 i, final_candidate, indexforchannel; + u8 channel_to_iqk = 7; + bool is_patha_ok, is_pathb_ok; + s32 rege94, rege9c, regea4, regeac, regeb4, regebc, regec4, regecc, reg_tmp = 0; + bool is12simular, is13simular, is23simular; + bool is_start_cont_tx = false, is_single_tone = false, is_carrier_suppression = false; + u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = { + REG_OFDM_0_XA_RX_IQ_IMBALANCE, REG_OFDM_0_XB_RX_IQ_IMBALANCE, + REG_OFDM_0_ECCA_THRESHOLD, REG_OFDM_0_AGC_RSSI_TABLE, + REG_OFDM_0_XA_TX_IQ_IMBALANCE, REG_OFDM_0_XB_TX_IQ_IMBALANCE, + REG_OFDM_0_XC_TX_AFE, REG_OFDM_0_XD_TX_AFE, + REG_OFDM_0_RX_IQ_EXT_ANTA + }; + u32 start_time; + s32 progressing_time; + + if (odm_check_power_status(p_adapter) == false) + return; + + if (!(p_dm_odm->support_ability & ODM_RF_CALIBRATION)) + return; + +#if MP_DRIVER == 1 + if (p_dm_odm->mp_mode == true) { + is_start_cont_tx = p_mpt_ctx->is_start_cont_tx; + is_single_tone = p_mpt_ctx->is_single_tone; + is_carrier_suppression = p_mpt_ctx->is_carrier_suppression; + } +#endif + + /* 20120213 Turn on when continuous Tx to pass lab testing. (required by Edlu) */ + if (is_single_tone || is_carrier_suppression) + return; + +#if DISABLE_BB_RF + return; +#endif + + if (p_dm_odm->rf_calibrate_info.is_iqk_in_progress) + return; + + if (is_recovery) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("phy_iq_calibrate_8188e: Return due to is_recovery!\n")); + _phy_reload_adda_registers(p_adapter, IQK_BB_REG_92C, p_dm_odm->rf_calibrate_info.IQK_BB_backup_recover, 9); + return; + } + + odm_acquire_spin_lock(p_dm_odm, RT_IQK_SPINLOCK); + p_dm_odm->rf_calibrate_info.is_iqk_in_progress = true; + odm_release_spin_lock(p_dm_odm, RT_IQK_SPINLOCK); + + start_time = odm_get_current_time(p_dm_odm); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK:Start!!!\n")); + + for (i = 0; i < 8; i++) { + result[0][i] = 0; + result[1][i] = 0; + result[2][i] = 0; + result[3][i] = 0; + } + final_candidate = 0xff; + is_patha_ok = false; + is_pathb_ok = false; + is12simular = false; + is23simular = false; + is13simular = false; + + for (i = 0; i < 3; i++) { + /* For 88C 1T1R */ + _phy_iq_calibrate_8188e(p_adapter, result, i, false); + + if (i == 1) { + is12simular = phy_simularity_compare_8188e(p_adapter, result, 0, 1); + if (is12simular) { + final_candidate = 0; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK: is12simular final_candidate is %x\n", final_candidate)); + break; + } + } + + if (i == 2) { + is13simular = phy_simularity_compare_8188e(p_adapter, result, 0, 2); + if (is13simular) { + final_candidate = 0; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK: is13simular final_candidate is %x\n", final_candidate)); + + break; + } + is23simular = phy_simularity_compare_8188e(p_adapter, result, 1, 2); + if (is23simular) { + final_candidate = 1; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK: is23simular final_candidate is %x\n", final_candidate)); + } else { + for (i = 0; i < 8; i++) + reg_tmp += result[3][i]; + + if (reg_tmp != 0) + final_candidate = 3; + else + final_candidate = 0xFF; + } + } + } + /* RT_TRACE(COMP_INIT,DBG_LOUD,("Release Mutex in IQCalibrate\n")); */ + + for (i = 0; i < 4; i++) { + rege94 = result[i][0]; + rege9c = result[i][1]; + regea4 = result[i][2]; + regeac = result[i][3]; + regeb4 = result[i][4]; + regebc = result[i][5]; + regec4 = result[i][6]; + regecc = result[i][7]; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK: rege94=%x rege9c=%x regea4=%x regeac=%x regeb4=%x regebc=%x regec4=%x regecc=%x\n ", rege94, rege9c, regea4, regeac, regeb4, regebc, regec4, regecc)); + } + + if (final_candidate != 0xff) { + p_dm_odm->rf_calibrate_info.rege94 = rege94 = result[final_candidate][0]; + p_dm_odm->rf_calibrate_info.rege9c = rege9c = result[final_candidate][1]; + regea4 = result[final_candidate][2]; + regeac = result[final_candidate][3]; + p_dm_odm->rf_calibrate_info.regeb4 = regeb4 = result[final_candidate][4]; + p_dm_odm->rf_calibrate_info.regebc = regebc = result[final_candidate][5]; + regec4 = result[final_candidate][6]; + regecc = result[final_candidate][7]; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK: final_candidate is %x\n", final_candidate)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK: rege94=%x rege9c=%x regea4=%x regeac=%x regeb4=%x regebc=%x regec4=%x regecc=%x\n ", rege94, rege9c, regea4, regeac, regeb4, regebc, regec4, regecc)); + is_patha_ok = is_pathb_ok = true; + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK: FAIL use default value\n")); + + p_dm_odm->rf_calibrate_info.rege94 = p_dm_odm->rf_calibrate_info.regeb4 = 0x100; /* X default value */ + p_dm_odm->rf_calibrate_info.rege9c = p_dm_odm->rf_calibrate_info.regebc = 0x0; /* Y default value */ + } + + if ((rege94 != 0)/*&&(regea4 != 0)*/) { + _phy_path_a_fill_iqk_matrix(p_adapter, is_patha_ok, result, final_candidate, (regea4 == 0)); + } + + indexforchannel = odm_get_right_chnl_place_for_iqk(*p_dm_odm->p_channel); + + /* To Fix BSOD when final_candidate is 0xff + * by sherry 20120321 */ + if (final_candidate < 4) { + for (i = 0; i < iqk_matrix_reg_num; i++) + p_dm_odm->rf_calibrate_info.iqk_matrix_reg_setting[indexforchannel].value[0][i] = result[final_candidate][i]; + p_dm_odm->rf_calibrate_info.iqk_matrix_reg_setting[indexforchannel].is_iqk_done = true; + } + /* RT_DISP(FINIT, INIT_IQK, ("\nIQK OK indexforchannel %d.\n", indexforchannel)); */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("\nIQK OK indexforchannel %d.\n", indexforchannel)); + + _phy_save_adda_registers(p_adapter, IQK_BB_REG_92C, p_dm_odm->rf_calibrate_info.IQK_BB_backup_recover, 9); + + odm_acquire_spin_lock(p_dm_odm, RT_IQK_SPINLOCK); + p_dm_odm->rf_calibrate_info.is_iqk_in_progress = false; + odm_release_spin_lock(p_dm_odm, RT_IQK_SPINLOCK); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK finished\n")); + progressing_time = odm_get_progressing_time(p_dm_odm, start_time); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK progressing_time = %d\n", progressing_time)); + +} + +void +phy_lc_calibrate_8188e( + void *p_dm_void +) +{ + bool is_start_cont_tx = false, is_single_tone = false, is_carrier_suppression = false; + u32 timeout = 2000, timecount = 0; + u32 start_time; + s32 progressing_time; + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + struct _ADAPTER *p_adapter = p_dm_odm->adapter; + /* HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); */ + +#if (MP_DRIVER == 1) + PMPT_CONTEXT p_mpt_ctx = &(p_adapter->mppriv.mpt_ctx); + + if (p_dm_odm->mp_mode == true) { + is_start_cont_tx = p_mpt_ctx->is_start_cont_tx; + is_single_tone = p_mpt_ctx->is_single_tone; + is_carrier_suppression = p_mpt_ctx->is_carrier_suppression; + } +#endif + +#if DISABLE_BB_RF + return; +#endif + + if (!(p_dm_odm->support_ability & ODM_RF_CALIBRATION)) + return; + /* 20120213 Turn on when continuous Tx to pass lab testing. (required by Edlu) */ + if (is_single_tone || is_carrier_suppression) + return; + + start_time = odm_get_current_time(p_dm_odm); + while (*(p_dm_odm->p_is_scan_in_process) && timecount < timeout) { + ODM_delay_ms(50); + timecount += 50; + } + + p_dm_odm->rf_calibrate_info.is_lck_in_progress = true; + + /* ODM_RT_TRACE(p_dm_odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LCK:Start!!!interface %d currentband %x delay %d ms\n", p_dm_odm->interface_index, p_hal_data->CurrentBandType92D, timecount)); */ + _phy_lc_calibrate_8188e(p_dm_odm, false); + + p_dm_odm->rf_calibrate_info.is_lck_in_progress = false; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LCK:Finish!!!interface %d\n", p_dm_odm->interface_index)); + progressing_time = odm_get_progressing_time(p_dm_odm, start_time); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LCK progressing_time = %d\n", progressing_time)); +} + +static void _phy_set_rf_path_switch_8188e( + struct _ADAPTER *p_adapter, + bool is_main, + bool is2T +) +{ + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + + if (!rtw_is_hw_init_completed(p_adapter)) { + u8 u1b_tmp; + u1b_tmp = odm_read_1byte(p_dm_odm, REG_LEDCFG2) | BIT(7); + odm_write_1byte(p_dm_odm, REG_LEDCFG2, u1b_tmp); + /* odm_set_bb_reg(p_dm_odm, REG_LEDCFG0, BIT23, 0x01); */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XAB_RF_PARAMETER, BIT(13), 0x01); + } + + if (is2T) { /* 92C */ + if (is_main) + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XB_RF_INTERFACE_OE, BIT(5) | BIT6, 0x1); /* 92C_Path_A */ + else + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XB_RF_INTERFACE_OE, BIT(5) | BIT6, 0x2); /* BT */ + } else { /* 88C */ + + /* <20120504, Kordan> [8188E] We should make AntDiversity controlled by HW (0x870[9:8] = 0), */ + /* otherwise the following action has no effect. (0x860[9:8] has the effect only if AntDiversity controlled by SW) */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XAB_RF_INTERFACE_SW, BIT(8) | BIT(9), 0x0); + odm_set_bb_reg(p_dm_odm, 0x914, MASKLWORD, 0x0201); /* Set up the ant mapping table */ + + if (is_main) { + /* odm_set_bb_reg(p_dm_odm, REG_FPGA0_XA_RF_INTERFACE_OE, BIT(8)|BIT9, 0x2); */ /* Tx Main (SW control)(The right antenna) */ + /* 4 [ Tx ] */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XA_RF_INTERFACE_OE, BIT(14) | BIT13 | BIT12, 0x1); /* Tx Main (HW control)(The right antenna) */ + + /* 4 [ Rx ] */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XB_RF_INTERFACE_OE, BIT(5) | BIT4 | BIT3, 0x1); /* ant_div_type = TRDiv, right antenna */ + if (p_dm_odm->ant_div_type == CGCS_RX_HW_ANTDIV) + odm_set_bb_reg(p_dm_odm, REG_CONFIG_RAM64X16, BIT(31), 0x1); /* RxCG, Default is RxCG. ant_div_type = 2RDiv, left antenna */ + + } else { + /* odm_set_bb_reg(p_dm_odm, REG_FPGA0_XA_RF_INTERFACE_OE, BIT(8)|BIT9, 0x1); */ /* Tx Aux (SW control)(The left antenna) */ + /* 4 [ Tx ] */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XA_RF_INTERFACE_OE, BIT(14) | BIT13 | BIT12, 0x0); /* Tx Aux (HW control)(The left antenna) */ + + /* 4 [ Rx ] */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XB_RF_INTERFACE_OE, BIT(5) | BIT4 | BIT3, 0x0); /* ant_div_type = TRDiv, left antenna */ + if (p_dm_odm->ant_div_type == CGCS_RX_HW_ANTDIV) + odm_set_bb_reg(p_dm_odm, REG_CONFIG_RAM64X16, BIT(31), 0x0); /* RxCS, ant_div_type = 2RDiv, right antenna */ + } + + } +} +void phy_set_rf_path_switch_8188e( + struct _ADAPTER *p_adapter, + bool is_main +) +{ + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + +#if DISABLE_BB_RF + return; +#endif + + { + /* For 88C 1T1R */ + _phy_set_rf_path_switch_8188e(p_adapter, is_main, false); + } +} + + diff --git a/drivers/staging/rtl8188eu/hal/halphyrf_8188e_ce.h b/drivers/staging/rtl8188eu/hal/halphyrf_8188e_ce.h new file mode 100644 index 000000000000..bd40705904c4 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/halphyrf_8188e_ce.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __HAL_PHY_RF_8188E_H__ +#define __HAL_PHY_RF_8188E_H__ + +/*--------------------------Define Parameters-------------------------------*/ +#define IQK_DELAY_TIME_88E 10 /* ms */ +#define index_mapping_NUM_88E 15 +#define AVG_THERMAL_NUM_88E 4 + +#include "halphyrf_ce.h" + +void configure_txpower_track_8188e( + struct _TXPWRTRACK_CFG *p_config +); + +void +get_delta_swing_table_8188e( + void *p_dm_void, + u8 **temperature_up_a, + u8 **temperature_down_a, + u8 **temperature_up_b, + u8 **temperature_down_b +); + +void do_iqk_8188e( + void *p_dm_void, + u8 delta_thermal_index, + u8 thermal_value, + u8 threshold +); + +void +odm_tx_pwr_track_set_pwr88_e( + void *p_dm_void, + enum pwrtrack_method method, + u8 rf_path, + u8 channel_mapped_index +); + +/* 1 7. IQK */ + +void +phy_iq_calibrate_8188e( + struct _ADAPTER *adapter, + bool is_recovery); + +/* + * LC calibrate + * */ +void +phy_lc_calibrate_8188e( + void *p_dm_void +); + +void +phy_digital_predistortion_8188e(struct _ADAPTER *p_adapter); + + +void +_phy_save_adda_registers( + struct _ADAPTER *p_adapter, + u32 *adda_reg, + u32 *adda_backup, + u32 register_num +); + +void +_phy_path_adda_on( + struct _ADAPTER *p_adapter, + u32 *adda_reg, + bool is_path_a_on, + bool is2T +); + +void +_phy_mac_setting_calibration( + struct _ADAPTER *p_adapter, + u32 *mac_reg, + u32 *mac_backup +); + + +void +_phy_path_a_stand_by( + struct _ADAPTER *p_adapter +); + + +#endif /* #ifndef __HAL_PHY_RF_8188E_H__ */ diff --git a/drivers/staging/rtl8188eu/hal/halphyrf_ap.h b/drivers/staging/rtl8188eu/hal/halphyrf_ap.h new file mode 100644 index 000000000000..065fe30dadf5 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/halphyrf_ap.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __HAL_PHY_RF_H__ +#define __HAL_PHY_RF_H__ + +#include "phydm_powertracking_ap.h" + +enum pwrtrack_method { + BBSWING, + TXAGC, + MIX_MODE, + TSSI_MODE +}; + +typedef void (*func_set_pwr)(void *, enum pwrtrack_method, u8, u8); +typedef void(*func_iqk)(void *, u8, u8, u8); +typedef void (*func_lck)(void *); +/* refine by YuChen for 8814A */ +typedef void (*func_swing)(void *, u8 **, u8 **, u8 **, u8 **); +typedef void (*func_swing8814only)(void *, u8 **, u8 **, u8 **, u8 **); +typedef void (*func_all_swing)(void *, u8 **, u8 **, u8 **, u8 **, u8 **, u8 **, u8 **, u8 **); + + +struct _TXPWRTRACK_CFG { + u8 swing_table_size_cck; + u8 swing_table_size_ofdm; + u8 threshold_iqk; + u8 threshold_dpk; + u8 average_thermal_num; + u8 rf_path_count; + u32 thermal_reg_addr; + func_set_pwr odm_tx_pwr_track_set_pwr; + func_iqk do_iqk; + func_lck phy_lc_calibrate; + func_swing get_delta_swing_table; + func_swing8814only get_delta_swing_table8814only; + func_all_swing get_delta_all_swing_table; +}; + +void +configure_txpower_track( + void *p_dm_void, + struct _TXPWRTRACK_CFG *p_config +); + +void +odm_txpowertracking_callback_thermal_meter( + struct _ADAPTER *adapter +); + +#if ODM_IC_11AC_SERIES_SUPPORT +void +odm_txpowertracking_callback_thermal_meter_jaguar_series( + struct _ADAPTER *adapter +); + +#define IS_CCK_RATE(_rate) (ODM_MGN_1M == _rate || _rate == ODM_MGN_2M || _rate == ODM_MGN_5_5M || _rate == ODM_MGN_11M) + + +#define ODM_TARGET_CHNL_NUM_2G_5G 59 + +void +odm_reset_iqk_result( + void *p_dm_void +); +u8 +odm_get_right_chnl_place_for_iqk( + u8 chnl +); + +void phydm_rf_init(void *p_dm_void); +void phydm_rf_watchdog(void *p_dm_void); + +#endif /* #ifndef __HAL_PHY_RF_H__ */ diff --git a/drivers/staging/rtl8188eu/hal/halphyrf_ce.c b/drivers/staging/rtl8188eu/hal/halphyrf_ce.c new file mode 100644 index 000000000000..d5737272dee9 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/halphyrf_ce.c @@ -0,0 +1,635 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#include "mp_precomp.h" +#include "phydm_precomp.h" + +#define CALCULATE_SWINGTALBE_OFFSET(_offset, _direction, _size, _delta_thermal) \ + do {\ + for (_offset = 0; _offset < _size; _offset++) { \ + \ + if (_delta_thermal < thermal_threshold[_direction][_offset]) { \ + \ + if (_offset != 0)\ + _offset--;\ + break;\ + } \ + } \ + if (_offset >= _size)\ + _offset = _size-1;\ + } while (0) + +void configure_txpower_track( + void *p_dm_void, + struct _TXPWRTRACK_CFG *p_config +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (p_dm_odm->support_ic_type == ODM_RTL8188E) + configure_txpower_track_8188e(p_config); +} + +/* ********************************************************************** + * <20121113, Kordan> This function should be called when tx_agc changed. + * Otherwise the previous compensation is gone, because we record the + * delta of temperature between two TxPowerTracking watch dogs. + * + * NOTE: If Tx BB swing or Tx scaling is varified during run-time, still + * need to call this function. + * ********************************************************************** */ +void +odm_clear_txpowertracking_state( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + PHAL_DATA_TYPE p_hal_data = GET_HAL_DATA(p_dm_odm->adapter); + u8 p = 0; + struct odm_rf_calibration_structure *p_rf_calibrate_info = &(p_dm_odm->rf_calibrate_info); + + p_rf_calibrate_info->bb_swing_idx_cck_base = p_rf_calibrate_info->default_cck_index; + p_rf_calibrate_info->bb_swing_idx_cck = p_rf_calibrate_info->default_cck_index; + p_dm_odm->rf_calibrate_info.CCK_index = 0; + + for (p = ODM_RF_PATH_A; p < MAX_RF_PATH; ++p) { + p_rf_calibrate_info->bb_swing_idx_ofdm_base[p] = p_rf_calibrate_info->default_ofdm_index; + p_rf_calibrate_info->bb_swing_idx_ofdm[p] = p_rf_calibrate_info->default_ofdm_index; + p_rf_calibrate_info->OFDM_index[p] = p_rf_calibrate_info->default_ofdm_index; + + p_rf_calibrate_info->power_index_offset[p] = 0; + p_rf_calibrate_info->delta_power_index[p] = 0; + p_rf_calibrate_info->delta_power_index_last[p] = 0; + + p_rf_calibrate_info->absolute_ofdm_swing_idx[p] = 0; /* Initial Mix mode power tracking*/ + p_rf_calibrate_info->remnant_ofdm_swing_idx[p] = 0; + p_rf_calibrate_info->kfree_offset[p] = 0; + } + + p_rf_calibrate_info->modify_tx_agc_flag_path_a = false; /*Initial at Modify Tx Scaling mode*/ + p_rf_calibrate_info->modify_tx_agc_flag_path_b = false; /*Initial at Modify Tx Scaling mode*/ + p_rf_calibrate_info->modify_tx_agc_flag_path_c = false; /*Initial at Modify Tx Scaling mode*/ + p_rf_calibrate_info->modify_tx_agc_flag_path_d = false; /*Initial at Modify Tx Scaling mode*/ + p_rf_calibrate_info->remnant_cck_swing_idx = 0; + p_rf_calibrate_info->thermal_value = p_hal_data->eeprom_thermal_meter; + + p_rf_calibrate_info->modify_tx_agc_value_cck = 0; /* modify by Mingzhi.Guo */ + p_rf_calibrate_info->modify_tx_agc_value_ofdm = 0; /* modify by Mingzhi.Guo */ + +} + +void +odm_txpowertracking_callback_thermal_meter( + struct _ADAPTER *adapter +) +{ + + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(adapter); + struct PHY_DM_STRUCT *p_dm_odm = &p_hal_data->odmpriv; + struct odm_rf_calibration_structure *p_rf_calibrate_info = &(p_dm_odm->rf_calibrate_info); + u8 thermal_value = 0, delta, delta_LCK, delta_IQK, p = 0, i = 0; + s8 diff_DPK[4] = {0}; + u8 thermal_value_avg_count = 0; + u32 thermal_value_avg = 0, regc80, regcd0, regcd4, regab4; + u8 OFDM_min_index = 0; /* OFDM BB Swing should be less than +3.0dB, which is required by Arthur */ + u8 indexforchannel = 0; /* get_right_chnl_place_for_iqk(p_hal_data->current_channel) */ + u8 power_tracking_type = p_hal_data->rf_power_tracking_type; + u8 xtal_offset_eanble = 0; + struct _TXPWRTRACK_CFG c; + /* 4 1. The following TWO tables decide the final index of OFDM/CCK swing table. */ + u8 *delta_swing_table_idx_tup_a = NULL; + u8 *delta_swing_table_idx_tdown_a = NULL; + u8 *delta_swing_table_idx_tup_b = NULL; + u8 *delta_swing_table_idx_tdown_b = NULL; + /*for 8814 add by Yu Chen*/ + u8 *delta_swing_table_idx_tup_c = NULL; + u8 *delta_swing_table_idx_tdown_c = NULL; + u8 *delta_swing_table_idx_tup_d = NULL; + u8 *delta_swing_table_idx_tdown_d = NULL; + /*for Xtal Offset by James.Tung*/ + s8 *delta_swing_table_xtal_up = NULL; + s8 *delta_swing_table_xtal_down = NULL; + + /* 4 2. Initilization ( 7 steps in total ) */ + + configure_txpower_track(p_dm_odm, &c); + + (*c.get_delta_swing_table)(p_dm_odm, (u8 **)&delta_swing_table_idx_tup_a, (u8 **)&delta_swing_table_idx_tdown_a, + (u8 **)&delta_swing_table_idx_tup_b, (u8 **)&delta_swing_table_idx_tdown_b); + + if (p_dm_odm->support_ic_type & ODM_RTL8814A) /*for 8814 path C & D*/ + (*c.get_delta_swing_table8814only)(p_dm_odm, (u8 **)&delta_swing_table_idx_tup_c, (u8 **)&delta_swing_table_idx_tdown_c, + (u8 **)&delta_swing_table_idx_tup_d, (u8 **)&delta_swing_table_idx_tdown_d); + + if (p_dm_odm->support_ic_type & (ODM_RTL8703B | ODM_RTL8723D)) /*for Xtal Offset*/ + (*c.get_delta_swing_xtal_table)(p_dm_odm, (s8 **)&delta_swing_table_xtal_up, (s8 **)&delta_swing_table_xtal_down); + + p_rf_calibrate_info->txpowertracking_callback_cnt++; /*cosa add for debug*/ + p_rf_calibrate_info->is_txpowertracking_init = true; + + /*p_rf_calibrate_info->txpowertrack_control = p_hal_data->txpowertrack_control; + We should keep updating the control variable according to HalData. + rf_calibrate_info.rega24 will be initialized when ODM HW configuring, but MP configures with para files. */ + if (p_dm_odm->mp_mode == true) + p_rf_calibrate_info->rega24 = 0x090e1317; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("===>odm_txpowertracking_callback_thermal_meter\n p_rf_calibrate_info->bb_swing_idx_cck_base: %d, p_rf_calibrate_info->bb_swing_idx_ofdm_base[A]: %d, p_rf_calibrate_info->default_ofdm_index: %d\n", + p_rf_calibrate_info->bb_swing_idx_cck_base, p_rf_calibrate_info->bb_swing_idx_ofdm_base[ODM_RF_PATH_A], p_rf_calibrate_info->default_ofdm_index)); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("p_rf_calibrate_info->txpowertrack_control=%d, p_hal_data->eeprom_thermal_meter %d\n", p_rf_calibrate_info->txpowertrack_control, p_hal_data->eeprom_thermal_meter)); + thermal_value = (u8)odm_get_rf_reg(p_dm_odm, ODM_RF_PATH_A, c.thermal_reg_addr, 0xfc00); /* 0x42: RF Reg[15:10] 88E */ + + /*add log by zhao he, check c80/c94/c14/ca0 value*/ + if (p_dm_odm->support_ic_type == ODM_RTL8723D) { + regc80 = odm_get_bb_reg(p_dm_odm, 0xc80, MASKDWORD); + regcd0 = odm_get_bb_reg(p_dm_odm, 0xcd0, MASKDWORD); + regcd4 = odm_get_bb_reg(p_dm_odm, 0xcd4, MASKDWORD); + regab4 = odm_get_bb_reg(p_dm_odm, 0xab4, 0x000007FF); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xc80 = 0x%x 0xcd0 = 0x%x 0xcd4 = 0x%x 0xab4 = 0x%x\n", regc80, regcd0, regcd4, regab4)); + } + + if (!p_rf_calibrate_info->txpowertrack_control) + return; + + + /*4 3. Initialize ThermalValues of rf_calibrate_info*/ + + if (p_rf_calibrate_info->is_reloadtxpowerindex) + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("reload ofdm index for band switch\n")); + + /*4 4. Calculate average thermal meter*/ + + p_rf_calibrate_info->thermal_value_avg[p_rf_calibrate_info->thermal_value_avg_index] = thermal_value; + p_rf_calibrate_info->thermal_value_avg_index++; + if (p_rf_calibrate_info->thermal_value_avg_index == c.average_thermal_num) /*Average times = c.average_thermal_num*/ + p_rf_calibrate_info->thermal_value_avg_index = 0; + + for (i = 0; i < c.average_thermal_num; i++) { + if (p_rf_calibrate_info->thermal_value_avg[i]) { + thermal_value_avg += p_rf_calibrate_info->thermal_value_avg[i]; + thermal_value_avg_count++; + } + } + + if (thermal_value_avg_count) { /* Calculate Average thermal_value after average enough times */ + thermal_value = (u8)(thermal_value_avg / thermal_value_avg_count); + p_rf_calibrate_info->thermal_value_delta = thermal_value - p_hal_data->eeprom_thermal_meter; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("AVG Thermal Meter = 0x%X, EFUSE Thermal base = 0x%X\n", thermal_value, p_hal_data->eeprom_thermal_meter)); + } + + /* 4 5. Calculate delta, delta_LCK, delta_IQK. */ + + /* "delta" here is used to determine whether thermal value changes or not. */ + delta = (thermal_value > p_rf_calibrate_info->thermal_value) ? (thermal_value - p_rf_calibrate_info->thermal_value) : (p_rf_calibrate_info->thermal_value - thermal_value); + delta_LCK = (thermal_value > p_rf_calibrate_info->thermal_value_lck) ? (thermal_value - p_rf_calibrate_info->thermal_value_lck) : (p_rf_calibrate_info->thermal_value_lck - thermal_value); + delta_IQK = (thermal_value > p_rf_calibrate_info->thermal_value_iqk) ? (thermal_value - p_rf_calibrate_info->thermal_value_iqk) : (p_rf_calibrate_info->thermal_value_iqk - thermal_value); + + if (p_rf_calibrate_info->thermal_value_iqk == 0xff) { /*no PG, use thermal value for IQK*/ + p_rf_calibrate_info->thermal_value_iqk = thermal_value; + delta_IQK = (thermal_value > p_rf_calibrate_info->thermal_value_iqk) ? (thermal_value - p_rf_calibrate_info->thermal_value_iqk) : (p_rf_calibrate_info->thermal_value_iqk - thermal_value); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("no PG, use thermal_value for IQK\n")); + } + + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) + diff_DPK[p] = (s8)thermal_value - (s8)p_rf_calibrate_info->dpk_thermal[p]; + + /*4 6. If necessary, do LCK.*/ + + if (!(p_dm_odm->support_ic_type & ODM_RTL8821)) { /*no PG, do LCK at initial status*/ + if (p_rf_calibrate_info->thermal_value_lck == 0xff) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("no PG, do LCK\n")); + p_rf_calibrate_info->thermal_value_lck = thermal_value; + + /*Use RTLCK, so close power tracking driver LCK*/ + if (!(p_dm_odm->support_ic_type & ODM_RTL8814A)) { + if (c.phy_lc_calibrate) + (*c.phy_lc_calibrate)(p_dm_odm); + } + + delta_LCK = (thermal_value > p_rf_calibrate_info->thermal_value_lck) ? (thermal_value - p_rf_calibrate_info->thermal_value_lck) : (p_rf_calibrate_info->thermal_value_lck - thermal_value); + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n", delta, delta_LCK, delta_IQK)); + + /* Delta temperature is equal to or larger than 20 centigrade.*/ + if (delta_LCK >= c.threshold_iqk) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("delta_LCK(%d) >= threshold_iqk(%d)\n", delta_LCK, c.threshold_iqk)); + p_rf_calibrate_info->thermal_value_lck = thermal_value; + + /*Use RTLCK, so close power tracking driver LCK*/ + if (!(p_dm_odm->support_ic_type & ODM_RTL8814A)) { + if (c.phy_lc_calibrate) + (*c.phy_lc_calibrate)(p_dm_odm); + } + } + } + + /*3 7. If necessary, move the index of swing table to adjust Tx power.*/ + + if (delta > 0 && p_rf_calibrate_info->txpowertrack_control) { + /* "delta" here is used to record the absolute value of differrence. */ + delta = thermal_value > p_hal_data->eeprom_thermal_meter ? (thermal_value - p_hal_data->eeprom_thermal_meter) : (p_hal_data->eeprom_thermal_meter - thermal_value); + if (delta >= TXPWR_TRACK_TABLE_SIZE) + delta = TXPWR_TRACK_TABLE_SIZE - 1; + + /*4 7.1 The Final Power index = BaseIndex + power_index_offset*/ + + if (thermal_value > p_hal_data->eeprom_thermal_meter) { + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) { + p_rf_calibrate_info->delta_power_index_last[p] = p_rf_calibrate_info->delta_power_index[p]; /*recording poer index offset*/ + switch (p) { + case ODM_RF_PATH_B: + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("delta_swing_table_idx_tup_b[%d] = %d\n", delta, delta_swing_table_idx_tup_b[delta])); + + p_rf_calibrate_info->delta_power_index[p] = delta_swing_table_idx_tup_b[delta]; + p_rf_calibrate_info->absolute_ofdm_swing_idx[p] = delta_swing_table_idx_tup_b[delta]; /*Record delta swing for mix mode power tracking*/ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("******Temp is higher and p_rf_calibrate_info->absolute_ofdm_swing_idx[ODM_RF_PATH_B] = %d\n", p_rf_calibrate_info->absolute_ofdm_swing_idx[p])); + break; + + case ODM_RF_PATH_C: + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("delta_swing_table_idx_tup_c[%d] = %d\n", delta, delta_swing_table_idx_tup_c[delta])); + + p_rf_calibrate_info->delta_power_index[p] = delta_swing_table_idx_tup_c[delta]; + p_rf_calibrate_info->absolute_ofdm_swing_idx[p] = delta_swing_table_idx_tup_c[delta]; /*Record delta swing for mix mode power tracking*/ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("******Temp is higher and p_rf_calibrate_info->absolute_ofdm_swing_idx[ODM_RF_PATH_C] = %d\n", p_rf_calibrate_info->absolute_ofdm_swing_idx[p])); + break; + + case ODM_RF_PATH_D: + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("delta_swing_table_idx_tup_d[%d] = %d\n", delta, delta_swing_table_idx_tup_d[delta])); + + p_rf_calibrate_info->delta_power_index[p] = delta_swing_table_idx_tup_d[delta]; + p_rf_calibrate_info->absolute_ofdm_swing_idx[p] = delta_swing_table_idx_tup_d[delta]; /*Record delta swing for mix mode power tracking*/ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("******Temp is higher and p_rf_calibrate_info->absolute_ofdm_swing_idx[ODM_RF_PATH_D] = %d\n", p_rf_calibrate_info->absolute_ofdm_swing_idx[p])); + break; + + default: + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("delta_swing_table_idx_tup_a[%d] = %d\n", delta, delta_swing_table_idx_tup_a[delta])); + + p_rf_calibrate_info->delta_power_index[p] = delta_swing_table_idx_tup_a[delta]; + p_rf_calibrate_info->absolute_ofdm_swing_idx[p] = delta_swing_table_idx_tup_a[delta]; /*Record delta swing for mix mode power tracking*/ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("******Temp is higher and p_rf_calibrate_info->absolute_ofdm_swing_idx[ODM_RF_PATH_A] = %d\n", p_rf_calibrate_info->absolute_ofdm_swing_idx[p])); + break; + } + } + + if (p_dm_odm->support_ic_type & (ODM_RTL8703B | ODM_RTL8723D)) { + /*Save xtal_offset from Xtal table*/ + p_rf_calibrate_info->xtal_offset_last = p_rf_calibrate_info->xtal_offset; /*recording last Xtal offset*/ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("[Xtal] delta_swing_table_xtal_up[%d] = %d\n", delta, delta_swing_table_xtal_up[delta])); + p_rf_calibrate_info->xtal_offset = delta_swing_table_xtal_up[delta]; + + if (p_rf_calibrate_info->xtal_offset_last == p_rf_calibrate_info->xtal_offset) + xtal_offset_eanble = 0; + else + xtal_offset_eanble = 1; + } + + } else { + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) { + p_rf_calibrate_info->delta_power_index_last[p] = p_rf_calibrate_info->delta_power_index[p]; /*recording poer index offset*/ + + switch (p) { + case ODM_RF_PATH_B: + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("delta_swing_table_idx_tdown_b[%d] = %d\n", delta, delta_swing_table_idx_tdown_b[delta])); + p_rf_calibrate_info->delta_power_index[p] = -1 * delta_swing_table_idx_tdown_b[delta]; + p_rf_calibrate_info->absolute_ofdm_swing_idx[p] = -1 * delta_swing_table_idx_tdown_b[delta]; /*Record delta swing for mix mode power tracking*/ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("******Temp is lower and p_rf_calibrate_info->absolute_ofdm_swing_idx[ODM_RF_PATH_B] = %d\n", p_rf_calibrate_info->absolute_ofdm_swing_idx[p])); + break; + + case ODM_RF_PATH_C: + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("delta_swing_table_idx_tdown_c[%d] = %d\n", delta, delta_swing_table_idx_tdown_c[delta])); + p_rf_calibrate_info->delta_power_index[p] = -1 * delta_swing_table_idx_tdown_c[delta]; + p_rf_calibrate_info->absolute_ofdm_swing_idx[p] = -1 * delta_swing_table_idx_tdown_c[delta]; /*Record delta swing for mix mode power tracking*/ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("******Temp is lower and p_rf_calibrate_info->absolute_ofdm_swing_idx[ODM_RF_PATH_C] = %d\n", p_rf_calibrate_info->absolute_ofdm_swing_idx[p])); + break; + + case ODM_RF_PATH_D: + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("delta_swing_table_idx_tdown_d[%d] = %d\n", delta, delta_swing_table_idx_tdown_d[delta])); + p_rf_calibrate_info->delta_power_index[p] = -1 * delta_swing_table_idx_tdown_d[delta]; + p_rf_calibrate_info->absolute_ofdm_swing_idx[p] = -1 * delta_swing_table_idx_tdown_d[delta]; /*Record delta swing for mix mode power tracking*/ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("******Temp is lower and p_rf_calibrate_info->absolute_ofdm_swing_idx[ODM_RF_PATH_D] = %d\n", p_rf_calibrate_info->absolute_ofdm_swing_idx[p])); + break; + + default: + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("delta_swing_table_idx_tdown_a[%d] = %d\n", delta, delta_swing_table_idx_tdown_a[delta])); + p_rf_calibrate_info->delta_power_index[p] = -1 * delta_swing_table_idx_tdown_a[delta]; + p_rf_calibrate_info->absolute_ofdm_swing_idx[p] = -1 * delta_swing_table_idx_tdown_a[delta]; /*Record delta swing for mix mode power tracking*/ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("******Temp is lower and p_rf_calibrate_info->absolute_ofdm_swing_idx[ODM_RF_PATH_A] = %d\n", p_rf_calibrate_info->absolute_ofdm_swing_idx[p])); + break; + } + } + + if (p_dm_odm->support_ic_type & (ODM_RTL8703B | ODM_RTL8723D)) { + /*Save xtal_offset from Xtal table*/ + p_rf_calibrate_info->xtal_offset_last = p_rf_calibrate_info->xtal_offset; /*recording last Xtal offset*/ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("[Xtal] delta_swing_table_xtal_down[%d] = %d\n", delta, delta_swing_table_xtal_down[delta])); + p_rf_calibrate_info->xtal_offset = delta_swing_table_xtal_down[delta]; + + if (p_rf_calibrate_info->xtal_offset_last == p_rf_calibrate_info->xtal_offset) + xtal_offset_eanble = 0; + else + xtal_offset_eanble = 1; + } + + } + + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("\n\n=========================== [path-%d] Calculating power_index_offset===========================\n", p)); + + if (p_rf_calibrate_info->delta_power_index[p] == p_rf_calibrate_info->delta_power_index_last[p]) /*If Thermal value changes but lookup table value still the same*/ + p_rf_calibrate_info->power_index_offset[p] = 0; + else + p_rf_calibrate_info->power_index_offset[p] = p_rf_calibrate_info->delta_power_index[p] - p_rf_calibrate_info->delta_power_index_last[p]; /*Power index diff between 2 times Power Tracking*/ + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("[path-%d] power_index_offset(%d) = delta_power_index(%d) - delta_power_index_last(%d)\n", p, p_rf_calibrate_info->power_index_offset[p], p_rf_calibrate_info->delta_power_index[p], p_rf_calibrate_info->delta_power_index_last[p])); + + p_rf_calibrate_info->OFDM_index[p] = p_rf_calibrate_info->bb_swing_idx_ofdm_base[p] + p_rf_calibrate_info->power_index_offset[p]; + p_rf_calibrate_info->CCK_index = p_rf_calibrate_info->bb_swing_idx_cck_base + p_rf_calibrate_info->power_index_offset[p]; + + p_rf_calibrate_info->bb_swing_idx_cck = p_rf_calibrate_info->CCK_index; + p_rf_calibrate_info->bb_swing_idx_ofdm[p] = p_rf_calibrate_info->OFDM_index[p]; + + /*************Print BB Swing base and index Offset*************/ + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("The 'CCK' final index(%d) = BaseIndex(%d) + power_index_offset(%d)\n", p_rf_calibrate_info->bb_swing_idx_cck, p_rf_calibrate_info->bb_swing_idx_cck_base, p_rf_calibrate_info->power_index_offset[p])); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("The 'OFDM' final index(%d) = BaseIndex[%d](%d) + power_index_offset(%d)\n", p_rf_calibrate_info->bb_swing_idx_ofdm[p], p, p_rf_calibrate_info->bb_swing_idx_ofdm_base[p], p_rf_calibrate_info->power_index_offset[p])); + + /*4 7.1 Handle boundary conditions of index.*/ + + if (p_rf_calibrate_info->OFDM_index[p] > c.swing_table_size_ofdm - 1) + p_rf_calibrate_info->OFDM_index[p] = c.swing_table_size_ofdm - 1; + else if (p_rf_calibrate_info->OFDM_index[p] <= OFDM_min_index) + p_rf_calibrate_info->OFDM_index[p] = OFDM_min_index; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("\n\n========================================================================================================\n")); + + if (p_rf_calibrate_info->CCK_index > c.swing_table_size_cck - 1) + p_rf_calibrate_info->CCK_index = c.swing_table_size_cck - 1; + else if (p_rf_calibrate_info->CCK_index <= 0) + p_rf_calibrate_info->CCK_index = 0; + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("The thermal meter is unchanged or TxPowerTracking OFF(%d): thermal_value: %d, p_rf_calibrate_info->thermal_value: %d\n", + p_rf_calibrate_info->txpowertrack_control, thermal_value, p_rf_calibrate_info->thermal_value)); + + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) + p_rf_calibrate_info->power_index_offset[p] = 0; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("TxPowerTracking: [CCK] Swing Current index: %d, Swing base index: %d\n", + p_rf_calibrate_info->CCK_index, p_rf_calibrate_info->bb_swing_idx_cck_base)); /*Print Swing base & current*/ + + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("TxPowerTracking: [OFDM] Swing Current index: %d, Swing base index[%d]: %d\n", + p_rf_calibrate_info->OFDM_index[p], p, p_rf_calibrate_info->bb_swing_idx_ofdm_base[p])); + } + + if ((p_dm_odm->support_ic_type & ODM_RTL8814A)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("power_tracking_type=%d\n", power_tracking_type)); + + if (power_tracking_type == 0) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter POWER Tracking MIX_MODE**********\n")); + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) + (*c.odm_tx_pwr_track_set_pwr)(p_dm_odm, MIX_MODE, p, 0); + } else if (power_tracking_type == 1) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter POWER Tracking MIX(2G) TSSI(5G) MODE**********\n")); + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) + (*c.odm_tx_pwr_track_set_pwr)(p_dm_odm, MIX_2G_TSSI_5G_MODE, p, 0); + } else if (power_tracking_type == 2) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter POWER Tracking MIX(5G) TSSI(2G)MODE**********\n")); + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) + (*c.odm_tx_pwr_track_set_pwr)(p_dm_odm, MIX_5G_TSSI_2G_MODE, p, 0); + } else if (power_tracking_type == 3) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter POWER Tracking TSSI MODE**********\n")); + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) + (*c.odm_tx_pwr_track_set_pwr)(p_dm_odm, TSSI_MODE, p, 0); + } + p_rf_calibrate_info->thermal_value = thermal_value; /*Record last Power Tracking Thermal value*/ + + } else if ((p_rf_calibrate_info->power_index_offset[ODM_RF_PATH_A] != 0 || + p_rf_calibrate_info->power_index_offset[ODM_RF_PATH_B] != 0 || + p_rf_calibrate_info->power_index_offset[ODM_RF_PATH_C] != 0 || + p_rf_calibrate_info->power_index_offset[ODM_RF_PATH_D] != 0) && + p_rf_calibrate_info->txpowertrack_control && (p_hal_data->eeprom_thermal_meter != 0xff)) { + /* 4 7.2 Configure the Swing Table to adjust Tx Power. */ + + p_rf_calibrate_info->is_tx_power_changed = true; /*Always true after Tx Power is adjusted by power tracking.*/ + /* */ + /* 2012/04/23 MH According to Luke's suggestion, we can not write BB digital */ + /* to increase TX power. Otherwise, EVM will be bad. */ + /* */ + /* 2012/04/25 MH Add for tx power tracking to set tx power in tx agc for 88E. */ + if (thermal_value > p_rf_calibrate_info->thermal_value) { + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("Temperature Increasing(%d): delta_pi: %d, delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", + p, p_rf_calibrate_info->power_index_offset[p], delta, thermal_value, p_hal_data->eeprom_thermal_meter, p_rf_calibrate_info->thermal_value)); + } + } else if (thermal_value < p_rf_calibrate_info->thermal_value) { /*Low temperature*/ + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("Temperature Decreasing(%d): delta_pi: %d, delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", + p, p_rf_calibrate_info->power_index_offset[p], delta, thermal_value, p_hal_data->eeprom_thermal_meter, p_rf_calibrate_info->thermal_value)); + } + } + + if (thermal_value > p_hal_data->eeprom_thermal_meter) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("Temperature(%d) higher than PG value(%d)\n", thermal_value, p_hal_data->eeprom_thermal_meter)); + + if (p_dm_odm->support_ic_type == ODM_RTL8188E || p_dm_odm->support_ic_type == ODM_RTL8192E || p_dm_odm->support_ic_type == ODM_RTL8821 || + p_dm_odm->support_ic_type == ODM_RTL8812 || p_dm_odm->support_ic_type == ODM_RTL8723B || p_dm_odm->support_ic_type == ODM_RTL8814A || + p_dm_odm->support_ic_type == ODM_RTL8703B || p_dm_odm->support_ic_type == ODM_RTL8188F || p_dm_odm->support_ic_type == ODM_RTL8822B || + p_dm_odm->support_ic_type == ODM_RTL8723D || p_dm_odm->support_ic_type == ODM_RTL8821C) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter POWER Tracking MIX_MODE**********\n")); + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) + (*c.odm_tx_pwr_track_set_pwr)(p_dm_odm, MIX_MODE, p, 0); + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter POWER Tracking BBSWING_MODE**********\n")); + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) + (*c.odm_tx_pwr_track_set_pwr)(p_dm_odm, BBSWING, p, indexforchannel); + } + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("Temperature(%d) lower than PG value(%d)\n", thermal_value, p_hal_data->eeprom_thermal_meter)); + + if (p_dm_odm->support_ic_type == ODM_RTL8188E || p_dm_odm->support_ic_type == ODM_RTL8192E || p_dm_odm->support_ic_type == ODM_RTL8821 || + p_dm_odm->support_ic_type == ODM_RTL8812 || p_dm_odm->support_ic_type == ODM_RTL8723B || p_dm_odm->support_ic_type == ODM_RTL8814A || + p_dm_odm->support_ic_type == ODM_RTL8703B || p_dm_odm->support_ic_type == ODM_RTL8188F || p_dm_odm->support_ic_type == ODM_RTL8822B || + p_dm_odm->support_ic_type == ODM_RTL8723D || p_dm_odm->support_ic_type == ODM_RTL8821C) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter POWER Tracking MIX_MODE**********\n")); + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) + (*c.odm_tx_pwr_track_set_pwr)(p_dm_odm, MIX_MODE, p, indexforchannel); + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter POWER Tracking BBSWING_MODE**********\n")); + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) + (*c.odm_tx_pwr_track_set_pwr)(p_dm_odm, BBSWING, p, indexforchannel); + } + + } + + p_rf_calibrate_info->bb_swing_idx_cck_base = p_rf_calibrate_info->bb_swing_idx_cck; /*Record last time Power Tracking result as base.*/ + for (p = ODM_RF_PATH_A; p < c.rf_path_count; p++) + p_rf_calibrate_info->bb_swing_idx_ofdm_base[p] = p_rf_calibrate_info->bb_swing_idx_ofdm[p]; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("p_rf_calibrate_info->thermal_value = %d thermal_value= %d\n", p_rf_calibrate_info->thermal_value, thermal_value)); + + p_rf_calibrate_info->thermal_value = thermal_value; /*Record last Power Tracking Thermal value*/ + + } + + + if (p_dm_odm->support_ic_type == ODM_RTL8703B || p_dm_odm->support_ic_type == ODM_RTL8723D) { + + if (xtal_offset_eanble != 0 && p_rf_calibrate_info->txpowertrack_control && (p_hal_data->eeprom_thermal_meter != 0xff)) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter Xtal Tracking**********\n")); + + if (thermal_value > p_hal_data->eeprom_thermal_meter) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("Temperature(%d) higher than PG value(%d)\n", thermal_value, p_hal_data->eeprom_thermal_meter)); + (*c.odm_txxtaltrack_set_xtal)(p_dm_odm); + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, + ("Temperature(%d) lower than PG value(%d)\n", thermal_value, p_hal_data->eeprom_thermal_meter)); + (*c.odm_txxtaltrack_set_xtal)(p_dm_odm); + } + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********End Xtal Tracking**********\n")); + } + if (p_rf_calibrate_info->dpk_thermal[ODM_RF_PATH_A] != 0) { + if (diff_DPK[ODM_RF_PATH_A] >= c.threshold_dpk) { + odm_set_bb_reg(p_dm_odm, 0x82c, BIT(31), 0x1); + odm_set_bb_reg(p_dm_odm, 0xcc4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), (diff_DPK[ODM_RF_PATH_A] / c.threshold_dpk)); + odm_set_bb_reg(p_dm_odm, 0x82c, BIT(31), 0x0); + } else if ((diff_DPK[ODM_RF_PATH_A] <= -1 * c.threshold_dpk)) { + s32 value = 0x20 + (diff_DPK[ODM_RF_PATH_A] / c.threshold_dpk); + + odm_set_bb_reg(p_dm_odm, 0x82c, BIT(31), 0x1); + odm_set_bb_reg(p_dm_odm, 0xcc4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), value); + odm_set_bb_reg(p_dm_odm, 0x82c, BIT(31), 0x0); + } else { + odm_set_bb_reg(p_dm_odm, 0x82c, BIT(31), 0x1); + odm_set_bb_reg(p_dm_odm, 0xcc4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), 0); + odm_set_bb_reg(p_dm_odm, 0x82c, BIT(31), 0x0); + } + } + if (p_rf_calibrate_info->dpk_thermal[ODM_RF_PATH_B] != 0) { + if (diff_DPK[ODM_RF_PATH_B] >= c.threshold_dpk) { + odm_set_bb_reg(p_dm_odm, 0x82c, BIT(31), 0x1); + odm_set_bb_reg(p_dm_odm, 0xec4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), (diff_DPK[ODM_RF_PATH_B] / c.threshold_dpk)); + odm_set_bb_reg(p_dm_odm, 0x82c, BIT(31), 0x0); + } else if ((diff_DPK[ODM_RF_PATH_B] <= -1 * c.threshold_dpk)) { + s32 value = 0x20 + (diff_DPK[ODM_RF_PATH_B] / c.threshold_dpk); + + odm_set_bb_reg(p_dm_odm, 0x82c, BIT(31), 0x1); + odm_set_bb_reg(p_dm_odm, 0xec4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), value); + odm_set_bb_reg(p_dm_odm, 0x82c, BIT(31), 0x0); + } else { + odm_set_bb_reg(p_dm_odm, 0x82c, BIT(31), 0x1); + odm_set_bb_reg(p_dm_odm, 0xec4, BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10), 0); + odm_set_bb_reg(p_dm_odm, 0x82c, BIT(31), 0x0); + } + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("<===odm_txpowertracking_callback_thermal_meter\n")); + + p_rf_calibrate_info->tx_powercount = 0; +} + + + +/* 3============================================================ + * 3 IQ Calibration + * 3============================================================ */ + +void +odm_reset_iqk_result( + void *p_dm_void +) +{ + return; +} +u8 odm_get_right_chnl_place_for_iqk(u8 chnl) +{ + u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153, 155, 157, 159, 161, 163, 165 + }; + u8 place = chnl; + + + if (chnl > 14) { + for (place = 14; place < sizeof(channel_all); place++) { + if (channel_all[place] == chnl) + return place - 13; + } + } + return 0; + +} + +static void odm_iq_calibrate(struct PHY_DM_STRUCT *p_dm_odm) +{ + struct _ADAPTER *adapter = p_dm_odm->adapter; + + if (p_dm_odm->is_linked) { + if ((*p_dm_odm->p_channel != p_dm_odm->pre_channel) && (!*p_dm_odm->p_is_scan_in_process)) { + p_dm_odm->pre_channel = *p_dm_odm->p_channel; + p_dm_odm->linked_interval = 0; + } + + if (p_dm_odm->linked_interval < 3) + p_dm_odm->linked_interval++; + } else + p_dm_odm->linked_interval = 0; +} + +void phydm_rf_init(void *p_dm_void) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + odm_txpowertracking_init(p_dm_odm); + + odm_clear_txpowertracking_state(p_dm_odm); +} + +void phydm_rf_watchdog(void *p_dm_void) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + odm_txpowertracking_check(p_dm_odm); + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) + odm_iq_calibrate(p_dm_odm); +} diff --git a/drivers/staging/rtl8188eu/hal/halphyrf_ce.h b/drivers/staging/rtl8188eu/hal/halphyrf_ce.h new file mode 100644 index 000000000000..12870601c09c --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/halphyrf_ce.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __HAL_PHY_RF_H__ +#define __HAL_PHY_RF_H__ + +#include "phydm_kfree.h" +#include "phydm_powertracking_ce.h" + +enum spur_cal_method { + PLL_RESET, + AFE_PHASE_SEL +}; + +enum pwrtrack_method { + BBSWING, + TXAGC, + MIX_MODE, + TSSI_MODE, + MIX_2G_TSSI_5G_MODE, + MIX_5G_TSSI_2G_MODE +}; + +typedef void (*func_set_pwr)(void *, enum pwrtrack_method, u8, u8); +typedef void(*func_iqk)(void *, u8, u8, u8); +typedef void (*func_lck)(void *); +typedef void (*func_swing)(void *, u8 **, u8 **, u8 **, u8 **); +typedef void (*func_swing8814only)(void *, u8 **, u8 **, u8 **, u8 **); +typedef void(*func_swing_xtal)(void *, s8 **, s8 **); +typedef void(*func_set_xtal)(void *); + +struct _TXPWRTRACK_CFG { + u8 swing_table_size_cck; + u8 swing_table_size_ofdm; + u8 threshold_iqk; + u8 threshold_dpk; + u8 average_thermal_num; + u8 rf_path_count; + u32 thermal_reg_addr; + func_set_pwr odm_tx_pwr_track_set_pwr; + func_iqk do_iqk; + func_lck phy_lc_calibrate; + func_swing get_delta_swing_table; + func_swing8814only get_delta_swing_table8814only; + func_swing_xtal get_delta_swing_xtal_table; + func_set_xtal odm_txxtaltrack_set_xtal; +}; + +void +configure_txpower_track( + void *p_dm_void, + struct _TXPWRTRACK_CFG *p_config +); + + +void +odm_clear_txpowertracking_state( + void *p_dm_void +); + +void +odm_txpowertracking_callback_thermal_meter( + struct _ADAPTER *adapter +); + +#define ODM_TARGET_CHNL_NUM_2G_5G 59 + +void +odm_reset_iqk_result( + void *p_dm_void +); +u8 +odm_get_right_chnl_place_for_iqk( + u8 chnl +); + +void phydm_rf_init(void *p_dm_void); +void phydm_rf_watchdog(void *p_dm_void); + +#endif /* #ifndef __HAL_PHY_RF_H__ */ diff --git a/drivers/staging/rtl8188eu/hal/haltxbfinterface.h b/drivers/staging/rtl8188eu/hal/haltxbfinterface.h new file mode 100644 index 000000000000..4bf9502d4355 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/haltxbfinterface.h @@ -0,0 +1,14 @@ +#ifndef __HAL_TXBF_INTERFACE_H__ +#define __HAL_TXBF_INTERFACE_H__ + +#define beamforming_get_ndpa_frame(p_dm_odm, _pdu_os) +#define beamforming_get_report_frame(adapter, precv_frame) RT_STATUS_FAILURE +#define send_fw_ht_ndpa_packet(p_dm_void, RA, BW) +#define send_sw_ht_ndpa_packet(p_dm_void, RA, BW) +#define send_fw_vht_ndpa_packet(p_dm_void, RA, AID, BW) +#define send_sw_vht_ndpa_packet(p_dm_void, RA, AID, BW) +#define send_sw_vht_gid_mgnt_frame(p_dm_void, RA, idx) +#define send_sw_vht_bf_report_poll(p_dm_void, RA, is_final_poll) +#define send_sw_vht_mu_ndpa_packet(p_dm_void, BW) + +#endif diff --git a/drivers/staging/rtl8188eu/hal/haltxbfjaguar.h b/drivers/staging/rtl8188eu/hal/haltxbfjaguar.h new file mode 100644 index 000000000000..7c7f73ed391a --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/haltxbfjaguar.h @@ -0,0 +1,74 @@ +#ifndef __HAL_TXBF_JAGUAR_H__ +#define __HAL_TXBF_JAGUAR_H__ +#if ((RTL8812A_SUPPORT == 1) || (RTL8821A_SUPPORT == 1)) +#if (BEAMFORMING_SUPPORT == 1) + +void +hal_txbf_8812a_set_ndpa_rate( + void *p_dm_void, + u8 BW, + u8 rate +); + + +void +hal_txbf_jaguar_enter( + void *p_dm_void, + u8 idx +); + + +void +hal_txbf_jaguar_leave( + void *p_dm_void, + u8 idx +); + + +void +hal_txbf_jaguar_status( + void *p_dm_void, + u8 idx +); + + +void +hal_txbf_jaguar_fw_txbf( + void *p_dm_void, + u8 idx +); + + +void +hal_txbf_jaguar_patch( + void *p_dm_void, + u8 operation +); + + +void +hal_txbf_jaguar_clk_8812a( + void *p_dm_void +); +#else + +#define hal_txbf_8812a_set_ndpa_rate(p_dm_void, BW, rate) +#define hal_txbf_jaguar_enter(p_dm_void, idx) +#define hal_txbf_jaguar_leave(p_dm_void, idx) +#define hal_txbf_jaguar_status(p_dm_void, idx) +#define hal_txbf_jaguar_fw_txbf(p_dm_void, idx) +#define hal_txbf_jaguar_patch(p_dm_void, operation) +#define hal_txbf_jaguar_clk_8812a(p_dm_void) +#endif +#else + +#define hal_txbf_8812a_set_ndpa_rate(p_dm_void, BW, rate) +#define hal_txbf_jaguar_enter(p_dm_void, idx) +#define hal_txbf_jaguar_leave(p_dm_void, idx) +#define hal_txbf_jaguar_status(p_dm_void, idx) +#define hal_txbf_jaguar_fw_txbf(p_dm_void, idx) +#define hal_txbf_jaguar_patch(p_dm_void, operation) +#define hal_txbf_jaguar_clk_8812a(p_dm_void) +#endif + +#endif /* #ifndef __HAL_TXBF_JAGUAR_H__ */ diff --git a/drivers/staging/rtl8188eu/hal/mp_precomp.h b/drivers/staging/rtl8188eu/hal/mp_precomp.h new file mode 100644 index 000000000000..0b2a7707a499 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/mp_precomp.h @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + diff --git a/drivers/staging/rtl8188eu/hal/phydm.c b/drivers/staging/rtl8188eu/hal/phydm.c new file mode 100644 index 000000000000..beab57636586 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm.c @@ -0,0 +1,2341 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* ************************************************************ + * include files + * ************************************************************ */ + +#include "mp_precomp.h" +#include "phydm_precomp.h" + +static const u16 db_invert_table[12][8] = { + { 1, 1, 1, 2, 2, 2, 2, 3}, + { 3, 3, 4, 4, 4, 5, 6, 6}, + { 7, 8, 9, 10, 11, 13, 14, 16}, + { 18, 20, 22, 25, 28, 32, 35, 40}, + { 45, 50, 56, 63, 71, 79, 89, 100}, + { 112, 126, 141, 158, 178, 200, 224, 251}, + { 282, 316, 355, 398, 447, 501, 562, 631}, + { 708, 794, 891, 1000, 1122, 1259, 1413, 1585}, + { 1778, 1995, 2239, 2512, 2818, 3162, 3548, 3981}, + { 4467, 5012, 5623, 6310, 7079, 7943, 8913, 10000}, + { 11220, 12589, 14125, 15849, 17783, 19953, 22387, 25119}, + { 28184, 31623, 35481, 39811, 44668, 50119, 56234, 65535} +}; + + +/* ************************************************************ + * Local Function predefine. + * ************************************************************ */ + +/* START------------COMMON INFO RELATED--------------- */ + +void +odm_global_adapter_check( + void +); + +/* move to odm_PowerTacking.h by YuChen */ + + + +void +odm_update_power_training_state( + struct PHY_DM_STRUCT *p_dm_odm +); + +/* ************************************************************ + * 3 Export Interface + * ************************************************************ */ + +/*Y = 10*log(X)*/ +s32 +odm_pwdb_conversion( + s32 X, + u32 total_bit, + u32 decimal_bit +) +{ + s32 Y, integer = 0, decimal = 0; + u32 i; + + if (X == 0) + X = 1; /* log2(x), x can't be 0 */ + + for (i = (total_bit - 1); i > 0; i--) { + if (X & BIT(i)) { + integer = i; + if (i > 0) + decimal = (X & BIT(i - 1)) ? 2 : 0; /* decimal is 0.5dB*3=1.5dB~=2dB */ + break; + } + } + + Y = 3 * (integer - decimal_bit) + decimal; /* 10*log(x)=3*log2(x), */ + + return Y; +} + +s32 +odm_sign_conversion( + s32 value, + u32 total_bit +) +{ + if (value & BIT(total_bit - 1)) + value -= BIT(total_bit); + return value; +} + +void +phydm_seq_sorting( + void *p_dm_void, + u32 *p_value, + u32 *rank_idx, + u32 *p_idx_out, + u8 seq_length +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 i = 0, j = 0; + u32 tmp_a, tmp_b; + u32 tmp_idx_a, tmp_idx_b; + + for (i = 0; i < seq_length; i++) { + rank_idx[i] = i; + /**/ + } + + for (i = 0; i < (seq_length - 1); i++) { + + for (j = 0; j < (seq_length - 1 - i); j++) { + + tmp_a = p_value[j]; + tmp_b = p_value[j + 1]; + + tmp_idx_a = rank_idx[j]; + tmp_idx_b = rank_idx[j + 1]; + + if (tmp_a < tmp_b) { + p_value[j] = tmp_b; + p_value[j + 1] = tmp_a; + + rank_idx[j] = tmp_idx_b; + rank_idx[j + 1] = tmp_idx_a; + } + } + } + + for (i = 0; i < seq_length; i++) { + p_idx_out[rank_idx[i]] = i + 1; + /**/ + } + + + +} + +void +odm_init_mp_driver_status( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + struct _ADAPTER *adapter = p_dm_odm->adapter; + + /* Update information every period */ + p_dm_odm->mp_mode = (bool)adapter->registrypriv.mp_mode; + +} + +static void +odm_update_mp_driver_status( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + struct _ADAPTER *adapter = p_dm_odm->adapter; + + /* Update information erery period */ + p_dm_odm->mp_mode = (bool)adapter->registrypriv.mp_mode; +} + +static void +phydm_init_trx_antenna_setting( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + if (p_dm_odm->support_ic_type & (ODM_RTL8814A)) { + u8 rx_ant = 0, tx_ant = 0; + + rx_ant = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG(BB_RX_PATH, p_dm_odm), ODM_BIT(BB_RX_PATH, p_dm_odm)); + tx_ant = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG(BB_TX_PATH, p_dm_odm), ODM_BIT(BB_TX_PATH, p_dm_odm)); + p_dm_odm->tx_ant_status = (tx_ant & 0xf); + p_dm_odm->rx_ant_status = (rx_ant & 0xf); + } else if (p_dm_odm->support_ic_type & (ODM_RTL8723D | ODM_RTL8821C)) { + p_dm_odm->tx_ant_status = 0x1; + p_dm_odm->rx_ant_status = 0x1; + + } +} + +static void +phydm_traffic_load_decision( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _sw_antenna_switch_ *p_dm_swat_table = &p_dm_odm->dm_swat_table; + + /*---TP & Trafic-load calculation---*/ + + if (p_dm_odm->last_tx_ok_cnt > (*(p_dm_odm->p_num_tx_bytes_unicast))) + p_dm_odm->last_tx_ok_cnt = (*(p_dm_odm->p_num_tx_bytes_unicast)); + + if (p_dm_odm->last_rx_ok_cnt > (*(p_dm_odm->p_num_rx_bytes_unicast))) + p_dm_odm->last_rx_ok_cnt = (*(p_dm_odm->p_num_rx_bytes_unicast)); + + p_dm_odm->cur_tx_ok_cnt = *(p_dm_odm->p_num_tx_bytes_unicast) - p_dm_odm->last_tx_ok_cnt; + p_dm_odm->cur_rx_ok_cnt = *(p_dm_odm->p_num_rx_bytes_unicast) - p_dm_odm->last_rx_ok_cnt; + p_dm_odm->last_tx_ok_cnt = *(p_dm_odm->p_num_tx_bytes_unicast); + p_dm_odm->last_rx_ok_cnt = *(p_dm_odm->p_num_rx_bytes_unicast); + + p_dm_odm->tx_tp = ((p_dm_odm->tx_tp) >> 1) + (u32)(((p_dm_odm->cur_tx_ok_cnt) >> 18) >> 1); /* <<3(8bit), >>20(10^6,M), >>1(2sec)*/ + p_dm_odm->rx_tp = ((p_dm_odm->rx_tp) >> 1) + (u32)(((p_dm_odm->cur_rx_ok_cnt) >> 18) >> 1); /* <<3(8bit), >>20(10^6,M), >>1(2sec)*/ + p_dm_odm->total_tp = p_dm_odm->tx_tp + p_dm_odm->rx_tp; + + if (p_dm_odm->total_tp == 0) + p_dm_odm->consecutive_idlel_time += PHYDM_WATCH_DOG_PERIOD; + else + p_dm_odm->consecutive_idlel_time = 0; + + p_dm_odm->pre_traffic_load = p_dm_odm->traffic_load; + + if (p_dm_odm->cur_tx_ok_cnt > 1875000 || p_dm_odm->cur_rx_ok_cnt > 1875000) { /* ( 1.875M * 8bit ) / 2sec= 7.5M bits /sec )*/ + + p_dm_odm->traffic_load = TRAFFIC_HIGH; + /**/ + } else if (p_dm_odm->cur_tx_ok_cnt > 500000 || p_dm_odm->cur_rx_ok_cnt > 500000) { /*( 0.5M * 8bit ) / 2sec = 2M bits /sec )*/ + + p_dm_odm->traffic_load = TRAFFIC_MID; + /**/ + } else if (p_dm_odm->cur_tx_ok_cnt > 100000 || p_dm_odm->cur_rx_ok_cnt > 100000) { /*( 0.1M * 8bit ) / 2sec = 0.4M bits /sec )*/ + + p_dm_odm->traffic_load = TRAFFIC_LOW; + /**/ + } else { + + p_dm_odm->traffic_load = TRAFFIC_ULTRA_LOW; + /**/ + } +} + +static void +phydm_config_ofdm_tx_path( + struct PHY_DM_STRUCT *p_dm_odm, + u32 path +) +{ + u8 ofdm_tx_path = 0x33; +} + +void +phydm_config_ofdm_rx_path( + struct PHY_DM_STRUCT *p_dm_odm, + u32 path +) +{ + u8 ofdm_rx_path = 0; + + + if (p_dm_odm->support_ic_type & (ODM_RTL8192E)) { + } +} + +static void +phydm_config_cck_rx_antenna_init( + struct PHY_DM_STRUCT *p_dm_odm +) +{ +} + +static void +phydm_config_cck_rx_path( + struct PHY_DM_STRUCT *p_dm_odm, + u8 path, + u8 path_div_en +) +{ + u8 path_div_select = 0; + u8 cck_1_path = 0, cck_2_path = 0; +} + +void +phydm_config_trx_path( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 pre_support_ability; + u32 used = *_used; + u32 out_len = *_out_len; + + /* CCK */ + if (dm_value[0] == 0) { + + if (dm_value[1] == 1) { /*TX*/ + if (dm_value[2] == 1) + odm_set_bb_reg(p_dm_odm, 0xa04, 0xf0000000, 0x8); + else if (dm_value[2] == 2) + odm_set_bb_reg(p_dm_odm, 0xa04, 0xf0000000, 0x4); + else if (dm_value[2] == 3) + odm_set_bb_reg(p_dm_odm, 0xa04, 0xf0000000, 0xc); + } else if (dm_value[1] == 2) { /*RX*/ + + phydm_config_cck_rx_antenna_init(p_dm_odm); + + if (dm_value[2] == 1) + phydm_config_cck_rx_path(p_dm_odm, PHYDM_A, CCA_PATHDIV_DISABLE); + else if (dm_value[2] == 2) + phydm_config_cck_rx_path(p_dm_odm, PHYDM_B, CCA_PATHDIV_DISABLE); + else if (dm_value[2] == 3) { + if (dm_value[3] == 1) /*enable path diversity*/ + phydm_config_cck_rx_path(p_dm_odm, PHYDM_AB, CCA_PATHDIV_ENABLE); + else + phydm_config_cck_rx_path(p_dm_odm, PHYDM_B, CCA_PATHDIV_DISABLE); + } + } + } + /* OFDM */ + else if (dm_value[0] == 1) { + + if (dm_value[1] == 1) { /*TX*/ + phydm_config_ofdm_tx_path(p_dm_odm, dm_value[2]); + /**/ + } else if (dm_value[1] == 2) { /*RX*/ + phydm_config_ofdm_rx_path(p_dm_odm, dm_value[2]); + /**/ + } + } + + PHYDM_SNPRINTF((output + used, out_len - used, "PHYDM Set path [%s] [%s] = [%s%s%s%s]\n", + (dm_value[0] == 1) ? "OFDM" : "CCK", + (dm_value[1] == 1) ? "TX" : "RX", + (dm_value[2] & 0x1) ? "A" : "", + (dm_value[2] & 0x2) ? "B" : "", + (dm_value[2] & 0x4) ? "C" : "", + (dm_value[2] & 0x8) ? "D" : "" + )); + +} + +static void +phydm_init_cck_setting( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u32 value_824, value_82c; + + p_dm_odm->is_cck_high_power = (bool) odm_get_bb_reg(p_dm_odm, ODM_REG(CCK_RPT_FORMAT, p_dm_odm), ODM_BIT(CCK_RPT_FORMAT, p_dm_odm)); + + p_dm_odm->cck_new_agc = false; +} + +static void +phydm_init_soft_ml_setting( + struct PHY_DM_STRUCT *p_dm_odm +) +{ +} + +static void +phydm_init_hw_info_by_rfe( + struct PHY_DM_STRUCT *p_dm_odm +) +{ +} + +static void +odm_common_info_self_init( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + phydm_init_cck_setting(p_dm_odm); + p_dm_odm->rf_path_rx_enable = (u8) odm_get_bb_reg(p_dm_odm, ODM_REG(BB_RX_PATH, p_dm_odm), ODM_BIT(BB_RX_PATH, p_dm_odm)); + odm_init_mp_driver_status(p_dm_odm); + phydm_init_trx_antenna_setting(p_dm_odm); + phydm_init_soft_ml_setting(p_dm_odm); + + p_dm_odm->phydm_period = PHYDM_WATCH_DOG_PERIOD; + p_dm_odm->phydm_sys_up_time = 0; + + if (p_dm_odm->support_ic_type & ODM_IC_1SS) + p_dm_odm->num_rf_path = 1; + else if (p_dm_odm->support_ic_type & ODM_IC_2SS) + p_dm_odm->num_rf_path = 2; + else if (p_dm_odm->support_ic_type & ODM_IC_3SS) + p_dm_odm->num_rf_path = 3; + else if (p_dm_odm->support_ic_type & ODM_IC_4SS) + p_dm_odm->num_rf_path = 4; + + p_dm_odm->tx_rate = 0xFF; + + p_dm_odm->number_linked_client = 0; + p_dm_odm->pre_number_linked_client = 0; + p_dm_odm->number_active_client = 0; + p_dm_odm->pre_number_active_client = 0; + + p_dm_odm->last_tx_ok_cnt = 0; + p_dm_odm->last_rx_ok_cnt = 0; + p_dm_odm->tx_tp = 0; + p_dm_odm->rx_tp = 0; + p_dm_odm->total_tp = 0; + p_dm_odm->traffic_load = TRAFFIC_LOW; + + p_dm_odm->nbi_set_result = 0; + p_dm_odm->is_init_hw_info_by_rfe = false; + +} + +static void +odm_common_info_self_update( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u8 entry_cnt = 0, num_active_client = 0; + u32 i, one_entry_macid = 0, ma_rx_tp = 0; + struct sta_info *p_entry; + + if (*(p_dm_odm->p_band_width) == ODM_BW40M) { + if (*(p_dm_odm->p_sec_ch_offset) == 1) + p_dm_odm->control_channel = *(p_dm_odm->p_channel) - 2; + else if (*(p_dm_odm->p_sec_ch_offset) == 2) + p_dm_odm->control_channel = *(p_dm_odm->p_channel) + 2; + } else + p_dm_odm->control_channel = *(p_dm_odm->p_channel); + + for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { + p_entry = p_dm_odm->p_odm_sta_info[i]; + if (IS_STA_VALID(p_entry)) { + entry_cnt++; + if (entry_cnt == 1) + one_entry_macid = i; + } + } + + if (entry_cnt == 1) { + p_dm_odm->is_one_entry_only = true; + p_dm_odm->one_entry_macid = one_entry_macid; + } else + p_dm_odm->is_one_entry_only = false; + + p_dm_odm->pre_number_linked_client = p_dm_odm->number_linked_client; + p_dm_odm->pre_number_active_client = p_dm_odm->number_active_client; + + p_dm_odm->number_linked_client = entry_cnt; + p_dm_odm->number_active_client = num_active_client; + + /* Update MP driver status*/ + odm_update_mp_driver_status(p_dm_odm); + + /*Traffic load information update*/ + phydm_traffic_load_decision(p_dm_odm); + + p_dm_odm->phydm_sys_up_time += p_dm_odm->phydm_period; +} + +static void +odm_common_info_self_reset( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + p_dm_odm->phy_dbg_info.num_qry_beacon_pkt = 0; +} + +void * +phydm_get_structure( + struct PHY_DM_STRUCT *p_dm_odm, + u8 structure_type +) + +{ + void *p_struct = NULL; + + switch (structure_type) { + case PHYDMfalseALMCNT: + p_struct = &(p_dm_odm->false_alm_cnt); + break; + case PHYDM_CFOTRACK: + p_struct = &(p_dm_odm->dm_cfo_track); + break; + case PHYDM_ADAPTIVITY: + p_struct = &(p_dm_odm->adaptivity); + break; + default: + break; + } + + return p_struct; +} + +static void +odm_hw_setting( + struct PHY_DM_STRUCT *p_dm_odm +) +{ +} +#if SUPPORTABLITY_PHYDMLIZE +static void +phydm_supportability_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 support_ability = 0; + + if (p_dm_odm->support_ic_type != ODM_RTL8821C) + return; + + switch (p_dm_odm->support_ic_type) { + + /*---------------N Series--------------------*/ + case ODM_RTL8188E: + support_ability |= + ODM_BB_DIG | + ODM_BB_RA_MASK | + ODM_BB_DYNAMIC_TXPWR | + ODM_BB_FA_CNT | + ODM_BB_RSSI_MONITOR | + ODM_BB_CCK_PD | + ODM_RF_TX_PWR_TRACK | + ODM_RF_RX_GAIN_TRACK | + ODM_RF_CALIBRATION | + ODM_BB_CFO_TRACKING | + ODM_BB_NHM_CNT | + ODM_BB_PRIMARY_CCA; + break; + + case ODM_RTL8192E: + support_ability |= + ODM_BB_DIG | + ODM_RF_TX_PWR_TRACK | + ODM_BB_RA_MASK | + ODM_BB_FA_CNT | + ODM_BB_RSSI_MONITOR | + ODM_BB_CFO_TRACKING | + /* ODM_BB_PWR_TRAIN |*/ + ODM_BB_NHM_CNT | + ODM_BB_PRIMARY_CCA; + break; + + case ODM_RTL8723B: + support_ability |= + ODM_BB_DIG | + ODM_BB_RA_MASK | + ODM_BB_FA_CNT | + ODM_BB_RSSI_MONITOR | + ODM_BB_CCK_PD | + ODM_RF_TX_PWR_TRACK | + ODM_RF_RX_GAIN_TRACK | + ODM_RF_CALIBRATION | + ODM_BB_CFO_TRACKING | + /* ODM_BB_PWR_TRAIN |*/ + ODM_BB_NHM_CNT; + break; + + case ODM_RTL8703B: + support_ability |= + ODM_BB_DIG | + ODM_BB_RA_MASK | + ODM_BB_FA_CNT | + ODM_BB_RSSI_MONITOR | + ODM_BB_CCK_PD | + ODM_BB_CFO_TRACKING | + /* ODM_BB_PWR_TRAIN | */ + ODM_BB_NHM_CNT | + ODM_RF_TX_PWR_TRACK | + /* ODM_RF_RX_GAIN_TRACK | */ + ODM_RF_CALIBRATION; + break; + + case ODM_RTL8723D: + support_ability |= + ODM_BB_DIG | + ODM_BB_RA_MASK | + ODM_BB_FA_CNT | + ODM_BB_RSSI_MONITOR | + ODM_BB_CCK_PD | + ODM_BB_CFO_TRACKING | + /* ODM_BB_PWR_TRAIN | */ + ODM_BB_NHM_CNT | + ODM_RF_TX_PWR_TRACK; + /* ODM_RF_RX_GAIN_TRACK | */ + /* ODM_RF_CALIBRATION | */ + break; + + case ODM_RTL8188F: + support_ability |= + ODM_BB_DIG | + ODM_BB_RA_MASK | + ODM_BB_FA_CNT | + ODM_BB_RSSI_MONITOR | + ODM_BB_CCK_PD | + ODM_BB_CFO_TRACKING | + ODM_BB_NHM_CNT | + ODM_RF_TX_PWR_TRACK | + ODM_RF_CALIBRATION; + break; + /*---------------AC Series-------------------*/ + + case ODM_RTL8812: + case ODM_RTL8821: + support_ability |= + ODM_BB_DIG | + ODM_BB_FA_CNT | + ODM_BB_RSSI_MONITOR | + ODM_BB_RA_MASK | + ODM_RF_TX_PWR_TRACK | + ODM_BB_CFO_TRACKING | + /* ODM_BB_PWR_TRAIN |*/ + ODM_BB_DYNAMIC_TXPWR | + ODM_BB_NHM_CNT; + break; + + case ODM_RTL8814A: + support_ability |= + ODM_BB_DIG | + ODM_BB_FA_CNT | + ODM_BB_RSSI_MONITOR | + ODM_BB_RA_MASK | + ODM_RF_TX_PWR_TRACK | + ODM_BB_CCK_PD | + ODM_BB_CFO_TRACKING | + ODM_BB_DYNAMIC_TXPWR | + ODM_BB_NHM_CNT; + break; + + case ODM_RTL8822B: + support_ability |= + ODM_BB_DIG | + ODM_BB_FA_CNT | + ODM_BB_CCK_PD | + ODM_BB_CFO_TRACKING | + ODM_BB_RATE_ADAPTIVE | + ODM_BB_RSSI_MONITOR | + ODM_BB_RA_MASK | + ODM_RF_TX_PWR_TRACK; + break; + + case ODM_RTL8821C: + support_ability |= + ODM_BB_DIG | + ODM_BB_RA_MASK | + ODM_BB_CCK_PD | + ODM_BB_FA_CNT | + ODM_BB_RSSI_MONITOR | + ODM_BB_RATE_ADAPTIVE | + ODM_RF_TX_PWR_TRACK | + ODM_MAC_EDCA_TURBO | + ODM_BB_CFO_TRACKING; + break; + default: + dbg_print("[Warning] Supportability Init error !!!\n"); + break; + + } + + if (*(p_dm_odm->p_enable_antdiv)) + support_ability |= ODM_BB_ANT_DIV; + + if (*(p_dm_odm->p_enable_adaptivity)) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("ODM adaptivity is set to Enabled!!!\n")); + + support_ability |= ODM_BB_ADAPTIVITY; + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("ODM adaptivity is set to disnabled!!!\n")); + /**/ + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("PHYDM support_ability = ((0x%x))\n", support_ability)); + odm_cmn_info_init(p_dm_odm, ODM_CMNINFO_ABILITY, support_ability); +} +#endif + +/* + * 2011/09/21 MH Add to describe different team necessary resource allocate?? + * */ +void +odm_dm_init( + struct PHY_DM_STRUCT *p_dm_odm +) +{ +#if SUPPORTABLITY_PHYDMLIZE + phydm_supportability_init(p_dm_odm); +#endif + odm_common_info_self_init(p_dm_odm); + odm_dig_init(p_dm_odm); + phydm_nhm_counter_statistics_init(p_dm_odm); + phydm_adaptivity_init(p_dm_odm); + phydm_ra_info_init(p_dm_odm); + odm_rate_adaptive_mask_init(p_dm_odm); + odm_cfo_tracking_init(p_dm_odm); +#if PHYDM_SUPPORT_EDCA + odm_edca_turbo_init(p_dm_odm); +#endif + odm_rssi_monitor_init(p_dm_odm); + phydm_rf_init(p_dm_odm); + odm_txpowertracking_init(p_dm_odm); + + odm_antenna_diversity_init(p_dm_odm); +#if (CONFIG_DYNAMIC_RX_PATH == 1) + phydm_dynamic_rx_path_init(p_dm_odm); +#endif + odm_auto_channel_select_init(p_dm_odm); + odm_path_diversity_init(p_dm_odm); + odm_dynamic_tx_power_init(p_dm_odm); + phydm_init_ra_info(p_dm_odm); +#if (PHYDM_LA_MODE_SUPPORT == 1) + adc_smp_init(p_dm_odm); +#endif + + +#ifdef BEAMFORMING_VERSION_1 + if (p_hal_data->beamforming_version == BEAMFORMING_VERSION_1) +#endif + { + phydm_beamforming_init(p_dm_odm); + } + + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { +#if (defined(CONFIG_BB_POWER_SAVING)) + odm_dynamic_bb_power_saving_init(p_dm_odm); +#endif + + if (p_dm_odm->support_ic_type == ODM_RTL8188E) { + odm_primary_cca_init(p_dm_odm); + odm_ra_info_init_all(p_dm_odm); + } + } +} + +void +odm_dm_reset( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + + odm_ant_div_reset(p_dm_odm); + phydm_set_edcca_threshold_api(p_dm_odm, p_dm_dig_table->cur_ig_value); +} + + +void +phydm_support_ability_debug( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 pre_support_ability; + u32 used = *_used; + u32 out_len = *_out_len; + + pre_support_ability = p_dm_odm->support_ability ; + PHYDM_SNPRINTF((output + used, out_len - used, "\n%s\n", "================================")); + if (dm_value[0] == 100) { + PHYDM_SNPRINTF((output + used, out_len - used, "[Supportability] PhyDM Selection\n")); + PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "================================")); + PHYDM_SNPRINTF((output + used, out_len - used, "00. (( %s ))DIG\n", ((p_dm_odm->support_ability & ODM_BB_DIG) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "01. (( %s ))RA_MASK\n", ((p_dm_odm->support_ability & ODM_BB_RA_MASK) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "02. (( %s ))DYNAMIC_TXPWR\n", ((p_dm_odm->support_ability & ODM_BB_DYNAMIC_TXPWR) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "03. (( %s ))FA_CNT\n", ((p_dm_odm->support_ability & ODM_BB_FA_CNT) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "04. (( %s ))RSSI_MONITOR\n", ((p_dm_odm->support_ability & ODM_BB_RSSI_MONITOR) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "05. (( %s ))CCK_PD\n", ((p_dm_odm->support_ability & ODM_BB_CCK_PD) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "06. (( %s ))ANT_DIV\n", ((p_dm_odm->support_ability & ODM_BB_ANT_DIV) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "08. (( %s ))PWR_TRAIN\n", ((p_dm_odm->support_ability & ODM_BB_PWR_TRAIN) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "09. (( %s ))RATE_ADAPTIVE\n", ((p_dm_odm->support_ability & ODM_BB_RATE_ADAPTIVE) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "10. (( %s ))PATH_DIV\n", ((p_dm_odm->support_ability & ODM_BB_PATH_DIV) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "13. (( %s ))ADAPTIVITY\n", ((p_dm_odm->support_ability & ODM_BB_ADAPTIVITY) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "14. (( %s ))struct _CFO_TRACKING_\n", ((p_dm_odm->support_ability & ODM_BB_CFO_TRACKING) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "15. (( %s ))NHM_CNT\n", ((p_dm_odm->support_ability & ODM_BB_NHM_CNT) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "16. (( %s ))PRIMARY_CCA\n", ((p_dm_odm->support_ability & ODM_BB_PRIMARY_CCA) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "17. (( %s ))TXBF\n", ((p_dm_odm->support_ability & ODM_BB_TXBF) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "18. (( %s ))DYNAMIC_ARFR\n", ((p_dm_odm->support_ability & ODM_BB_DYNAMIC_ARFR) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "20. (( %s ))EDCA_TURBO\n", ((p_dm_odm->support_ability & ODM_MAC_EDCA_TURBO) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "21. (( %s ))DYNAMIC_RX_PATH\n", ((p_dm_odm->support_ability & ODM_BB_DYNAMIC_RX_PATH) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "24. (( %s ))TX_PWR_TRACK\n", ((p_dm_odm->support_ability & ODM_RF_TX_PWR_TRACK) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "25. (( %s ))RX_GAIN_TRACK\n", ((p_dm_odm->support_ability & ODM_RF_RX_GAIN_TRACK) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "26. (( %s ))RF_CALIBRATION\n", ((p_dm_odm->support_ability & ODM_RF_CALIBRATION) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "================================")); + } + /* + else if(dm_value[0] == 101) + { + p_dm_odm->support_ability = 0 ; + dbg_print("Disable all support_ability components\n"); + PHYDM_SNPRINTF((output+used, out_len-used,"%s\n", "Disable all support_ability components")); + } + */ + else { + + if (dm_value[1] == 1) { /* enable */ + p_dm_odm->support_ability |= BIT(dm_value[0]) ; + if (BIT(dm_value[0]) & ODM_BB_PATH_DIV) + odm_path_diversity_init(p_dm_odm); + } else if (dm_value[1] == 2) /* disable */ + p_dm_odm->support_ability &= ~(BIT(dm_value[0])) ; + else { + /* dbg_print("\n[Warning!!!] 1:enable, 2:disable \n\n"); */ + PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "[Warning!!!] 1:enable, 2:disable")); + } + } + PHYDM_SNPRINTF((output + used, out_len - used, "pre-support_ability = 0x%x\n", pre_support_ability)); + PHYDM_SNPRINTF((output + used, out_len - used, "Curr-support_ability = 0x%x\n", p_dm_odm->support_ability)); + PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "================================")); +} + +void +phydm_watchdog_mp( + struct PHY_DM_STRUCT *p_dm_odm +) +{ +#if (CONFIG_DYNAMIC_RX_PATH == 1) + phydm_dynamic_rx_path_caller(p_dm_odm); +#endif +} +/* + * 2011/09/20 MH This is the entry pointer for all team to execute HW out source DM. + * You can not add any dummy function here, be care, you can only use DM structure + * to perform any new ODM_DM. + * */ +void +odm_dm_watchdog( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + odm_common_info_self_update(p_dm_odm); + phydm_basic_dbg_message(p_dm_odm); + phydm_receiver_blocking(p_dm_odm); + odm_hw_setting(p_dm_odm); + + odm_false_alarm_counter_statistics(p_dm_odm); + phydm_noisy_detection(p_dm_odm); + + odm_rssi_monitor_check(p_dm_odm); + + if (*(p_dm_odm->p_is_power_saving) == true) { + odm_dig_by_rssi_lps(p_dm_odm); + phydm_adaptivity(p_dm_odm); + odm_antenna_diversity(p_dm_odm); /*enable AntDiv in PS mode, request from SD4 Jeff*/ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("DMWatchdog in power saving mode\n")); + return; + } + + phydm_check_adaptivity(p_dm_odm); + odm_update_power_training_state(p_dm_odm); + odm_DIG(p_dm_odm); + phydm_adaptivity(p_dm_odm); + odm_cck_packet_detection_thresh(p_dm_odm); + + phydm_ra_info_watchdog(p_dm_odm); +#if PHYDM_SUPPORT_EDCA + odm_edca_turbo_check(p_dm_odm); +#endif + odm_path_diversity(p_dm_odm); + odm_cfo_tracking(p_dm_odm); + odm_dynamic_tx_power(p_dm_odm); + odm_antenna_diversity(p_dm_odm); +#if (CONFIG_DYNAMIC_RX_PATH == 1) + phydm_dynamic_rx_path(p_dm_odm); +#endif + + phydm_beamforming_watchdog(p_dm_odm); + + phydm_rf_watchdog(p_dm_odm); + + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + + if (p_dm_odm->support_ic_type == ODM_RTL8188E) + odm_dynamic_primary_cca(p_dm_odm); + } + odm_dtc(p_dm_odm); + + odm_common_info_self_reset(p_dm_odm); +} + +/* + * Init /.. Fixed HW value. Only init time. + * */ +void +odm_cmn_info_init( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_cmninfo_e cmn_info, + u32 value +) +{ + /* */ + /* This section is used for init value */ + /* */ + switch (cmn_info) { + /* */ + /* Fixed ODM value. */ + /* */ + case ODM_CMNINFO_ABILITY: + p_dm_odm->support_ability = (u32)value; + break; + + case ODM_CMNINFO_RF_TYPE: + p_dm_odm->rf_type = (u8)value; + break; + + case ODM_CMNINFO_PLATFORM: + p_dm_odm->support_platform = (u8)value; + break; + + case ODM_CMNINFO_INTERFACE: + p_dm_odm->support_interface = (u8)value; + break; + + case ODM_CMNINFO_MP_TEST_CHIP: + p_dm_odm->is_mp_chip = (u8)value; + break; + + case ODM_CMNINFO_IC_TYPE: + p_dm_odm->support_ic_type = value; + break; + + case ODM_CMNINFO_CUT_VER: + p_dm_odm->cut_version = (u8)value; + break; + + case ODM_CMNINFO_FAB_VER: + p_dm_odm->fab_version = (u8)value; + break; + + case ODM_CMNINFO_RFE_TYPE: + p_dm_odm->rfe_type = (u8)value; + phydm_init_hw_info_by_rfe(p_dm_odm); + break; + + case ODM_CMNINFO_RF_ANTENNA_TYPE: + p_dm_odm->ant_div_type = (u8)value; + break; + + case ODM_CMNINFO_WITH_EXT_ANTENNA_SWITCH: + p_dm_odm->with_extenal_ant_switch = (u8)value; + break; + + case ODM_CMNINFO_BE_FIX_TX_ANT: + p_dm_odm->dm_fat_table.b_fix_tx_ant = (u8)value; + break; + + case ODM_CMNINFO_BOARD_TYPE: + if (!p_dm_odm->is_init_hw_info_by_rfe) + p_dm_odm->board_type = (u8)value; + break; + + case ODM_CMNINFO_PACKAGE_TYPE: + if (!p_dm_odm->is_init_hw_info_by_rfe) + p_dm_odm->package_type = (u8)value; + break; + + case ODM_CMNINFO_EXT_LNA: + if (!p_dm_odm->is_init_hw_info_by_rfe) + p_dm_odm->ext_lna = (u8)value; + break; + + case ODM_CMNINFO_5G_EXT_LNA: + if (!p_dm_odm->is_init_hw_info_by_rfe) + p_dm_odm->ext_lna_5g = (u8)value; + break; + + case ODM_CMNINFO_EXT_PA: + if (!p_dm_odm->is_init_hw_info_by_rfe) + p_dm_odm->ext_pa = (u8)value; + break; + + case ODM_CMNINFO_5G_EXT_PA: + if (!p_dm_odm->is_init_hw_info_by_rfe) + p_dm_odm->ext_pa_5g = (u8)value; + break; + + case ODM_CMNINFO_GPA: + if (!p_dm_odm->is_init_hw_info_by_rfe) + p_dm_odm->type_gpa = (u16)value; + break; + + case ODM_CMNINFO_APA: + if (!p_dm_odm->is_init_hw_info_by_rfe) + p_dm_odm->type_apa = (u16)value; + break; + + case ODM_CMNINFO_GLNA: + if (!p_dm_odm->is_init_hw_info_by_rfe) + p_dm_odm->type_glna = (u16)value; + break; + + case ODM_CMNINFO_ALNA: + if (!p_dm_odm->is_init_hw_info_by_rfe) + p_dm_odm->type_alna = (u16)value; + break; + + case ODM_CMNINFO_EXT_TRSW: + if (!p_dm_odm->is_init_hw_info_by_rfe) + p_dm_odm->ext_trsw = (u8)value; + break; + case ODM_CMNINFO_EXT_LNA_GAIN: + p_dm_odm->ext_lna_gain = (u8)value; + break; + case ODM_CMNINFO_PATCH_ID: + p_dm_odm->patch_id = (u8)value; + break; + case ODM_CMNINFO_BINHCT_TEST: + p_dm_odm->is_in_hct_test = (bool)value; + break; + case ODM_CMNINFO_BWIFI_TEST: + p_dm_odm->wifi_test = (u8)value; + break; + case ODM_CMNINFO_SMART_CONCURRENT: + p_dm_odm->is_dual_mac_smart_concurrent = (bool)value; + break; + case ODM_CMNINFO_DOMAIN_CODE_2G: + p_dm_odm->odm_regulation_2_4g = (u8)value; + break; + case ODM_CMNINFO_DOMAIN_CODE_5G: + p_dm_odm->odm_regulation_5g = (u8)value; + break; + case ODM_CMNINFO_CONFIG_BB_RF: + p_dm_odm->config_bbrf = (bool)value; + break; + case ODM_CMNINFO_IQKFWOFFLOAD: + p_dm_odm->iqk_fw_offload = (u8)value; + break; + case ODM_CMNINFO_IQKPAOFF: + p_dm_odm->rf_calibrate_info.is_iqk_pa_off = (bool)value; + break; + case ODM_CMNINFO_REGRFKFREEENABLE: + p_dm_odm->rf_calibrate_info.reg_rf_kfree_enable = (u8)value; + break; + case ODM_CMNINFO_RFKFREEENABLE: + p_dm_odm->rf_calibrate_info.rf_kfree_enable = (u8)value; + break; + case ODM_CMNINFO_NORMAL_RX_PATH_CHANGE: + p_dm_odm->normal_rx_path = (u8)value; + break; + case ODM_CMNINFO_EFUSE0X3D8: + p_dm_odm->efuse0x3d8 = (u8)value; + break; + case ODM_CMNINFO_EFUSE0X3D7: + p_dm_odm->efuse0x3d7 = (u8)value; + break; +#ifdef CONFIG_PHYDM_DFS_MASTER + case ODM_CMNINFO_DFS_REGION_DOMAIN: + p_dm_odm->dfs_region_domain = (u8)value; + break; +#endif + /* To remove the compiler warning, must add an empty default statement to handle the other values. */ + default: + /* do nothing */ + break; + + } + +} + + +void +odm_cmn_info_hook( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_cmninfo_e cmn_info, + void *p_value +) +{ + /* */ + /* Hook call by reference pointer. */ + /* */ + switch (cmn_info) { + /* */ + /* Dynamic call by reference pointer. */ + /* */ + case ODM_CMNINFO_MAC_PHY_MODE: + p_dm_odm->p_mac_phy_mode = (u8 *)p_value; + break; + + case ODM_CMNINFO_TX_UNI: + p_dm_odm->p_num_tx_bytes_unicast = (u64 *)p_value; + break; + + case ODM_CMNINFO_RX_UNI: + p_dm_odm->p_num_rx_bytes_unicast = (u64 *)p_value; + break; + + case ODM_CMNINFO_WM_MODE: + p_dm_odm->p_wireless_mode = (u8 *)p_value; + break; + + case ODM_CMNINFO_BAND: + p_dm_odm->p_band_type = (u8 *)p_value; + break; + + case ODM_CMNINFO_SEC_CHNL_OFFSET: + p_dm_odm->p_sec_ch_offset = (u8 *)p_value; + break; + + case ODM_CMNINFO_SEC_MODE: + p_dm_odm->p_security = (u8 *)p_value; + break; + + case ODM_CMNINFO_BW: + p_dm_odm->p_band_width = (u8 *)p_value; + break; + + case ODM_CMNINFO_CHNL: + p_dm_odm->p_channel = (u8 *)p_value; + break; + + case ODM_CMNINFO_DMSP_GET_VALUE: + p_dm_odm->p_is_get_value_from_other_mac = (bool *)p_value; + break; + + case ODM_CMNINFO_BUDDY_ADAPTOR: + p_dm_odm->p_buddy_adapter = (struct _ADAPTER **)p_value; + break; + + case ODM_CMNINFO_DMSP_IS_MASTER: + p_dm_odm->p_is_master_of_dmsp = (bool *)p_value; + break; + + case ODM_CMNINFO_SCAN: + p_dm_odm->p_is_scan_in_process = (bool *)p_value; + break; + + case ODM_CMNINFO_POWER_SAVING: + p_dm_odm->p_is_power_saving = (bool *)p_value; + break; + + case ODM_CMNINFO_ONE_PATH_CCA: + p_dm_odm->p_one_path_cca = (u8 *)p_value; + break; + + case ODM_CMNINFO_DRV_STOP: + p_dm_odm->p_is_driver_stopped = (bool *)p_value; + break; + + case ODM_CMNINFO_PNP_IN: + p_dm_odm->p_is_driver_is_going_to_pnp_set_power_sleep = (bool *)p_value; + break; + + case ODM_CMNINFO_INIT_ON: + p_dm_odm->pinit_adpt_in_progress = (bool *)p_value; + break; + + case ODM_CMNINFO_ANT_TEST: + p_dm_odm->p_antenna_test = (u8 *)p_value; + break; + + case ODM_CMNINFO_NET_CLOSED: + p_dm_odm->p_is_net_closed = (bool *)p_value; + break; + + case ODM_CMNINFO_FORCED_RATE: + p_dm_odm->p_forced_data_rate = (u16 *)p_value; + break; + case ODM_CMNINFO_ANT_DIV: + p_dm_odm->p_enable_antdiv = (u8 *)p_value; + break; + case ODM_CMNINFO_ADAPTIVITY: + p_dm_odm->p_enable_adaptivity = (u8 *)p_value; + break; + case ODM_CMNINFO_FORCED_IGI_LB: + p_dm_odm->pu1_forced_igi_lb = (u8 *)p_value; + break; + + case ODM_CMNINFO_P2P_LINK: + p_dm_odm->dm_dig_table.is_p2p_in_process = (u8 *)p_value; + break; + + case ODM_CMNINFO_IS1ANTENNA: + p_dm_odm->p_is_1_antenna = (bool *)p_value; + break; + + case ODM_CMNINFO_RFDEFAULTPATH: + p_dm_odm->p_rf_default_path = (u8 *)p_value; + break; + + case ODM_CMNINFO_FCS_MODE: + p_dm_odm->p_is_fcs_mode_enable = (bool *)p_value; + break; + /*add by YuChen for beamforming PhyDM*/ + case ODM_CMNINFO_HUBUSBMODE: + p_dm_odm->hub_usb_mode = (u8 *)p_value; + break; + case ODM_CMNINFO_FWDWRSVDPAGEINPROGRESS: + p_dm_odm->p_is_fw_dw_rsvd_page_in_progress = (bool *)p_value; + break; + case ODM_CMNINFO_TX_TP: + p_dm_odm->p_current_tx_tp = (u32 *)p_value; + break; + case ODM_CMNINFO_RX_TP: + p_dm_odm->p_current_rx_tp = (u32 *)p_value; + break; + case ODM_CMNINFO_SOUNDING_SEQ: + p_dm_odm->p_sounding_seq = (u8 *)p_value; + break; +#ifdef CONFIG_PHYDM_DFS_MASTER + case ODM_CMNINFO_DFS_MASTER_ENABLE: + p_dm_odm->dfs_master_enabled = (u8 *)p_value; + break; +#endif + case ODM_CMNINFO_FORCE_TX_ANT_BY_TXDESC: + p_dm_odm->dm_fat_table.p_force_tx_ant_by_desc = (u8 *)p_value; + break; + case ODM_CMNINFO_SET_S0S1_DEFAULT_ANTENNA: + p_dm_odm->dm_fat_table.p_default_s0_s1 = (u8 *)p_value; + break; + + default: + /*do nothing*/ + break; + + } + +} + + +void +odm_cmn_info_ptr_array_hook( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_cmninfo_e cmn_info, + u16 index, + void *p_value +) +{ + /*Hook call by reference pointer.*/ + switch (cmn_info) { + /*Dynamic call by reference pointer. */ + case ODM_CMNINFO_STA_STATUS: + p_dm_odm->p_odm_sta_info[index] = (struct sta_info *)p_value; + + if (IS_STA_VALID(p_dm_odm->p_odm_sta_info[index])) + p_dm_odm->platform2phydm_macid_table[((struct sta_info *)p_value)->mac_id] = index; + + break; + /* To remove the compiler warning, must add an empty default statement to handle the other values. */ + default: + /* do nothing */ + break; + } + +} + + +/* + * Update band/CHannel/.. The values are dynamic but non-per-packet. + * */ +void +odm_cmn_info_update( + struct PHY_DM_STRUCT *p_dm_odm, + u32 cmn_info, + u64 value +) +{ + /* */ + /* This init variable may be changed in run time. */ + /* */ + switch (cmn_info) { + case ODM_CMNINFO_LINK_IN_PROGRESS: + p_dm_odm->is_link_in_process = (bool)value; + break; + + case ODM_CMNINFO_ABILITY: + p_dm_odm->support_ability = (u32)value; + break; + + case ODM_CMNINFO_RF_TYPE: + p_dm_odm->rf_type = (u8)value; + break; + + case ODM_CMNINFO_WIFI_DIRECT: + p_dm_odm->is_wifi_direct = (bool)value; + break; + + case ODM_CMNINFO_WIFI_DISPLAY: + p_dm_odm->is_wifi_display = (bool)value; + break; + + case ODM_CMNINFO_LINK: + p_dm_odm->is_linked = (bool)value; + break; + + case ODM_CMNINFO_STATION_STATE: + p_dm_odm->bsta_state = (bool)value; + break; + + case ODM_CMNINFO_RSSI_MIN: + p_dm_odm->rssi_min = (u8)value; + break; + + case ODM_CMNINFO_DBG_COMP: + p_dm_odm->debug_components = (u32)value; + break; + + case ODM_CMNINFO_DBG_LEVEL: + p_dm_odm->debug_level = (u32)value; + break; + case ODM_CMNINFO_RA_THRESHOLD_HIGH: + p_dm_odm->rate_adaptive.high_rssi_thresh = (u8)value; + break; + + case ODM_CMNINFO_RA_THRESHOLD_LOW: + p_dm_odm->rate_adaptive.low_rssi_thresh = (u8)value; + break; +#if defined(BT_SUPPORT) && (BT_SUPPORT == 1) + /* The following is for BT HS mode and BT coexist mechanism. */ + case ODM_CMNINFO_BT_ENABLED: + p_dm_odm->is_bt_enabled = (bool)value; + break; + + case ODM_CMNINFO_BT_HS_CONNECT_PROCESS: + p_dm_odm->is_bt_connect_process = (bool)value; + break; + + case ODM_CMNINFO_BT_HS_RSSI: + p_dm_odm->bt_hs_rssi = (u8)value; + break; + + case ODM_CMNINFO_BT_OPERATION: + p_dm_odm->is_bt_hs_operation = (bool)value; + break; + + case ODM_CMNINFO_BT_LIMITED_DIG: + p_dm_odm->is_bt_limited_dig = (bool)value; + break; + + case ODM_CMNINFO_BT_DIG: + p_dm_odm->bt_hs_dig_val = (u8)value; + break; + + case ODM_CMNINFO_BT_BUSY: + p_dm_odm->is_bt_busy = (bool)value; + break; + + case ODM_CMNINFO_BT_DISABLE_EDCA: + p_dm_odm->is_bt_disable_edca_turbo = (bool)value; + break; +#endif + case ODM_CMNINFO_AP_TOTAL_NUM: + p_dm_odm->ap_total_num = (u8)value; + break; + + case ODM_CMNINFO_POWER_TRAINING: + p_dm_odm->is_disable_power_training = (bool)value; + break; + +#ifdef CONFIG_PHYDM_DFS_MASTER + case ODM_CMNINFO_DFS_REGION_DOMAIN: + p_dm_odm->dfs_region_domain = (u8)value; + break; +#endif + default: + /* do nothing */ + break; + } +} + +u32 +phydm_cmn_info_query( + struct PHY_DM_STRUCT *p_dm_odm, + enum phydm_info_query_e info_type +) +{ + struct false_ALARM_STATISTICS *false_alm_cnt = (struct false_ALARM_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDMfalseALMCNT); + + switch (info_type) { + case PHYDM_INFO_FA_OFDM: + return false_alm_cnt->cnt_ofdm_fail; + + case PHYDM_INFO_FA_CCK: + return false_alm_cnt->cnt_cck_fail; + + case PHYDM_INFO_FA_TOTAL: + return false_alm_cnt->cnt_all; + + case PHYDM_INFO_CCA_OFDM: + return false_alm_cnt->cnt_ofdm_cca; + + case PHYDM_INFO_CCA_CCK: + return false_alm_cnt->cnt_cck_cca; + + case PHYDM_INFO_CCA_ALL: + return false_alm_cnt->cnt_cca_all; + + case PHYDM_INFO_CRC32_OK_VHT: + return false_alm_cnt->cnt_vht_crc32_ok; + + case PHYDM_INFO_CRC32_OK_HT: + return false_alm_cnt->cnt_ht_crc32_ok; + + case PHYDM_INFO_CRC32_OK_LEGACY: + return false_alm_cnt->cnt_ofdm_crc32_ok; + + case PHYDM_INFO_CRC32_OK_CCK: + return false_alm_cnt->cnt_cck_crc32_ok; + + case PHYDM_INFO_CRC32_ERROR_VHT: + return false_alm_cnt->cnt_vht_crc32_error; + + case PHYDM_INFO_CRC32_ERROR_HT: + return false_alm_cnt->cnt_ht_crc32_error; + + case PHYDM_INFO_CRC32_ERROR_LEGACY: + return false_alm_cnt->cnt_ofdm_crc32_error; + + case PHYDM_INFO_CRC32_ERROR_CCK: + return false_alm_cnt->cnt_cck_crc32_error; + + case PHYDM_INFO_EDCCA_FLAG: + return false_alm_cnt->edcca_flag; + + case PHYDM_INFO_OFDM_ENABLE: + return false_alm_cnt->ofdm_block_enable; + + case PHYDM_INFO_CCK_ENABLE: + return false_alm_cnt->cck_block_enable; + + case PHYDM_INFO_DBG_PORT_0: + return false_alm_cnt->dbg_port0; + + default: + return 0xffffffff; + + } +} + +void +odm_init_all_timers( + struct PHY_DM_STRUCT *p_dm_odm +) +{ +#if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY)) + odm_ant_div_timers(p_dm_odm, INIT_ANTDIV_TIMMER); +#endif + +#if (CONFIG_DYNAMIC_RX_PATH == 1) + phydm_dynamic_rx_path_timers(p_dm_odm, INIT_DRP_TIMMER); +#endif + +#if (BEAMFORMING_SUPPORT == 1) + odm_initialize_timer(p_dm_odm, &p_dm_odm->beamforming_info.beamforming_timer, + (void *)beamforming_sw_timer_callback, NULL, "beamforming_timer"); +#endif +} + +void +odm_cancel_all_timers( + struct PHY_DM_STRUCT *p_dm_odm +) +{ +#if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY)) + odm_ant_div_timers(p_dm_odm, CANCEL_ANTDIV_TIMMER); +#endif + +#if (CONFIG_DYNAMIC_RX_PATH == 1) + phydm_dynamic_rx_path_timers(p_dm_odm, CANCEL_DRP_TIMMER); +#endif + +#if (BEAMFORMING_SUPPORT == 1) + odm_cancel_timer(p_dm_odm, &p_dm_odm->beamforming_info.beamforming_timer); +#endif +} + + +void +odm_release_all_timers( + struct PHY_DM_STRUCT *p_dm_odm +) +{ +#if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY)) + odm_ant_div_timers(p_dm_odm, RELEASE_ANTDIV_TIMMER); +#endif + +#if (CONFIG_DYNAMIC_RX_PATH == 1) + phydm_dynamic_rx_path_timers(p_dm_odm, RELEASE_DRP_TIMMER); +#endif + +#if (BEAMFORMING_SUPPORT == 1) + odm_release_timer(p_dm_odm, &p_dm_odm->beamforming_info.beamforming_timer); +#endif +} + + +/* 3============================================================ + * 3 Tx Power Tracking + * 3============================================================ */ + +/* need to ODM CE Platform + * move to here for ANT detection mechanism using */ + +u32 +get_psd_data( + struct PHY_DM_STRUCT *p_dm_odm, + unsigned int point, + u8 initial_gain_psd) +{ + /* unsigned int val, rfval; */ + /* int psd_report; */ + u32 psd_report; + + /* HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(adapter); */ + /* Debug Message */ + /* val = phy_query_bb_reg(adapter,0x908, MASKDWORD); */ + /* dbg_print("reg908 = 0x%x\n",val); */ + /* val = phy_query_bb_reg(adapter,0xDF4, MASKDWORD); */ + /* rfval = phy_query_rf_reg(adapter, ODM_RF_PATH_A, 0x00, RFREGOFFSETMASK); */ + /* dbg_print("RegDF4 = 0x%x, RFReg00 = 0x%x\n",val, rfval); */ + /* dbg_print("PHYTXON = %x, OFDMCCA_PP = %x, CCKCCA_PP = %x, RFReg00 = %x\n", */ + /* (val&BIT25)>>25, (val&BIT14)>>14, (val&BIT15)>>15, rfval); */ + + /* Set DCO frequency index, offset=(40MHz/SamplePts)*point */ + odm_set_bb_reg(p_dm_odm, 0x808, 0x3FF, point); + + /* Start PSD calculation, Reg808[22]=0->1 */ + odm_set_bb_reg(p_dm_odm, 0x808, BIT(22), 1); + /* Need to wait for HW PSD report */ + odm_stall_execution(1000); + odm_set_bb_reg(p_dm_odm, 0x808, BIT(22), 0); + /* Read PSD report, Reg8B4[15:0] */ + psd_report = odm_get_bb_reg(p_dm_odm, 0x8B4, MASKDWORD) & 0x0000FFFF; + + psd_report = (u32)(odm_convert_to_db(psd_report)) + (u32)(initial_gain_psd - 0x1c); + + return psd_report; +} + +u32 +odm_convert_to_db( + u32 value) +{ + u8 i; + u8 j; + u32 dB; + + value = value & 0xFFFF; + + for (i = 0; i < 12; i++) { + if (value <= db_invert_table[i][7]) + break; + } + + if (i >= 12) { + return 96; /* maximum 96 dB */ + } + + for (j = 0; j < 8; j++) { + if (value <= db_invert_table[i][j]) + break; + } + + dB = (i << 3) + j + 1; + + return dB; +} + +u32 +odm_convert_to_linear( + u32 value) +{ + u8 i; + u8 j; + u32 linear; + + /* 1dB~96dB */ + + value = value & 0xFF; + + i = (u8)((value - 1) >> 3); + j = (u8)(value - 1) - (i << 3); + + linear = db_invert_table[i][j]; + + return linear; +} + +/* + * ODM multi-port consideration, added by Roger, 2013.10.01. + * */ +void +odm_asoc_entry_init( + struct PHY_DM_STRUCT *p_dm_odm +) +{ +} + +/* Justin: According to the current RRSI to adjust Response Frame TX power, 2012/11/05 */ +void odm_dtc(struct PHY_DM_STRUCT *p_dm_odm) +{ +#ifdef CONFIG_DM_RESP_TXAGC +#define DTC_BASE 35 /* RSSI higher than this value, start to decade TX power */ +#define DTC_DWN_BASE (DTC_BASE-5) /* RSSI lower than this value, start to increase TX power */ + + /* RSSI vs TX power step mapping: decade TX power */ + static const u8 dtc_table_down[] = { + DTC_BASE, + (DTC_BASE + 5), + (DTC_BASE + 10), + (DTC_BASE + 15), + (DTC_BASE + 20), + (DTC_BASE + 25) + }; + + /* RSSI vs TX power step mapping: increase TX power */ + static const u8 dtc_table_up[] = { + DTC_DWN_BASE, + (DTC_DWN_BASE - 5), + (DTC_DWN_BASE - 10), + (DTC_DWN_BASE - 15), + (DTC_DWN_BASE - 15), + (DTC_DWN_BASE - 20), + (DTC_DWN_BASE - 20), + (DTC_DWN_BASE - 25), + (DTC_DWN_BASE - 25), + (DTC_DWN_BASE - 30), + (DTC_DWN_BASE - 35) + }; + + u8 i; + u8 dtc_steps = 0; + u8 sign; + u8 resp_txagc = 0; + + if (DTC_BASE < p_dm_odm->rssi_min) { + /* need to decade the CTS TX power */ + sign = 1; + for (i = 0; i < ARRAY_SIZE(dtc_table_down); i++) { + if ((dtc_table_down[i] >= p_dm_odm->rssi_min) || (dtc_steps >= 6)) + break; + else + dtc_steps++; + } + } else { + sign = 0; + dtc_steps = 0; + } + + resp_txagc = dtc_steps | (sign << 4); + resp_txagc = resp_txagc | (resp_txagc << 5); + odm_write_1byte(p_dm_odm, 0x06d9, resp_txagc); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_PWR_TRAIN, ODM_DBG_LOUD, ("%s rssi_min:%u, set RESP_TXAGC to %s %u\n", + __func__, p_dm_odm->rssi_min, sign ? "minus" : "plus", dtc_steps)); +#endif /* CONFIG_RESP_TXAGC_ADJUST */ +} + +void +odm_update_power_training_state( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + struct false_ALARM_STATISTICS *false_alm_cnt = (struct false_ALARM_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDMfalseALMCNT); + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + u32 score = 0; + + if (!(p_dm_odm->support_ability & ODM_BB_PWR_TRAIN)) + return; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("odm_update_power_training_state()============>\n")); + p_dm_odm->is_change_state = false; + + /* Debug command */ + if (p_dm_odm->force_power_training_state) { + if (p_dm_odm->force_power_training_state == 1 && !p_dm_odm->is_disable_power_training) { + p_dm_odm->is_change_state = true; + p_dm_odm->is_disable_power_training = true; + } else if (p_dm_odm->force_power_training_state == 2 && p_dm_odm->is_disable_power_training) { + p_dm_odm->is_change_state = true; + p_dm_odm->is_disable_power_training = false; + } + + p_dm_odm->PT_score = 0; + p_dm_odm->phy_dbg_info.num_qry_phy_status_ofdm = 0; + p_dm_odm->phy_dbg_info.num_qry_phy_status_cck = 0; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("odm_update_power_training_state(): force_power_training_state = %d\n", + p_dm_odm->force_power_training_state)); + return; + } + + if (!p_dm_odm->is_linked) + return; + + /* First connect */ + if ((p_dm_odm->is_linked) && (p_dm_dig_table->is_media_connect_0 == false)) { + p_dm_odm->PT_score = 0; + p_dm_odm->is_change_state = true; + p_dm_odm->phy_dbg_info.num_qry_phy_status_ofdm = 0; + p_dm_odm->phy_dbg_info.num_qry_phy_status_cck = 0; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("odm_update_power_training_state(): First Connect\n")); + return; + } + + /* Compute score */ + if (p_dm_odm->nhm_cnt_0 >= 215) + score = 2; + else if (p_dm_odm->nhm_cnt_0 >= 190) + score = 1; /* unknow state */ + else { + u32 rx_pkt_cnt; + + rx_pkt_cnt = (u32)(p_dm_odm->phy_dbg_info.num_qry_phy_status_ofdm) + (u32)(p_dm_odm->phy_dbg_info.num_qry_phy_status_cck); + + if ((false_alm_cnt->cnt_cca_all > 31 && rx_pkt_cnt > 31) && (false_alm_cnt->cnt_cca_all >= rx_pkt_cnt)) { + if ((rx_pkt_cnt + (rx_pkt_cnt >> 1)) <= false_alm_cnt->cnt_cca_all) + score = 0; + else if ((rx_pkt_cnt + (rx_pkt_cnt >> 2)) <= false_alm_cnt->cnt_cca_all) + score = 1; + else + score = 2; + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("odm_update_power_training_state(): rx_pkt_cnt = %d, cnt_cca_all = %d\n", + rx_pkt_cnt, false_alm_cnt->cnt_cca_all)); + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("odm_update_power_training_state(): num_qry_phy_status_ofdm = %d, num_qry_phy_status_cck = %d\n", + (u32)(p_dm_odm->phy_dbg_info.num_qry_phy_status_ofdm), (u32)(p_dm_odm->phy_dbg_info.num_qry_phy_status_cck))); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("odm_update_power_training_state(): nhm_cnt_0 = %d, score = %d\n", + p_dm_odm->nhm_cnt_0, score)); + + /* smoothing */ + p_dm_odm->PT_score = (score << 4) + (p_dm_odm->PT_score >> 1) + (p_dm_odm->PT_score >> 2); + score = (p_dm_odm->PT_score + 32) >> 6; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("odm_update_power_training_state(): PT_score = %d, score after smoothing = %d\n", + p_dm_odm->PT_score, score)); + + /* mode decision */ + if (score == 2) { + if (p_dm_odm->is_disable_power_training) { + p_dm_odm->is_change_state = true; + p_dm_odm->is_disable_power_training = false; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("odm_update_power_training_state(): Change state\n")); + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("odm_update_power_training_state(): Enable Power Training\n")); + } else if (score == 0) { + if (!p_dm_odm->is_disable_power_training) { + p_dm_odm->is_change_state = true; + p_dm_odm->is_disable_power_training = true; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("odm_update_power_training_state(): Change state\n")); + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("odm_update_power_training_state(): Disable Power Training\n")); + } + + p_dm_odm->phy_dbg_info.num_qry_phy_status_ofdm = 0; + p_dm_odm->phy_dbg_info.num_qry_phy_status_cck = 0; +} + + + +/*===========================================================*/ +/* The following is for compile only*/ +/*===========================================================*/ +/*#define TARGET_CHNL_NUM_2G_5G 59*/ +/*===========================================================*/ + +void +phydm_noisy_detection( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u32 total_fa_cnt, total_cca_cnt; + u32 score = 0, i, score_smooth; + + total_cca_cnt = p_dm_odm->false_alm_cnt.cnt_cca_all; + total_fa_cnt = p_dm_odm->false_alm_cnt.cnt_all; + + for (i = 0; i <= 16; i++) { + if (total_fa_cnt * 16 >= total_cca_cnt * (16 - i)) { + score = 16 - i; + break; + } + } + + /* noisy_decision_smooth = noisy_decision_smooth>>1 + (score<<3)>>1; */ + p_dm_odm->noisy_decision_smooth = (p_dm_odm->noisy_decision_smooth >> 1) + (score << 2); + + /* Round the noisy_decision_smooth: +"3" comes from (2^3)/2-1 */ + score_smooth = (total_cca_cnt >= 300) ? ((p_dm_odm->noisy_decision_smooth + 3) >> 3) : 0; + + p_dm_odm->noisy_decision = (score_smooth >= 3) ? 1 : 0; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_NOISY_DETECT, ODM_DBG_LOUD, + ("[NoisyDetection] total_cca_cnt=%d, total_fa_cnt=%d, noisy_decision_smooth=%d, score=%d, score_smooth=%d, p_dm_odm->noisy_decision=%d\n", + total_cca_cnt, total_fa_cnt, p_dm_odm->noisy_decision_smooth, score, score_smooth, p_dm_odm->noisy_decision)); + +} + +void +phydm_set_ext_switch( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 used = *_used; + u32 out_len = *_out_len; + u32 ext_ant_switch = dm_value[0]; + + if (p_dm_odm->support_ic_type & (ODM_RTL8821 | ODM_RTL8881A)) { + + /*Output Pin Settings*/ + odm_set_mac_reg(p_dm_odm, 0x4C, BIT(23), 0); /*select DPDT_P and DPDT_N as output pin*/ + odm_set_mac_reg(p_dm_odm, 0x4C, BIT(24), 1); /*by WLAN control*/ + + odm_set_bb_reg(p_dm_odm, 0xCB4, 0xF, 7); /*DPDT_P = 1b'0*/ + odm_set_bb_reg(p_dm_odm, 0xCB4, 0xF0, 7); /*DPDT_N = 1b'0*/ + + if (ext_ant_switch == MAIN_ANT) { + odm_set_bb_reg(p_dm_odm, 0xCB4, (BIT(29) | BIT(28)), 1); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("***8821A set ant switch = 2b'01 (Main)\n")); + } else if (ext_ant_switch == AUX_ANT) { + odm_set_bb_reg(p_dm_odm, 0xCB4, BIT(29) | BIT(28), 2); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("***8821A set ant switch = 2b'10 (Aux)\n")); + } + } +} + +static void +phydm_csi_mask_enable( + void *p_dm_void, + u32 enable +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 reg_value = 0; + + reg_value = (enable == CSI_MASK_ENABLE) ? 1 : 0; + + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + + odm_set_bb_reg(p_dm_odm, 0xD2C, BIT(28), reg_value); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("Enable CSI Mask: Reg 0xD2C[28] = ((0x%x))\n", reg_value)); + + } else if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + + odm_set_bb_reg(p_dm_odm, 0x874, BIT(0), reg_value); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("Enable CSI Mask: Reg 0x874[0] = ((0x%x))\n", reg_value)); + } + +} + +static void +phydm_clean_all_csi_mask( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + + odm_set_bb_reg(p_dm_odm, 0xD40, MASKDWORD, 0); + odm_set_bb_reg(p_dm_odm, 0xD44, MASKDWORD, 0); + odm_set_bb_reg(p_dm_odm, 0xD48, MASKDWORD, 0); + odm_set_bb_reg(p_dm_odm, 0xD4c, MASKDWORD, 0); + + } else if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + + odm_set_bb_reg(p_dm_odm, 0x880, MASKDWORD, 0); + odm_set_bb_reg(p_dm_odm, 0x884, MASKDWORD, 0); + odm_set_bb_reg(p_dm_odm, 0x888, MASKDWORD, 0); + odm_set_bb_reg(p_dm_odm, 0x88c, MASKDWORD, 0); + odm_set_bb_reg(p_dm_odm, 0x890, MASKDWORD, 0); + odm_set_bb_reg(p_dm_odm, 0x894, MASKDWORD, 0); + odm_set_bb_reg(p_dm_odm, 0x898, MASKDWORD, 0); + odm_set_bb_reg(p_dm_odm, 0x89c, MASKDWORD, 0); + } +} + +static void +phydm_set_csi_mask_reg( + void *p_dm_void, + u32 tone_idx_tmp, + u8 tone_direction +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 byte_offset, bit_offset; + u32 target_reg; + u8 reg_tmp_value; + u32 tone_num = 64; + u32 tone_num_shift = 0; + u32 csi_mask_reg_p = 0, csi_mask_reg_n = 0; + + /* calculate real tone idx*/ + if ((tone_idx_tmp % 10) >= 5) + tone_idx_tmp += 10; + + tone_idx_tmp = (tone_idx_tmp / 10); + + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + + tone_num = 64; + csi_mask_reg_p = 0xD40; + csi_mask_reg_n = 0xD48; + + } else if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + + tone_num = 128; + csi_mask_reg_p = 0x880; + csi_mask_reg_n = 0x890; + } + + if (tone_direction == FREQ_POSITIVE) { + + if (tone_idx_tmp >= (tone_num - 1)) + tone_idx_tmp = (tone_num - 1); + + byte_offset = (u8)(tone_idx_tmp >> 3); + bit_offset = (u8)(tone_idx_tmp & 0x7); + target_reg = csi_mask_reg_p + byte_offset; + + } else { + tone_num_shift = tone_num; + + if (tone_idx_tmp >= tone_num) + tone_idx_tmp = tone_num; + + tone_idx_tmp = tone_num - tone_idx_tmp; + + byte_offset = (u8)(tone_idx_tmp >> 3); + bit_offset = (u8)(tone_idx_tmp & 0x7); + target_reg = csi_mask_reg_n + byte_offset; + } + + reg_tmp_value = odm_read_1byte(p_dm_odm, target_reg); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("Pre Mask tone idx[%d]: Reg0x%x = ((0x%x))\n", (tone_idx_tmp + tone_num_shift), target_reg, reg_tmp_value)); + reg_tmp_value |= BIT(bit_offset); + odm_write_1byte(p_dm_odm, target_reg, reg_tmp_value); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("New Mask tone idx[%d]: Reg0x%x = ((0x%x))\n", (tone_idx_tmp + tone_num_shift), target_reg, reg_tmp_value)); +} + +static void +phydm_set_nbi_reg( + void *p_dm_void, + u32 tone_idx_tmp, + u32 bw +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 nbi_table_128[NBI_TABLE_SIZE_128] = {25, 55, 85, 115, 135, 155, 185, 205, 225, 245, /*1~10*/ /*tone_idx X 10*/ + 265, 285, 305, 335, 355, 375, 395, 415, 435, 455, /*11~20*/ + 485, 505, 525, 555, 585, 615, 635 + }; /*21~27*/ + + u32 nbi_table_256[NBI_TABLE_SIZE_256] = { 25, 55, 85, 115, 135, 155, 175, 195, 225, 245, /*1~10*/ + 265, 285, 305, 325, 345, 365, 385, 405, 425, 445, /*11~20*/ + 465, 485, 505, 525, 545, 565, 585, 605, 625, 645, /*21~30*/ + 665, 695, 715, 735, 755, 775, 795, 815, 835, 855, /*31~40*/ + 875, 895, 915, 935, 955, 975, 995, 1015, 1035, 1055, /*41~50*/ + 1085, 1105, 1125, 1145, 1175, 1195, 1225, 1255, 1275 + }; /*51~59*/ + + u32 reg_idx = 0; + u32 i; + u8 nbi_table_idx = FFT_128_TYPE; + + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) + + nbi_table_idx = FFT_128_TYPE; + else if (p_dm_odm->support_ic_type & ODM_IC_11AC_1_SERIES) + + nbi_table_idx = FFT_256_TYPE; + else if (p_dm_odm->support_ic_type & ODM_IC_11AC_2_SERIES) { + + if (bw == 80) + nbi_table_idx = FFT_256_TYPE; + else /*20M, 40M*/ + nbi_table_idx = FFT_128_TYPE; + } + + if (nbi_table_idx == FFT_128_TYPE) { + + for (i = 0; i < NBI_TABLE_SIZE_128; i++) { + if (tone_idx_tmp < nbi_table_128[i]) { + reg_idx = i + 1; + break; + } + } + + } else if (nbi_table_idx == FFT_256_TYPE) { + + for (i = 0; i < NBI_TABLE_SIZE_256; i++) { + if (tone_idx_tmp < nbi_table_256[i]) { + reg_idx = i + 1; + break; + } + } + } + + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + odm_set_bb_reg(p_dm_odm, 0xc40, 0x1f000000, reg_idx); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("Set tone idx: Reg0xC40[28:24] = ((0x%x))\n", reg_idx)); + /**/ + } else { + odm_set_bb_reg(p_dm_odm, 0x87c, 0xfc000, reg_idx); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("Set tone idx: Reg0x87C[19:14] = ((0x%x))\n", reg_idx)); + /**/ + } +} + + +static void +phydm_nbi_enable( + void *p_dm_void, + u32 enable +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 reg_value = 0; + + reg_value = (enable == NBI_ENABLE) ? 1 : 0; + + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + + odm_set_bb_reg(p_dm_odm, 0xc40, BIT(9), reg_value); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("Enable NBI Reg0xC40[9] = ((0x%x))\n", reg_value)); + + } else if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + + odm_set_bb_reg(p_dm_odm, 0x87c, BIT(13), reg_value); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("Enable NBI Reg0x87C[13] = ((0x%x))\n", reg_value)); + } +} + +static u8 +phydm_calculate_fc( + void *p_dm_void, + u32 channel, + u32 bw, + u32 second_ch, + u32 *fc_in +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 fc = *fc_in; + u32 start_ch_per_40m[NUM_START_CH_40M] = {36, 44, 52, 60, 100, 108, 116, 124, 132, 140, 149, 157, 165, 173}; + u32 start_ch_per_80m[NUM_START_CH_80M] = {36, 52, 100, 116, 132, 149, 165}; + u32 *p_start_ch = &(start_ch_per_40m[0]); + u32 num_start_channel = NUM_START_CH_40M; + u32 channel_offset = 0; + u32 i; + + /*2.4G*/ + if (channel <= 14 && channel > 0) { + + if (bw == 80) + return SET_ERROR; + + fc = 2412 + (channel - 1) * 5; + + if (bw == 40 && (second_ch == PHYDM_ABOVE)) { + + if (channel >= 10) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("CH = ((%d)), Scnd_CH = ((%d)) Error setting\n", channel, second_ch)); + return SET_ERROR; + } + fc += 10; + } else if (bw == 40 && (second_ch == PHYDM_BELOW)) { + + if (channel <= 2) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("CH = ((%d)), Scnd_CH = ((%d)) Error setting\n", channel, second_ch)); + return SET_ERROR; + } + fc -= 10; + } + } + /*5G*/ + else if (channel >= 36 && channel <= 177) { + + if (bw != 20) { + + if (bw == 40) { + num_start_channel = NUM_START_CH_40M; + p_start_ch = &(start_ch_per_40m[0]); + channel_offset = CH_OFFSET_40M; + } else if (bw == 80) { + num_start_channel = NUM_START_CH_80M; + p_start_ch = &(start_ch_per_80m[0]); + channel_offset = CH_OFFSET_80M; + } + + for (i = 0; i < num_start_channel; i++) { + + if (channel < p_start_ch[i + 1]) { + channel = p_start_ch[i] + channel_offset; + break; + } + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("Mod_CH = ((%d))\n", channel)); + } + + fc = 5180 + (channel - 36) * 5; + + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("CH = ((%d)) Error setting\n", channel)); + return SET_ERROR; + } + + *fc_in = fc; + + return SET_SUCCESS; +} + + +static u8 +phydm_calculate_intf_distance( + void *p_dm_void, + u32 bw, + u32 fc, + u32 f_interference, + u32 *p_tone_idx_tmp_in +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 bw_up, bw_low; + u32 int_distance; + u32 tone_idx_tmp; + u8 set_result = SET_NO_NEED; + + bw_up = fc + bw / 2; + bw_low = fc - bw / 2; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("[f_l, fc, fh] = [ %d, %d, %d ], f_int = ((%d))\n", bw_low, fc, bw_up, f_interference)); + + if ((f_interference >= bw_low) && (f_interference <= bw_up)) { + + int_distance = (fc >= f_interference) ? (fc - f_interference) : (f_interference - fc); + tone_idx_tmp = (int_distance << 5); /* =10*(int_distance /0.3125) */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("int_distance = ((%d MHz)) Mhz, tone_idx_tmp = ((%d.%d))\n", int_distance, (tone_idx_tmp / 10), (tone_idx_tmp % 10))); + *p_tone_idx_tmp_in = tone_idx_tmp; + set_result = SET_SUCCESS; + } + + return set_result; + +} + + +static u8 +phydm_csi_mask_setting( + void *p_dm_void, + u32 enable, + u32 channel, + u32 bw, + u32 f_interference, + u32 second_ch +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 fc; + u32 int_distance; + u8 tone_direction; + u32 tone_idx_tmp; + u8 set_result = SET_SUCCESS; + + if (enable == CSI_MASK_DISABLE) { + set_result = SET_SUCCESS; + phydm_clean_all_csi_mask(p_dm_odm); + + } else { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("[Set CSI MASK_] CH = ((%d)), BW = ((%d)), f_intf = ((%d)), Scnd_CH = ((%s))\n", + channel, bw, f_interference, (((bw == 20) || (channel > 14)) ? "Don't care" : (second_ch == PHYDM_ABOVE) ? "H" : "L"))); + + /*calculate fc*/ + if (phydm_calculate_fc(p_dm_odm, channel, bw, second_ch, &fc) == SET_ERROR) + set_result = SET_ERROR; + + else { + /*calculate interference distance*/ + if (phydm_calculate_intf_distance(p_dm_odm, bw, fc, f_interference, &tone_idx_tmp) == SET_SUCCESS) { + + tone_direction = (f_interference >= fc) ? FREQ_POSITIVE : FREQ_NEGATIVE; + phydm_set_csi_mask_reg(p_dm_odm, tone_idx_tmp, tone_direction); + set_result = SET_SUCCESS; + } else + set_result = SET_NO_NEED; + } + } + + if (set_result == SET_SUCCESS) + phydm_csi_mask_enable(p_dm_odm, enable); + else + phydm_csi_mask_enable(p_dm_odm, CSI_MASK_DISABLE); + + return set_result; +} + +u8 +phydm_nbi_setting( + void *p_dm_void, + u32 enable, + u32 channel, + u32 bw, + u32 f_interference, + u32 second_ch +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 fc; + u32 int_distance; + u32 tone_idx_tmp; + u8 set_result = SET_SUCCESS; + u32 bw_max = 40; + + if (enable == NBI_DISABLE) + set_result = SET_SUCCESS; + + else { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_API, ODM_DBG_LOUD, ("[Set NBI] CH = ((%d)), BW = ((%d)), f_intf = ((%d)), Scnd_CH = ((%s))\n", + channel, bw, f_interference, (((second_ch == PHYDM_DONT_CARE) || (bw == 20) || (channel > 14)) ? "Don't care" : (second_ch == PHYDM_ABOVE) ? "H" : "L"))); + + /*calculate fc*/ + if (phydm_calculate_fc(p_dm_odm, channel, bw, second_ch, &fc) == SET_ERROR) + set_result = SET_ERROR; + + else { + /*calculate interference distance*/ + if (phydm_calculate_intf_distance(p_dm_odm, bw, fc, f_interference, &tone_idx_tmp) == SET_SUCCESS) { + + phydm_set_nbi_reg(p_dm_odm, tone_idx_tmp, bw); + set_result = SET_SUCCESS; + } else + set_result = SET_NO_NEED; + } + } + + if (set_result == SET_SUCCESS) + phydm_nbi_enable(p_dm_odm, enable); + else + phydm_nbi_enable(p_dm_odm, NBI_DISABLE); + + return set_result; +} + +void +phydm_api_debug( + void *p_dm_void, + u32 function_map, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 used = *_used; + u32 out_len = *_out_len; + u32 channel = dm_value[1]; + u32 bw = dm_value[2]; + u32 f_interference = dm_value[3]; + u32 second_ch = dm_value[4]; + u8 set_result = 0; + + /*PHYDM_API_NBI*/ + /*-------------------------------------------------------------------------------------------------------------------------------*/ + if (function_map == PHYDM_API_NBI) { + + if (dm_value[0] == 100) { + + PHYDM_SNPRINTF((output + used, out_len - used, "[HELP-NBI] EN(on=1, off=2) CH BW(20/40/80) f_intf(Mhz) Scnd_CH(L=1, H=2)\n")); + return; + + } else if (dm_value[0] == NBI_ENABLE) { + + PHYDM_SNPRINTF((output + used, out_len - used, "[Enable NBI] CH = ((%d)), BW = ((%d)), f_intf = ((%d)), Scnd_CH = ((%s))\n", + channel, bw, f_interference, ((second_ch == PHYDM_DONT_CARE) || (bw == 20) || (channel > 14)) ? "Don't care" : ((second_ch == PHYDM_ABOVE) ? "H" : "L"))); + set_result = phydm_nbi_setting(p_dm_odm, NBI_ENABLE, channel, bw, f_interference, second_ch); + + } else if (dm_value[0] == NBI_DISABLE) { + + PHYDM_SNPRINTF((output + used, out_len - used, "[Disable NBI]\n")); + set_result = phydm_nbi_setting(p_dm_odm, NBI_DISABLE, channel, bw, f_interference, second_ch); + + } else + + set_result = SET_ERROR; + PHYDM_SNPRINTF((output + used, out_len - used, "[NBI set result: %s]\n", (set_result == SET_SUCCESS) ? "Success" : ((set_result == SET_NO_NEED) ? "No need" : "Error"))); + + } + + /*PHYDM_CSI_MASK*/ + /*-------------------------------------------------------------------------------------------------------------------------------*/ + else if (function_map == PHYDM_API_CSI_MASK) { + + if (dm_value[0] == 100) { + + PHYDM_SNPRINTF((output + used, out_len - used, "[HELP-CSI MASK] EN(on=1, off=2) CH BW(20/40/80) f_intf(Mhz) Scnd_CH(L=1, H=2)\n")); + return; + + } else if (dm_value[0] == CSI_MASK_ENABLE) { + + PHYDM_SNPRINTF((output + used, out_len - used, "[Enable CSI MASK] CH = ((%d)), BW = ((%d)), f_intf = ((%d)), Scnd_CH = ((%s))\n", + channel, bw, f_interference, (channel > 14) ? "Don't care" : (((second_ch == PHYDM_DONT_CARE) || (bw == 20) || (channel > 14)) ? "H" : "L"))); + set_result = phydm_csi_mask_setting(p_dm_odm, CSI_MASK_ENABLE, channel, bw, f_interference, second_ch); + + } else if (dm_value[0] == CSI_MASK_DISABLE) { + + PHYDM_SNPRINTF((output + used, out_len - used, "[Disable CSI MASK]\n")); + set_result = phydm_csi_mask_setting(p_dm_odm, CSI_MASK_DISABLE, channel, bw, f_interference, second_ch); + + } else + + set_result = SET_ERROR; + PHYDM_SNPRINTF((output + used, out_len - used, "[CSI MASK set result: %s]\n", (set_result == SET_SUCCESS) ? "Success" : ((set_result == SET_NO_NEED) ? "No need" : "Error"))); + } +} + +void +phydm_receiver_blocking( + void *p_dm_void +) +{ +#ifdef CONFIG_RECEIVER_BLOCKING + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 channel = *p_dm_odm->p_channel; + u8 bw = *p_dm_odm->p_band_width; + u8 set_result = 0; + + if (!(p_dm_odm->support_ic_type & ODM_RECEIVER_BLOCKING_SUPPORT)) + return; + + if (p_dm_odm->consecutive_idlel_time > 10 && p_dm_odm->mp_mode == false && p_dm_odm->adaptivity_enable == true) { + if ((bw == ODM_BW20M) && (channel == 1)) { + set_result = phydm_nbi_setting(p_dm_odm, NBI_ENABLE, channel, 20, 2410, PHYDM_DONT_CARE); + p_dm_odm->is_receiver_blocking_en = true; + } else if ((bw == ODM_BW20M) && (channel == 13)) { + set_result = phydm_nbi_setting(p_dm_odm, NBI_ENABLE, channel, 20, 2473, PHYDM_DONT_CARE); + p_dm_odm->is_receiver_blocking_en = true; + } else if (*(p_dm_odm->p_is_scan_in_process) == false) { + if (p_dm_odm->is_receiver_blocking_en && channel != 1 && channel != 13) { + phydm_nbi_enable(p_dm_odm, NBI_DISABLE); + odm_set_bb_reg(p_dm_odm, 0xc40, 0x1f000000, 0x1f); + p_dm_odm->is_receiver_blocking_en = false; + } + } + } else { + if (p_dm_odm->is_receiver_blocking_en) { + phydm_nbi_enable(p_dm_odm, NBI_DISABLE); + odm_set_bb_reg(p_dm_odm, 0xc40, 0x1f000000, 0x1f); + p_dm_odm->is_receiver_blocking_en = false; + } + } + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_ADAPTIVITY, ODM_DBG_LOUD, + ("[NBI set result: %s]\n", (set_result == SET_SUCCESS ? "Success" : (set_result == SET_NO_NEED ? "No need" : "Error")))); +#endif +} diff --git a/drivers/staging/rtl8188eu/hal/phydm.h b/drivers/staging/rtl8188eu/hal/phydm.h new file mode 100644 index 000000000000..004354ceb84f --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm.h @@ -0,0 +1,1069 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __HALDMOUTSRC_H__ +#define __HALDMOUTSRC_H__ + +/*============================================================*/ +/*include files*/ +/*============================================================*/ +#include "phydm_pre_define.h" +#include "phydm_dig.h" +#if PHYDM_SUPPORT_EDCA +#include "phydm_edcaturbocheck.h" +#endif +#include "phydm_pathdiv.h" +#include "phydm_antdiv.h" +#include "phydm_antdect.h" +#include "phydm_dynamicbbpowersaving.h" +#include "phydm_rainfo.h" +#include "phydm_dynamictxpower.h" +#include "phydm_cfotracking.h" +#include "phydm_acs.h" +#include "phydm_adaptivity.h" +#include "phydm_iqk.h" +#include "phydm_dfs.h" +#include "phydm_ccx.h" +#include "phydm_hal_txbf_api.h" + +#include "phydm_adc_sampling.h" +#include "phydm_dynamic_rx_path.h" + +#include "phydm_beamforming.h" + +#include "phydm_noisemonitor.h" +#include "halphyrf_ce.h" + +/*============================================================*/ +/*Definition */ +/*============================================================*/ + +/* Traffic load decision */ +#define TRAFFIC_ULTRA_LOW 1 +#define TRAFFIC_LOW 2 +#define TRAFFIC_MID 3 +#define TRAFFIC_HIGH 4 + +#define NONE 0 + +/*NBI API------------------------------------*/ +#define NBI_ENABLE 1 +#define NBI_DISABLE 2 + +#define NBI_TABLE_SIZE_128 27 +#define NBI_TABLE_SIZE_256 59 + +#define NUM_START_CH_80M 7 +#define NUM_START_CH_40M 14 + +#define CH_OFFSET_40M 2 +#define CH_OFFSET_80M 6 + +/*CSI MASK API------------------------------------*/ +#define CSI_MASK_ENABLE 1 +#define CSI_MASK_DISABLE 2 + +/*------------------------------------------------*/ + +#define FFT_128_TYPE 1 +#define FFT_256_TYPE 2 + +#define SET_SUCCESS 1 +#define SET_ERROR 2 +#define SET_NO_NEED 3 + +#define FREQ_POSITIVE 1 +#define FREQ_NEGATIVE 2 + +#define PHYDM_WATCH_DOG_PERIOD 2 + +/*============================================================*/ +/*structure and define*/ +/*============================================================*/ + +/*2011/09/20 MH Add for AP/ADSLpseudo DM structuer requirement.*/ +/*We need to remove to other position???*/ + +struct rtl8192cd_priv { + u8 temp; +}; + +struct _dynamic_primary_cca { + u8 pri_cca_flag; + u8 intf_flag; + u8 intf_type; + u8 dup_rts_flag; + u8 monitor_flag; + u8 CH_offset; + u8 MF_state; +}; + +#define dm_type_by_fw 0 +#define dm_type_by_driver 1 + +/*Declare for common info*/ + +#define IQK_THRESHOLD 8 +#define DPK_THRESHOLD 4 + +struct _odm_phy_status_info_ { + /* */ + /* Be care, if you want to add any element please insert between */ + /* rx_pwdb_all & signal_strength. */ + /* */ + u8 rx_pwdb_all; + u8 signal_quality; /* in 0-100 index. */ + s8 rx_mimo_signal_quality[4]; /* per-path's EVM translate to 0~100% */ + u8 rx_mimo_evm_dbm[4]; /* per-path's original EVM (dbm) */ + u8 rx_mimo_signal_strength[4]; /* in 0~100 index */ + s16 cfo_short[4]; /* per-path's cfo_short */ + s16 cfo_tail[4]; /* per-path's cfo_tail */ + s8 rx_power; /* in dBm Translate from PWdB */ + s8 recv_signal_power; /* Real power in dBm for this packet, no beautification and aggregation. Keep this raw info to be used for the other procedures. */ + u8 bt_rx_rssi_percentage; + u8 signal_strength; /* in 0-100 index. */ + s8 rx_pwr[4]; /* per-path's pwdb */ + s8 rx_snr[4]; /* per-path's SNR */ + /* s8 BB_Backup[13]; backup reg. */ +#if (ODM_PHY_STATUS_NEW_TYPE_SUPPORT == 1) + u8 rx_count:2; /* RX path counter---*/ + u8 band_width:2; + u8 rxsc:4; /* sub-channel---*/ +#else + u8 band_width; +#endif + u8 bt_coex_pwr_adjust; +#if (ODM_PHY_STATUS_NEW_TYPE_SUPPORT == 1) + u8 channel; /* channel number---*/ + bool is_mu_packet; /* is MU packet or not---*/ + bool is_beamformed; /* BF packet---*/ +#endif +}; + +struct _odm_per_pkt_info_ { + u8 data_rate; + u8 station_id; + bool is_packet_match_bssid; + bool is_packet_to_self; + bool is_packet_beacon; + bool is_to_self; + u8 ppdu_cnt; +}; + +struct _odm_phy_dbg_info_ { + /*ODM Write,debug info*/ + s8 rx_snr_db[4]; + u32 num_qry_phy_status; + u32 num_qry_phy_status_cck; + u32 num_qry_phy_status_ofdm; +#if (ODM_PHY_STATUS_NEW_TYPE_SUPPORT == 1) + u32 num_qry_mu_pkt; + u32 num_qry_bf_pkt; + u32 num_qry_mu_vht_pkt[40]; + u32 num_qry_vht_pkt[40]; + bool is_ldpc_pkt; + bool is_stbc_pkt; + u8 num_of_ppdu[4]; + u8 gid_num[4]; +#endif + u8 num_qry_beacon_pkt; + /* Others */ + s32 rx_evm[4]; + +}; + +/*2011/20/20 MH For MP driver RT_WLAN_STA = struct sta_info*/ +/*Please declare below ODM relative info in your STA info structure.*/ + +struct _ODM_STA_INFO { + /*Driver Write*/ + bool is_used; /*record the sta status link or not?*/ + u8 iot_peer; /*Enum value. HT_IOT_PEER_E*/ + + /*ODM Write*/ + /*PHY_STATUS_INFO*/ + u8 rssi_path[4]; + u8 rssi_ave; + u8 RXEVM[4]; + u8 RXSNR[4]; + +}; + +enum odm_cmninfo_e { + /*Fixed value*/ + /*-----------HOOK BEFORE REG INIT-----------*/ + ODM_CMNINFO_PLATFORM = 0, + ODM_CMNINFO_ABILITY, + ODM_CMNINFO_INTERFACE, + ODM_CMNINFO_MP_TEST_CHIP, + ODM_CMNINFO_IC_TYPE, + ODM_CMNINFO_CUT_VER, + ODM_CMNINFO_FAB_VER, + ODM_CMNINFO_RF_TYPE, + ODM_CMNINFO_RFE_TYPE, + ODM_CMNINFO_BOARD_TYPE, + ODM_CMNINFO_PACKAGE_TYPE, + ODM_CMNINFO_EXT_LNA, + ODM_CMNINFO_5G_EXT_LNA, + ODM_CMNINFO_EXT_PA, + ODM_CMNINFO_5G_EXT_PA, + ODM_CMNINFO_GPA, + ODM_CMNINFO_APA, + ODM_CMNINFO_GLNA, + ODM_CMNINFO_ALNA, + ODM_CMNINFO_EXT_TRSW, + ODM_CMNINFO_EXT_LNA_GAIN, + ODM_CMNINFO_PATCH_ID, + ODM_CMNINFO_BINHCT_TEST, + ODM_CMNINFO_BWIFI_TEST, + ODM_CMNINFO_SMART_CONCURRENT, + ODM_CMNINFO_CONFIG_BB_RF, + ODM_CMNINFO_DOMAIN_CODE_2G, + ODM_CMNINFO_DOMAIN_CODE_5G, + ODM_CMNINFO_IQKFWOFFLOAD, + ODM_CMNINFO_IQKPAOFF, + ODM_CMNINFO_HUBUSBMODE, + ODM_CMNINFO_FWDWRSVDPAGEINPROGRESS, + ODM_CMNINFO_TX_TP, + ODM_CMNINFO_RX_TP, + ODM_CMNINFO_SOUNDING_SEQ, + ODM_CMNINFO_REGRFKFREEENABLE, + ODM_CMNINFO_RFKFREEENABLE, + ODM_CMNINFO_NORMAL_RX_PATH_CHANGE, + ODM_CMNINFO_EFUSE0X3D8, + ODM_CMNINFO_EFUSE0X3D7, + /*-----------HOOK BEFORE REG INIT-----------*/ + + /*Dynamic value:*/ + + /*--------- POINTER REFERENCE-----------*/ + ODM_CMNINFO_MAC_PHY_MODE, + ODM_CMNINFO_TX_UNI, + ODM_CMNINFO_RX_UNI, + ODM_CMNINFO_WM_MODE, + ODM_CMNINFO_BAND, + ODM_CMNINFO_SEC_CHNL_OFFSET, + ODM_CMNINFO_SEC_MODE, + ODM_CMNINFO_BW, + ODM_CMNINFO_CHNL, + ODM_CMNINFO_FORCED_RATE, + ODM_CMNINFO_ANT_DIV, + ODM_CMNINFO_ADAPTIVITY, + ODM_CMNINFO_DMSP_GET_VALUE, + ODM_CMNINFO_BUDDY_ADAPTOR, + ODM_CMNINFO_DMSP_IS_MASTER, + ODM_CMNINFO_SCAN, + ODM_CMNINFO_POWER_SAVING, + ODM_CMNINFO_ONE_PATH_CCA, + ODM_CMNINFO_DRV_STOP, + ODM_CMNINFO_PNP_IN, + ODM_CMNINFO_INIT_ON, + ODM_CMNINFO_ANT_TEST, + ODM_CMNINFO_NET_CLOSED, + ODM_CMNINFO_FORCED_IGI_LB, + ODM_CMNINFO_P2P_LINK, + ODM_CMNINFO_FCS_MODE, + ODM_CMNINFO_IS1ANTENNA, + ODM_CMNINFO_RFDEFAULTPATH, + ODM_CMNINFO_DFS_MASTER_ENABLE, + ODM_CMNINFO_FORCE_TX_ANT_BY_TXDESC, + ODM_CMNINFO_SET_S0S1_DEFAULT_ANTENNA, + /*--------- POINTER REFERENCE-----------*/ + + /*------------CALL BY VALUE-------------*/ + ODM_CMNINFO_WIFI_DIRECT, + ODM_CMNINFO_WIFI_DISPLAY, + ODM_CMNINFO_LINK_IN_PROGRESS, + ODM_CMNINFO_LINK, + ODM_CMNINFO_STATION_STATE, + ODM_CMNINFO_RSSI_MIN, + ODM_CMNINFO_DBG_COMP, + ODM_CMNINFO_DBG_LEVEL, + ODM_CMNINFO_RA_THRESHOLD_HIGH, + ODM_CMNINFO_RA_THRESHOLD_LOW, + ODM_CMNINFO_RF_ANTENNA_TYPE, + ODM_CMNINFO_WITH_EXT_ANTENNA_SWITCH, + ODM_CMNINFO_BE_FIX_TX_ANT, + ODM_CMNINFO_BT_ENABLED, + ODM_CMNINFO_BT_HS_CONNECT_PROCESS, + ODM_CMNINFO_BT_HS_RSSI, + ODM_CMNINFO_BT_OPERATION, + ODM_CMNINFO_BT_LIMITED_DIG, + ODM_CMNINFO_BT_DIG, + ODM_CMNINFO_BT_BUSY, + ODM_CMNINFO_BT_DISABLE_EDCA, + ODM_CMNINFO_AP_TOTAL_NUM, + ODM_CMNINFO_POWER_TRAINING, + ODM_CMNINFO_DFS_REGION_DOMAIN, + /*------------CALL BY VALUE-------------*/ + + /*Dynamic ptr array hook itms.*/ + ODM_CMNINFO_STA_STATUS, + ODM_CMNINFO_MAX, + +}; + +enum phydm_info_query_e { + PHYDM_INFO_FA_OFDM, + PHYDM_INFO_FA_CCK, + PHYDM_INFO_FA_TOTAL, + PHYDM_INFO_CCA_OFDM, + PHYDM_INFO_CCA_CCK, + PHYDM_INFO_CCA_ALL, + PHYDM_INFO_CRC32_OK_VHT, + PHYDM_INFO_CRC32_OK_HT, + PHYDM_INFO_CRC32_OK_LEGACY, + PHYDM_INFO_CRC32_OK_CCK, + PHYDM_INFO_CRC32_ERROR_VHT, + PHYDM_INFO_CRC32_ERROR_HT, + PHYDM_INFO_CRC32_ERROR_LEGACY, + PHYDM_INFO_CRC32_ERROR_CCK, + PHYDM_INFO_EDCCA_FLAG, + PHYDM_INFO_OFDM_ENABLE, + PHYDM_INFO_CCK_ENABLE, + PHYDM_INFO_DBG_PORT_0 +}; + +enum phydm_api_e { + + PHYDM_API_NBI = 1, + PHYDM_API_CSI_MASK, + +}; + +/*2011/10/20 MH Define ODM support ability. ODM_CMNINFO_ABILITY*/ +enum odm_ability_e { + + /*BB ODM section BIT 0-19*/ + ODM_BB_DIG = BIT(0), + ODM_BB_RA_MASK = BIT(1), + ODM_BB_DYNAMIC_TXPWR = BIT(2), + ODM_BB_FA_CNT = BIT(3), + ODM_BB_RSSI_MONITOR = BIT(4), + ODM_BB_CCK_PD = BIT(5), + ODM_BB_ANT_DIV = BIT(6), + ODM_BB_PWR_TRAIN = BIT(8), + ODM_BB_RATE_ADAPTIVE = BIT(9), + ODM_BB_PATH_DIV = BIT(10), + ODM_BB_ADAPTIVITY = BIT(13), + ODM_BB_CFO_TRACKING = BIT(14), + ODM_BB_NHM_CNT = BIT(15), + ODM_BB_PRIMARY_CCA = BIT(16), + ODM_BB_TXBF = BIT(17), + ODM_BB_DYNAMIC_ARFR = BIT(18), + + ODM_MAC_EDCA_TURBO = BIT(20), + ODM_BB_DYNAMIC_RX_PATH = BIT(21), + + /*RF ODM section BIT 24-31*/ + ODM_RF_TX_PWR_TRACK = BIT(24), + ODM_RF_RX_GAIN_TRACK = BIT(25), + ODM_RF_CALIBRATION = BIT(26), + +}; + +/*ODM_CMNINFO_ONE_PATH_CCA*/ +enum odm_cca_path_e { + ODM_CCA_2R = 0, + ODM_CCA_1R_A = 1, + ODM_CCA_1R_B = 2, +}; + +enum cca_pathdiv_en_e { + CCA_PATHDIV_DISABLE = 0, + CCA_PATHDIV_ENABLE = 1, + +}; + +enum phy_reg_pg_type { + PHY_REG_PG_RELATIVE_VALUE = 0, + PHY_REG_PG_EXACT_VALUE = 1 +}; + +/*2011/09/22 MH Copy from SD4 defined structure. We use to support PHY DM integration.*/ + +struct PHY_DM_STRUCT { + /*Add for different team use temporarily*/ + struct _ADAPTER *adapter; /*For CE/NIC team*/ + struct rtl8192cd_priv *priv; /*For AP/ADSL team*/ + /*WHen you use adapter or priv pointer, you must make sure the pointer is ready.*/ + bool odm_ready; + + struct rtl8192cd_priv fake_priv; + enum phy_reg_pg_type phy_reg_pg_value_type; + u8 phy_reg_pg_version; + + u32 debug_components; + u32 fw_debug_components; + u32 debug_level; + + u32 num_qry_phy_status_all; /*CCK + OFDM*/ + u32 last_num_qry_phy_status_all; + u32 rx_pwdb_ave; + bool MPDIG_2G; /*off MPDIG*/ + u8 times_2g; + bool is_init_hw_info_by_rfe; + + /*------ ODM HANDLE, DRIVER NEEDS NOT TO HOOK------*/ + bool is_cck_high_power; + u8 rf_path_rx_enable; + u8 control_channel; + /*------ ODM HANDLE, DRIVER NEEDS NOT TO HOOK------*/ + + /* 1 COMMON INFORMATION */ + + /*Init value*/ + /*-----------HOOK BEFORE REG INIT-----------*/ + /*ODM Platform info AP/ADSL/CE/MP = 1/2/3/4*/ + u8 support_platform; + /* ODM Platform info WIN/AP/CE = 1/2/3 */ + u8 normal_rx_path; + /*ODM Support Ability DIG/RATR/TX_PWR_TRACK/ �K�K = 1/2/3/�K*/ + u32 support_ability; + /*ODM PCIE/USB/SDIO = 1/2/3*/ + u8 support_interface; + /*ODM composite or independent. Bit oriented/ 92C+92D+ .... or any other type = 1/2/3/...*/ + u32 support_ic_type; + /*cut version TestChip/A-cut/B-cut... = 0/1/2/3/...*/ + u8 cut_version; + /*Fab version TSMC/UMC = 0/1*/ + u8 fab_version; + /*RF type 4T4R/3T3R/2T2R/1T2R/1T1R/...*/ + u8 rf_type; + u8 rfe_type; + /*Board type Normal/HighPower/MiniCard/SLIM/Combo/... = 0/1/2/3/4/...*/ + u8 board_type; + u8 package_type; + u16 type_glna; + u16 type_gpa; + u16 type_alna; + u16 type_apa; + /*with external LNA NO/Yes = 0/1*/ + u8 ext_lna; /*2G*/ + u8 ext_lna_5g; /*5G*/ + /*with external PA NO/Yes = 0/1*/ + u8 ext_pa; /*2G*/ + u8 ext_pa_5g; /*5G*/ + /*with Efuse number*/ + u8 efuse0x3d7; + u8 efuse0x3d8; + /*with external TRSW NO/Yes = 0/1*/ + u8 ext_trsw; + u8 ext_lna_gain; /*2G*/ + u8 patch_id; /*Customer ID*/ + bool is_in_hct_test; + u8 wifi_test; + + bool is_dual_mac_smart_concurrent; + u32 bk_support_ability; + u8 ant_div_type; + u8 with_extenal_ant_switch; + bool config_bbrf; + u8 odm_regulation_2_4g; + u8 odm_regulation_5g; + u8 iqk_fw_offload; + bool cck_new_agc; + u8 phydm_period; + u32 phydm_sys_up_time; + u8 num_rf_path; + u8 is_receiver_blocking_en; + /*-----------HOOK BEFORE REG INIT-----------*/ + + /*Dynamic value*/ + + /*--------- POINTER REFERENCE-----------*/ + + u8 u1_byte_temp; + bool BOOLEAN_temp; + struct _ADAPTER *PADAPTER_temp; + + /*MAC PHY mode SMSP/DMSP/DMDP = 0/1/2*/ + u8 *p_mac_phy_mode; + /*TX Unicast byte count*/ + u64 *p_num_tx_bytes_unicast; + /*RX Unicast byte count*/ + u64 *p_num_rx_bytes_unicast; + /*Wireless mode B/G/A/N = BIT0/BIT1/BIT2/BIT3*/ + u8 *p_wireless_mode; + /*Frequence band 2.4G/5G = 0/1*/ + u8 *p_band_type; + /*Secondary channel offset don't_care/below/above = 0/1/2*/ + u8 *p_sec_ch_offset; + /*security mode Open/WEP/AES/TKIP = 0/1/2/3*/ + u8 *p_security; + /*BW info 20M/40M/80M = 0/1/2*/ + u8 *p_band_width; + /*Central channel location Ch1/Ch2/....*/ + u8 *p_channel; /*central channel number*/ + bool dpk_done; + /*Common info for 92D DMSP*/ + + bool *p_is_get_value_from_other_mac; + struct _ADAPTER **p_buddy_adapter; + bool *p_is_master_of_dmsp; /* MAC0: master, MAC1: slave */ + /*Common info for status*/ + bool *p_is_scan_in_process; + bool *p_is_power_saving; + /*CCA path 2-path/path-A/path-B = 0/1/2; using enum odm_cca_path_e.*/ + u8 *p_one_path_cca; + u8 *p_antenna_test; + bool *p_is_net_closed; + u8 *pu1_forced_igi_lb; + bool *p_is_fcs_mode_enable; + /*--------- For 8723B IQK-----------*/ + bool *p_is_1_antenna; + u8 *p_rf_default_path; + /* 0:S1, 1:S0 */ + + /*--------- POINTER REFERENCE-----------*/ + u16 *p_forced_data_rate; + u8 *p_enable_antdiv; + u8 *p_enable_adaptivity; + u8 *hub_usb_mode; + bool *p_is_fw_dw_rsvd_page_in_progress; + u32 *p_current_tx_tp; + u32 *p_current_rx_tp; + u8 *p_sounding_seq; + /*------------CALL BY VALUE-------------*/ + bool is_link_in_process; + bool is_wifi_direct; + bool is_wifi_display; + bool is_linked; + bool bsta_state; + u8 rssi_min; + u8 interface_index; /*Add for 92D dual MAC: 0--Mac0 1--Mac1*/ + bool is_mp_chip; + bool is_one_entry_only; + bool mp_mode; + u32 one_entry_macid; + u8 pre_number_linked_client; + u8 number_linked_client; + u8 pre_number_active_client; + u8 number_active_client; + /*Common info for BTDM*/ + bool is_bt_enabled; /*BT is enabled*/ + bool is_bt_connect_process; /*BT HS is under connection progress.*/ + u8 bt_hs_rssi; /*BT HS mode wifi rssi value.*/ + bool is_bt_hs_operation; /*BT HS mode is under progress*/ + u8 bt_hs_dig_val; /*use BT rssi to decide the DIG value*/ + bool is_bt_disable_edca_turbo; /*Under some condition, don't enable the EDCA Turbo*/ + bool is_bt_busy; /*BT is busy.*/ + bool is_bt_limited_dig; /*BT is busy.*/ + bool is_disable_phy_api; + /*------------CALL BY VALUE-------------*/ + u8 RSSI_A; + u8 RSSI_B; + u8 RSSI_C; + u8 RSSI_D; + u64 RSSI_TRSW; + u64 RSSI_TRSW_H; + u64 RSSI_TRSW_L; + u64 RSSI_TRSW_iso; + u8 tx_ant_status; + u8 rx_ant_status; + u8 cck_lna_idx; + u8 cck_vga_idx; + u8 curr_station_id; + u8 ofdm_agc_idx[4]; + + u8 rx_rate; + bool is_noisy_state; + u8 tx_rate; + u8 linked_interval; + u8 pre_channel; + u32 txagc_offset_value_a; + bool is_txagc_offset_positive_a; + u32 txagc_offset_value_b; + bool is_txagc_offset_positive_b; + u32 tx_tp; + u32 rx_tp; + u32 total_tp; + u64 cur_tx_ok_cnt; + u64 cur_rx_ok_cnt; + u64 last_tx_ok_cnt; + u64 last_rx_ok_cnt; + u16 consecutive_idlel_time; /*unit: second*/ + u32 bb_swing_offset_a; + bool is_bb_swing_offset_positive_a; + u32 bb_swing_offset_b; + bool is_bb_swing_offset_positive_b; + u8 igi_lower_bound; + u8 igi_upper_bound; + u8 antdiv_rssi; + u8 fat_comb_a; + u8 fat_comb_b; + u8 antdiv_intvl; + u8 ant_type; + u8 pre_ant_type; + u8 antdiv_period; + u8 evm_antdiv_period; + u8 antdiv_select; + u8 path_select; + u8 antdiv_evm_en; + u8 bdc_holdstate; + u8 ndpa_period; + bool h2c_rarpt_connect; + bool cck_agc_report_type; + + u8 dm_dig_max_TH; + u8 dm_dig_min_TH; + u8 print_agc; + u8 traffic_load; + u8 pre_traffic_load; + /*8821C Antenna BTG/WLG/WLA Select*/ + u8 current_rf_set_8821c; + u8 default_rf_set_8821c; + /*For Adaptivtiy*/ + u16 nhm_cnt_0; + u16 nhm_cnt_1; + s8 TH_L2H_default; + s8 th_edcca_hl_diff_default; + s8 th_l2h_ini; + s8 th_edcca_hl_diff; + s8 th_l2h_ini_mode2; + s8 th_edcca_hl_diff_mode2; + bool carrier_sense_enable; + u8 adaptivity_igi_upper; + bool adaptivity_flag; + u8 dc_backoff; + bool adaptivity_enable; + u8 ap_total_num; + bool edcca_enable; + struct _ADAPTIVITY_STATISTICS adaptivity; + /*For Adaptivtiy*/ + u8 last_usb_hub; + u8 tx_bf_data_rate; + + u8 nbi_set_result; + + u8 c2h_cmd_start; + u8 fw_debug_trace[60]; + u8 pre_c2h_seq; + bool fw_buff_is_enpty; + u32 data_frame_num; + + /*for noise detection*/ + bool noisy_decision; /*b_noisy*/ + bool pre_b_noisy; + u32 noisy_decision_smooth; + bool is_disable_dym_ecs; + struct _ODM_NOISE_MONITOR_ noise_level; + /*Define STA info.*/ + /*_ODM_STA_INFO*/ + /*2012/01/12 MH For MP, we need to reduce one array pointer for default port.??*/ + struct sta_info *p_odm_sta_info[ODM_ASSOCIATE_ENTRY_NUM]; + u16 platform2phydm_macid_table[ODM_ASSOCIATE_ENTRY_NUM]; + /* platform_macid_table[platform_macid] = phydm_macid */ +#if (ODM_PHY_STATUS_NEW_TYPE_SUPPORT == 1) + s32 accumulate_pwdb[ODM_ASSOCIATE_ENTRY_NUM]; +#endif + +#if (RATE_ADAPTIVE_SUPPORT == 1) + u16 currmin_rpt_time; + struct _odm_ra_info_ ra_info[ODM_ASSOCIATE_ENTRY_NUM]; + /*Use mac_id as array index. STA mac_id=0, VWiFi Client mac_id={1, ODM_ASSOCIATE_ENTRY_NUM-1} //YJ,add,120119*/ +#endif + + /*2012/02/14 MH Add to share 88E ra with other SW team.*/ + /*We need to colelct all support abilit to a proper area.*/ + + bool ra_support88e; + + struct _odm_phy_dbg_info_ phy_dbg_info; + + /*ODM Structure*/ +#if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY)) + +#ifdef CONFIG_HL_SMART_ANTENNA_TYPE1 + struct _SMART_ANTENNA_TRAINNING_ dm_sat_table; +#endif + +#endif + struct _FAST_ANTENNA_TRAINNING_ dm_fat_table; + struct _dynamic_initial_gain_threshold_ dm_dig_table; +#if (defined(CONFIG_BB_POWER_SAVING)) + struct _dynamic_power_saving dm_ps_table; +#endif + struct _dynamic_primary_cca dm_pri_cca; + struct _rate_adaptive_table_ dm_ra_table; + struct false_ALARM_STATISTICS false_alm_cnt; + struct false_ALARM_STATISTICS flase_alm_cnt_buddy_adapter; + struct _sw_antenna_switch_ dm_swat_table; + struct _CFO_TRACKING_ dm_cfo_track; + struct _ACS_ dm_acs; + struct _CCX_INFO dm_ccx_info; +#if (PHYDM_LA_MODE_SUPPORT == 1) + struct _RT_ADCSMP adcsmp; +#endif +#if (CONFIG_DYNAMIC_RX_PATH == 1) + struct _DYNAMIC_RX_PATH_ dm_drp_table; +#endif + +#if (defined(CONFIG_PATH_DIVERSITY)) + struct _ODM_PATH_DIVERSITY_ dm_path_div; +#endif + +#if PHYDM_SUPPORT_EDCA + struct _EDCA_TURBO_ dm_edca_table; + u32 WMMEDCA_BE; +#endif + + bool *p_is_driver_stopped; + bool *p_is_driver_is_going_to_pnp_set_power_sleep; + bool *pinit_adpt_in_progress; + + /*PSD*/ + bool is_user_assign_level; + u8 RSSI_BT; /*come from BT*/ + bool is_psd_in_process; + bool is_psd_active; + bool is_dm_initial_gain_enable; + + /*MPT DIG*/ + struct timer_list mpt_dig_timer; + + /*for rate adaptive, in fact, 88c/92c fw will handle this*/ + u8 is_use_ra_mask; + + struct _ODM_RATE_ADAPTIVE rate_adaptive; +#if (defined(CONFIG_ANT_DETECTION)) + struct _ANT_DETECTED_INFO ant_detected_info; /* Antenna detected information for RSSI tool*/ +#endif + struct odm_rf_calibration_structure rf_calibrate_info; + u32 n_iqk_cnt; + u32 n_iqk_ok_cnt; + u32 n_iqk_fail_cnt; + + /*Power Training*/ + u8 force_power_training_state; + bool is_change_state; + u32 PT_score; + u64 ofdm_rx_cnt; + u64 cck_rx_cnt; + bool is_disable_power_training; + u8 dynamic_tx_high_power_lvl; + u8 last_dtp_lvl; + u32 tx_agc_ofdm_18_6; + u8 rx_pkt_type; + + /*ODM relative time.*/ + struct timer_list path_div_switch_timer; + /*2011.09.27 add for path Diversity*/ + struct timer_list cck_path_diversity_timer; + struct timer_list fast_ant_training_timer; +#ifdef ODM_EVM_ENHANCE_ANTDIV + struct timer_list evm_fast_ant_training_timer; +#endif + struct timer_list sbdcnt_timer; + + /*ODM relative workitem.*/ +#if (BEAMFORMING_SUPPORT == 1) + struct _RT_BEAMFORMING_INFO beamforming_info; +#endif + +#ifdef CONFIG_PHYDM_DFS_MASTER + u8 dfs_region_domain; + u8 *dfs_master_enabled; + + /*====== phydm_radar_detect_with_dbg_parm start ======*/ + u8 radar_detect_dbg_parm_en; + u32 radar_detect_reg_918; + u32 radar_detect_reg_91c; + u32 radar_detect_reg_920; + u32 radar_detect_reg_924; + /*====== phydm_radar_detect_with_dbg_parm end ======*/ +#endif +}; + +enum phydm_structure_type { + PHYDMfalseALMCNT, + PHYDM_CFOTRACK, + PHYDM_ADAPTIVITY, + PHYDM_ROMINFO, + +}; + +enum odm_rf_content { + odm_radioa_txt = 0x1000, + odm_radiob_txt = 0x1001, + odm_radioc_txt = 0x1002, + odm_radiod_txt = 0x1003 +}; + +enum odm_bb_config_type { + CONFIG_BB_PHY_REG, + CONFIG_BB_AGC_TAB, + CONFIG_BB_AGC_TAB_2G, + CONFIG_BB_AGC_TAB_5G, + CONFIG_BB_PHY_REG_PG, + CONFIG_BB_PHY_REG_MP, + CONFIG_BB_AGC_TAB_DIFF, +}; + +enum odm_rf_config_type { + CONFIG_RF_RADIO, + CONFIG_RF_TXPWR_LMT, +}; + +enum odm_fw_config_type { + CONFIG_FW_NIC, + CONFIG_FW_NIC_2, + CONFIG_FW_AP, + CONFIG_FW_AP_2, + CONFIG_FW_MP, + CONFIG_FW_WOWLAN, + CONFIG_FW_WOWLAN_2, + CONFIG_FW_AP_WOWLAN, + CONFIG_FW_BT, +}; + +/*status code*/ +enum rt_status { + RT_STATUS_SUCCESS, + RT_STATUS_FAILURE, + RT_STATUS_PENDING, + RT_STATUS_RESOURCE, + RT_STATUS_INVALID_CONTEXT, + RT_STATUS_INVALID_PARAMETER, + RT_STATUS_NOT_SUPPORT, + RT_STATUS_OS_API_FAILED, +}; + +#ifdef REMOVE_PACK + #pragma pack() +#endif + +/*===========================================================*/ +/*AGC RX High Power mode*/ +/*===========================================================*/ +#define lna_low_gain_1 0x64 +#define lna_low_gain_2 0x5A +#define lna_low_gain_3 0x58 + +#define FA_RXHP_TH1 5000 +#define FA_RXHP_TH2 1500 +#define FA_RXHP_TH3 800 +#define FA_RXHP_TH4 600 +#define FA_RXHP_TH5 500 + +enum dm_1r_cca_e { + CCA_1R = 0, + CCA_2R = 1, + CCA_MAX = 2, +}; + +enum dm_rf_e { + rf_save = 0, + rf_normal = 1, + RF_MAX = 2, +}; + +/*check Sta pointer valid or not*/ + +#define IS_STA_VALID(p_sta) (p_sta) + +u32 odm_convert_to_db(u32 value); + +u32 odm_convert_to_linear(u32 value); + +u32 +get_psd_data( + struct PHY_DM_STRUCT *p_dm_odm, + unsigned int point, + u8 initial_gain_psd); + +s32 +odm_pwdb_conversion( + s32 X, + u32 total_bit, + u32 decimal_bit +); + +s32 +odm_sign_conversion( + s32 value, + u32 total_bit +); + +void +odm_init_mp_driver_status( + struct PHY_DM_STRUCT *p_dm_odm +); + +void +phydm_txcurrentcalibration( + struct PHY_DM_STRUCT *p_dm_odm +); + +void +phydm_seq_sorting( + void *p_dm_void, + u32 *p_value, + u32 *rank_idx, + u32 *p_idx_out, + u8 seq_length +); + +void +odm_dm_init( + struct PHY_DM_STRUCT *p_dm_odm +); + +void +odm_dm_reset( + struct PHY_DM_STRUCT *p_dm_odm +); + +void +phydm_support_ability_debug( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +); + +void +phydm_config_ofdm_rx_path( + struct PHY_DM_STRUCT *p_dm_odm, + u32 path +); + +void +phydm_config_trx_path( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +); + +void +odm_dm_watchdog( + struct PHY_DM_STRUCT *p_dm_odm +); + +void +phydm_watchdog_mp( + struct PHY_DM_STRUCT *p_dm_odm +); + +void +odm_cmn_info_init( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_cmninfo_e cmn_info, + u32 value +); + +void +odm_cmn_info_hook( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_cmninfo_e cmn_info, + void *p_value +); + +void +odm_cmn_info_ptr_array_hook( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_cmninfo_e cmn_info, + u16 index, + void *p_value +); + +void +odm_cmn_info_update( + struct PHY_DM_STRUCT *p_dm_odm, + u32 cmn_info, + u64 value +); + +u32 +phydm_cmn_info_query( + struct PHY_DM_STRUCT *p_dm_odm, + enum phydm_info_query_e info_type +); + +void +odm_init_all_timers( + struct PHY_DM_STRUCT *p_dm_odm +); + +void +odm_cancel_all_timers( + struct PHY_DM_STRUCT *p_dm_odm +); + +void +odm_release_all_timers( + struct PHY_DM_STRUCT *p_dm_odm +); + +void +odm_asoc_entry_init( + struct PHY_DM_STRUCT *p_dm_odm +); + +void * +phydm_get_structure( + struct PHY_DM_STRUCT *p_dm_odm, + u8 structure_type +); + + /*===========================================================*/ + /* The following is for compile only*/ + /*===========================================================*/ + + #define IS_HARDWARE_TYPE_8723A(_adapter) false + #define IS_HARDWARE_TYPE_8723AE(_adapter) false + #define IS_HARDWARE_TYPE_8192C(_adapter) false + #define IS_HARDWARE_TYPE_8192D(_adapter) false + #define RF_T_METER_92D 0x42 + + #define GET_RX_STATUS_DESC_RX_MCS(__prx_status_desc) LE_BITS_TO_1BYTE(__prx_status_desc+12, 0, 6) + + #define REG_CONFIG_RAM64X16 0xb2c + + #define TARGET_CHNL_NUM_2G_5G 59 + + /* *********************************************************** */ + + void odm_dtc(struct PHY_DM_STRUCT *p_dm_odm); + +void phydm_noisy_detection(struct PHY_DM_STRUCT *p_dm_odm); + +#endif + +void +phydm_set_ext_switch( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +); + +void +phydm_api_debug( + void *p_dm_void, + u32 function_map, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +); + +u8 +phydm_nbi_setting( + void *p_dm_void, + u32 enable, + u32 channel, + u32 bw, + u32 f_interference, + u32 second_ch +); + +void +phydm_receiver_blocking( + void *p_dm_void +); diff --git a/drivers/staging/rtl8188eu/hal/phydm_acs.c b/drivers/staging/rtl8188eu/hal/phydm_acs.c new file mode 100644 index 000000000000..b3ae46f5cd95 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_acs.c @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* ************************************************************ + * include files + * ************************************************************ */ +#include "mp_precomp.h" +#include "phydm_precomp.h" + + +u8 +odm_get_auto_channel_select_result( + void *p_dm_void, + u8 band +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ACS_ *p_acs = &p_dm_odm->dm_acs; + + if (band == ODM_BAND_2_4G) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ACS, ODM_DBG_LOUD, ("[struct _ACS_] odm_get_auto_channel_select_result(): clean_channel_2g(%d)\n", p_acs->clean_channel_2g)); + return (u8)p_acs->clean_channel_2g; + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ACS, ODM_DBG_LOUD, ("[struct _ACS_] odm_get_auto_channel_select_result(): clean_channel_5g(%d)\n", p_acs->clean_channel_5g)); + return (u8)p_acs->clean_channel_5g; + } +} + +static void +odm_auto_channel_select_setting( + void *p_dm_void, + bool is_enable +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u16 period = 0x2710;/* 40ms in default */ + u16 nhm_type = 0x7; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ACS, ODM_DBG_LOUD, ("odm_auto_channel_select_setting()=========>\n")); + + if (is_enable) { + /* 20 ms */ + period = 0x1388; + nhm_type = 0x1; + } + + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + /* PHY parameters initialize for ac series */ + odm_write_2byte(p_dm_odm, ODM_REG_CCX_PERIOD_11AC + 2, period); /* 0x990[31:16]=0x2710 Time duration for NHM unit: 4us, 0x2710=40ms */ + /* odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, BIT(8)|BIT9|BIT10, nhm_type); */ /* 0x994[9:8]=3 enable CCX */ + } else if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + /* PHY parameters initialize for n series */ + odm_write_2byte(p_dm_odm, ODM_REG_CCX_PERIOD_11N + 2, period); /* 0x894[31:16]=0x2710 Time duration for NHM unit: 4us, 0x2710=40ms */ + /* odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, BIT(10)|BIT9|BIT8, nhm_type); */ /* 0x890[9:8]=3 enable CCX */ + } +} + +void +odm_auto_channel_select_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ACS_ *p_acs = &p_dm_odm->dm_acs; + u8 i; + + if (!(p_dm_odm->support_ability & ODM_BB_NHM_CNT)) + return; + + if (p_acs->is_force_acs_result) + return; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ACS, ODM_DBG_LOUD, ("odm_auto_channel_select_init()=========>\n")); + + p_acs->clean_channel_2g = 1; + p_acs->clean_channel_5g = 36; + + for (i = 0; i < ODM_MAX_CHANNEL_2G; ++i) { + p_acs->channel_info_2g[0][i] = 0; + p_acs->channel_info_2g[1][i] = 0; + } + + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + for (i = 0; i < ODM_MAX_CHANNEL_5G; ++i) { + p_acs->channel_info_5g[0][i] = 0; + p_acs->channel_info_5g[1][i] = 0; + } + } +} + +void +odm_auto_channel_select_reset( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ACS_ *p_acs = &p_dm_odm->dm_acs; + + if (!(p_dm_odm->support_ability & ODM_BB_NHM_CNT)) + return; + + if (p_acs->is_force_acs_result) + return; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ACS, ODM_DBG_LOUD, ("odm_auto_channel_select_reset()=========>\n")); + + odm_auto_channel_select_setting(p_dm_odm, true); /* for 20ms measurement */ + phydm_nhm_counter_statistics_reset(p_dm_odm); +} + +void +odm_auto_channel_select( + void *p_dm_void, + u8 channel +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ACS_ *p_acs = &p_dm_odm->dm_acs; + u8 channel_idx = 0, search_idx = 0; + u16 max_score = 0; + + if (!(p_dm_odm->support_ability & ODM_BB_NHM_CNT)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_auto_channel_select(): Return: support_ability ODM_BB_NHM_CNT is disabled\n")); + return; + } + + if (p_acs->is_force_acs_result) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_auto_channel_select(): Force 2G clean channel = %d, 5G clean channel = %d\n", + p_acs->clean_channel_2g, p_acs->clean_channel_5g)); + return; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ACS, ODM_DBG_LOUD, ("odm_auto_channel_select(): channel = %d=========>\n", channel)); + + phydm_get_nhm_counter_statistics(p_dm_odm); + odm_auto_channel_select_setting(p_dm_odm, false); + + if (channel >= 1 && channel <= 14) { + channel_idx = channel - 1; + p_acs->channel_info_2g[1][channel_idx]++; + + if (p_acs->channel_info_2g[1][channel_idx] >= 2) + p_acs->channel_info_2g[0][channel_idx] = (p_acs->channel_info_2g[0][channel_idx] >> 1) + + (p_acs->channel_info_2g[0][channel_idx] >> 2) + (p_dm_odm->nhm_cnt_0 >> 2); + else + p_acs->channel_info_2g[0][channel_idx] = p_dm_odm->nhm_cnt_0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ACS, ODM_DBG_LOUD, ("odm_auto_channel_select(): nhm_cnt_0 = %d\n", p_dm_odm->nhm_cnt_0)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ACS, ODM_DBG_LOUD, ("odm_auto_channel_select(): Channel_Info[0][%d] = %d, Channel_Info[1][%d] = %d\n", channel_idx, p_acs->channel_info_2g[0][channel_idx], channel_idx, p_acs->channel_info_2g[1][channel_idx])); + + for (search_idx = 0; search_idx < ODM_MAX_CHANNEL_2G; search_idx++) { + if (p_acs->channel_info_2g[1][search_idx] != 0) { + if (p_acs->channel_info_2g[0][search_idx] >= max_score) { + max_score = p_acs->channel_info_2g[0][search_idx]; + p_acs->clean_channel_2g = search_idx + 1; + } + } + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ACS, ODM_DBG_LOUD, ("(1)odm_auto_channel_select(): 2G: clean_channel_2g = %d, max_score = %d\n", + p_acs->clean_channel_2g, max_score)); + + } else if (channel >= 36) { + /* Need to do */ + p_acs->clean_channel_5g = channel; + } +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_acs.h b/drivers/staging/rtl8188eu/hal/phydm_acs.h new file mode 100644 index 000000000000..29f0f792975b --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_acs.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDMACS_H__ +#define __PHYDMACS_H__ + +#define ACS_VERSION "1.1" /*20150729 by YuChen*/ +#define CLM_VERSION "1.0" + +#define ODM_MAX_CHANNEL_2G 14 +#define ODM_MAX_CHANNEL_5G 24 + +/* For phydm_auto_channel_select_setting_ap() */ +#define STORE_DEFAULT_NHM_SETTING 0 +#define RESTORE_DEFAULT_NHM_SETTING 1 +#define ACS_NHM_SETTING 2 + +struct _ACS_ { + bool is_force_acs_result; + u8 clean_channel_2g; + u8 clean_channel_5g; + u16 channel_info_2g[2][ODM_MAX_CHANNEL_2G]; /* Channel_Info[1]: channel score, Channel_Info[2]:Channel_Scan_Times */ + u16 channel_info_5g[2][ODM_MAX_CHANNEL_5G]; +}; + + +void +odm_auto_channel_select_init( + void *p_dm_void +); + +void +odm_auto_channel_select_reset( + void *p_dm_void +); + +void +odm_auto_channel_select( + void *p_dm_void, + u8 channel +); + +u8 +odm_get_auto_channel_select_result( + void *p_dm_void, + u8 band +); + +#endif /* #ifndef __PHYDMACS_H__ */ diff --git a/drivers/staging/rtl8188eu/hal/phydm_adaptivity.c b/drivers/staging/rtl8188eu/hal/phydm_adaptivity.c new file mode 100644 index 000000000000..adfab691ca1b --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_adaptivity.c @@ -0,0 +1,823 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* ************************************************************ + * include files + * ************************************************************ */ +#include "mp_precomp.h" +#include "phydm_precomp.h" + +void +phydm_check_adaptivity( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTIVITY_STATISTICS *adaptivity = (struct _ADAPTIVITY_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDM_ADAPTIVITY); + + if (p_dm_odm->support_ability & ODM_BB_ADAPTIVITY) { + { + if (adaptivity->dynamic_link_adaptivity || adaptivity->acs_for_adaptivity) { + if (p_dm_odm->is_linked && adaptivity->is_check == false) { + phydm_nhm_counter_statistics(p_dm_odm); + phydm_check_environment(p_dm_odm); + } else if (!p_dm_odm->is_linked) + adaptivity->is_check = false; + } else { + p_dm_odm->adaptivity_enable = true; + + if (p_dm_odm->support_ic_type & (ODM_IC_11AC_GAIN_IDX_EDCCA | ODM_IC_11N_GAIN_IDX_EDCCA)) + p_dm_odm->adaptivity_flag = false; + else + p_dm_odm->adaptivity_flag = true; + } + } + } else { + p_dm_odm->adaptivity_enable = false; + p_dm_odm->adaptivity_flag = false; + } +} + +void +phydm_nhm_counter_statistics_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + /*PHY parameters initialize for n series*/ + odm_write_2byte(p_dm_odm, ODM_REG_CCX_PERIOD_11N + 2, 0xC350); /*0x894[31:16]=0x0xC350 Time duration for NHM unit: us, 0xc350=200ms*/ + odm_write_2byte(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N + 2, 0xffff); /*0x890[31:16]=0xffff th_9, th_10*/ + odm_write_4byte(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff50); /*0x898=0xffffff52 th_3, th_2, th_1, th_0*/ + odm_write_4byte(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11N, 0xffffffff); /*0x89c=0xffffffff th_7, th_6, th_5, th_4*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_FPGA0_IQK_11N, MASKBYTE0, 0xff); /*0xe28[7:0]=0xff th_8*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, BIT(10) | BIT9 | BIT8, 0x1); /*0x890[10:8]=1 ignoreCCA ignore PHYTXON enable CCX*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_OFDM_FA_RSTC_11N, BIT(7), 0x1); /*0xc0c[7]=1 max power among all RX ants*/ + } + else if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + /*PHY parameters initialize for ac series*/ + odm_write_2byte(p_dm_odm, ODM_REG_CCX_PERIOD_11AC + 2, 0xC350); /*0x990[31:16]=0xC350 Time duration for NHM unit: us, 0xc350=200ms*/ + odm_write_2byte(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC + 2, 0xffff); /*0x994[31:16]=0xffff th_9, th_10*/ + odm_write_4byte(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11AC, 0xffffff50); /*0x998=0xffffff52 th_3, th_2, th_1, th_0*/ + odm_write_4byte(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11AC, 0xffffffff); /*0x99c=0xffffffff th_7, th_6, th_5, th_4*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH8_11AC, MASKBYTE0, 0xff); /*0x9a0[7:0]=0xff th_8*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, BIT(8) | BIT9 | BIT10, 0x1); /*0x994[10:8]=1 ignoreCCA ignore PHYTXON enable CCX*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_9E8_11AC, BIT(0), 0x1); /*0x9e8[7]=1 max power among all RX ants*/ + + } +} + +void +phydm_nhm_counter_statistics( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (!(p_dm_odm->support_ability & ODM_BB_NHM_CNT)) + return; + + /*Get NHM report*/ + phydm_get_nhm_counter_statistics(p_dm_odm); + + /*Reset NHM counter*/ + phydm_nhm_counter_statistics_reset(p_dm_odm); +} + +void +phydm_get_nhm_counter_statistics( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 value32 = 0; + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_CNT_11AC, MASKDWORD); + else if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_CNT_11N, MASKDWORD); + + p_dm_odm->nhm_cnt_0 = (u8)(value32 & MASKBYTE0); + p_dm_odm->nhm_cnt_1 = (u8)((value32 & MASKBYTE1) >> 8); + +} + +void +phydm_nhm_counter_statistics_reset( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, BIT(1), 0); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, BIT(1), 1); + } else if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, BIT(1), 0); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, BIT(1), 1); + } +} + +void +phydm_set_edcca_threshold( + void *p_dm_void, + s8 H2L, + s8 L2H +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_ECCA_THRESHOLD, MASKBYTE2 | MASKBYTE0, (u32)((u8)L2H | (u8)H2L << 16)); + else if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XB_LSSI_READ_BACK, MASKLWORD, (u16)((u8)L2H | (u8)H2L << 8)); +} + +static void +phydm_set_lna( + void *p_dm_void, + enum phydm_set_lna type +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (p_dm_odm->support_ic_type & (ODM_RTL8188E | ODM_RTL8192E)) { + if (type == phydm_disable_lna) { + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xef, 0x80000, 0x1); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x30, 0xfffff, 0x18000); /*select Rx mode*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x31, 0xfffff, 0x0000f); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x32, 0xfffff, 0x37f82); /*disable LNA*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xef, 0x80000, 0x0); + if (p_dm_odm->rf_type > ODM_1T1R) { + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0xef, 0x80000, 0x1); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x30, 0xfffff, 0x18000); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x31, 0xfffff, 0x0000f); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x32, 0xfffff, 0x37f82); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0xef, 0x80000, 0x0); + } + } else if (type == phydm_enable_lna) { + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xef, 0x80000, 0x1); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x30, 0xfffff, 0x18000); /*select Rx mode*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x31, 0xfffff, 0x0000f); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x32, 0xfffff, 0x77f82); /*back to normal*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xef, 0x80000, 0x0); + if (p_dm_odm->rf_type > ODM_1T1R) { + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0xef, 0x80000, 0x1); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x30, 0xfffff, 0x18000); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x31, 0xfffff, 0x0000f); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x32, 0xfffff, 0x77f82); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0xef, 0x80000, 0x0); + } + } + } else if (p_dm_odm->support_ic_type & ODM_RTL8723B) { + if (type == phydm_disable_lna) { + /*S0*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xef, 0x80000, 0x1); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x30, 0xfffff, 0x18000); /*select Rx mode*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x31, 0xfffff, 0x0001f); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x32, 0xfffff, 0xe6137); /*disable LNA*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xef, 0x80000, 0x0); + /*S1*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xed, 0x00020, 0x1); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x43, 0xfffff, 0x3008d); /*select Rx mode and disable LNA*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xed, 0x00020, 0x0); + } else if (type == phydm_enable_lna) { + /*S0*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xef, 0x80000, 0x1); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x30, 0xfffff, 0x18000); /*select Rx mode*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x31, 0xfffff, 0x0001f); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x32, 0xfffff, 0xe6177); /*disable LNA*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xef, 0x80000, 0x0); + /*S1*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xed, 0x00020, 0x1); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x43, 0xfffff, 0x300bd); /*select Rx mode and disable LNA*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xed, 0x00020, 0x0); + } + + } else if (p_dm_odm->support_ic_type & ODM_RTL8812) { + if (type == phydm_disable_lna) { + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xef, 0x80000, 0x1); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x30, 0xfffff, 0x18000); /*select Rx mode*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x31, 0xfffff, 0x3f7ff); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x32, 0xfffff, 0xc22bf); /*disable LNA*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xef, 0x80000, 0x0); + if (p_dm_odm->rf_type > ODM_1T1R) { + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0xef, 0x80000, 0x1); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x30, 0xfffff, 0x18000); /*select Rx mode*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x31, 0xfffff, 0x3f7ff); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x32, 0xfffff, 0xc22bf); /*disable LNA*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0xef, 0x80000, 0x0); + } + } else if (type == phydm_enable_lna) { + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xef, 0x80000, 0x1); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x30, 0xfffff, 0x18000); /*select Rx mode*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x31, 0xfffff, 0x3f7ff); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x32, 0xfffff, 0xc26bf); /*disable LNA*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xef, 0x80000, 0x0); + if (p_dm_odm->rf_type > ODM_1T1R) { + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0xef, 0x80000, 0x1); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x30, 0xfffff, 0x18000); /*select Rx mode*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x31, 0xfffff, 0x3f7ff); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x32, 0xfffff, 0xc26bf); /*disable LNA*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0xef, 0x80000, 0x0); + } + } + } else if (p_dm_odm->support_ic_type & (ODM_RTL8821 | ODM_RTL8881A)) { + if (type == phydm_disable_lna) { + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xef, 0x80000, 0x1); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x30, 0xfffff, 0x18000); /*select Rx mode*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x31, 0xfffff, 0x0002f); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x32, 0xfffff, 0xfb09b); /*disable LNA*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xef, 0x80000, 0x0); + } else if (type == phydm_enable_lna) { + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xef, 0x80000, 0x1); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x30, 0xfffff, 0x18000); /*select Rx mode*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x31, 0xfffff, 0x0002f); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x32, 0xfffff, 0xfb0bb); /*disable LNA*/ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0xef, 0x80000, 0x0); + } + } +} + + + +void +phydm_set_trx_mux( + void *p_dm_void, + enum phydm_trx_mux_type tx_mode, + enum phydm_trx_mux_type rx_mode +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + odm_set_bb_reg(p_dm_odm, ODM_REG_CCK_RPT_FORMAT_11N, BIT(3) | BIT2 | BIT1, tx_mode); /*set TXmod to standby mode to remove outside noise affect*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_CCK_RPT_FORMAT_11N, BIT(22) | BIT21 | BIT20, rx_mode); /*set RXmod to standby mode to remove outside noise affect*/ + if (p_dm_odm->rf_type > ODM_1T1R) { + odm_set_bb_reg(p_dm_odm, ODM_REG_CCK_RPT_FORMAT_11N_B, BIT(3) | BIT2 | BIT1, tx_mode); /*set TXmod to standby mode to remove outside noise affect*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_CCK_RPT_FORMAT_11N_B, BIT(22) | BIT21 | BIT20, rx_mode); /*set RXmod to standby mode to remove outside noise affect*/ + } + } else if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + odm_set_bb_reg(p_dm_odm, ODM_REG_TRMUX_11AC, BIT(11) | BIT10 | BIT9 | BIT8, tx_mode); /*set TXmod to standby mode to remove outside noise affect*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_TRMUX_11AC, BIT(7) | BIT6 | BIT5 | BIT4, rx_mode); /*set RXmod to standby mode to remove outside noise affect*/ + if (p_dm_odm->rf_type > ODM_1T1R) { + odm_set_bb_reg(p_dm_odm, ODM_REG_TRMUX_11AC_B, BIT(11) | BIT10 | BIT9 | BIT8, tx_mode); /*set TXmod to standby mode to remove outside noise affect*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_TRMUX_11AC_B, BIT(7) | BIT6 | BIT5 | BIT4, rx_mode); /*set RXmod to standby mode to remove outside noise affect*/ + } + } +} + +void +phydm_mac_edcca_state( + void *p_dm_void, + enum phydm_mac_edcca_type state +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + if (state == phydm_ignore_edcca) { + odm_set_mac_reg(p_dm_odm, REG_TX_PTCL_CTRL, BIT(15), 1); /*ignore EDCCA reg520[15]=1*/ + /* odm_set_mac_reg(p_dm_odm, REG_RD_CTRL, BIT(11), 0); */ /*reg524[11]=0*/ + } else { /*don't set MAC ignore EDCCA signal*/ + odm_set_mac_reg(p_dm_odm, REG_TX_PTCL_CTRL, BIT(15), 0); /*don't ignore EDCCA reg520[15]=0*/ + /* odm_set_mac_reg(p_dm_odm, REG_RD_CTRL, BIT(11), 1); */ /*reg524[11]=1 */ + } + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_ADAPTIVITY, ODM_DBG_LOUD, ("EDCCA enable state = %d\n", state)); + +} + +bool +phydm_cal_nhm_cnt( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u16 base = 0; + + base = p_dm_odm->nhm_cnt_0 + p_dm_odm->nhm_cnt_1; + + if (base != 0) { + p_dm_odm->nhm_cnt_0 = ((p_dm_odm->nhm_cnt_0) << 8) / base; + p_dm_odm->nhm_cnt_1 = ((p_dm_odm->nhm_cnt_1) << 8) / base; + } + if ((p_dm_odm->nhm_cnt_0 - p_dm_odm->nhm_cnt_1) >= 100) + return true; /*clean environment*/ + else + return false; /*noisy environment*/ + +} + + +void +phydm_check_environment( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTIVITY_STATISTICS *adaptivity = (struct _ADAPTIVITY_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDM_ADAPTIVITY); + bool is_clean_environment = false; + + if (adaptivity->is_first_link == true) { + if (p_dm_odm->support_ic_type & (ODM_IC_11AC_GAIN_IDX_EDCCA | ODM_IC_11N_GAIN_IDX_EDCCA)) + p_dm_odm->adaptivity_flag = false; + else + p_dm_odm->adaptivity_flag = true; + + adaptivity->is_first_link = false; + return; + } else { + if (adaptivity->nhm_wait < 3) { /*Start enter NHM after 4 nhm_wait*/ + adaptivity->nhm_wait++; + phydm_nhm_counter_statistics(p_dm_odm); + return; + } else { + phydm_nhm_counter_statistics(p_dm_odm); + is_clean_environment = phydm_cal_nhm_cnt(p_dm_odm); + if (is_clean_environment == true) { + p_dm_odm->th_l2h_ini = adaptivity->th_l2h_ini_backup; /*adaptivity mode*/ + p_dm_odm->th_edcca_hl_diff = adaptivity->th_edcca_hl_diff_backup; + + p_dm_odm->adaptivity_enable = true; + + if (p_dm_odm->support_ic_type & (ODM_IC_11AC_GAIN_IDX_EDCCA | ODM_IC_11N_GAIN_IDX_EDCCA)) + p_dm_odm->adaptivity_flag = false; + else + p_dm_odm->adaptivity_flag = true; + } else { + if (!adaptivity->acs_for_adaptivity) { + p_dm_odm->th_l2h_ini = p_dm_odm->th_l2h_ini_mode2; /*mode2*/ + p_dm_odm->th_edcca_hl_diff = p_dm_odm->th_edcca_hl_diff_mode2; + + p_dm_odm->adaptivity_flag = false; + p_dm_odm->adaptivity_enable = false; + } + } + adaptivity->nhm_wait = 0; + adaptivity->is_first_link = true; + adaptivity->is_check = true; + } + + } + + +} + +void +phydm_search_pwdb_lower_bound( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTIVITY_STATISTICS *adaptivity = (struct _ADAPTIVITY_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDM_ADAPTIVITY); + u32 value32 = 0, reg_value32 = 0; + u8 cnt, try_count = 0; + u8 tx_edcca1 = 0, tx_edcca0 = 0; + bool is_adjust = true; + s8 th_l2h_dmc, th_h2l_dmc, igi_target = 0x32; + s8 diff; + u8 IGI = adaptivity->igi_base + 30 + (u8)p_dm_odm->th_l2h_ini - (u8)p_dm_odm->th_edcca_hl_diff; + + if (p_dm_odm->support_ic_type & (ODM_RTL8723B | ODM_RTL8188E | ODM_RTL8192E | ODM_RTL8812 | ODM_RTL8821 | ODM_RTL8881A)) + phydm_set_lna(p_dm_odm, phydm_disable_lna); + else { + phydm_set_trx_mux(p_dm_odm, phydm_standby_mode, phydm_standby_mode); + odm_pause_dig(p_dm_odm, PHYDM_PAUSE, PHYDM_PAUSE_LEVEL_0, 0x7e); + } + + diff = igi_target - (s8)IGI; + th_l2h_dmc = p_dm_odm->th_l2h_ini + diff; + if (th_l2h_dmc > 10) + th_l2h_dmc = 10; + th_h2l_dmc = th_l2h_dmc - p_dm_odm->th_edcca_hl_diff; + + phydm_set_edcca_threshold(p_dm_odm, th_h2l_dmc, th_l2h_dmc); + ODM_delay_ms(30); + + while (is_adjust) { + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11N, MASKDWORD, 0x0); + reg_value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11N, MASKDWORD); + } else if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0x0); + reg_value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + } + while (reg_value32 & BIT(3) && try_count < 3) { + try_count = try_count + 1; + ODM_delay_ms(3); + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) + reg_value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11N, MASKDWORD); + else if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) + reg_value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + } + try_count = 0; + + for (cnt = 0; cnt < 20; cnt++) { + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11N, MASKDWORD, 0x208); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11N, MASKDWORD); + } else if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0x209); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + } + if (value32 & BIT(30) && (p_dm_odm->support_ic_type & (ODM_RTL8723B | ODM_RTL8188E))) + tx_edcca1 = tx_edcca1 + 1; + else if (value32 & BIT(29)) + tx_edcca1 = tx_edcca1 + 1; + else + tx_edcca0 = tx_edcca0 + 1; + } + + if (tx_edcca1 > 1) { + IGI = IGI - 1; + th_l2h_dmc = th_l2h_dmc + 1; + if (th_l2h_dmc > 10) + th_l2h_dmc = 10; + th_h2l_dmc = th_l2h_dmc - p_dm_odm->th_edcca_hl_diff; + + phydm_set_edcca_threshold(p_dm_odm, th_h2l_dmc, th_l2h_dmc); + if (th_l2h_dmc == 10) { + is_adjust = false; + adaptivity->h2l_lb = th_h2l_dmc; + adaptivity->l2h_lb = th_l2h_dmc; + p_dm_odm->adaptivity_igi_upper = IGI; + } + + tx_edcca1 = 0; + tx_edcca0 = 0; + + } else { + is_adjust = false; + adaptivity->h2l_lb = th_h2l_dmc; + adaptivity->l2h_lb = th_l2h_dmc; + p_dm_odm->adaptivity_igi_upper = IGI; + tx_edcca1 = 0; + tx_edcca0 = 0; + } + } + + p_dm_odm->adaptivity_igi_upper = p_dm_odm->adaptivity_igi_upper - p_dm_odm->dc_backoff; + adaptivity->h2l_lb = adaptivity->h2l_lb + p_dm_odm->dc_backoff; + adaptivity->l2h_lb = adaptivity->l2h_lb + p_dm_odm->dc_backoff; + + if (p_dm_odm->support_ic_type & (ODM_RTL8723B | ODM_RTL8188E | ODM_RTL8192E | ODM_RTL8812 | ODM_RTL8821 | ODM_RTL8881A)) + phydm_set_lna(p_dm_odm, phydm_enable_lna); + else { + phydm_set_trx_mux(p_dm_odm, phydm_tx_mode, phydm_rx_mode); + odm_pause_dig(p_dm_odm, PHYDM_RESUME, PHYDM_PAUSE_LEVEL_0, NONE); + } + + phydm_set_edcca_threshold(p_dm_odm, 0x7f, 0x7f); /*resume to no link state*/ +} + +static bool +phydm_re_search_condition( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + /*struct _ADAPTIVITY_STATISTICS* adaptivity = (struct _ADAPTIVITY_STATISTICS*)phydm_get_structure(p_dm_odm, PHYDM_ADAPTIVITY);*/ + u8 adaptivity_igi_upper; + u8 count = 0; + /*s8 TH_L2H_dmc, IGI_target = 0x32;*/ + /*s8 diff;*/ + + adaptivity_igi_upper = p_dm_odm->adaptivity_igi_upper + p_dm_odm->dc_backoff; + + /*TH_L2H_dmc = 10;*/ + + /*diff = TH_L2H_dmc - p_dm_odm->TH_L2H_ini;*/ + /*lowest_IGI_upper = IGI_target - diff;*/ + + /*if ((adaptivity_igi_upper - lowest_IGI_upper) <= 5)*/ + if (adaptivity_igi_upper <= 0x26 && count < 3) { + count = count + 1; + return true; + } + else + return false; + +} + +void +phydm_adaptivity_info_init( + void *p_dm_void, + enum phydm_adapinfo_e cmn_info, + u32 value +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTIVITY_STATISTICS *adaptivity = (struct _ADAPTIVITY_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDM_ADAPTIVITY); + + switch (cmn_info) { + case PHYDM_ADAPINFO_CARRIER_SENSE_ENABLE: + p_dm_odm->carrier_sense_enable = (bool)value; + break; + + case PHYDM_ADAPINFO_DCBACKOFF: + p_dm_odm->dc_backoff = (u8)value; + break; + + case PHYDM_ADAPINFO_DYNAMICLINKADAPTIVITY: + adaptivity->dynamic_link_adaptivity = (bool)value; + break; + + case PHYDM_ADAPINFO_TH_L2H_INI: + p_dm_odm->th_l2h_ini = (s8)value; + break; + + case PHYDM_ADAPINFO_TH_EDCCA_HL_DIFF: + p_dm_odm->th_edcca_hl_diff = (s8)value; + break; + + case PHYDM_ADAPINFO_AP_NUM_TH: + adaptivity->ap_num_th = (u8)value; + break; + + default: + break; + + } + +} + + + +void +phydm_adaptivity_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTIVITY_STATISTICS *adaptivity = (struct _ADAPTIVITY_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDM_ADAPTIVITY); + s8 igi_target = 0x32; + + if (p_dm_odm->carrier_sense_enable == false) { + if (p_dm_odm->th_l2h_ini == 0) + p_dm_odm->th_l2h_ini = 0xf5; + } else + p_dm_odm->th_l2h_ini = 0xa; + + if (p_dm_odm->th_edcca_hl_diff == 0) + p_dm_odm->th_edcca_hl_diff = 7; + if (p_dm_odm->wifi_test == true || p_dm_odm->mp_mode == true) + p_dm_odm->edcca_enable = false; /*even no adaptivity, we still enable EDCCA, AP side use mib control*/ + else + p_dm_odm->edcca_enable = true; + + p_dm_odm->adaptivity_igi_upper = 0; + p_dm_odm->adaptivity_enable = false; /*use this flag to decide enable or disable*/ + + p_dm_odm->th_l2h_ini_mode2 = 20; + p_dm_odm->th_edcca_hl_diff_mode2 = 8; + adaptivity->th_l2h_ini_backup = p_dm_odm->th_l2h_ini; + adaptivity->th_edcca_hl_diff_backup = p_dm_odm->th_edcca_hl_diff; + + adaptivity->igi_base = 0x32; + adaptivity->igi_target = 0x1c; + adaptivity->h2l_lb = 0; + adaptivity->l2h_lb = 0; + adaptivity->nhm_wait = 0; + adaptivity->is_check = false; + adaptivity->is_first_link = true; + adaptivity->adajust_igi_level = 0; + adaptivity->is_stop_edcca = false; + adaptivity->backup_h2l = 0; + adaptivity->backup_l2h = 0; + + phydm_mac_edcca_state(p_dm_odm, phydm_dont_ignore_edcca); + + /*Search pwdB lower bound*/ + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11N, MASKDWORD, 0x208); + else if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0x209); + + if (p_dm_odm->support_ic_type & ODM_IC_11N_GAIN_IDX_EDCCA) { + /*odm_set_bb_reg(p_dm_odm, ODM_REG_EDCCA_DOWN_OPT_11N, BIT(12) | BIT11 | BIT10, 0x7);*/ /*interfernce need > 2^x us, and then EDCCA will be 1*/ + if (p_dm_odm->support_ic_type & ODM_RTL8197F) { + odm_set_bb_reg(p_dm_odm, ODM_REG_PAGE_B1_97F, BIT(30), 0x1); /*set to page B1*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_EDCCA_DCNF_97F, BIT(27) | BIT26, 0x1); /*0:rx_dfir, 1: dcnf_out, 2 :rx_iq, 3: rx_nbi_nf_out*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_PAGE_B1_97F, BIT(30), 0x0); + } else + odm_set_bb_reg(p_dm_odm, ODM_REG_EDCCA_DCNF_11N, BIT(21) | BIT20, 0x1); /*0:rx_dfir, 1: dcnf_out, 2 :rx_iq, 3: rx_nbi_nf_out*/ + } + if (p_dm_odm->support_ic_type & ODM_IC_11AC_GAIN_IDX_EDCCA) { /*8814a no need to find pwdB lower bound, maybe*/ + /*odm_set_bb_reg(p_dm_odm, ODM_REG_EDCCA_DOWN_OPT, BIT(30) | BIT29 | BIT28, 0x7);*/ /*interfernce need > 2^x us, and then EDCCA will be 1*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_ACBB_EDCCA_ENHANCE, BIT(29) | BIT28, 0x1); /*0:rx_dfir, 1: dcnf_out, 2 :rx_iq, 3: rx_nbi_nf_out*/ + } + + if (!(p_dm_odm->support_ic_type & (ODM_IC_11AC_GAIN_IDX_EDCCA | ODM_IC_11N_GAIN_IDX_EDCCA))) { + phydm_search_pwdb_lower_bound(p_dm_odm); + if (phydm_re_search_condition(p_dm_odm)) + phydm_search_pwdb_lower_bound(p_dm_odm); + } + + /*we need to consider PwdB upper bound for 8814 later IC*/ + adaptivity->adajust_igi_level = (u8)((p_dm_odm->th_l2h_ini + igi_target) - pwdb_upper_bound + dfir_loss); /*IGI = L2H - PwdB - dfir_loss*/ + + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_ADAPTIVITY, ODM_DBG_LOUD, ("th_l2h_ini = 0x%x, th_edcca_hl_diff = 0x%x, adaptivity->adajust_igi_level = 0x%x\n", p_dm_odm->th_l2h_ini, p_dm_odm->th_edcca_hl_diff, adaptivity->adajust_igi_level)); + + /*Check this later on Windows*/ + /*phydm_set_edcca_threshold_api(p_dm_odm, p_dm_dig_table->cur_ig_value);*/ + +} + + +void +phydm_adaptivity( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + u8 IGI = p_dm_dig_table->cur_ig_value; + s8 th_l2h_dmc, th_h2l_dmc; + s8 diff = 0, igi_target; + struct _ADAPTIVITY_STATISTICS *adaptivity = (struct _ADAPTIVITY_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDM_ADAPTIVITY); + + if ((p_dm_odm->edcca_enable == false) || (adaptivity->is_stop_edcca == true)) { + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_ADAPTIVITY, ODM_DBG_LOUD, ("Disable EDCCA!!!\n")); + return; + } + + if (!(p_dm_odm->support_ability & ODM_BB_ADAPTIVITY)) { + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_ADAPTIVITY, ODM_DBG_LOUD, ("adaptivity disable, enable EDCCA mode!!!\n")); + p_dm_odm->th_l2h_ini = p_dm_odm->th_l2h_ini_mode2; + p_dm_odm->th_edcca_hl_diff = p_dm_odm->th_edcca_hl_diff_mode2; + } + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_ADAPTIVITY, ODM_DBG_LOUD, ("odm_Adaptivity() =====>\n")); + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_ADAPTIVITY, ODM_DBG_LOUD, ("igi_base=0x%x, th_l2h_ini = %d, th_edcca_hl_diff = %d\n", + adaptivity->igi_base, p_dm_odm->th_l2h_ini, p_dm_odm->th_edcca_hl_diff)); + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + /*fix AC series when enable EDCCA hang issue*/ + odm_set_bb_reg(p_dm_odm, 0x800, BIT(10), 1); /*ADC_mask disable*/ + odm_set_bb_reg(p_dm_odm, 0x800, BIT(10), 0); /*ADC_mask enable*/ + } + if (*p_dm_odm->p_band_width == ODM_BW20M) /*CHANNEL_WIDTH_20*/ + igi_target = adaptivity->igi_base; + else if (*p_dm_odm->p_band_width == ODM_BW40M) + igi_target = adaptivity->igi_base + 2; + else if (*p_dm_odm->p_band_width == ODM_BW80M) + igi_target = adaptivity->igi_base + 2; + else + igi_target = adaptivity->igi_base; + adaptivity->igi_target = (u8) igi_target; + + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_ADAPTIVITY, ODM_DBG_LOUD, ("band_width=%s, igi_target=0x%x, dynamic_link_adaptivity = %d, acs_for_adaptivity = %d\n", + (*p_dm_odm->p_band_width == ODM_BW80M) ? "80M" : ((*p_dm_odm->p_band_width == ODM_BW40M) ? "40M" : "20M"), igi_target, adaptivity->dynamic_link_adaptivity, adaptivity->acs_for_adaptivity)); + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_ADAPTIVITY, ODM_DBG_LOUD, ("RSSI_min = %d, adaptivity->adajust_igi_level= 0x%x, adaptivity_flag = %d, adaptivity_enable = %d\n", + p_dm_odm->rssi_min, adaptivity->adajust_igi_level, p_dm_odm->adaptivity_flag, p_dm_odm->adaptivity_enable)); + + if ((adaptivity->dynamic_link_adaptivity == true) && (!p_dm_odm->is_linked) && (p_dm_odm->adaptivity_enable == false)) { + phydm_set_edcca_threshold(p_dm_odm, 0x7f, 0x7f); + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_ADAPTIVITY, ODM_DBG_LOUD, ("In DynamicLink mode(noisy) and No link, Turn off EDCCA!!\n")); + return; + } + + if (p_dm_odm->support_ic_type & (ODM_IC_11AC_GAIN_IDX_EDCCA | ODM_IC_11N_GAIN_IDX_EDCCA)) { + if ((adaptivity->adajust_igi_level > IGI) && (p_dm_odm->adaptivity_enable == true)) + diff = adaptivity->adajust_igi_level - IGI; + + th_l2h_dmc = p_dm_odm->th_l2h_ini - diff + igi_target; + th_h2l_dmc = th_l2h_dmc - p_dm_odm->th_edcca_hl_diff; + } else { + diff = igi_target - (s8)IGI; + th_l2h_dmc = p_dm_odm->th_l2h_ini + diff; + if (th_l2h_dmc > 10 && (p_dm_odm->adaptivity_enable == true)) + th_l2h_dmc = 10; + + th_h2l_dmc = th_l2h_dmc - p_dm_odm->th_edcca_hl_diff; + + /*replace lower bound to prevent EDCCA always equal 1*/ + if (th_h2l_dmc < adaptivity->h2l_lb) + th_h2l_dmc = adaptivity->h2l_lb; + if (th_l2h_dmc < adaptivity->l2h_lb) + th_l2h_dmc = adaptivity->l2h_lb; + } + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_ADAPTIVITY, ODM_DBG_LOUD, ("IGI=0x%x, th_l2h_dmc = %d, th_h2l_dmc = %d\n", IGI, th_l2h_dmc, th_h2l_dmc)); + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_ADAPTIVITY, ODM_DBG_LOUD, ("adaptivity_igi_upper=0x%x, h2l_lb = 0x%x, l2h_lb = 0x%x\n", p_dm_odm->adaptivity_igi_upper, adaptivity->h2l_lb, adaptivity->l2h_lb)); + + phydm_set_edcca_threshold(p_dm_odm, th_h2l_dmc, th_l2h_dmc); + + if (p_dm_odm->adaptivity_enable == true) + odm_set_mac_reg(p_dm_odm, REG_RD_CTRL, BIT(11), 1); + + return; +} + +/*This API is for solving USB can't Tx problem due to USB3.0 interference in 2.4G*/ +void +phydm_pause_edcca( + void *p_dm_void, + bool is_pasue_edcca +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTIVITY_STATISTICS *adaptivity = (struct _ADAPTIVITY_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDM_ADAPTIVITY); + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + u8 IGI = p_dm_dig_table->cur_ig_value; + s8 diff = 0; + + if (is_pasue_edcca) { + adaptivity->is_stop_edcca = true; + if (p_dm_odm->support_ic_type & (ODM_IC_11AC_GAIN_IDX_EDCCA | ODM_IC_11N_GAIN_IDX_EDCCA)) { + if (adaptivity->adajust_igi_level > IGI) + diff = adaptivity->adajust_igi_level - IGI; + + adaptivity->backup_l2h = p_dm_odm->th_l2h_ini - diff + adaptivity->igi_target; + adaptivity->backup_h2l = adaptivity->backup_l2h - p_dm_odm->th_edcca_hl_diff; + } else { + diff = adaptivity->igi_target - (s8)IGI; + adaptivity->backup_l2h = p_dm_odm->th_l2h_ini + diff; + if (adaptivity->backup_l2h > 10) + adaptivity->backup_l2h = 10; + + adaptivity->backup_h2l = adaptivity->backup_l2h - p_dm_odm->th_edcca_hl_diff; + + /*replace lower bound to prevent EDCCA always equal 1*/ + if (adaptivity->backup_h2l < adaptivity->h2l_lb) + adaptivity->backup_h2l = adaptivity->h2l_lb; + if (adaptivity->backup_l2h < adaptivity->l2h_lb) + adaptivity->backup_l2h = adaptivity->l2h_lb; + } + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_ADAPTIVITY, ODM_DBG_LOUD, ("pauseEDCCA : L2Hbak = 0x%x, H2Lbak = 0x%x, IGI = 0x%x\n", adaptivity->backup_l2h, adaptivity->backup_h2l, IGI)); + + /*Disable EDCCA*/ + phydm_pause_edcca_work_item_callback(p_dm_odm); + } else { + + adaptivity->is_stop_edcca = false; + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_ADAPTIVITY, ODM_DBG_LOUD, ("resumeEDCCA : L2Hbak = 0x%x, H2Lbak = 0x%x, IGI = 0x%x\n", adaptivity->backup_l2h, adaptivity->backup_h2l, IGI)); + /*Resume EDCCA*/ + phydm_resume_edcca_work_item_callback(p_dm_odm); + } +} + + +void +phydm_pause_edcca_work_item_callback( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_ECCA_THRESHOLD, MASKBYTE2 | MASKBYTE0, (u32)(0x7f | 0x7f << 16)); + else if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XB_LSSI_READ_BACK, MASKLWORD, (u16)(0x7f | 0x7f << 8)); +} + +void +phydm_resume_edcca_work_item_callback( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTIVITY_STATISTICS *adaptivity = (struct _ADAPTIVITY_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDM_ADAPTIVITY); + + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_ECCA_THRESHOLD, MASKBYTE2 | MASKBYTE0, (u32)((u8)adaptivity->backup_l2h | (u8)adaptivity->backup_h2l << 16)); + else if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XB_LSSI_READ_BACK, MASKLWORD, (u16)((u8)adaptivity->backup_l2h | (u8)adaptivity->backup_h2l << 8)); +} + + +void +phydm_set_edcca_threshold_api( + void *p_dm_void, + u8 IGI +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTIVITY_STATISTICS *adaptivity = (struct _ADAPTIVITY_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDM_ADAPTIVITY); + s8 th_l2h_dmc, th_h2l_dmc; + s8 diff = 0, igi_target = 0x32; + + if (p_dm_odm->support_ability & ODM_BB_ADAPTIVITY) { + if (p_dm_odm->support_ic_type & (ODM_IC_11AC_GAIN_IDX_EDCCA | ODM_IC_11N_GAIN_IDX_EDCCA)) { + if (adaptivity->adajust_igi_level > IGI) + diff = adaptivity->adajust_igi_level - IGI; + + th_l2h_dmc = p_dm_odm->th_l2h_ini - diff + igi_target; + th_h2l_dmc = th_l2h_dmc - p_dm_odm->th_edcca_hl_diff; + } else { + diff = igi_target - (s8)IGI; + th_l2h_dmc = p_dm_odm->th_l2h_ini + diff; + if (th_l2h_dmc > 10) + th_l2h_dmc = 10; + + th_h2l_dmc = th_l2h_dmc - p_dm_odm->th_edcca_hl_diff; + + /*replace lower bound to prevent EDCCA always equal 1*/ + if (th_h2l_dmc < adaptivity->h2l_lb) + th_h2l_dmc = adaptivity->h2l_lb; + if (th_l2h_dmc < adaptivity->l2h_lb) + th_l2h_dmc = adaptivity->l2h_lb; + } + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_ADAPTIVITY, ODM_DBG_LOUD, ("API :IGI=0x%x, th_l2h_dmc = %d, th_h2l_dmc = %d\n", IGI, th_l2h_dmc, th_h2l_dmc)); + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_ADAPTIVITY, ODM_DBG_LOUD, ("API :adaptivity_igi_upper=0x%x, h2l_lb = 0x%x, l2h_lb = 0x%x\n", p_dm_odm->adaptivity_igi_upper, adaptivity->h2l_lb, adaptivity->l2h_lb)); + + phydm_set_edcca_threshold(p_dm_odm, th_h2l_dmc, th_l2h_dmc); + } + +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_adaptivity.h b/drivers/staging/rtl8188eu/hal/phydm_adaptivity.h new file mode 100644 index 000000000000..2a4a208be479 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_adaptivity.h @@ -0,0 +1,159 @@ + +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDMADAPTIVITY_H__ +#define __PHYDMADAPTIVITY_H__ + +#define ADAPTIVITY_VERSION "9.3.5" /*20160902 changed by Kevin, refine method for searching pwdb lower bound*/ + +#define pwdb_upper_bound 7 +#define dfir_loss 5 + +enum phydm_adapinfo_e { + PHYDM_ADAPINFO_CARRIER_SENSE_ENABLE = 0, + PHYDM_ADAPINFO_DCBACKOFF, + PHYDM_ADAPINFO_DYNAMICLINKADAPTIVITY, + PHYDM_ADAPINFO_TH_L2H_INI, + PHYDM_ADAPINFO_TH_EDCCA_HL_DIFF, + PHYDM_ADAPINFO_AP_NUM_TH +}; + +enum phydm_set_lna { + phydm_disable_lna = 0, + phydm_enable_lna = 1, +}; + + +enum phydm_trx_mux_type { + phydm_shutdown = 0, + phydm_standby_mode = 1, + phydm_tx_mode = 2, + phydm_rx_mode = 3 +}; + +enum phydm_mac_edcca_type { + phydm_ignore_edcca = 0, + phydm_dont_ignore_edcca = 1 +}; + +struct _ADAPTIVITY_STATISTICS { + s8 th_l2h_ini_backup; + s8 th_edcca_hl_diff_backup; + s8 igi_base; + u8 igi_target; + u8 nhm_wait; + s8 h2l_lb; + s8 l2h_lb; + bool is_first_link; + bool is_check; + bool dynamic_link_adaptivity; + u8 ap_num_th; + u8 adajust_igi_level; + bool acs_for_adaptivity; + s8 backup_l2h; + s8 backup_h2l; + bool is_stop_edcca; +}; + +void +phydm_pause_edcca( + void *p_dm_void, + bool is_pasue_edcca +); + +void +phydm_check_adaptivity( + void *p_dm_void +); + +void +phydm_check_environment( + void *p_dm_void +); + +void +phydm_nhm_counter_statistics_init( + void *p_dm_void +); + +void +phydm_nhm_counter_statistics( + void *p_dm_void +); + +void +phydm_nhm_counter_statistics_reset( + void *p_dm_void +); + +void +phydm_get_nhm_counter_statistics( + void *p_dm_void +); + +void +phydm_mac_edcca_state( + void *p_dm_void, + enum phydm_mac_edcca_type state +); + +void +phydm_set_edcca_threshold( + void *p_dm_void, + s8 H2L, + s8 L2H +); + +void +phydm_set_trx_mux( + void *p_dm_void, + enum phydm_trx_mux_type tx_mode, + enum phydm_trx_mux_type rx_mode +); + +bool +phydm_cal_nhm_cnt( + void *p_dm_void +); + +void +phydm_search_pwdb_lower_bound( + void *p_dm_void +); + +void +phydm_adaptivity_info_init( + void *p_dm_void, + enum phydm_adapinfo_e cmn_info, + u32 value +); + +void +phydm_adaptivity_init( + void *p_dm_void +); + +void +phydm_adaptivity( + void *p_dm_void +); + +void +phydm_set_edcca_threshold_api( + void *p_dm_void, + u8 IGI +); + +void +phydm_pause_edcca_work_item_callback( + void *p_dm_void +); + +void +phydm_resume_edcca_work_item_callback( + void *p_dm_void +); + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_adc_sampling.c b/drivers/staging/rtl8188eu/hal/phydm_adc_sampling.c new file mode 100644 index 000000000000..89739a27bc97 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_adc_sampling.c @@ -0,0 +1,594 @@ +#include "mp_precomp.h" +#include "phydm_precomp.h" + + +#if (PHYDM_LA_MODE_SUPPORT == 1) + +bool +phydm_la_buffer_allocate( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _RT_ADCSMP *adc_smp = &(p_dm_odm->adcsmp); + struct _ADAPTER *adapter = p_dm_odm->adapter; + struct _RT_ADCSMP_STRING *adc_smp_buf = &(adc_smp->adc_smp_buf); + bool ret = false; + + dbg_print("[LA mode BufferAllocate]\n"); + + if (adc_smp_buf->length == 0) { + + odm_allocate_memory(p_dm_odm, (void **)&adc_smp_buf->octet, adc_smp_buf->buffer_size); + if (!adc_smp_buf->octet) { + ret = false; + } else + adc_smp_buf->length = adc_smp_buf->buffer_size; + ret = true; + } + + return ret; +} + +void +phydm_la_get_tx_pkt_buf( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _RT_ADCSMP *adc_smp = &(p_dm_odm->adcsmp); + struct _RT_ADCSMP_STRING *adc_smp_buf = &(adc_smp->adc_smp_buf); + u32 i = 0, value32, data_l = 0, data_h = 0; + u32 addr, finish_addr; + u32 end_addr = (adc_smp_buf->start_pos + adc_smp_buf->buffer_size) - 1; /*end_addr = 0x3ffff;*/ + bool is_round_up; + static u32 page = 0xFF; + u32 smp_cnt = 0, smp_number = 0, addr_8byte = 0; + + odm_memory_set(p_dm_odm, adc_smp_buf->octet, 0, adc_smp_buf->length); + odm_write_1byte(p_dm_odm, 0x0106, 0x69); + + dbg_print("GetTxPktBuf\n"); + + value32 = odm_read_4byte(p_dm_odm, 0x7c0); + is_round_up = (bool)((value32 & BIT(31)) >> 31); + finish_addr = (value32 & 0x7FFF0000) >> 16; /*Reg7C0[30:16]: finish addr (unit: 8byte)*/ + + if (is_round_up) { + addr = (finish_addr + 1) << 3; + dbg_print("is_round_up = ((%d)), finish_addr=((0x%x)), 0x7c0=((0x%x))\n", is_round_up, finish_addr, value32); + smp_number = ((adc_smp_buf->buffer_size) >> 3); /*Byte to 64Byte*/ + } else { + addr = adc_smp_buf->start_pos; + + addr_8byte = addr >> 3; + if (addr_8byte > finish_addr) + smp_number = addr_8byte - finish_addr; + else + smp_number = finish_addr - addr_8byte; + + dbg_print("is_round_up = ((%d)), finish_addr=((0x%x * 8Byte)), Start_Addr = ((0x%x * 8Byte)), smp_number = ((%d))\n", is_round_up, finish_addr, addr_8byte, smp_number); + + } + if (p_dm_odm->support_ic_type & ODM_RTL8197F) { + for (addr = 0x0, i = 0; addr < end_addr; addr += 8, i += 2) { /*64K byte*/ + if ((addr & 0xfff) == 0) + odm_set_bb_reg(p_dm_odm, 0x0140, MASKLWORD, 0x780 + (addr >> 12)); + data_l = odm_get_bb_reg(p_dm_odm, 0x8000 + (addr & 0xfff), MASKDWORD); + data_h = odm_get_bb_reg(p_dm_odm, 0x8000 + (addr & 0xfff) + 4, MASKDWORD); + + dbg_print("%08x%08x\n", data_h, data_l); + } + } else { + while (addr != (finish_addr << 3)) { + if (page != (addr >> 12)) { + /*Reg140=0x780+(addr>>12), addr=0x30~0x3F, total 16 pages*/ + page = (addr >> 12); + } + odm_set_bb_reg(p_dm_odm, 0x0140, MASKLWORD, 0x780 + page); + + /*pDataL = 0x8000+(addr&0xfff);*/ + data_l = odm_get_bb_reg(p_dm_odm, 0x8000 + (addr & 0xfff), MASKDWORD); + data_h = odm_get_bb_reg(p_dm_odm, 0x8000 + (addr & 0xfff) + 4, MASKDWORD); + + adc_smp_buf->octet[i] = data_h; + adc_smp_buf->octet[i + 1] = data_l; + +#if DBG + dbg_print("%08x%08x\n", data_h, data_l); +#endif + i = i + 2; + + if ((addr + 8) >= end_addr) + addr = adc_smp_buf->start_pos; + else + addr = addr + 8; + + smp_cnt++; + if (smp_cnt >= (smp_number - 1)) + break; + } + dbg_print("smp_cnt = ((%d))\n", smp_cnt); + } +} + +void +phydm_la_mode_set_mac_iq_dump( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _RT_ADCSMP *adc_smp = &(p_dm_odm->adcsmp); + u32 reg_value; + + odm_write_1byte(p_dm_odm, 0x7c0, 0); /*clear all 0x7c0*/ + odm_set_mac_reg(p_dm_odm, 0x7c0, BIT(0), 1); /*Enable LA mode HW block*/ + + if (adc_smp->la_trig_mode == PHYDM_MAC_TRIG) { + + adc_smp->is_bb_trigger = 0; + odm_set_mac_reg(p_dm_odm, 0x7c0, BIT(2), 1); /*polling bit for MAC mode*/ + odm_set_mac_reg(p_dm_odm, 0x7c0, BIT(4) | BIT3, adc_smp->la_trigger_edge); /*trigger mode for MAC*/ + + dbg_print("[MAC_trig] ref_mask = ((0x%x)), ref_value = ((0x%x)), dbg_port = ((0x%x))\n", adc_smp->la_mac_ref_mask, adc_smp->la_trig_sig_sel, adc_smp->la_dbg_port); + /*[Set MAC Debug Port]*/ + odm_set_mac_reg(p_dm_odm, 0xF4, BIT(16), 1); + odm_set_mac_reg(p_dm_odm, 0x38, 0xff0000, adc_smp->la_dbg_port); + odm_set_mac_reg(p_dm_odm, 0x7c4, MASKDWORD, adc_smp->la_mac_ref_mask); + odm_set_mac_reg(p_dm_odm, 0x7c8, MASKDWORD, adc_smp->la_trig_sig_sel); + + } else { + + adc_smp->is_bb_trigger = 1; + odm_set_mac_reg(p_dm_odm, 0x7c0, BIT(1), 1); /*polling bit for BB ADC mode*/ + + if (adc_smp->la_trig_mode == PHYDM_ADC_MAC_TRIG) { + + odm_set_mac_reg(p_dm_odm, 0x7c0, BIT(3), 1); /*polling bit for MAC trigger event*/ + odm_set_mac_reg(p_dm_odm, 0x7c0, BIT(7) | BIT(6), adc_smp->la_trig_sig_sel); + + if (adc_smp->la_trig_sig_sel == ADCSMP_TRIG_REG) + odm_set_mac_reg(p_dm_odm, 0x7c0, BIT(5), 1); /* manual trigger 0x7C0[5] = 0->1*/ + } + } + + reg_value = odm_get_bb_reg(p_dm_odm, 0x7c0, 0xff); + dbg_print("4. [Set MAC IQ dump] 0x7c0[7:0] = ((0x%x))\n", reg_value); +} + +void +phydm_la_mode_set_dma_type( + void *p_dm_void, + u8 la_dma_type +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + dbg_print("2. [LA mode DMA setting] Dma_type = ((%d))\n", la_dma_type); + if (p_dm_odm->support_ic_type & ODM_N_ANTDIV_SUPPORT) + odm_set_bb_reg(p_dm_odm, 0x9a0, 0xf00, la_dma_type); /*0x9A0[11:8]*/ + else + odm_set_bb_reg(p_dm_odm, odm_adc_trigger_jaguar2, 0xf00, la_dma_type); /*0x95C[11:8]*/ +} + +void +phydm_adc_smp_start( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _RT_ADCSMP *adc_smp = &(p_dm_odm->adcsmp); + u8 tmp_u1b; + u8 backup_DMA, while_cnt = 0; + u8 polling_ok = false, target_polling_bit; + + phydm_la_mode_bb_setting(p_dm_odm); + phydm_la_mode_set_dma_type(p_dm_odm, adc_smp->la_dma_type); + phydm_la_mode_set_trigger_time(p_dm_odm, adc_smp->la_trigger_time); + + if (p_dm_odm->support_ic_type & ODM_RTL8197F) + odm_set_bb_reg(p_dm_odm, 0xd00, BIT(26), 0x1); + else { /*for 8814A and 8822B?*/ + odm_write_1byte(p_dm_odm, 0x198c, 0x7); + odm_write_1byte(p_dm_odm, 0x8b4, 0x80); + /* odm_set_bb_reg(p_dm_odm, 0x8b4, BIT7, 1); */ + } + + phydm_la_mode_set_mac_iq_dump(p_dm_odm); + /* return; */ + + target_polling_bit = (adc_smp->is_bb_trigger) ? BIT(1) : BIT(2); + do { /*Polling time always use 100ms, when it exceed 2s, break while loop*/ + tmp_u1b = odm_read_1byte(p_dm_odm, 0x7c0); + + if (adc_smp->adc_smp_state != ADCSMP_STATE_SET) { + dbg_print("[state Error] adc_smp_state != ADCSMP_STATE_SET\n"); + break; + + } else if (tmp_u1b & target_polling_bit) { + ODM_delay_ms(100); + while_cnt = while_cnt + 1; + continue; + } else { + dbg_print("[LA Query OK] polling_bit=((0x%x))\n", target_polling_bit); + polling_ok = true; + if (p_dm_odm->support_ic_type & ODM_RTL8197F) + odm_set_bb_reg(p_dm_odm, 0x7c0, BIT(0), 0x0); + break; + } + } while (while_cnt < 20); + + if (adc_smp->adc_smp_state == ADCSMP_STATE_SET) { + + if (polling_ok) + phydm_la_get_tx_pkt_buf(p_dm_odm); + else + dbg_print("[Polling timeout]\n"); + } + + if (adc_smp->adc_smp_state == ADCSMP_STATE_SET) + adc_smp->adc_smp_state = ADCSMP_STATE_QUERY; + + dbg_print("[LA mode] LA_pattern_count = ((%d))\n", adc_smp->la_count); + + adc_smp_stop(p_dm_odm); + + if (adc_smp->la_count == 0) { + dbg_print("LA Dump finished ---------->\n\n\n"); + /**/ + } else { + adc_smp->la_count--; + dbg_print("LA Dump more ---------->\n\n\n"); + adc_smp_set(p_dm_odm, adc_smp->la_trig_mode, adc_smp->la_trig_sig_sel, adc_smp->la_dma_type, adc_smp->la_trigger_time, 0); + } + +} + +void +adc_smp_set( + void *p_dm_void, + u8 trig_mode, + u32 trig_sig_sel, + u8 dma_data_sig_sel, + u32 trigger_time, + u16 polling_time +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + bool is_set_success = true; + struct _RT_ADCSMP *adc_smp = &(p_dm_odm->adcsmp); + + adc_smp->la_trig_mode = trig_mode; + adc_smp->la_trig_sig_sel = trig_sig_sel; + adc_smp->la_dma_type = dma_data_sig_sel; + adc_smp->la_trigger_time = trigger_time; + + if (adc_smp->adc_smp_state != ADCSMP_STATE_IDLE) + is_set_success = false; + else if (adc_smp->adc_smp_buf.length == 0) + is_set_success = phydm_la_buffer_allocate(p_dm_odm); + + if (is_set_success) { + adc_smp->adc_smp_state = ADCSMP_STATE_SET; + + dbg_print("[LA Set Success] LA_State=((%d))\n", adc_smp->adc_smp_state); + + phydm_adc_smp_start(p_dm_odm); + } else + dbg_print("[LA Set Fail] LA_State=((%d))\n", adc_smp->adc_smp_state); + + +} + +void +adc_smp_query( + void *p_dm_void, + void *output, + u32 out_len, + u32 *pused +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _RT_ADCSMP *adc_smp = &(p_dm_odm->adcsmp); + struct _RT_ADCSMP_STRING *adc_smp_buf = &(adc_smp->adc_smp_buf); + u32 used = *pused; + u32 i; + /* struct timespec t; */ + /* rtw_get_current_timespec(&t); */ + + dbg_print("%s adc_smp_state %d", __func__, adc_smp->adc_smp_state); + + for (i = 0; i < (adc_smp_buf->length >> 2) - 2; i += 2) { + PHYDM_SNPRINTF((output + used, out_len - used, + "%08x%08x\n", adc_smp_buf->octet[i], adc_smp_buf->octet[i + 1])); + } + + PHYDM_SNPRINTF((output + used, out_len - used, "\n")); + /* PHYDM_SNPRINTF((output+used, out_len-used, "\n[%lu.%06lu]\n", t.tv_sec, t.tv_nsec)); */ + *pused = used; +} + +s32 +adc_smp_get_sample_counts( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _RT_ADCSMP *adc_smp = &(p_dm_odm->adcsmp); + struct _RT_ADCSMP_STRING *adc_smp_buf = &(adc_smp->adc_smp_buf); + + return (adc_smp_buf->length >> 2) - 2; +} + +s32 +adc_smp_query_single_data( + void *p_dm_void, + void *output, + u32 out_len, + u32 index +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _RT_ADCSMP *adc_smp = &(p_dm_odm->adcsmp); + struct _RT_ADCSMP_STRING *adc_smp_buf = &(adc_smp->adc_smp_buf); + u32 used = 0; + + /* dbg_print("%s adc_smp_state %d\n", __func__, adc_smp->adc_smp_state); */ + if (adc_smp->adc_smp_state != ADCSMP_STATE_QUERY) { + PHYDM_SNPRINTF((output + used, out_len - used, + "Error: la data is not ready yet ...\n")); + return -1; + } + + if (index < ((adc_smp_buf->length >> 2) - 2)) { + PHYDM_SNPRINTF((output + used, out_len - used, "%08x%08x\n", + adc_smp_buf->octet[index], adc_smp_buf->octet[index + 1])); + } + return 0; +} + +void +adc_smp_stop( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _RT_ADCSMP *adc_smp = &(p_dm_odm->adcsmp); + + adc_smp->adc_smp_state = ADCSMP_STATE_IDLE; + dbg_print("[LA_Stop] LA_state = ((%d))\n", adc_smp->adc_smp_state); +} + +void +adc_smp_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _RT_ADCSMP *adc_smp = &(p_dm_odm->adcsmp); + struct _RT_ADCSMP_STRING *adc_smp_buf = &(adc_smp->adc_smp_buf); + + adc_smp->adc_smp_state = ADCSMP_STATE_IDLE; + + if (p_dm_odm->support_ic_type & ODM_RTL8814A) { + adc_smp_buf->start_pos = 0x30000; + adc_smp_buf->buffer_size = 0x10000; + } else if (p_dm_odm->support_ic_type & ODM_RTL8822B) { + adc_smp_buf->start_pos = 0x20000; + adc_smp_buf->buffer_size = 0x20000; + } else if (p_dm_odm->support_ic_type & ODM_RTL8197F) { + adc_smp_buf->start_pos = 0x00000; + adc_smp_buf->buffer_size = 0x10000; + } else if (p_dm_odm->support_ic_type & ODM_RTL8821C) { + adc_smp_buf->start_pos = 0x8000; + adc_smp_buf->buffer_size = 0x8000; + } + +} + +void +adc_smp_de_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _RT_ADCSMP *adc_smp = &(p_dm_odm->adcsmp); + struct _RT_ADCSMP_STRING *adc_smp_buf = &(adc_smp->adc_smp_buf); + + adc_smp_stop(p_dm_odm); + + if (adc_smp_buf->length != 0x0) { + odm_free_memory(p_dm_odm, adc_smp_buf->octet, adc_smp_buf->length); + adc_smp_buf->length = 0x0; + } +} + +void +phydm_la_mode_bb_setting( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _RT_ADCSMP *adc_smp = &(p_dm_odm->adcsmp); + + u8 trig_mode = adc_smp->la_trig_mode; + u32 trig_sig_sel = adc_smp->la_trig_sig_sel; + u32 dbg_port = adc_smp->la_dbg_port; + u8 is_trigger_edge = adc_smp->la_trigger_edge; + u8 sampling_rate = adc_smp->la_smp_rate; + + dbg_print("1. [LA mode bb_setting] trig_mode = ((%d)), dbg_port = ((0x%x)), Trig_Edge = ((%d)), smp_rate = ((%d)), Trig_Sel = ((0x%x))\n", + trig_mode, dbg_port, is_trigger_edge, sampling_rate, trig_sig_sel); + + if (trig_mode == PHYDM_MAC_TRIG) + trig_sig_sel = 0; /*ignore this setting*/ + + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + + if (trig_mode == PHYDM_ADC_RF0_TRIG) { + odm_set_bb_reg(p_dm_odm, 0x8f8, BIT(25) | BIT24 | BIT23 | BIT22, 9); /*DBGOUT_RFC_a[31:0]*/ + } else if (trig_mode == PHYDM_ADC_RF1_TRIG) { + odm_set_bb_reg(p_dm_odm, 0x8f8, BIT(25) | BIT24 | BIT23 | BIT22, 8); /*DBGOUT_RFC_b[31:0]*/ + } else + odm_set_bb_reg(p_dm_odm, 0x8f8, BIT(25) | BIT(24) | BIT(23) | BIT(22), 0); + /* + (0:) '{ofdm_dbg[31:0]}' + (1:) '{cca,crc32_fail,dbg_ofdm[29:0]}' + (2:) '{vbon,crc32_fail,dbg_ofdm[29:0]}' + (3:) '{cca,crc32_ok,dbg_ofdm[29:0]}' + (4:) '{vbon,crc32_ok,dbg_ofdm[29:0]}' + (5:) '{dbg_iqk_anta}' + (6:) '{cca,ofdm_crc_ok,dbg_dp_anta[29:0]}' + (7:) '{dbg_iqk_antb}' + (8:) '{DBGOUT_RFC_b[31:0]}' + (9:) '{DBGOUT_RFC_a[31:0]}' + (a:) '{dbg_ofdm}' + (b:) '{dbg_cck}' + */ + + odm_set_bb_reg(p_dm_odm, 0x198C, BIT(2) | BIT1 | BIT0, 7); /*disable dbg clk gating*/ + + /*dword= odm_get_bb_reg(p_dm_odm, 0x8FC, MASKDWORD);*/ + /*dbg_print("dbg_port = ((0x%x))\n", dword);*/ + odm_set_bb_reg(p_dm_odm, 0x95C, 0x1f, trig_sig_sel); /*0x95C[4:0], BB debug port bit*/ + odm_set_bb_reg(p_dm_odm, 0x8FC, MASKDWORD, dbg_port); + odm_set_bb_reg(p_dm_odm, 0x95C, BIT(31), is_trigger_edge); /*0: posedge, 1: negedge*/ + odm_set_bb_reg(p_dm_odm, 0x95c, 0xe0, sampling_rate); + /* (0:) '80MHz' + (1:) '40MHz' + (2:) '20MHz' + (3:) '10MHz' + (4:) '5MHz' + (5:) '2.5MHz' + (6:) '1.25MHz' + (7:) '160MHz (for BW160 ic)' + */ + } else { + odm_set_bb_reg(p_dm_odm, 0x9a0, 0x1f, trig_sig_sel); /*0x9A0[4:0], BB debug port bit*/ + odm_set_bb_reg(p_dm_odm, 0x908, MASKDWORD, dbg_port); + odm_set_bb_reg(p_dm_odm, 0x9A0, BIT(31), is_trigger_edge); /*0: posedge, 1: negedge*/ + odm_set_bb_reg(p_dm_odm, 0x9A0, 0xe0, sampling_rate); + /* (0:) '80MHz' + (1:) '40MHz' + (2:) '20MHz' + (3:) '10MHz' + (4:) '5MHz' + (5:) '2.5MHz' + (6:) '1.25MHz' + (7:) '160MHz (for BW160 ic)' + */ + } +} + +void +phydm_la_mode_set_trigger_time( + void *p_dm_void, + u32 trigger_time_mu_sec +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 trigger_time_unit_num; + u32 time_unit = 0; + + if (trigger_time_mu_sec < 128) { + time_unit = 0; /*unit: 1mu sec*/ + } else if (trigger_time_mu_sec < 256) { + time_unit = 1; /*unit: 2mu sec*/ + } else if (trigger_time_mu_sec < 512) { + time_unit = 2; /*unit: 4mu sec*/ + } else if (trigger_time_mu_sec < 1024) { + time_unit = 3; /*unit: 8mu sec*/ + } else if (trigger_time_mu_sec < 2048) { + time_unit = 4; /*unit: 16mu sec*/ + } else if (trigger_time_mu_sec < 4096) { + time_unit = 5; /*unit: 32mu sec*/ + } else if (trigger_time_mu_sec < 8192) { + time_unit = 6; /*unit: 64mu sec*/ + } + + trigger_time_unit_num = (u8)(trigger_time_mu_sec >> time_unit); + + dbg_print("3. [Set Trigger Time] Trig_Time = ((%d)) * unit = ((2^%d us))\n", trigger_time_unit_num, time_unit); + + odm_set_mac_reg(p_dm_odm, 0x7cc, BIT(20) | BIT(19) | BIT(18), time_unit); + odm_set_mac_reg(p_dm_odm, 0x7c0, 0x7f00, (trigger_time_unit_num & 0x7f)); + +} + +void +phydm_lamode_trigger_setting( + void *p_dm_void, + char input[][16], + u32 *_used, + char *output, + u32 *_out_len, + u32 input_num +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _RT_ADCSMP *adc_smp = &(p_dm_odm->adcsmp); + u8 trig_mode, dma_data_sig_sel; + u32 trig_sig_sel; + bool is_enable_la_mode, is_trigger_edge; + u32 dbg_port, trigger_time_mu_sec; + u32 mac_ref_signal_mask; + u8 sampling_rate = 0, i; + char help[] = "-h"; + u32 var1[10] = {0}; + u32 used = *_used; + u32 out_len = *_out_len; + + if (p_dm_odm->support_ic_type & PHYDM_IC_SUPPORT_LA_MODE) { + + PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]); + is_enable_la_mode = (bool)var1[0]; + /*dbg_print("echo cmd input_num = %d\n", input_num);*/ + + if ((strcmp(input[1], help) == 0)) { + PHYDM_SNPRINTF((output + used, out_len - used, "{En} {0:BB,1:BB_MAC,2:RF0,3:RF1,4:MAC} \n {BB:dbg_port[bit],BB_MAC:0-ok/1-fail/2-cca,MAC:ref} {DMA type} {TrigTime} \n {polling_time/ref_mask} {dbg_port} {0:P_Edge, 1:N_Edge} {SpRate:0-80M,1-40M,2-20M} {Capture num}\n")); + /**/ + } else if ((is_enable_la_mode == 1)) { + + PHYDM_SSCANF(input[2], DCMD_DECIMAL, &var1[1]); + + trig_mode = (u8)var1[1]; + + if (trig_mode == PHYDM_MAC_TRIG) + PHYDM_SSCANF(input[3], DCMD_HEX, &var1[2]); + else + PHYDM_SSCANF(input[3], DCMD_DECIMAL, &var1[2]); + trig_sig_sel = var1[2]; + + PHYDM_SSCANF(input[4], DCMD_DECIMAL, &var1[3]); + PHYDM_SSCANF(input[5], DCMD_DECIMAL, &var1[4]); + PHYDM_SSCANF(input[6], DCMD_HEX, &var1[5]); + PHYDM_SSCANF(input[7], DCMD_HEX, &var1[6]); + PHYDM_SSCANF(input[8], DCMD_DECIMAL, &var1[7]); + PHYDM_SSCANF(input[9], DCMD_DECIMAL, &var1[8]); + PHYDM_SSCANF(input[10], DCMD_DECIMAL, &var1[9]); + + dma_data_sig_sel = (u8)var1[3]; + trigger_time_mu_sec = var1[4]; /*unit: us*/ + + adc_smp->la_mac_ref_mask = var1[5]; + adc_smp->la_dbg_port = var1[6]; + adc_smp->la_trigger_edge = (u8) var1[7]; + adc_smp->la_smp_rate = (u8)(var1[8] & 0x7); + adc_smp->la_count = var1[9]; + + + dbg_print("echo lamode %d %d %d %d %d %d %x %d %d %d\n", var1[0], var1[1], var1[2], var1[3], var1[4], var1[5], var1[6], var1[7], var1[8], var1[9]); + PHYDM_SNPRINTF((output + used, out_len - used, "a.En= ((1)), b.mode = ((%d)), c.Trig_Sel = ((0x%x)), d.Dma_type = ((%d))\n", trig_mode, trig_sig_sel, dma_data_sig_sel)); + PHYDM_SNPRINTF((output + used, out_len - used, "e.Trig_Time = ((%dus)), f.mac_ref_mask = ((0x%x)), g.dbg_port = ((0x%x))\n", trigger_time_mu_sec, adc_smp->la_mac_ref_mask, adc_smp->la_dbg_port)); + PHYDM_SNPRINTF((output + used, out_len - used, "h.Trig_edge = ((%d)), i.smp rate = ((%d MHz)), j.Cap_num = ((%d))\n", adc_smp->la_trigger_edge, (80 >> adc_smp->la_smp_rate), adc_smp->la_count)); + + adc_smp_set(p_dm_odm, trig_mode, trig_sig_sel, dma_data_sig_sel, trigger_time_mu_sec, 0); + + } else { + adc_smp_stop(p_dm_odm); + PHYDM_SNPRINTF((output + used, out_len - used, "Disable LA mode\n")); + } + } +} + +#endif /*endif PHYDM_LA_MODE_SUPPORT == 1*/ diff --git a/drivers/staging/rtl8188eu/hal/phydm_adc_sampling.h b/drivers/staging/rtl8188eu/hal/phydm_adc_sampling.h new file mode 100644 index 000000000000..1aec84345dea --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_adc_sampling.h @@ -0,0 +1,123 @@ +#ifndef __INC_ADCSMP_H +#define __INC_ADCSMP_H + +#define DYNAMIC_LA_MODE "1.0" /*2016.07.15 Dino */ + +#if (PHYDM_LA_MODE_SUPPORT == 1) + +struct _RT_ADCSMP_STRING { + u32 *octet; + u32 length; + u32 buffer_size; + u32 start_pos; +}; + + +enum rt_adcsmp_trig_sel { + PHYDM_ADC_BB_TRIG = 0, + PHYDM_ADC_MAC_TRIG = 1, + PHYDM_ADC_RF0_TRIG = 2, + PHYDM_ADC_RF1_TRIG = 3, + PHYDM_MAC_TRIG = 4 +}; + + +enum rt_adcsmp_trig_sig_sel { + ADCSMP_TRIG_CRCOK = 0, + ADCSMP_TRIG_CRCFAIL = 1, + ADCSMP_TRIG_CCA = 2, + ADCSMP_TRIG_REG = 3 +}; + + +enum rt_adcsmp_state { + ADCSMP_STATE_IDLE = 0, + ADCSMP_STATE_SET = 1, + ADCSMP_STATE_QUERY = 2 +}; + + +struct _RT_ADCSMP { + struct _RT_ADCSMP_STRING adc_smp_buf; + enum rt_adcsmp_state adc_smp_state; + u8 la_trig_mode; + u32 la_trig_sig_sel; + u8 la_dma_type; + u32 la_trigger_time; + u32 la_mac_ref_mask; + u32 la_dbg_port; + u8 la_trigger_edge; + u8 la_smp_rate; + u32 la_count; + u8 is_bb_trigger; + u8 la_work_item_index; +}; + +void +adc_smp_set( + void *p_dm_void, + u8 trig_mode, + u32 trig_sig_sel, + u8 dma_data_sig_sel, + u32 trigger_time, + u16 polling_time +); + +void +adc_smp_query( + void *p_dm_void, + void *output, + u32 out_len, + u32 *pused +); + +s32 +adc_smp_get_sample_counts( + void *p_dm_void +); + +s32 +adc_smp_query_single_data( + void *p_dm_void, + void *output, + u32 out_len, + u32 index +); + +void +adc_smp_stop( + void *p_dm_void +); + +void +adc_smp_init( + void *p_dm_void +); + +void +adc_smp_de_init( + void *p_dm_void +); + +void +phydm_la_mode_bb_setting( + void *p_dm_void +); + +void +phydm_la_mode_set_trigger_time( + void *p_dm_void, + u32 trigger_time_mu_sec +); + +void +phydm_lamode_trigger_setting( + void *p_dm_void, + char input[][16], + u32 *_used, + char *output, + u32 *_out_len, + u32 input_num +); +#endif +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_antdect.c b/drivers/staging/rtl8188eu/hal/phydm_antdect.c new file mode 100644 index 000000000000..0ffd7109a24c --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_antdect.c @@ -0,0 +1,847 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* ************************************************************ + * include files + * ************************************************************ */ + +#include "mp_precomp.h" +#include "phydm_precomp.h" + +#if (defined(CONFIG_ANT_DETECTION)) + +/* IS_ANT_DETECT_SUPPORT_SINGLE_TONE(adapter) + * IS_ANT_DETECT_SUPPORT_RSSI(adapter) + * IS_ANT_DETECT_SUPPORT_PSD(adapter) */ + +/* 1 [1. Single Tone method] =================================================== */ + +/* + * Description: + * Set Single/Dual Antenna default setting for products that do not do detection in advance. + * + * Added by Joseph, 2012.03.22 + * */ +void +odm_single_dual_antenna_default_setting( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _sw_antenna_switch_ *p_dm_swat_table = &p_dm_odm->dm_swat_table; + struct _ADAPTER *p_adapter = p_dm_odm->adapter; + + u8 bt_ant_num = BT_GetPgAntNum(p_adapter); + /* Set default antenna A and B status */ + if (bt_ant_num == 2) { + p_dm_swat_table->ANTA_ON = true; + p_dm_swat_table->ANTB_ON = true; + + } else if (bt_ant_num == 1) { + /* Set antenna A as default */ + p_dm_swat_table->ANTA_ON = true; + p_dm_swat_table->ANTB_ON = false; + + } else + RT_ASSERT(false, ("Incorrect antenna number!!\n")); +} + + +/* 2 8723A ANT DETECT + * + * Description: + * Implement IQK single tone for RF DPK loopback and BB PSD scanning. + * This function is cooperated with BB team Neil. + * + * Added by Roger, 2011.12.15 + * */ +bool +odm_single_dual_antenna_detection( + void *p_dm_void, + u8 mode +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTER *p_adapter = p_dm_odm->adapter; + struct _sw_antenna_switch_ *p_dm_swat_table = &p_dm_odm->dm_swat_table; + u32 current_channel, rf_loop_reg; + u8 n; + u32 reg88c, regc08, reg874, regc50, reg948, regb2c, reg92c, reg930, reg064, afe_rrx_wait_cca; + u8 initial_gain = 0x5a; + u32 PSD_report_tmp; + u32 ant_a_report = 0x0, ant_b_report = 0x0, ant_0_report = 0x0; + bool is_result = true; + u32 afe_backup[16]; + u32 AFE_REG_8723A[16] = { + REG_RX_WAIT_CCA, REG_TX_CCK_RFON, + REG_TX_CCK_BBON, REG_TX_OFDM_RFON, + REG_TX_OFDM_BBON, REG_TX_TO_RX, + REG_TX_TO_TX, REG_RX_CCK, + REG_RX_OFDM, REG_RX_WAIT_RIFS, + REG_RX_TO_RX, REG_STANDBY, + REG_SLEEP, REG_PMPD_ANAEN, + REG_FPGA0_XCD_SWITCH_CONTROL, REG_BLUE_TOOTH + }; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_single_dual_antenna_detection()============>\n")); + + + if (!(p_dm_odm->support_ic_type & ODM_RTL8723B)) + return is_result; + + /* Retrieve antenna detection registry info, added by Roger, 2012.11.27. */ + if (!IS_ANT_DETECT_SUPPORT_SINGLE_TONE(p_adapter)) + return is_result; + + /* 1 Backup Current RF/BB Settings */ + + current_channel = odm_get_rf_reg(p_dm_odm, ODM_RF_PATH_A, ODM_CHANNEL, RFREGOFFSETMASK); + rf_loop_reg = odm_get_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x00, RFREGOFFSETMASK); + if (p_dm_odm->support_ic_type & ODM_RTL8723B) { + reg92c = odm_get_bb_reg(p_dm_odm, REG_DPDT_CONTROL, MASKDWORD); + reg930 = odm_get_bb_reg(p_dm_odm, rfe_ctrl_anta_src, MASKDWORD); + reg948 = odm_get_bb_reg(p_dm_odm, REG_S0_S1_PATH_SWITCH, MASKDWORD); + regb2c = odm_get_bb_reg(p_dm_odm, REG_AGC_TABLE_SELECT, MASKDWORD); + reg064 = odm_get_mac_reg(p_dm_odm, REG_SYM_WLBT_PAPE_SEL, BIT(29)); + odm_set_bb_reg(p_dm_odm, REG_DPDT_CONTROL, 0x3, 0x1); + odm_set_bb_reg(p_dm_odm, rfe_ctrl_anta_src, 0xff, 0x77); + odm_set_mac_reg(p_dm_odm, REG_SYM_WLBT_PAPE_SEL, BIT(29), 0x1); /* dbg 7 */ + odm_set_bb_reg(p_dm_odm, REG_S0_S1_PATH_SWITCH, 0x3c0, 0x0);/* dbg 8 */ + odm_set_bb_reg(p_dm_odm, REG_AGC_TABLE_SELECT, BIT(31), 0x0); + } + + odm_stall_execution(10); + + /* Store A path Register 88c, c08, 874, c50 */ + reg88c = odm_get_bb_reg(p_dm_odm, REG_FPGA0_ANALOG_PARAMETER4, MASKDWORD); + regc08 = odm_get_bb_reg(p_dm_odm, REG_OFDM_0_TR_MUX_PAR, MASKDWORD); + reg874 = odm_get_bb_reg(p_dm_odm, REG_FPGA0_XCD_RF_INTERFACE_SW, MASKDWORD); + regc50 = odm_get_bb_reg(p_dm_odm, REG_OFDM_0_XA_AGC_CORE1, MASKDWORD); + + /* Store AFE Registers */ + if (p_dm_odm->support_ic_type & ODM_RTL8723B) + afe_rrx_wait_cca = odm_get_bb_reg(p_dm_odm, REG_RX_WAIT_CCA, MASKDWORD); + + /* Set PSD 128 pts */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_PSD_FUNCTION, BIT(14) | BIT15, 0x0); /* 128 pts */ + + /* To SET CH1 to do */ + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, ODM_CHANNEL, RFREGOFFSETMASK, 0x7401); /* channel 1 */ + + /* AFE all on step */ + if (p_dm_odm->support_ic_type & ODM_RTL8723B) + odm_set_bb_reg(p_dm_odm, REG_RX_WAIT_CCA, MASKDWORD, 0x01c00016); + + /* 3 wire Disable */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_ANALOG_PARAMETER4, MASKDWORD, 0xCCF000C0); + + /* BB IQK setting */ + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_TR_MUX_PAR, MASKDWORD, 0x000800E4); + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XCD_RF_INTERFACE_SW, MASKDWORD, 0x22208000); + + /* IQK setting tone@ 4.34Mhz */ + odm_set_bb_reg(p_dm_odm, REG_TX_IQK_TONE_A, MASKDWORD, 0x10008C1C); + odm_set_bb_reg(p_dm_odm, REG_TX_IQK, MASKDWORD, 0x01007c00); + + /* Page B init */ + odm_set_bb_reg(p_dm_odm, REG_CONFIG_ANT_A, MASKDWORD, 0x00080000); + odm_set_bb_reg(p_dm_odm, REG_CONFIG_ANT_A, MASKDWORD, 0x0f600000); + odm_set_bb_reg(p_dm_odm, REG_RX_IQK, MASKDWORD, 0x01004800); + odm_set_bb_reg(p_dm_odm, REG_RX_IQK_TONE_A, MASKDWORD, 0x10008c1f); + if (p_dm_odm->support_ic_type & ODM_RTL8723B) { + odm_set_bb_reg(p_dm_odm, REG_TX_IQK_PI_A, MASKDWORD, 0x82150016); + odm_set_bb_reg(p_dm_odm, REG_RX_IQK_PI_A, MASKDWORD, 0x28150016); + } + odm_set_bb_reg(p_dm_odm, REG_IQK_AGC_RSP, MASKDWORD, 0x001028d0); + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XA_AGC_CORE1, 0x7f, initial_gain); + + /* IQK Single tone start */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_IQK, 0xffffff00, 0x808000); + odm_set_bb_reg(p_dm_odm, REG_IQK_AGC_PTS, MASKDWORD, 0xf9000000); + odm_set_bb_reg(p_dm_odm, REG_IQK_AGC_PTS, MASKDWORD, 0xf8000000); + + odm_stall_execution(10000); + + /* PSD report of antenna A */ + PSD_report_tmp = 0x0; + for (n = 0; n < 2; n++) { + PSD_report_tmp = get_psd_data(p_dm_odm, 14, initial_gain); + if (PSD_report_tmp > ant_a_report) + ant_a_report = PSD_report_tmp; + } + + /* change to Antenna B */ + if (p_dm_odm->support_ic_type & ODM_RTL8723B) { + /* odm_set_bb_reg(p_dm_odm, REG_DPDT_CONTROL, 0x3, 0x2); */ + odm_set_bb_reg(p_dm_odm, REG_S0_S1_PATH_SWITCH, 0xfff, 0x280); + odm_set_bb_reg(p_dm_odm, REG_AGC_TABLE_SELECT, BIT(31), 0x1); + } + + odm_stall_execution(10); + + /* PSD report of antenna B */ + PSD_report_tmp = 0x0; + for (n = 0; n < 2; n++) { + PSD_report_tmp = get_psd_data(p_dm_odm, 14, initial_gain); + if (PSD_report_tmp > ant_b_report) + ant_b_report = PSD_report_tmp; + } + + /* Close IQK Single Tone function */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_IQK, 0xffffff00, 0x000000); + + /* 1 Return to antanna A */ + if (p_dm_odm->support_ic_type & ODM_RTL8723B) { + /* external DPDT */ + odm_set_bb_reg(p_dm_odm, REG_DPDT_CONTROL, MASKDWORD, reg92c); + + /* internal S0/S1 */ + odm_set_bb_reg(p_dm_odm, REG_S0_S1_PATH_SWITCH, MASKDWORD, reg948); + odm_set_bb_reg(p_dm_odm, REG_AGC_TABLE_SELECT, MASKDWORD, regb2c); + odm_set_bb_reg(p_dm_odm, rfe_ctrl_anta_src, MASKDWORD, reg930); + odm_set_mac_reg(p_dm_odm, REG_SYM_WLBT_PAPE_SEL, BIT(29), reg064); + } + + odm_set_bb_reg(p_dm_odm, REG_FPGA0_ANALOG_PARAMETER4, MASKDWORD, reg88c); + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_TR_MUX_PAR, MASKDWORD, regc08); + odm_set_bb_reg(p_dm_odm, REG_FPGA0_XCD_RF_INTERFACE_SW, MASKDWORD, reg874); + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XA_AGC_CORE1, 0x7F, 0x40); + odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XA_AGC_CORE1, MASKDWORD, regc50); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_CHNLBW, RFREGOFFSETMASK, current_channel); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x00, RFREGOFFSETMASK, rf_loop_reg); + + /* Reload AFE Registers */ + if (p_dm_odm->support_ic_type & ODM_RTL8723B) + odm_set_bb_reg(p_dm_odm, REG_RX_WAIT_CCA, MASKDWORD, afe_rrx_wait_cca); + + if (p_dm_odm->support_ic_type & ODM_RTL8723B) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("psd_report_A[%d]= %d\n", 2416, ant_a_report)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("psd_report_B[%d]= %d\n", 2416, ant_b_report)); + + /* 2 Test ant B based on ant A is ON */ + if ((ant_a_report >= 100) && (ant_b_report >= 100) && (ant_a_report <= 135) && (ant_b_report <= 135)) { + u8 TH1 = 2, TH2 = 6; + + if ((ant_a_report - ant_b_report < TH1) || (ant_b_report - ant_a_report < TH1)) { + p_dm_swat_table->ANTA_ON = true; + p_dm_swat_table->ANTB_ON = true; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_single_dual_antenna_detection(): Dual Antenna\n")); + } else if (((ant_a_report - ant_b_report >= TH1) && (ant_a_report - ant_b_report <= TH2)) || + ((ant_b_report - ant_a_report >= TH1) && (ant_b_report - ant_a_report <= TH2))) { + p_dm_swat_table->ANTA_ON = false; + p_dm_swat_table->ANTB_ON = false; + is_result = false; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_single_dual_antenna_detection(): Need to check again\n")); + } else { + p_dm_swat_table->ANTA_ON = true; + p_dm_swat_table->ANTB_ON = false; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_single_dual_antenna_detection(): Single Antenna\n")); + } + p_dm_odm->ant_detected_info.is_ant_detected = true; + p_dm_odm->ant_detected_info.db_for_ant_a = ant_a_report; + p_dm_odm->ant_detected_info.db_for_ant_b = ant_b_report; + p_dm_odm->ant_detected_info.db_for_ant_o = ant_0_report; + + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("return false!!\n")); + is_result = false; + } + } + return is_result; + +} + + + +/* 1 [2. Scan AP RSSI method] ================================================== */ + + + + +bool +odm_sw_ant_div_check_before_link( + void *p_dm_void +) +{ + +#if (RT_MEM_SIZE_LEVEL != RT_MEM_SIZE_MINIMUM) + + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTER *adapter = p_dm_odm->adapter; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(adapter); + PMGNT_INFO p_mgnt_info = &adapter->MgntInfo; + struct _sw_antenna_switch_ *p_dm_swat_table = &p_dm_odm->dm_swat_table; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + s8 score = 0; + PRT_WLAN_BSS p_tmp_bss_desc, p_test_bss_desc; + u8 power_target_L = 9, power_target_H = 16; + u8 tmp_power_diff = 0, power_diff = 0, avg_power_diff = 0, max_power_diff = 0, min_power_diff = 0xff; + u16 index, counter = 0; + static u8 scan_channel; + u32 tmp_swas_no_link_bk_reg948; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ANTA_ON = (( %d )) , ANTB_ON = (( %d ))\n", p_dm_odm->dm_swat_table.ANTA_ON, p_dm_odm->dm_swat_table.ANTB_ON)); + + /* if(HP id) */ + { + if (p_dm_odm->dm_swat_table.rssi_ant_dect_result == true && p_dm_odm->support_ic_type == ODM_RTL8723B) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("8723B RSSI-based Antenna Detection is done\n")); + return false; + } + + if (p_dm_odm->support_ic_type == ODM_RTL8723B) { + if (p_dm_swat_table->swas_no_link_bk_reg948 == 0xff) + p_dm_swat_table->swas_no_link_bk_reg948 = odm_read_4byte(p_dm_odm, REG_S0_S1_PATH_SWITCH); + } + } + + if (p_dm_odm->adapter == NULL) { /* For BSOD when plug/unplug fast. //By YJ,120413 */ + /* The ODM structure is not initialized. */ + return false; + } + + /* Retrieve antenna detection registry info, added by Roger, 2012.11.27. */ + if (!IS_ANT_DETECT_SUPPORT_RSSI(adapter)) + return false; + else + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Antenna Detection: RSSI method\n")); + + /* Since driver is going to set BB register, it shall check if there is another thread controlling BB/RF. */ + odm_acquire_spin_lock(p_dm_odm, RT_RF_STATE_SPINLOCK); + if (p_hal_data->eRFPowerState != eRfOn || p_mgnt_info->RFChangeInProgress || p_mgnt_info->bMediaConnect) { + odm_release_spin_lock(p_dm_odm, RT_RF_STATE_SPINLOCK); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, + ("odm_sw_ant_div_check_before_link(): rf_change_in_progress(%x), e_rf_power_state(%x)\n", + p_mgnt_info->RFChangeInProgress, p_hal_data->eRFPowerState)); + + p_dm_swat_table->swas_no_link_state = 0; + + return false; + } else + odm_release_spin_lock(p_dm_odm, RT_RF_STATE_SPINLOCK); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("p_dm_swat_table->swas_no_link_state = %d\n", p_dm_swat_table->swas_no_link_state)); + /* 1 Run AntDiv mechanism "Before Link" part. */ + if (p_dm_swat_table->swas_no_link_state == 0) { + /* 1 Prepare to do Scan again to check current antenna state. */ + + /* Set check state to next step. */ + p_dm_swat_table->swas_no_link_state = 1; + + /* Copy Current Scan list. */ + p_mgnt_info->tmpNumBssDesc = p_mgnt_info->NumBssDesc; + PlatformMoveMemory((void *)adapter->MgntInfo.tmpbssDesc, (void *)p_mgnt_info->bssDesc, sizeof(RT_WLAN_BSS) * MAX_BSS_DESC); + + /* Go back to scan function again. */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_sw_ant_div_check_before_link: Scan one more time\n")); + p_mgnt_info->ScanStep = 0; + p_mgnt_info->bScanAntDetect = true; + scan_channel = odm_sw_ant_div_select_scan_chnl(adapter); + + + if (p_dm_odm->support_ic_type & (ODM_RTL8188E | ODM_RTL8821)) { + if (p_dm_fat_table->rx_idle_ant == MAIN_ANT) + odm_update_rx_idle_ant(p_dm_odm, AUX_ANT); + else + odm_update_rx_idle_ant(p_dm_odm, MAIN_ANT); + if (scan_channel == 0) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, + ("odm_sw_ant_div_check_before_link(): No AP List Avaiable, Using ant(%s)\n", (p_dm_fat_table->rx_idle_ant == MAIN_ANT) ? "AUX_ANT" : "MAIN_ANT")); + + if (IS_5G_WIRELESS_MODE(p_mgnt_info->dot11CurrentWirelessMode)) { + p_dm_swat_table->ant_5g = p_dm_fat_table->rx_idle_ant; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("p_dm_swat_table->ant_5g=%s\n", (p_dm_fat_table->rx_idle_ant == MAIN_ANT) ? "MAIN_ANT" : "AUX_ANT")); + } else { + p_dm_swat_table->ant_2g = p_dm_fat_table->rx_idle_ant; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("p_dm_swat_table->ant_2g=%s\n", (p_dm_fat_table->rx_idle_ant == MAIN_ANT) ? "MAIN_ANT" : "AUX_ANT")); + } + return false; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, + ("odm_sw_ant_div_check_before_link: Change to %s for testing.\n", ((p_dm_fat_table->rx_idle_ant == MAIN_ANT) ? "MAIN_ANT" : "AUX_ANT"))); + } else if (p_dm_odm->support_ic_type & (ODM_RTL8723B)) { + /*Switch Antenna to another one.*/ + + tmp_swas_no_link_bk_reg948 = odm_read_4byte(p_dm_odm, REG_S0_S1_PATH_SWITCH); + + if ((p_dm_swat_table->cur_antenna == MAIN_ANT) && (tmp_swas_no_link_bk_reg948 == 0x200)) { + odm_set_bb_reg(p_dm_odm, REG_S0_S1_PATH_SWITCH, 0xfff, 0x280); + odm_set_bb_reg(p_dm_odm, REG_AGC_TABLE_SELECT, BIT(31), 0x1); + p_dm_swat_table->cur_antenna = AUX_ANT; + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Reg[948]= (( %x )) was in wrong state\n", tmp_swas_no_link_bk_reg948)); + return false; + } + odm_stall_execution(10); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_sw_ant_div_check_before_link: Change to (( %s-ant)) for testing.\n", (p_dm_swat_table->cur_antenna == MAIN_ANT) ? "MAIN" : "AUX")); + } + + odm_sw_ant_div_construct_scan_chnl(adapter, scan_channel); + PlatformSetTimer(adapter, &p_mgnt_info->ScanTimer, 5); + + return true; + } else { /* p_dm_swat_table->swas_no_link_state == 1 */ + /* 1 ScanComple() is called after antenna swiched. */ + /* 1 Check scan result and determine which antenna is going */ + /* 1 to be used. */ + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, (" tmp_num_bss_desc= (( %d ))\n", p_mgnt_info->tmpNumBssDesc)); /* debug for Dino */ + + for (index = 0; index < p_mgnt_info->tmpNumBssDesc; index++) { + p_tmp_bss_desc = &(p_mgnt_info->tmpbssDesc[index]); /* Antenna 1 */ + p_test_bss_desc = &(p_mgnt_info->bssDesc[index]); /* Antenna 2 */ + + if (PlatformCompareMemory(p_test_bss_desc->bdBssIdBuf, p_tmp_bss_desc->bdBssIdBuf, 6) != 0) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_sw_ant_div_check_before_link(): ERROR!! This shall not happen.\n")); + continue; + } + + if (p_dm_odm->support_ic_type != ODM_RTL8723B) { + if (p_tmp_bss_desc->ChannelNumber == scan_channel) { + if (p_tmp_bss_desc->RecvSignalPower > p_test_bss_desc->RecvSignalPower) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_sw_ant_div_check_before_link: Compare scan entry: score++\n")); + RT_PRINT_STR(COMP_SCAN, DBG_WARNING, "GetScanInfo(): new Bss SSID:", p_tmp_bss_desc->bdSsIdBuf, p_tmp_bss_desc->bdSsIdLen); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("at ch %d, Original: %d, Test: %d\n\n", p_tmp_bss_desc->ChannelNumber, p_tmp_bss_desc->RecvSignalPower, p_test_bss_desc->RecvSignalPower)); + + score++; + PlatformMoveMemory(p_test_bss_desc, p_tmp_bss_desc, sizeof(RT_WLAN_BSS)); + } else if (p_tmp_bss_desc->RecvSignalPower < p_test_bss_desc->RecvSignalPower) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_sw_ant_div_check_before_link: Compare scan entry: score--\n")); + RT_PRINT_STR(COMP_SCAN, DBG_WARNING, "GetScanInfo(): new Bss SSID:", p_tmp_bss_desc->bdSsIdBuf, p_tmp_bss_desc->bdSsIdLen); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("at ch %d, Original: %d, Test: %d\n\n", p_tmp_bss_desc->ChannelNumber, p_tmp_bss_desc->RecvSignalPower, p_test_bss_desc->RecvSignalPower)); + score--; + } else { + if (p_test_bss_desc->bdTstamp - p_tmp_bss_desc->bdTstamp < 5000) { + RT_PRINT_STR(COMP_SCAN, DBG_WARNING, "GetScanInfo(): new Bss SSID:", p_tmp_bss_desc->bdSsIdBuf, p_tmp_bss_desc->bdSsIdLen); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("at ch %d, Original: %d, Test: %d\n", p_tmp_bss_desc->ChannelNumber, p_tmp_bss_desc->RecvSignalPower, p_test_bss_desc->RecvSignalPower)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("The 2nd Antenna didn't get this AP\n\n")); + } + } + } + } else { /* 8723B */ + if (p_tmp_bss_desc->ChannelNumber == scan_channel) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("channel_number == scan_channel->(( %d ))\n", p_tmp_bss_desc->ChannelNumber)); + + if (p_tmp_bss_desc->RecvSignalPower > p_test_bss_desc->RecvSignalPower) { /* Pow(Ant1) > Pow(Ant2) */ + counter++; + tmp_power_diff = (u8)(p_tmp_bss_desc->RecvSignalPower - p_test_bss_desc->RecvSignalPower); + power_diff = power_diff + tmp_power_diff; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Original: %d, Test: %d\n", p_tmp_bss_desc->RecvSignalPower, p_test_bss_desc->RecvSignalPower)); + ODM_PRINT_ADDR(p_dm_odm, ODM_COMP_ANT_DIV, DBG_LOUD, ("SSID:"), p_tmp_bss_desc->bdSsIdBuf); + ODM_PRINT_ADDR(p_dm_odm, ODM_COMP_ANT_DIV, DBG_LOUD, ("BSSID:"), p_tmp_bss_desc->bdSsIdBuf); + + /* ODM_RT_TRACE(p_dm_odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("tmp_power_diff: (( %d)),max_power_diff: (( %d)),min_power_diff: (( %d))\n", tmp_power_diff,max_power_diff,min_power_diff)); */ + if (tmp_power_diff > max_power_diff) + max_power_diff = tmp_power_diff; + if (tmp_power_diff < min_power_diff) + min_power_diff = tmp_power_diff; + /* ODM_RT_TRACE(p_dm_odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("max_power_diff: (( %d)),min_power_diff: (( %d))\n",max_power_diff,min_power_diff)); */ + + PlatformMoveMemory(p_test_bss_desc, p_tmp_bss_desc, sizeof(RT_WLAN_BSS)); + } else if (p_test_bss_desc->RecvSignalPower > p_tmp_bss_desc->RecvSignalPower) { /* Pow(Ant1) < Pow(Ant2) */ + counter++; + tmp_power_diff = (u8)(p_test_bss_desc->RecvSignalPower - p_tmp_bss_desc->RecvSignalPower); + power_diff = power_diff + tmp_power_diff; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Original: %d, Test: %d\n", p_tmp_bss_desc->RecvSignalPower, p_test_bss_desc->RecvSignalPower)); + ODM_PRINT_ADDR(p_dm_odm, ODM_COMP_ANT_DIV, DBG_LOUD, ("SSID:"), p_tmp_bss_desc->bdSsIdBuf); + ODM_PRINT_ADDR(p_dm_odm, ODM_COMP_ANT_DIV, DBG_LOUD, ("BSSID:"), p_tmp_bss_desc->bdSsIdBuf); + if (tmp_power_diff > max_power_diff) + max_power_diff = tmp_power_diff; + if (tmp_power_diff < min_power_diff) + min_power_diff = tmp_power_diff; + } else { /* Pow(Ant1) = Pow(Ant2) */ + if (p_test_bss_desc->bdTstamp > p_tmp_bss_desc->bdTstamp) { /* Stamp(Ant1) < Stamp(Ant2) */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("time_diff: %lld\n", (p_test_bss_desc->bdTstamp - p_tmp_bss_desc->bdTstamp) / 1000)); + if (p_test_bss_desc->bdTstamp - p_tmp_bss_desc->bdTstamp > 5000) { + counter++; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Original: %d, Test: %d\n", p_tmp_bss_desc->RecvSignalPower, p_test_bss_desc->RecvSignalPower)); + ODM_PRINT_ADDR(p_dm_odm, ODM_COMP_ANT_DIV, DBG_LOUD, ("SSID:"), p_tmp_bss_desc->bdSsIdBuf); + ODM_PRINT_ADDR(p_dm_odm, ODM_COMP_ANT_DIV, DBG_LOUD, ("BSSID:"), p_tmp_bss_desc->bdSsIdBuf); + min_power_diff = 0; + } + } else + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Error !!!]: Time_diff: %lld\n", (p_test_bss_desc->bdTstamp - p_tmp_bss_desc->bdTstamp) / 1000)); + } + } + } + } + + if (p_dm_odm->support_ic_type & (ODM_RTL8188E | ODM_RTL8821)) { + if (p_mgnt_info->NumBssDesc != 0 && score < 0) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, + ("odm_sw_ant_div_check_before_link(): Using ant(%s)\n", (p_dm_fat_table->rx_idle_ant == MAIN_ANT) ? "MAIN_ANT" : "AUX_ANT")); + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, + ("odm_sw_ant_div_check_before_link(): Remain ant(%s)\n", (p_dm_fat_table->rx_idle_ant == MAIN_ANT) ? "AUX_ANT" : "MAIN_ANT")); + + if (p_dm_fat_table->rx_idle_ant == MAIN_ANT) + odm_update_rx_idle_ant(p_dm_odm, AUX_ANT); + else + odm_update_rx_idle_ant(p_dm_odm, MAIN_ANT); + } + + if (IS_5G_WIRELESS_MODE(p_mgnt_info->dot11CurrentWirelessMode)) { + p_dm_swat_table->ant_5g = p_dm_fat_table->rx_idle_ant; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("p_dm_swat_table->ant_5g=%s\n", (p_dm_fat_table->rx_idle_ant == MAIN_ANT) ? "MAIN_ANT" : "AUX_ANT")); + } else { + p_dm_swat_table->ant_2g = p_dm_fat_table->rx_idle_ant; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("p_dm_swat_table->ant_2g=%s\n", (p_dm_fat_table->rx_idle_ant == MAIN_ANT) ? "MAIN_ANT" : "AUX_ANT")); + } + } else if (p_dm_odm->support_ic_type == ODM_RTL8723B) { + if (counter == 0) { + if (p_dm_odm->dm_swat_table.pre_aux_fail_detec == false) { + p_dm_odm->dm_swat_table.pre_aux_fail_detec = true; + p_dm_odm->dm_swat_table.rssi_ant_dect_result = false; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("counter=(( 0 )) , [[ Cannot find any AP with Aux-ant ]] -> Scan Target-channel again\n")); + + /* 3 [ Scan again ] */ + odm_sw_ant_div_construct_scan_chnl(adapter, scan_channel); + PlatformSetTimer(adapter, &p_mgnt_info->ScanTimer, 5); + return true; + } else { /* pre_aux_fail_detec == true */ + /* 2 [ Single Antenna ] */ + p_dm_odm->dm_swat_table.pre_aux_fail_detec = false; + p_dm_odm->dm_swat_table.rssi_ant_dect_result = true; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("counter=(( 0 )) , [[ Still cannot find any AP ]]\n")); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_sw_ant_div_check_before_link(): Single antenna\n")); + } + p_dm_odm->dm_swat_table.aux_fail_detec_counter++; + } else { + p_dm_odm->dm_swat_table.pre_aux_fail_detec = false; + + if (counter == 3) { + avg_power_diff = ((power_diff - max_power_diff - min_power_diff) >> 1) + ((max_power_diff + min_power_diff) >> 2); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("counter: (( %d )) , power_diff: (( %d ))\n", counter, power_diff)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ counter==3 ] Modified avg_power_diff: (( %d )) , max_power_diff: (( %d )) , min_power_diff: (( %d ))\n", avg_power_diff, max_power_diff, min_power_diff)); + } else if (counter >= 4) { + avg_power_diff = (power_diff - max_power_diff - min_power_diff) / (counter - 2); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("counter: (( %d )) , power_diff: (( %d ))\n", counter, power_diff)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ counter>=4 ] Modified avg_power_diff: (( %d )) , max_power_diff: (( %d )) , min_power_diff: (( %d ))\n", avg_power_diff, max_power_diff, min_power_diff)); + + } else { /* counter==1,2 */ + avg_power_diff = power_diff / counter; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("avg_power_diff: (( %d )) , counter: (( %d )) , power_diff: (( %d ))\n", avg_power_diff, counter, power_diff)); + } + + /* 2 [ Retry ] */ + if ((avg_power_diff >= power_target_L) && (avg_power_diff <= power_target_H)) { + p_dm_odm->dm_swat_table.retry_counter++; + + if (p_dm_odm->dm_swat_table.retry_counter <= 3) { + p_dm_odm->dm_swat_table.rssi_ant_dect_result = false; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[[ Low confidence result ]] avg_power_diff= (( %d )) -> Scan Target-channel again ]]\n", avg_power_diff)); + + /* 3 [ Scan again ] */ + odm_sw_ant_div_construct_scan_chnl(adapter, scan_channel); + PlatformSetTimer(adapter, &p_mgnt_info->ScanTimer, 5); + return true; + } else { + p_dm_odm->dm_swat_table.rssi_ant_dect_result = true; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[[ Still Low confidence result ]] (( retry_counter > 3 ))\n")); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_sw_ant_div_check_before_link(): Single antenna\n")); + } + + } + /* 2 [ Dual Antenna ] */ + else if ((p_mgnt_info->NumBssDesc != 0) && (avg_power_diff < power_target_L)) { + p_dm_odm->dm_swat_table.rssi_ant_dect_result = true; + if (p_dm_odm->dm_swat_table.ANTB_ON == false) { + p_dm_odm->dm_swat_table.ANTA_ON = true; + p_dm_odm->dm_swat_table.ANTB_ON = true; + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_sw_ant_div_check_before_link(): Dual antenna\n")); + p_dm_odm->dm_swat_table.dual_ant_counter++; + + /* set bt coexDM from 1ant coexDM to 2ant coexDM */ + BT_SetBtCoexAntNum(adapter, BT_COEX_ANT_TYPE_DETECTED, 2); + + /* 3 [ Init antenna diversity ] */ + p_dm_odm->support_ability |= ODM_BB_ANT_DIV; + odm_ant_div_init(p_dm_odm); + } + /* 2 [ Single Antenna ] */ + else if (avg_power_diff > power_target_H) { + p_dm_odm->dm_swat_table.rssi_ant_dect_result = true; + if (p_dm_odm->dm_swat_table.ANTB_ON == true) { + p_dm_odm->dm_swat_table.ANTA_ON = true; + p_dm_odm->dm_swat_table.ANTB_ON = false; + /* bt_set_bt_coex_ant_num(adapter, BT_COEX_ANT_TYPE_DETECTED, 1); */ + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_sw_ant_div_check_before_link(): Single antenna\n")); + p_dm_odm->dm_swat_table.single_ant_counter++; + } + } + /* ODM_RT_TRACE(p_dm_odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("is_result=(( %d ))\n",p_dm_odm->dm_swat_table.rssi_ant_dect_result)); */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("dual_ant_counter = (( %d )), single_ant_counter = (( %d )) , retry_counter = (( %d )) , aux_fail_detec_counter = (( %d ))\n\n\n", + p_dm_odm->dm_swat_table.dual_ant_counter, p_dm_odm->dm_swat_table.single_ant_counter, p_dm_odm->dm_swat_table.retry_counter, p_dm_odm->dm_swat_table.aux_fail_detec_counter)); + + /* 2 recover the antenna setting */ + + if (p_dm_odm->dm_swat_table.ANTB_ON == false) + odm_set_bb_reg(p_dm_odm, REG_S0_S1_PATH_SWITCH, 0xfff, (p_dm_swat_table->swas_no_link_bk_reg948)); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("is_result=(( %d )), Recover Reg[948]= (( %x )) \n\n", p_dm_odm->dm_swat_table.rssi_ant_dect_result, p_dm_swat_table->swas_no_link_bk_reg948)); + + + } + + /* Check state reset to default and wait for next time. */ + p_dm_swat_table->swas_no_link_state = 0; + p_mgnt_info->bScanAntDetect = false; + + return false; + } + +#else + return false; +#endif + + return false; +} + + + + + + +/* 1 [3. PSD method] ========================================================== */ + + + + +u32 +odm_get_psd_data( + void *p_dm_void, + u16 point, + u8 initial_gain) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 psd_report; + + odm_set_bb_reg(p_dm_odm, 0x808, 0x3FF, point); + odm_set_bb_reg(p_dm_odm, 0x808, BIT(22), 1); /* Start PSD calculation, Reg808[22]=0->1 */ + odm_stall_execution(150);/* Wait for HW PSD report */ + odm_set_bb_reg(p_dm_odm, 0x808, BIT(22), 0);/* Stop PSD calculation, Reg808[22]=1->0 */ + psd_report = odm_get_bb_reg(p_dm_odm, 0x8B4, MASKDWORD) & 0x0000FFFF; /* Read PSD report, Reg8B4[15:0] */ + + psd_report = (u32)(odm_convert_to_db(psd_report)); /* +(u32)(initial_gain); */ + return psd_report; +} + + + +void +odm_single_dual_antenna_detection_psd( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 channel_ori; + u8 initial_gain = 0x36; + u8 tone_idx; + u8 tone_lenth_1 = 7, tone_lenth_2 = 4; + u16 tone_idx_1[7] = {88, 104, 120, 8, 24, 40, 56}; + u16 tone_idx_2[4] = {8, 24, 40, 56}; + u32 psd_report_main[11] = {0}, psd_report_aux[11] = {0}; + /* u8 tone_lenth_1=4, tone_lenth_2=2; */ + /* u16 tone_idx_1[4]={88, 120, 24, 56}; */ + /* u16 tone_idx_2[2]={ 24, 56}; */ + /* u32 psd_report_main[6]={0}, psd_report_aux[6]={0}; */ + + u32 PSD_report_temp, max_psd_report_main = 0, max_psd_report_aux = 0; + u32 PSD_power_threshold; + u32 main_psd_result = 0, aux_psd_result = 0; + u32 regc50, reg948, regb2c, regc14, reg908; + u32 i = 0, test_num = 8; + + + if (p_dm_odm->support_ic_type != ODM_RTL8723B) + return; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_single_dual_antenna_detection_psd()============>\n")); + + /* 2 [ Backup Current RF/BB Settings ] */ + + channel_ori = odm_get_rf_reg(p_dm_odm, ODM_RF_PATH_A, ODM_CHANNEL, RFREGOFFSETMASK); + reg948 = odm_get_bb_reg(p_dm_odm, REG_S0_S1_PATH_SWITCH, MASKDWORD); + regb2c = odm_get_bb_reg(p_dm_odm, REG_AGC_TABLE_SELECT, MASKDWORD); + regc50 = odm_get_bb_reg(p_dm_odm, REG_OFDM_0_XA_AGC_CORE1, MASKDWORD); + regc14 = odm_get_bb_reg(p_dm_odm, 0xc14, MASKDWORD); + reg908 = odm_get_bb_reg(p_dm_odm, 0x908, MASKDWORD); + + /* 2 [ setting for doing PSD function (CH4)] */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_RFMOD, BIT(24), 0); /* disable whole CCK block */ + odm_write_1byte(p_dm_odm, REG_TXPAUSE, 0xFF); /* Turn off TX -> Pause TX Queue */ + odm_set_bb_reg(p_dm_odm, 0xC14, MASKDWORD, 0x0); /* [ Set IQK Matrix = 0 ] equivalent to [ Turn off CCA] */ + + /* PHYTXON while loop */ + odm_set_bb_reg(p_dm_odm, 0x908, MASKDWORD, 0x803); + while (odm_get_bb_reg(p_dm_odm, 0xdf4, BIT(6))) { + i++; + if (i > 1000000) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Wait in %s() more than %d times!\n", __func__, i)); + break; + } + } + + odm_set_bb_reg(p_dm_odm, 0xc50, 0x7f, initial_gain); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, ODM_CHANNEL, 0x7ff, 0x04); /* Set RF to CH4 & 40M */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_ANALOG_PARAMETER4, 0xf00000, 0xf); /* 3 wire Disable 88c[23:20]=0xf */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_PSD_FUNCTION, BIT(14) | BIT15, 0x0); /* 128 pt */ /* Set PSD 128 ptss */ + odm_stall_execution(3000); + + + /* 2 [ Doing PSD Function in (CH4)] */ + + /* Antenna A */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Switch to Main-ant (CH4)\n")); + odm_set_bb_reg(p_dm_odm, 0x948, 0xfff, 0x200); + odm_stall_execution(10); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("dbg\n")); + for (i = 0; i < test_num; i++) { + for (tone_idx = 0; tone_idx < tone_lenth_1; tone_idx++) { + PSD_report_temp = odm_get_psd_data(p_dm_odm, tone_idx_1[tone_idx], initial_gain); + /* if( PSD_report_temp>psd_report_main[tone_idx] ) */ + psd_report_main[tone_idx] += PSD_report_temp; + } + } + /* Antenna B */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Switch to Aux-ant (CH4)\n")); + odm_set_bb_reg(p_dm_odm, 0x948, 0xfff, 0x280); + odm_stall_execution(10); + for (i = 0; i < test_num; i++) { + for (tone_idx = 0; tone_idx < tone_lenth_1; tone_idx++) { + PSD_report_temp = odm_get_psd_data(p_dm_odm, tone_idx_1[tone_idx], initial_gain); + /* if( PSD_report_temp>psd_report_aux[tone_idx] ) */ + psd_report_aux[tone_idx] += PSD_report_temp; + } + } + /* 2 [ Doing PSD Function in (CH8)] */ + + odm_set_bb_reg(p_dm_odm, REG_FPGA0_ANALOG_PARAMETER4, 0xf00000, 0x0); /* 3 wire enable 88c[23:20]=0x0 */ + odm_stall_execution(3000); + + odm_set_bb_reg(p_dm_odm, 0xc50, 0x7f, initial_gain); + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, ODM_CHANNEL, 0x7ff, 0x04); /* Set RF to CH8 & 40M */ + + odm_set_bb_reg(p_dm_odm, REG_FPGA0_ANALOG_PARAMETER4, 0xf00000, 0xf); /* 3 wire Disable 88c[23:20]=0xf */ + odm_stall_execution(3000); + + /* Antenna A */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Switch to Main-ant (CH8)\n")); + odm_set_bb_reg(p_dm_odm, 0x948, 0xfff, 0x200); + odm_stall_execution(10); + + for (i = 0; i < test_num; i++) { + for (tone_idx = 0; tone_idx < tone_lenth_2; tone_idx++) { + PSD_report_temp = odm_get_psd_data(p_dm_odm, tone_idx_2[tone_idx], initial_gain); + /* if( PSD_report_temp>psd_report_main[tone_idx] ) */ + psd_report_main[tone_lenth_1 + tone_idx] += PSD_report_temp; + } + } + + /* Antenna B */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Switch to Aux-ant (CH8)\n")); + odm_set_bb_reg(p_dm_odm, 0x948, 0xfff, 0x280); + odm_stall_execution(10); + + for (i = 0; i < test_num; i++) { + for (tone_idx = 0; tone_idx < tone_lenth_2; tone_idx++) { + PSD_report_temp = odm_get_psd_data(p_dm_odm, tone_idx_2[tone_idx], initial_gain); + /* if( PSD_report_temp>psd_report_aux[tone_idx] ) */ + psd_report_aux[tone_lenth_1 + tone_idx] += PSD_report_temp; + } + } + + /* 2 [ Calculate Result ] */ + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("\nMain PSD Result: (ALL)\n")); + for (tone_idx = 0; tone_idx < (tone_lenth_1 + tone_lenth_2); tone_idx++) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Tone-%d]: %d,\n", (tone_idx + 1), psd_report_main[tone_idx])); + main_psd_result += psd_report_main[tone_idx]; + if (psd_report_main[tone_idx] > max_psd_report_main) + max_psd_report_main = psd_report_main[tone_idx]; + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("--------------------------- \nTotal_Main= (( %d ))\n", main_psd_result)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("MAX_Main = (( %d ))\n", max_psd_report_main)); + + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("\nAux PSD Result: (ALL)\n")); + for (tone_idx = 0; tone_idx < (tone_lenth_1 + tone_lenth_2); tone_idx++) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Tone-%d]: %d,\n", (tone_idx + 1), psd_report_aux[tone_idx])); + aux_psd_result += psd_report_aux[tone_idx]; + if (psd_report_aux[tone_idx] > max_psd_report_aux) + max_psd_report_aux = psd_report_aux[tone_idx]; + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("--------------------------- \nTotal_Aux= (( %d ))\n", aux_psd_result)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("MAX_Aux = (( %d ))\n\n", max_psd_report_aux)); + + /* main_psd_result=main_psd_result-max_psd_report_main; */ + /* aux_psd_result=aux_psd_result-max_psd_report_aux; */ + PSD_power_threshold = (main_psd_result * 7) >> 3; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ Main_result, Aux_result ] = [ %d , %d ], PSD_power_threshold=(( %d ))\n", main_psd_result, aux_psd_result, PSD_power_threshold)); + + /* 3 [ Dual Antenna ] */ + if (aux_psd_result >= PSD_power_threshold) { + if (p_dm_odm->dm_swat_table.ANTB_ON == false) { + p_dm_odm->dm_swat_table.ANTA_ON = true; + p_dm_odm->dm_swat_table.ANTB_ON = true; + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_sw_ant_div_check_before_link(): Dual antenna\n")); + + /* set bt coexDM from 1ant coexDM to 2ant coexDM */ + /* bt_set_bt_coex_ant_num(p_adapter, BT_COEX_ANT_TYPE_DETECTED, 2); */ + + /* Init antenna diversity */ + p_dm_odm->support_ability |= ODM_BB_ANT_DIV; + odm_ant_div_init(p_dm_odm); + } + /* 3 [ Single Antenna ] */ + else { + if (p_dm_odm->dm_swat_table.ANTB_ON == true) { + p_dm_odm->dm_swat_table.ANTA_ON = true; + p_dm_odm->dm_swat_table.ANTB_ON = false; + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_sw_ant_div_check_before_link(): Single antenna\n")); + } + + /* 2 [ Recover all parameters ] */ + + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_CHNLBW, RFREGOFFSETMASK, channel_ori); + odm_set_bb_reg(p_dm_odm, REG_FPGA0_ANALOG_PARAMETER4, 0xf00000, 0x0); /* 3 wire enable 88c[23:20]=0x0 */ + odm_set_bb_reg(p_dm_odm, 0xc50, 0x7f, regc50); + + odm_set_bb_reg(p_dm_odm, REG_S0_S1_PATH_SWITCH, MASKDWORD, reg948); + odm_set_bb_reg(p_dm_odm, REG_AGC_TABLE_SELECT, MASKDWORD, regb2c); + + odm_set_bb_reg(p_dm_odm, REG_FPGA0_RFMOD, BIT(24), 1); /* enable whole CCK block */ + odm_write_1byte(p_dm_odm, REG_TXPAUSE, 0x0); /* Turn on TX */ /* Resume TX Queue */ + odm_set_bb_reg(p_dm_odm, 0xC14, MASKDWORD, regc14); /* [ Set IQK Matrix = 0 ] equivalent to [ Turn on CCA] */ + odm_set_bb_reg(p_dm_odm, 0x908, MASKDWORD, reg908); + + return; + +} + +#endif +void +odm_sw_ant_detect_init( + void *p_dm_void +) +{ +#if (defined(CONFIG_ANT_DETECTION)) + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _sw_antenna_switch_ *p_dm_swat_table = &p_dm_odm->dm_swat_table; + + /* p_dm_swat_table->pre_antenna = MAIN_ANT; */ + /* p_dm_swat_table->cur_antenna = MAIN_ANT; */ + p_dm_swat_table->swas_no_link_state = 0; + p_dm_swat_table->pre_aux_fail_detec = false; + p_dm_swat_table->swas_no_link_bk_reg948 = 0xff; +#endif +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_antdect.h b/drivers/staging/rtl8188eu/hal/phydm_antdect.h new file mode 100644 index 000000000000..fcfab48cf1d6 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_antdect.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDMANTDECT_H__ +#define __PHYDMANTDECT_H__ + +#define ANTDECT_VERSION "2.1" /*2015.07.29 by YuChen*/ + +#if (defined(CONFIG_ANT_DETECTION)) +/* ANT Test */ +#define ANTTESTALL 0x00 /*ant A or B will be Testing*/ +#define ANTTESTA 0x01 /*ant A will be Testing*/ +#define ANTTESTB 0x02 /*ant B will be testing*/ + +#define MAX_ANTENNA_DETECTION_CNT 10 + + +struct _ANT_DETECTED_INFO { + bool is_ant_detected; + u32 db_for_ant_a; + u32 db_for_ant_b; + u32 db_for_ant_o; +}; + + +enum dm_swas_e { + antenna_a = 1, + antenna_b = 2, + antenna_max = 3, +}; + + + +/* 1 [1. Single Tone method] =================================================== */ + + + +void +odm_single_dual_antenna_default_setting( + void *p_dm_void +); + +bool +odm_single_dual_antenna_detection( + void *p_dm_void, + u8 mode +); + +/* 1 [2. Scan AP RSSI method] ================================================== */ + +#define sw_ant_div_check_before_link odm_sw_ant_div_check_before_link + +bool +odm_sw_ant_div_check_before_link( + void *p_dm_void +); + + + + +/* 1 [3. PSD method] ========================================================== */ + + +void +odm_single_dual_antenna_detection_psd( + void *p_dm_void +); + +#endif + +void +odm_sw_ant_detect_init( + void *p_dm_void +); + + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_antdiv.c b/drivers/staging/rtl8188eu/hal/phydm_antdiv.c new file mode 100644 index 000000000000..92d213b84482 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_antdiv.c @@ -0,0 +1,3194 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* ************************************************************ + * include files + * ************************************************************ */ + +#include "mp_precomp.h" +#include "phydm_precomp.h" + +/* ****************************************************** + * when antenna test utility is on or some testing need to disable antenna diversity + * call this function to disable all ODM related mechanisms which will switch antenna. + * ****************************************************** */ +void +odm_stop_antenna_switch_dm( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + /* disable ODM antenna diversity */ + p_dm_odm->support_ability &= ~ODM_BB_ANT_DIV; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("STOP Antenna Diversity\n")); +} + +void +phydm_enable_antenna_diversity( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + p_dm_odm->support_ability |= ODM_BB_ANT_DIV; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("AntDiv is enabled & Re-Init AntDiv\n")); + odm_antenna_diversity_init(p_dm_odm); +} + +void +odm_set_ant_config( + void *p_dm_void, + u8 ant_setting /* 0=A, 1=B, 2=C, .... */ +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + if (p_dm_odm->support_ic_type == ODM_RTL8723B) { + if (ant_setting == 0) /* ant A*/ + odm_set_bb_reg(p_dm_odm, 0x948, MASKDWORD, 0x00000000); + else if (ant_setting == 1) + odm_set_bb_reg(p_dm_odm, 0x948, MASKDWORD, 0x00000280); + } else if (p_dm_odm->support_ic_type == ODM_RTL8723D) { + if (ant_setting == 0) /* ant A*/ + odm_set_bb_reg(p_dm_odm, 0x948, MASKLWORD, 0x0000); + else if (ant_setting == 1) + odm_set_bb_reg(p_dm_odm, 0x948, MASKLWORD, 0x0280); + } +} + +/* ****************************************************** */ + + +void +odm_sw_ant_div_rest_after_link( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _sw_antenna_switch_ *p_dm_swat_table = &p_dm_odm->dm_swat_table; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + u32 i; + + if (p_dm_odm->ant_div_type == S0S1_SW_ANTDIV) { + + p_dm_swat_table->try_flag = SWAW_STEP_INIT; + p_dm_swat_table->rssi_trying = 0; + p_dm_swat_table->double_chk_flag = 0; + + p_dm_fat_table->rx_idle_ant = MAIN_ANT; + +#if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY)) + for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) + phydm_antdiv_reset_statistic(p_dm_odm, i); +#endif + + + } +} + + +#if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY)) +void +phydm_antdiv_reset_statistic( + void *p_dm_void, + u32 macid +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + + p_dm_fat_table->main_ant_sum[macid] = 0; + p_dm_fat_table->aux_ant_sum[macid] = 0; + p_dm_fat_table->main_ant_cnt[macid] = 0; + p_dm_fat_table->aux_ant_cnt[macid] = 0; + p_dm_fat_table->main_ant_sum_cck[macid] = 0; + p_dm_fat_table->aux_ant_sum_cck[macid] = 0; + p_dm_fat_table->main_ant_cnt_cck[macid] = 0; + p_dm_fat_table->aux_ant_cnt_cck[macid] = 0; +} + +void +odm_ant_div_on_off( + void *p_dm_void, + u8 swch +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + + if (p_dm_fat_table->ant_div_on_off != swch) { + if (p_dm_odm->ant_div_type == S0S1_SW_ANTDIV) + return; + + if (p_dm_odm->support_ic_type & ODM_N_ANTDIV_SUPPORT) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("(( Turn %s )) N-Series HW-AntDiv block\n", (swch == ANTDIV_ON) ? "ON" : "OFF")); + odm_set_bb_reg(p_dm_odm, 0xc50, BIT(7), swch); + odm_set_bb_reg(p_dm_odm, 0xa00, BIT(15), swch); + + } else if (p_dm_odm->support_ic_type & ODM_AC_ANTDIV_SUPPORT) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("(( Turn %s )) AC-Series HW-AntDiv block\n", (swch == ANTDIV_ON) ? "ON" : "OFF")); + if (p_dm_odm->support_ic_type & (ODM_RTL8812 | ODM_RTL8822B)) { + odm_set_bb_reg(p_dm_odm, 0xc50, BIT(7), swch); /* OFDM AntDiv function block enable */ + odm_set_bb_reg(p_dm_odm, 0xa00, BIT(15), swch); /* CCK AntDiv function block enable */ + } else { + odm_set_bb_reg(p_dm_odm, 0x8D4, BIT(24), swch); /* OFDM AntDiv function block enable */ + + if ((p_dm_odm->cut_version >= ODM_CUT_C) && (p_dm_odm->support_ic_type == ODM_RTL8821) && (p_dm_odm->ant_div_type != S0S1_SW_ANTDIV)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("(( Turn %s )) CCK HW-AntDiv block\n", (swch == ANTDIV_ON) ? "ON" : "OFF")); + odm_set_bb_reg(p_dm_odm, 0x800, BIT(25), swch); + odm_set_bb_reg(p_dm_odm, 0xA00, BIT(15), swch); /* CCK AntDiv function block enable */ + } else if (p_dm_odm->support_ic_type == ODM_RTL8821C) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("(( Turn %s )) CCK HW-AntDiv block\n", (swch == ANTDIV_ON) ? "ON" : "OFF")); + odm_set_bb_reg(p_dm_odm, 0x800, BIT(25), swch); + odm_set_bb_reg(p_dm_odm, 0xA00, BIT(15), swch); /* CCK AntDiv function block enable */ + } + } + } + } + p_dm_fat_table->ant_div_on_off = swch; + +} + +void +phydm_fast_training_enable( + void *p_dm_void, + u8 swch +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 enable; + + if (swch == FAT_ON) + enable = 1; + else + enable = 0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Fast ant Training_en = ((%d))\n", enable)); + + if (p_dm_odm->support_ic_type == ODM_RTL8188E) { + odm_set_bb_reg(p_dm_odm, 0xe08, BIT(16), enable); /*enable fast training*/ + /**/ + } else if (p_dm_odm->support_ic_type == ODM_RTL8192E) { + odm_set_bb_reg(p_dm_odm, 0xB34, BIT(28), enable); /*enable fast training (path-A)*/ + /*odm_set_bb_reg(p_dm_odm, 0xB34, BIT(29), enable);*/ /*enable fast training (path-B)*/ + } else if (p_dm_odm->support_ic_type & (ODM_RTL8821 | ODM_RTL8822B)) { + odm_set_bb_reg(p_dm_odm, 0x900, BIT(19), enable); /*enable fast training */ + /**/ + } +} + +void +phydm_keep_rx_ack_ant_by_tx_ant_time( + void *p_dm_void, + u32 time +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + /* Timming issue: keep Rx ant after tx for ACK ( time x 3.2 mu sec)*/ + if (p_dm_odm->support_ic_type & ODM_N_ANTDIV_SUPPORT) { + + odm_set_bb_reg(p_dm_odm, 0xE20, BIT(23) | BIT(22) | BIT(21) | BIT(20), time); + /**/ + } else if (p_dm_odm->support_ic_type & ODM_AC_ANTDIV_SUPPORT) { + + odm_set_bb_reg(p_dm_odm, 0x818, BIT(23) | BIT(22) | BIT(21) | BIT(20), time); + /**/ + } +} + +void +odm_tx_by_tx_desc_or_reg( + void *p_dm_void, + u8 swch +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + u8 enable; + + if (p_dm_fat_table->b_fix_tx_ant == NO_FIX_TX_ANT) + enable = (swch == TX_BY_DESC) ? 1 : 0; + else + enable = 0;/*Force TX by Reg*/ + + if (p_dm_odm->ant_div_type != CGCS_RX_HW_ANTDIV) { + if (p_dm_odm->support_ic_type & ODM_N_ANTDIV_SUPPORT) + odm_set_bb_reg(p_dm_odm, 0x80c, BIT(21), enable); + else if (p_dm_odm->support_ic_type & ODM_AC_ANTDIV_SUPPORT) + odm_set_bb_reg(p_dm_odm, 0x900, BIT(18), enable); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[AntDiv] TX_Ant_BY (( %s ))\n", (enable == TX_BY_DESC) ? "DESC" : "REG")); + } +} + +void +odm_update_rx_idle_ant( + void *p_dm_void, + u8 ant +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + u32 default_ant, optional_ant, value32, default_tx_ant; + + if (p_dm_fat_table->rx_idle_ant != ant) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ Update Rx-Idle-ant ] rx_idle_ant =%s\n", (ant == MAIN_ANT) ? "MAIN_ANT" : "AUX_ANT")); + + if (!(p_dm_odm->support_ic_type & ODM_RTL8723B)) + p_dm_fat_table->rx_idle_ant = ant; + + if (ant == MAIN_ANT) { + default_ant = ANT1_2G; + optional_ant = ANT2_2G; + } else { + default_ant = ANT2_2G; + optional_ant = ANT1_2G; + } + + if (p_dm_fat_table->b_fix_tx_ant != NO_FIX_TX_ANT) + default_tx_ant = (p_dm_fat_table->b_fix_tx_ant == FIX_TX_AT_MAIN) ? 0 : 1; + else + default_tx_ant = default_ant; + + if (p_dm_odm->support_ic_type & ODM_N_ANTDIV_SUPPORT) { + if (p_dm_odm->support_ic_type == ODM_RTL8192E) { + odm_set_bb_reg(p_dm_odm, 0xB38, BIT(5) | BIT4 | BIT3, default_ant); /* Default RX */ + odm_set_bb_reg(p_dm_odm, 0xB38, BIT(8) | BIT7 | BIT6, optional_ant); /* Optional RX */ + odm_set_bb_reg(p_dm_odm, 0x860, BIT(14) | BIT13 | BIT12, default_ant); /* Default TX */ + } +#if (RTL8723B_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8723B) { + + value32 = odm_get_bb_reg(p_dm_odm, 0x948, 0xFFF); + + if (value32 != 0x280) + odm_update_rx_idle_ant_8723b(p_dm_odm, ant, default_ant, optional_ant); + else + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ Update Rx-Idle-ant ] 8723B: Fail to set RX antenna due to 0x948 = 0x280\n")); + } +#endif + else { /*8188E & 8188F*/ + + if (p_dm_odm->support_ic_type == ODM_RTL8723D) { +#if (RTL8723D_SUPPORT == 1) + phydm_set_tx_ant_pwr_8723d(p_dm_odm, ant); +#endif + } +#if (RTL8188F_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8188F) { + phydm_update_rx_idle_antenna_8188F(p_dm_odm, default_ant); + /**/ + } +#endif + + odm_set_bb_reg(p_dm_odm, 0x864, BIT(5) | BIT4 | BIT3, default_ant); /*Default RX*/ + odm_set_bb_reg(p_dm_odm, 0x864, BIT(8) | BIT7 | BIT6, optional_ant); /*Optional RX*/ + odm_set_bb_reg(p_dm_odm, 0x860, BIT(14) | BIT13 | BIT12, default_tx_ant); /*Default TX*/ + } + } else if (p_dm_odm->support_ic_type & ODM_AC_ANTDIV_SUPPORT) { + u16 value16 = odm_read_2byte(p_dm_odm, ODM_REG_TRMUX_11AC + 2); + /* */ + /* 2014/01/14 MH/Luke.Lee Add direct write for register 0xc0a to prevnt */ + /* incorrect 0xc08 bit0-15 .We still not know why it is changed. */ + /* */ + value16 &= ~(BIT(11) | BIT(10) | BIT(9) | BIT(8) | BIT(7) | BIT(6) | BIT(5) | BIT(4) | BIT(3)); + value16 |= ((u16)default_ant << 3); + value16 |= ((u16)optional_ant << 6); + value16 |= ((u16)default_ant << 9); + odm_write_2byte(p_dm_odm, ODM_REG_TRMUX_11AC + 2, value16); + } + + if (p_dm_odm->support_ic_type == ODM_RTL8188E) { + odm_set_mac_reg(p_dm_odm, 0x6D8, BIT(7) | BIT6, default_tx_ant); /*PathA Resp Tx*/ + /**/ + } else { + odm_set_mac_reg(p_dm_odm, 0x6D8, BIT(10) | BIT9 | BIT8, default_tx_ant); /*PathA Resp Tx*/ + /**/ + } + + } else { /* p_dm_fat_table->rx_idle_ant == ant */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ Stay in Ori-ant ] rx_idle_ant =%s\n", (ant == MAIN_ANT) ? "MAIN_ANT" : "AUX_ANT")); + p_dm_fat_table->rx_idle_ant = ant; + } +} + +void +odm_update_tx_ant( + void *p_dm_void, + u8 ant, + u32 mac_id +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + u8 tx_ant; + + if (p_dm_fat_table->b_fix_tx_ant != NO_FIX_TX_ANT) + ant = (p_dm_fat_table->b_fix_tx_ant == FIX_TX_AT_MAIN) ? MAIN_ANT : AUX_ANT; + + if (p_dm_odm->ant_div_type == CG_TRX_SMART_ANTDIV) + tx_ant = ant; + else { + if (ant == MAIN_ANT) + tx_ant = ANT1_2G; + else + tx_ant = ANT2_2G; + } + + p_dm_fat_table->antsel_a[mac_id] = tx_ant & BIT(0); + p_dm_fat_table->antsel_b[mac_id] = (tx_ant & BIT(1)) >> 1; + p_dm_fat_table->antsel_c[mac_id] = (tx_ant & BIT(2)) >> 2; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Set TX-DESC value]: mac_id:(( %d )), tx_ant = (( %s ))\n", mac_id, (ant == MAIN_ANT) ? "MAIN_ANT" : "AUX_ANT")); + /* ODM_RT_TRACE(p_dm_odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD,("antsel_tr_mux=(( 3'b%d%d%d ))\n",p_dm_fat_table->antsel_c[mac_id] , p_dm_fat_table->antsel_b[mac_id] , p_dm_fat_table->antsel_a[mac_id] )); */ + +} + +#ifdef BEAMFORMING_SUPPORT + +void +odm_rx_hw_ant_div_init_88e( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 value32; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("***8188E AntDiv_Init => ant_div_type=[CGCS_RX_HW_ANTDIV]\n")); + + /* MAC setting */ + value32 = odm_get_mac_reg(p_dm_odm, ODM_REG_ANTSEL_PIN_11N, MASKDWORD); + odm_set_mac_reg(p_dm_odm, ODM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 | (BIT(23) | BIT25)); /* Reg4C[25]=1, Reg4C[23]=1 for pin output */ + /* Pin Settings */ + odm_set_bb_reg(p_dm_odm, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT8, 0);/* reg870[8]=1'b0, reg870[9]=1'b0 */ /* antsel antselb by HW */ + odm_set_bb_reg(p_dm_odm, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0); /* reg864[10]=1'b0 */ /* antsel2 by HW */ + odm_set_bb_reg(p_dm_odm, ODM_REG_LNA_SWITCH_11N, BIT(22), 1); /* regb2c[22]=1'b0 */ /* disable CS/CG switch */ + odm_set_bb_reg(p_dm_odm, ODM_REG_LNA_SWITCH_11N, BIT(31), 1); /* regb2c[31]=1'b1 */ /* output at CG only */ + /* OFDM Settings */ + odm_set_bb_reg(p_dm_odm, ODM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0); + /* CCK Settings */ + odm_set_bb_reg(p_dm_odm, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1); /* Fix CCK PHY status report issue */ + odm_set_bb_reg(p_dm_odm, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1); /* CCK complete HW AntDiv within 64 samples */ + + odm_set_bb_reg(p_dm_odm, ODM_REG_ANT_MAPPING1_11N, 0xFFFF, 0x0001); /* antenna mapping table */ + + p_dm_fat_table->enable_ctrl_frame_antdiv = 1; +} + +void +odm_trx_hw_ant_div_init_88e( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 value32; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("***8188E AntDiv_Init => ant_div_type=[CG_TRX_HW_ANTDIV (SPDT)]\n")); + + /* MAC setting */ + value32 = odm_get_mac_reg(p_dm_odm, ODM_REG_ANTSEL_PIN_11N, MASKDWORD); + odm_set_mac_reg(p_dm_odm, ODM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 | (BIT(23) | BIT25)); /* Reg4C[25]=1, Reg4C[23]=1 for pin output */ + /* Pin Settings */ + odm_set_bb_reg(p_dm_odm, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT8, 0);/* reg870[8]=1'b0, reg870[9]=1'b0 */ /* antsel antselb by HW */ + odm_set_bb_reg(p_dm_odm, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0); /* reg864[10]=1'b0 */ /* antsel2 by HW */ + odm_set_bb_reg(p_dm_odm, ODM_REG_LNA_SWITCH_11N, BIT(22), 0); /* regb2c[22]=1'b0 */ /* disable CS/CG switch */ + odm_set_bb_reg(p_dm_odm, ODM_REG_LNA_SWITCH_11N, BIT(31), 1); /* regb2c[31]=1'b1 */ /* output at CG only */ + /* OFDM Settings */ + odm_set_bb_reg(p_dm_odm, ODM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0); + /* CCK Settings */ + odm_set_bb_reg(p_dm_odm, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1); /* Fix CCK PHY status report issue */ + odm_set_bb_reg(p_dm_odm, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1); /* CCK complete HW AntDiv within 64 samples */ + + /* antenna mapping table */ + if (!p_dm_odm->is_mp_chip) { /* testchip */ + odm_set_bb_reg(p_dm_odm, ODM_REG_RX_DEFUALT_A_11N, BIT(10) | BIT9 | BIT8, 1); /* Reg858[10:8]=3'b001 */ + odm_set_bb_reg(p_dm_odm, ODM_REG_RX_DEFUALT_A_11N, BIT(13) | BIT12 | BIT11, 2); /* Reg858[13:11]=3'b010 */ + } else /* MPchip */ + odm_set_bb_reg(p_dm_odm, ODM_REG_ANT_MAPPING1_11N, MASKDWORD, 0x0201); /*Reg914=3'b010, Reg915=3'b001*/ + + p_dm_fat_table->enable_ctrl_frame_antdiv = 1; +} + + +#if (defined(CONFIG_5G_CG_SMART_ANT_DIVERSITY)) || (defined(CONFIG_2G_CG_SMART_ANT_DIVERSITY)) +void odm_smart_hw_ant_div_init_88e(void *p_dm_void) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 value32, i; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("***8188E AntDiv_Init => ant_div_type=[CG_TRX_SMART_ANTDIV]\n")); + + p_dm_fat_table->train_idx = 0; + p_dm_fat_table->fat_state = FAT_PREPARE_STATE; + + p_dm_odm->fat_comb_a = 5; + p_dm_odm->antdiv_intvl = 0x64; /* 100ms */ + + for (i = 0; i < 6; i++) + p_dm_fat_table->bssid[i] = 0; + for (i = 0; i < (p_dm_odm->fat_comb_a) ; i++) { + p_dm_fat_table->ant_sum_rssi[i] = 0; + p_dm_fat_table->ant_rssi_cnt[i] = 0; + p_dm_fat_table->ant_ave_rssi[i] = 0; + } + + /* MAC setting */ + value32 = odm_get_mac_reg(p_dm_odm, 0x4c, MASKDWORD); + odm_set_mac_reg(p_dm_odm, 0x4c, MASKDWORD, value32 | (BIT(23) | BIT25)); /* Reg4C[25]=1, Reg4C[23]=1 for pin output */ + value32 = odm_get_mac_reg(p_dm_odm, 0x7B4, MASKDWORD); + odm_set_mac_reg(p_dm_odm, 0x7b4, MASKDWORD, value32 | (BIT(16) | BIT17)); /* Reg7B4[16]=1 enable antenna training, Reg7B4[17]=1 enable A2 match */ + /* value32 = platform_efio_read_4byte(adapter, 0x7B4); */ + /* platform_efio_write_4byte(adapter, 0x7b4, value32|BIT(18)); */ /* append MACID in reponse packet */ + + /* Match MAC ADDR */ + odm_set_mac_reg(p_dm_odm, 0x7b4, 0xFFFF, 0); + odm_set_mac_reg(p_dm_odm, 0x7b0, MASKDWORD, 0); + + odm_set_bb_reg(p_dm_odm, 0x870, BIT(9) | BIT8, 0);/* reg870[8]=1'b0, reg870[9]=1'b0 */ /* antsel antselb by HW */ + odm_set_bb_reg(p_dm_odm, 0x864, BIT(10), 0); /* reg864[10]=1'b0 */ /* antsel2 by HW */ + odm_set_bb_reg(p_dm_odm, 0xb2c, BIT(22), 0); /* regb2c[22]=1'b0 */ /* disable CS/CG switch */ + odm_set_bb_reg(p_dm_odm, 0xb2c, BIT(31), 0); /* regb2c[31]=1'b1 */ /* output at CS only */ + odm_set_bb_reg(p_dm_odm, 0xca4, MASKDWORD, 0x000000a0); + + /* antenna mapping table */ + if (p_dm_odm->fat_comb_a == 2) { + if (!p_dm_odm->is_mp_chip) { /* testchip */ + odm_set_bb_reg(p_dm_odm, 0x858, BIT(10) | BIT9 | BIT8, 1); /* Reg858[10:8]=3'b001 */ + odm_set_bb_reg(p_dm_odm, 0x858, BIT(13) | BIT12 | BIT11, 2); /* Reg858[13:11]=3'b010 */ + } else { /* MPchip */ + odm_set_bb_reg(p_dm_odm, 0x914, MASKBYTE0, 1); + odm_set_bb_reg(p_dm_odm, 0x914, MASKBYTE1, 2); + } + } else { + if (!p_dm_odm->is_mp_chip) { /* testchip */ + odm_set_bb_reg(p_dm_odm, 0x858, BIT(10) | BIT9 | BIT8, 0); /* Reg858[10:8]=3'b000 */ + odm_set_bb_reg(p_dm_odm, 0x858, BIT(13) | BIT12 | BIT11, 1); /* Reg858[13:11]=3'b001 */ + odm_set_bb_reg(p_dm_odm, 0x878, BIT(16), 0); + odm_set_bb_reg(p_dm_odm, 0x858, BIT(15) | BIT14, 2); /* (Reg878[0],Reg858[14:15])=3'b010 */ + odm_set_bb_reg(p_dm_odm, 0x878, BIT(19) | BIT18 | BIT17, 3); /* Reg878[3:1]=3b'011 */ + odm_set_bb_reg(p_dm_odm, 0x878, BIT(22) | BIT21 | BIT20, 4); /* Reg878[6:4]=3b'100 */ + odm_set_bb_reg(p_dm_odm, 0x878, BIT(25) | BIT24 | BIT23, 5); /* Reg878[9:7]=3b'101 */ + odm_set_bb_reg(p_dm_odm, 0x878, BIT(28) | BIT27 | BIT26, 6); /* Reg878[12:10]=3b'110 */ + odm_set_bb_reg(p_dm_odm, 0x878, BIT(31) | BIT30 | BIT29, 7); /* Reg878[15:13]=3b'111 */ + } else { /* MPchip */ + odm_set_bb_reg(p_dm_odm, 0x914, MASKBYTE0, 4); /* 0: 3b'000 */ + odm_set_bb_reg(p_dm_odm, 0x914, MASKBYTE1, 2); /* 1: 3b'001 */ + odm_set_bb_reg(p_dm_odm, 0x914, MASKBYTE2, 0); /* 2: 3b'010 */ + odm_set_bb_reg(p_dm_odm, 0x914, MASKBYTE3, 1); /* 3: 3b'011 */ + odm_set_bb_reg(p_dm_odm, 0x918, MASKBYTE0, 3); /* 4: 3b'100 */ + odm_set_bb_reg(p_dm_odm, 0x918, MASKBYTE1, 5); /* 5: 3b'101 */ + odm_set_bb_reg(p_dm_odm, 0x918, MASKBYTE2, 6); /* 6: 3b'110 */ + odm_set_bb_reg(p_dm_odm, 0x918, MASKBYTE3, 255); /* 7: 3b'111 */ + } + } + + /* Default ant setting when no fast training */ + odm_set_bb_reg(p_dm_odm, 0x864, BIT(5) | BIT4 | BIT3, 0); /* Default RX */ + odm_set_bb_reg(p_dm_odm, 0x864, BIT(8) | BIT7 | BIT6, 1); /* Optional RX */ + odm_set_bb_reg(p_dm_odm, 0x860, BIT(14) | BIT13 | BIT12, 0); /* Default TX */ + + /* Enter Traing state */ + odm_set_bb_reg(p_dm_odm, 0x864, BIT(2) | BIT1 | BIT0, (p_dm_odm->fat_comb_a - 1)); /* reg864[2:0]=3'd6 */ /* ant combination=reg864[2:0]+1 */ + + /* SW Control */ + /* phy_set_bb_reg(adapter, 0x864, BIT10, 1); */ + /* phy_set_bb_reg(adapter, 0x870, BIT9, 1); */ + /* phy_set_bb_reg(adapter, 0x870, BIT8, 1); */ + /* phy_set_bb_reg(adapter, 0x864, BIT11, 1); */ + /* phy_set_bb_reg(adapter, 0x860, BIT9, 0); */ + /* phy_set_bb_reg(adapter, 0x860, BIT8, 0); */ +} +#endif + +#ifdef ODM_EVM_ENHANCE_ANTDIV + +void +odm_evm_fast_ant_reset( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + + p_dm_fat_table->EVM_method_enable = 0; + odm_ant_div_on_off(p_dm_odm, ANTDIV_ON); + p_dm_fat_table->fat_state = NORMAL_STATE_MIAN; + p_dm_odm->antdiv_period = 0; + odm_set_mac_reg(p_dm_odm, 0x608, BIT(8), 0); +} + + +void +odm_evm_enhance_ant_div( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 main_rssi, aux_rssi ; + u32 main_crc_utility = 0, aux_crc_utility = 0, utility_ratio = 1; + u32 main_evm, aux_evm, diff_rssi = 0, diff_EVM = 0; + u8 score_EVM = 0, score_CRC = 0; + u8 rssi_larger_ant = 0; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + u32 value32, i; + bool main_above1 = false, aux_above1 = false; + bool force_antenna = false; + struct sta_info *p_entry; + p_dm_fat_table->target_ant_enhance = 0xFF; + + + if ((p_dm_odm->support_ic_type & ODM_EVM_ENHANCE_ANTDIV_SUPPORT_IC)) { + if (p_dm_odm->is_one_entry_only) { + /* ODM_RT_TRACE(p_dm_odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[One Client only]\n")); */ + i = p_dm_odm->one_entry_macid; + + main_rssi = (p_dm_fat_table->main_ant_cnt[i] != 0) ? (p_dm_fat_table->main_ant_sum[i] / p_dm_fat_table->main_ant_cnt[i]) : 0; + aux_rssi = (p_dm_fat_table->aux_ant_cnt[i] != 0) ? (p_dm_fat_table->aux_ant_sum[i] / p_dm_fat_table->aux_ant_cnt[i]) : 0; + + if ((main_rssi == 0 && aux_rssi != 0 && aux_rssi >= FORCE_RSSI_DIFF) || (main_rssi != 0 && aux_rssi == 0 && main_rssi >= FORCE_RSSI_DIFF)) + diff_rssi = FORCE_RSSI_DIFF; + else if (main_rssi != 0 && aux_rssi != 0) + diff_rssi = (main_rssi >= aux_rssi) ? (main_rssi - aux_rssi) : (aux_rssi - main_rssi); + + if (main_rssi >= aux_rssi) + rssi_larger_ant = MAIN_ANT; + else + rssi_larger_ant = AUX_ANT; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, (" Main_Cnt = (( %d )) , main_rssi= (( %d ))\n", p_dm_fat_table->main_ant_cnt[i], main_rssi)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, (" Aux_Cnt = (( %d )) , aux_rssi = (( %d ))\n", p_dm_fat_table->aux_ant_cnt[i], aux_rssi)); + + if (((main_rssi >= evm_rssi_th_high || aux_rssi >= evm_rssi_th_high) || (p_dm_fat_table->EVM_method_enable == 1)) + /* && (diff_rssi <= FORCE_RSSI_DIFF + 1) */ + ) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[> TH_H || EVM_method_enable==1] && ")); + + if (((main_rssi >= evm_rssi_th_low) || (aux_rssi >= evm_rssi_th_low))) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[> TH_L ]\n")); + + /* 2 [ Normal state Main] */ + if (p_dm_fat_table->fat_state == NORMAL_STATE_MIAN) { + + p_dm_fat_table->EVM_method_enable = 1; + odm_ant_div_on_off(p_dm_odm, ANTDIV_OFF); + p_dm_odm->antdiv_period = p_dm_odm->evm_antdiv_period; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ start training: MIAN]\n")); + p_dm_fat_table->main_ant_evm_sum[i] = 0; + p_dm_fat_table->aux_ant_evm_sum[i] = 0; + p_dm_fat_table->main_ant_evm_cnt[i] = 0; + p_dm_fat_table->aux_ant_evm_cnt[i] = 0; + + p_dm_fat_table->fat_state = NORMAL_STATE_AUX; + odm_set_mac_reg(p_dm_odm, 0x608, BIT(8), 1); /* Accept CRC32 Error packets. */ + odm_update_rx_idle_ant(p_dm_odm, MAIN_ANT); + + p_dm_fat_table->crc32_ok_cnt = 0; + p_dm_fat_table->crc32_fail_cnt = 0; + odm_set_timer(p_dm_odm, &p_dm_odm->evm_fast_ant_training_timer, p_dm_odm->antdiv_intvl); /* m */ + } + /* 2 [ Normal state Aux ] */ + else if (p_dm_fat_table->fat_state == NORMAL_STATE_AUX) { + p_dm_fat_table->main_crc32_ok_cnt = p_dm_fat_table->crc32_ok_cnt; + p_dm_fat_table->main_crc32_fail_cnt = p_dm_fat_table->crc32_fail_cnt; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ start training: AUX]\n")); + p_dm_fat_table->fat_state = TRAINING_STATE; + odm_update_rx_idle_ant(p_dm_odm, AUX_ANT); + + p_dm_fat_table->crc32_ok_cnt = 0; + p_dm_fat_table->crc32_fail_cnt = 0; + odm_set_timer(p_dm_odm, &p_dm_odm->evm_fast_ant_training_timer, p_dm_odm->antdiv_intvl); /* ms */ + } else if (p_dm_fat_table->fat_state == TRAINING_STATE) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Training state ]\n")); + p_dm_fat_table->fat_state = NORMAL_STATE_MIAN; + + /* 3 [CRC32 statistic] */ + p_dm_fat_table->aux_crc32_ok_cnt = p_dm_fat_table->crc32_ok_cnt; + p_dm_fat_table->aux_crc32_fail_cnt = p_dm_fat_table->crc32_fail_cnt; + + if ((p_dm_fat_table->main_crc32_ok_cnt > ((p_dm_fat_table->aux_crc32_ok_cnt) << 1)) || ((diff_rssi >= 20) && (rssi_larger_ant == MAIN_ANT))) { + p_dm_fat_table->target_ant_crc32 = MAIN_ANT; + force_antenna = true; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("CRC32 Force Main\n")); + } else if ((p_dm_fat_table->aux_crc32_ok_cnt > ((p_dm_fat_table->main_crc32_ok_cnt) << 1)) || ((diff_rssi >= 20) && (rssi_larger_ant == AUX_ANT))) { + p_dm_fat_table->target_ant_crc32 = AUX_ANT; + force_antenna = true; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("CRC32 Force Aux\n")); + } else { + if (p_dm_fat_table->main_crc32_fail_cnt <= 5) + p_dm_fat_table->main_crc32_fail_cnt = 5; + + if (p_dm_fat_table->aux_crc32_fail_cnt <= 5) + p_dm_fat_table->aux_crc32_fail_cnt = 5; + + if (p_dm_fat_table->main_crc32_ok_cnt > p_dm_fat_table->main_crc32_fail_cnt) + main_above1 = true; + + if (p_dm_fat_table->aux_crc32_ok_cnt > p_dm_fat_table->aux_crc32_fail_cnt) + aux_above1 = true; + + if (main_above1 == true && aux_above1 == false) { + force_antenna = true; + p_dm_fat_table->target_ant_crc32 = MAIN_ANT; + } else if (main_above1 == false && aux_above1 == true) { + force_antenna = true; + p_dm_fat_table->target_ant_crc32 = AUX_ANT; + } else if (main_above1 == true && aux_above1 == true) { + main_crc_utility = ((p_dm_fat_table->main_crc32_ok_cnt) << 7) / p_dm_fat_table->main_crc32_fail_cnt; + aux_crc_utility = ((p_dm_fat_table->aux_crc32_ok_cnt) << 7) / p_dm_fat_table->aux_crc32_fail_cnt; + p_dm_fat_table->target_ant_crc32 = (main_crc_utility == aux_crc_utility) ? (p_dm_fat_table->pre_target_ant_enhance) : ((main_crc_utility >= aux_crc_utility) ? MAIN_ANT : AUX_ANT); + + if (main_crc_utility != 0 && aux_crc_utility != 0) { + if (main_crc_utility >= aux_crc_utility) + utility_ratio = (main_crc_utility << 1) / aux_crc_utility; + else + utility_ratio = (aux_crc_utility << 1) / main_crc_utility; + } + } else if (main_above1 == false && aux_above1 == false) { + if (p_dm_fat_table->main_crc32_ok_cnt == 0) + p_dm_fat_table->main_crc32_ok_cnt = 1; + if (p_dm_fat_table->aux_crc32_ok_cnt == 0) + p_dm_fat_table->aux_crc32_ok_cnt = 1; + + main_crc_utility = ((p_dm_fat_table->main_crc32_fail_cnt) << 7) / p_dm_fat_table->main_crc32_ok_cnt; + aux_crc_utility = ((p_dm_fat_table->aux_crc32_fail_cnt) << 7) / p_dm_fat_table->aux_crc32_ok_cnt; + p_dm_fat_table->target_ant_crc32 = (main_crc_utility == aux_crc_utility) ? (p_dm_fat_table->pre_target_ant_enhance) : ((main_crc_utility <= aux_crc_utility) ? MAIN_ANT : AUX_ANT); + + if (main_crc_utility != 0 && aux_crc_utility != 0) { + if (main_crc_utility >= aux_crc_utility) + utility_ratio = (main_crc_utility << 1) / (aux_crc_utility); + else + utility_ratio = (aux_crc_utility << 1) / (main_crc_utility); + } + } + } + odm_set_mac_reg(p_dm_odm, 0x608, BIT(8), 0);/* NOT Accept CRC32 Error packets. */ + + /* 3 [EVM statistic] */ + main_evm = (p_dm_fat_table->main_ant_evm_cnt[i] != 0) ? (p_dm_fat_table->main_ant_evm_sum[i] / p_dm_fat_table->main_ant_evm_cnt[i]) : 0; + aux_evm = (p_dm_fat_table->aux_ant_evm_cnt[i] != 0) ? (p_dm_fat_table->aux_ant_evm_sum[i] / p_dm_fat_table->aux_ant_evm_cnt[i]) : 0; + p_dm_fat_table->target_ant_evm = (main_evm == aux_evm) ? (p_dm_fat_table->pre_target_ant_enhance) : ((main_evm >= aux_evm) ? MAIN_ANT : AUX_ANT); + + if ((main_evm == 0 || aux_evm == 0)) + diff_EVM = 0; + else if (main_evm >= aux_evm) + diff_EVM = main_evm - aux_evm; + else + diff_EVM = aux_evm - main_evm; + + /* 2 [ Decision state ] */ + if (p_dm_fat_table->target_ant_evm == p_dm_fat_table->target_ant_crc32) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Decision type 1, CRC_utility = ((%d)), EVM_diff = ((%d))\n", utility_ratio, diff_EVM)); + + if ((utility_ratio < 2 && force_antenna == false) && diff_EVM <= 30) + p_dm_fat_table->target_ant_enhance = p_dm_fat_table->pre_target_ant_enhance; + else + p_dm_fat_table->target_ant_enhance = p_dm_fat_table->target_ant_evm; + } else if ((diff_EVM <= 50 && (utility_ratio > 4 && force_antenna == false)) || (force_antenna == true)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Decision type 2, CRC_utility = ((%d)), EVM_diff = ((%d))\n", utility_ratio, diff_EVM)); + p_dm_fat_table->target_ant_enhance = p_dm_fat_table->target_ant_crc32; + } else if (diff_EVM >= 100) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Decision type 3, CRC_utility = ((%d)), EVM_diff = ((%d))\n", utility_ratio, diff_EVM)); + p_dm_fat_table->target_ant_enhance = p_dm_fat_table->target_ant_evm; + } else if (utility_ratio >= 6 && force_antenna == false) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Decision type 4, CRC_utility = ((%d)), EVM_diff = ((%d))\n", utility_ratio, diff_EVM)); + p_dm_fat_table->target_ant_enhance = p_dm_fat_table->target_ant_crc32; + } else { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Decision type 5, CRC_utility = ((%d)), EVM_diff = ((%d))\n", utility_ratio, diff_EVM)); + + if (force_antenna == true) + score_CRC = 3; + else if (utility_ratio >= 3) /*>0.5*/ + score_CRC = 2; + else if (utility_ratio >= 2) /*>1*/ + score_CRC = 1; + else + score_CRC = 0; + + if (diff_EVM >= 100) + score_EVM = 2; + else if (diff_EVM >= 50) + score_EVM = 1; + else + score_EVM = 0; + + if (score_CRC > score_EVM) + p_dm_fat_table->target_ant_enhance = p_dm_fat_table->target_ant_crc32; + else if (score_CRC < score_EVM) + p_dm_fat_table->target_ant_enhance = p_dm_fat_table->target_ant_evm; + else + p_dm_fat_table->target_ant_enhance = p_dm_fat_table->pre_target_ant_enhance; + } + p_dm_fat_table->pre_target_ant_enhance = p_dm_fat_table->target_ant_enhance; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("*** Client[ %d ] : MainEVM_Cnt = (( %d )) , main_evm= (( %d ))\n", i, p_dm_fat_table->main_ant_evm_cnt[i], main_evm)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("*** Client[ %d ] : AuxEVM_Cnt = (( %d )) , aux_evm = (( %d ))\n", i, p_dm_fat_table->aux_ant_evm_cnt[i], aux_evm)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("*** target_ant_evm = (( %s ))\n", (p_dm_fat_table->target_ant_evm == MAIN_ANT) ? "MAIN_ANT" : "AUX_ANT")); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("M_CRC_Ok = (( %d )) , M_CRC_Fail = (( %d )), main_crc_utility = (( %d ))\n", p_dm_fat_table->main_crc32_ok_cnt, p_dm_fat_table->main_crc32_fail_cnt, main_crc_utility)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("A_CRC_Ok = (( %d )) , A_CRC_Fail = (( %d )), aux_crc_utility = (( %d ))\n", p_dm_fat_table->aux_crc32_ok_cnt, p_dm_fat_table->aux_crc32_fail_cnt, aux_crc_utility)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("*** target_ant_crc32 = (( %s ))\n", (p_dm_fat_table->target_ant_crc32 == MAIN_ANT) ? "MAIN_ANT" : "AUX_ANT")); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("****** target_ant_enhance = (( %s ))******\n", (p_dm_fat_table->target_ant_enhance == MAIN_ANT) ? "MAIN_ANT" : "AUX_ANT")); + + + } + } else { /* RSSI< = evm_rssi_th_low */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ TH_L ]\n")); + odm_evm_fast_ant_reset(p_dm_odm); + } + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[escape from> TH_H || EVM_method_enable==1]\n")); + odm_evm_fast_ant_reset(p_dm_odm); + } + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[multi-Client]\n")); + odm_evm_fast_ant_reset(p_dm_odm); + } + } +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) +void odm_evm_fast_ant_training_callback(void *p_dm_void) +#else +void odm_evm_fast_ant_training_callback(struct timer_list *t) +#endif +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; +#else + struct PHY_DM_STRUCT *p_dm_odm = from_timer(p_dm_odm, t, evm_fast_ant_training_timer); +#endif + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("******odm_evm_fast_ant_training_callback******\n")); + odm_hw_ant_div(p_dm_odm); +} +#endif + +void +odm_hw_ant_div( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 i, min_max_rssi = 0xFF, ant_div_max_rssi = 0, max_rssi = 0, local_max_rssi; + u32 main_rssi, aux_rssi, mian_cnt, aux_cnt; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + u8 rx_idle_ant = p_dm_fat_table->rx_idle_ant, target_ant = 7; + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + struct sta_info *p_entry; + + if (!p_dm_odm->is_linked) { /* is_linked==False */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[No Link!!!]\n")); + + if (p_dm_fat_table->is_become_linked == true) { + odm_ant_div_on_off(p_dm_odm, ANTDIV_OFF); + odm_update_rx_idle_ant(p_dm_odm, MAIN_ANT); + odm_tx_by_tx_desc_or_reg(p_dm_odm, TX_BY_REG); + p_dm_odm->antdiv_period = 0; + + p_dm_fat_table->is_become_linked = p_dm_odm->is_linked; + } + return; + } else { + if (p_dm_fat_table->is_become_linked == false) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Linked !!!]\n")); + odm_ant_div_on_off(p_dm_odm, ANTDIV_ON); + p_dm_fat_table->is_become_linked = p_dm_odm->is_linked; + + if (p_dm_odm->support_ic_type == ODM_RTL8723B && p_dm_odm->ant_div_type == CG_TRX_HW_ANTDIV) { + odm_set_bb_reg(p_dm_odm, 0x930, 0xF0, 8); /* DPDT_P = ANTSEL[0] */ /* for 8723B AntDiv function patch. BB Dino 130412 */ + odm_set_bb_reg(p_dm_odm, 0x930, 0xF, 8); /* DPDT_N = ANTSEL[0] */ + } + + /* 2 BDC Init */ + +#ifdef ODM_EVM_ENHANCE_ANTDIV + odm_evm_fast_ant_reset(p_dm_odm); +#endif + } + } + + if (*(p_dm_fat_table->p_force_tx_ant_by_desc) == false) { + if (p_dm_odm->is_one_entry_only == true) + odm_tx_by_tx_desc_or_reg(p_dm_odm, TX_BY_REG); + else + odm_tx_by_tx_desc_or_reg(p_dm_odm, TX_BY_DESC); + } + +#ifdef ODM_EVM_ENHANCE_ANTDIV + if (p_dm_odm->antdiv_evm_en == 1) { + odm_evm_enhance_ant_div(p_dm_odm); + if (p_dm_fat_table->fat_state != NORMAL_STATE_MIAN) + return; + } else + odm_evm_fast_ant_reset(p_dm_odm); +#endif + + /* 2 BDC mode Arbitration */ + + for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { + p_entry = p_dm_odm->p_odm_sta_info[i]; + if (IS_STA_VALID(p_entry)) { + /* 2 Caculate RSSI per Antenna */ + if ((p_dm_fat_table->main_ant_cnt[i] != 0) || (p_dm_fat_table->aux_ant_cnt[i] != 0)) { + mian_cnt = p_dm_fat_table->main_ant_cnt[i]; + aux_cnt = p_dm_fat_table->aux_ant_cnt[i]; + main_rssi = (mian_cnt != 0) ? (p_dm_fat_table->main_ant_sum[i] / mian_cnt) : 0; + aux_rssi = (aux_cnt != 0) ? (p_dm_fat_table->aux_ant_sum[i] / aux_cnt) : 0; + target_ant = (mian_cnt == aux_cnt) ? p_dm_fat_table->rx_idle_ant : ((mian_cnt >= aux_cnt) ? MAIN_ANT : AUX_ANT); /*Use counter number for OFDM*/ + + } else { /*CCK only case*/ + mian_cnt = p_dm_fat_table->main_ant_cnt_cck[i]; + aux_cnt = p_dm_fat_table->aux_ant_cnt_cck[i]; + main_rssi = (mian_cnt != 0) ? (p_dm_fat_table->main_ant_sum_cck[i] / mian_cnt) : 0; + aux_rssi = (aux_cnt != 0) ? (p_dm_fat_table->aux_ant_sum_cck[i] / aux_cnt) : 0; + target_ant = (main_rssi == aux_rssi) ? p_dm_fat_table->rx_idle_ant : ((main_rssi >= aux_rssi) ? MAIN_ANT : AUX_ANT); /*Use RSSI for CCK only case*/ + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("*** Client[ %d ] : Main_Cnt = (( %d )) , CCK_Main_Cnt = (( %d )) , main_rssi= (( %d ))\n", i, p_dm_fat_table->main_ant_cnt[i], p_dm_fat_table->main_ant_cnt_cck[i], main_rssi)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("*** Client[ %d ] : Aux_Cnt = (( %d )) , CCK_Aux_Cnt = (( %d )) , aux_rssi = (( %d ))\n", i, p_dm_fat_table->aux_ant_cnt[i], p_dm_fat_table->aux_ant_cnt_cck[i], aux_rssi)); + /* ODM_RT_TRACE(p_dm_odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("*** MAC ID:[ %d ] , target_ant = (( %s ))\n", i ,( target_ant ==MAIN_ANT)?"MAIN_ANT":"AUX_ANT")); */ + + local_max_rssi = (main_rssi > aux_rssi) ? main_rssi : aux_rssi; + /* 2 Select max_rssi for DIG */ + if ((local_max_rssi > ant_div_max_rssi) && (local_max_rssi < 40)) + ant_div_max_rssi = local_max_rssi; + if (local_max_rssi > max_rssi) + max_rssi = local_max_rssi; + + /* 2 Select RX Idle Antenna */ + if ((local_max_rssi != 0) && (local_max_rssi < min_max_rssi)) { + rx_idle_ant = target_ant; + min_max_rssi = local_max_rssi; + } + +#ifdef ODM_EVM_ENHANCE_ANTDIV + if (p_dm_odm->antdiv_evm_en == 1) { + if (p_dm_fat_table->target_ant_enhance != 0xFF) { + target_ant = p_dm_fat_table->target_ant_enhance; + rx_idle_ant = p_dm_fat_table->target_ant_enhance; + } + } +#endif + + /* 2 Select TX Antenna */ + if (p_dm_odm->ant_div_type != CGCS_RX_HW_ANTDIV) { + odm_update_tx_ant(p_dm_odm, target_ant, i); + } + + /* ------------------------------------------------------------ */ + + } + phydm_antdiv_reset_statistic(p_dm_odm, i); + } + + + + /* 2 Set RX Idle Antenna & TX Antenna(Because of HW Bug ) */ + + odm_update_rx_idle_ant(p_dm_odm, rx_idle_ant); + + /* 2 BDC Main Algorithm */ + if (ant_div_max_rssi == 0) + p_dm_dig_table->ant_div_rssi_max = p_dm_odm->rssi_min; + else + p_dm_dig_table->ant_div_rssi_max = ant_div_max_rssi; + + p_dm_dig_table->RSSI_max = max_rssi; +} + + + +#ifdef CONFIG_S0S1_SW_ANTENNA_DIVERSITY + +void +odm_s0s1_sw_ant_div_reset( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _sw_antenna_switch_ *p_dm_swat_table = &p_dm_odm->dm_swat_table; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + + p_dm_fat_table->is_become_linked = false; + p_dm_swat_table->try_flag = SWAW_STEP_INIT; + p_dm_swat_table->double_chk_flag = 0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_s0s1_sw_ant_div_reset(): p_dm_fat_table->is_become_linked = %d\n", p_dm_fat_table->is_become_linked)); +} + +void +odm_s0s1_sw_ant_div( + void *p_dm_void, + u8 step +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _sw_antenna_switch_ *p_dm_swat_table = &p_dm_odm->dm_swat_table; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + u32 i, min_max_rssi = 0xFF, local_max_rssi, local_min_rssi; + u32 main_rssi, aux_rssi; + u8 high_traffic_train_time_u = 0x32, high_traffic_train_time_l = 0, train_time_temp; + u8 low_traffic_train_time_u = 200, low_traffic_train_time_l = 0; + u8 rx_idle_ant = p_dm_swat_table->pre_antenna, target_ant, next_ant = 0; + struct sta_info *p_entry = NULL; + u32 value32; + u32 main_ant_sum; + u32 aux_ant_sum; + u32 main_ant_cnt; + u32 aux_ant_cnt; + + + if (!p_dm_odm->is_linked) { /* is_linked==False */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[No Link!!!]\n")); + if (p_dm_fat_table->is_become_linked == true) { + odm_tx_by_tx_desc_or_reg(p_dm_odm, TX_BY_REG); + if (p_dm_odm->support_ic_type == ODM_RTL8723B) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Set REG 948[9:6]=0x0\n")); + odm_set_bb_reg(p_dm_odm, 0x948, (BIT(9) | BIT(8) | BIT(7) | BIT(6)), 0x0); + } + p_dm_fat_table->is_become_linked = p_dm_odm->is_linked; + } + return; + } else { + if (p_dm_fat_table->is_become_linked == false) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Linked !!!]\n")); + + if (p_dm_odm->support_ic_type == ODM_RTL8723B) { + value32 = odm_get_bb_reg(p_dm_odm, 0x864, BIT(5) | BIT(4) | BIT(3)); + +#if (RTL8723B_SUPPORT == 1) + if (value32 == 0x0) + odm_update_rx_idle_ant_8723b(p_dm_odm, MAIN_ANT, ANT1_2G, ANT2_2G); + else if (value32 == 0x1) + odm_update_rx_idle_ant_8723b(p_dm_odm, AUX_ANT, ANT2_2G, ANT1_2G); +#endif + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("8723B: First link! Force antenna to %s\n", (value32 == 0x0 ? "MAIN" : "AUX"))); + } + p_dm_fat_table->is_become_linked = p_dm_odm->is_linked; + } + } + + if (*(p_dm_fat_table->p_force_tx_ant_by_desc) == false) { + if (p_dm_odm->is_one_entry_only == true) + odm_tx_by_tx_desc_or_reg(p_dm_odm, TX_BY_REG); + else + odm_tx_by_tx_desc_or_reg(p_dm_odm, TX_BY_DESC); + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[%d] { try_flag=(( %d )), step=(( %d )), double_chk_flag = (( %d )) }\n", + __LINE__, p_dm_swat_table->try_flag, step, p_dm_swat_table->double_chk_flag)); + + /* Handling step mismatch condition. */ + /* Peak step is not finished at last time. Recover the variable and check again. */ + if (step != p_dm_swat_table->try_flag) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[step != try_flag] Need to Reset After Link\n")); + odm_sw_ant_div_rest_after_link(p_dm_odm); + } + + if (p_dm_swat_table->try_flag == SWAW_STEP_INIT) { + + p_dm_swat_table->try_flag = SWAW_STEP_PEEK; + p_dm_swat_table->train_time_flag = 0; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[set try_flag = 0] Prepare for peek!\n\n")); + return; + + } else { + + /* 1 Normal state (Begin Trying) */ + if (p_dm_swat_table->try_flag == SWAW_STEP_PEEK) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("TxOkCnt=(( %llu )), RxOkCnt=(( %llu )), traffic_load = (%d))\n", p_dm_odm->cur_tx_ok_cnt, p_dm_odm->cur_rx_ok_cnt, p_dm_odm->traffic_load)); + + if (p_dm_odm->traffic_load == TRAFFIC_HIGH) { + train_time_temp = p_dm_swat_table->train_time ; + + if (p_dm_swat_table->train_time_flag == 3) { + high_traffic_train_time_l = 0xa; + + if (train_time_temp <= 16) + train_time_temp = high_traffic_train_time_l; + else + train_time_temp -= 16; + + } else if (p_dm_swat_table->train_time_flag == 2) { + train_time_temp -= 8; + high_traffic_train_time_l = 0xf; + } else if (p_dm_swat_table->train_time_flag == 1) { + train_time_temp -= 4; + high_traffic_train_time_l = 0x1e; + } else if (p_dm_swat_table->train_time_flag == 0) { + train_time_temp += 8; + high_traffic_train_time_l = 0x28; + } + + + /* ODM_RT_TRACE(p_dm_odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("*** train_time_temp = ((%d))\n",train_time_temp)); */ + + /* -- */ + if (train_time_temp > high_traffic_train_time_u) + train_time_temp = high_traffic_train_time_u; + + else if (train_time_temp < high_traffic_train_time_l) + train_time_temp = high_traffic_train_time_l; + + p_dm_swat_table->train_time = train_time_temp; /*10ms~200ms*/ + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("train_time_flag=((%d)), train_time=((%d))\n", p_dm_swat_table->train_time_flag, p_dm_swat_table->train_time)); + + } else if ((p_dm_odm->traffic_load == TRAFFIC_MID) || (p_dm_odm->traffic_load == TRAFFIC_LOW)) { + + train_time_temp = p_dm_swat_table->train_time ; + + if (p_dm_swat_table->train_time_flag == 3) { + low_traffic_train_time_l = 10; + if (train_time_temp < 50) + train_time_temp = low_traffic_train_time_l; + else + train_time_temp -= 50; + } else if (p_dm_swat_table->train_time_flag == 2) { + train_time_temp -= 30; + low_traffic_train_time_l = 36; + } else if (p_dm_swat_table->train_time_flag == 1) { + train_time_temp -= 10; + low_traffic_train_time_l = 40; + } else { + + train_time_temp += 10; + low_traffic_train_time_l = 50; + } + + /* -- */ + if (train_time_temp >= low_traffic_train_time_u) + train_time_temp = low_traffic_train_time_u; + + else if (train_time_temp <= low_traffic_train_time_l) + train_time_temp = low_traffic_train_time_l; + + p_dm_swat_table->train_time = train_time_temp; /*10ms~200ms*/ + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("train_time_flag=((%d)) , train_time=((%d))\n", p_dm_swat_table->train_time_flag, p_dm_swat_table->train_time)); + + } else { + p_dm_swat_table->train_time = 0xc8; /*200ms*/ + + } + + /* ----------------- */ + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Current min_max_rssi is ((%d))\n", p_dm_fat_table->min_max_rssi)); + + /* ---reset index--- */ + if (p_dm_swat_table->reset_idx >= RSSI_CHECK_RESET_PERIOD) { + + p_dm_fat_table->min_max_rssi = 0; + p_dm_swat_table->reset_idx = 0; + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("reset_idx = (( %d ))\n", p_dm_swat_table->reset_idx)); + + p_dm_swat_table->reset_idx++; + + /* ---double check flag--- */ + if ((p_dm_fat_table->min_max_rssi > RSSI_CHECK_THRESHOLD) && (p_dm_swat_table->double_chk_flag == 0)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, (" min_max_rssi is ((%d)), and > %d\n", + p_dm_fat_table->min_max_rssi, RSSI_CHECK_THRESHOLD)); + + p_dm_swat_table->double_chk_flag = 1; + p_dm_swat_table->try_flag = SWAW_STEP_DETERMINE; + p_dm_swat_table->rssi_trying = 0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Test the current ant for (( %d )) ms again\n", p_dm_swat_table->train_time)); + odm_update_rx_idle_ant(p_dm_odm, p_dm_fat_table->rx_idle_ant); + odm_set_timer(p_dm_odm, &(p_dm_swat_table->phydm_sw_antenna_switch_timer), p_dm_swat_table->train_time); /*ms*/ + return; + } + + next_ant = (p_dm_fat_table->rx_idle_ant == MAIN_ANT) ? AUX_ANT : MAIN_ANT; + + p_dm_swat_table->try_flag = SWAW_STEP_DETERMINE; + + if (p_dm_swat_table->reset_idx <= 1) + p_dm_swat_table->rssi_trying = 2; + else + p_dm_swat_table->rssi_trying = 1; + + odm_s0s1_sw_ant_div_by_ctrl_frame(p_dm_odm, SWAW_STEP_PEEK); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[set try_flag=1] Normal state: Begin Trying!!\n")); + + } else if ((p_dm_swat_table->try_flag == SWAW_STEP_DETERMINE) && (p_dm_swat_table->double_chk_flag == 0)) { + + next_ant = (p_dm_fat_table->rx_idle_ant == MAIN_ANT) ? AUX_ANT : MAIN_ANT; + p_dm_swat_table->rssi_trying--; + } + + /* 1 Decision state */ + if ((p_dm_swat_table->try_flag == SWAW_STEP_DETERMINE) && (p_dm_swat_table->rssi_trying == 0)) { + + bool is_by_ctrl_frame = false; + u64 pkt_cnt_total = 0; + + for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { + p_entry = p_dm_odm->p_odm_sta_info[i]; + if (IS_STA_VALID(p_entry)) { + /* 2 Caculate RSSI per Antenna */ + + main_ant_sum = (u32)p_dm_fat_table->main_ant_sum[i] + (u32)p_dm_fat_table->main_ant_sum_cck[i]; + aux_ant_sum = (u32)p_dm_fat_table->aux_ant_sum[i] + (u32)p_dm_fat_table->aux_ant_sum_cck[i]; + main_ant_cnt = (u32)p_dm_fat_table->main_ant_cnt[i] + (u32)p_dm_fat_table->main_ant_cnt_cck[i]; + aux_ant_cnt = (u32)p_dm_fat_table->aux_ant_cnt[i] + (u32)p_dm_fat_table->aux_ant_cnt_cck[i]; + + main_rssi = (main_ant_cnt != 0) ? (main_ant_sum / main_ant_cnt) : 0; + aux_rssi = (aux_ant_cnt != 0) ? (aux_ant_sum / aux_ant_cnt) : 0; + + if (p_dm_fat_table->main_ant_cnt[i] <= 1 && p_dm_fat_table->main_ant_cnt_cck[i] >= 1) + main_rssi = 0; + + if (p_dm_fat_table->aux_ant_cnt[i] <= 1 && p_dm_fat_table->aux_ant_cnt_cck[i] >= 1) + aux_rssi = 0; + + target_ant = (main_rssi == aux_rssi) ? p_dm_swat_table->pre_antenna : ((main_rssi >= aux_rssi) ? MAIN_ANT : AUX_ANT); + local_max_rssi = (main_rssi >= aux_rssi) ? main_rssi : aux_rssi; + local_min_rssi = (main_rssi >= aux_rssi) ? aux_rssi : main_rssi; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("*** CCK_counter_main = (( %d )) , CCK_counter_aux= (( %d ))\n", p_dm_fat_table->main_ant_cnt_cck[i], p_dm_fat_table->aux_ant_cnt_cck[i])); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("*** OFDM_counter_main = (( %d )) , OFDM_counter_aux= (( %d ))\n", p_dm_fat_table->main_ant_cnt[i], p_dm_fat_table->aux_ant_cnt[i])); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("*** Main_Cnt = (( %d )) , main_rssi= (( %d ))\n", main_ant_cnt, main_rssi)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("*** Aux_Cnt = (( %d )) , aux_rssi = (( %d ))\n", aux_ant_cnt, aux_rssi)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("*** MAC ID:[ %d ] , target_ant = (( %s ))\n", i, (target_ant == MAIN_ANT) ? "MAIN_ANT" : "AUX_ANT")); + + /* 2 Select RX Idle Antenna */ + + if (local_max_rssi != 0 && local_max_rssi < min_max_rssi) { + rx_idle_ant = target_ant; + min_max_rssi = local_max_rssi; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("*** local_max_rssi-local_min_rssi = ((%d))\n", (local_max_rssi - local_min_rssi))); + + if ((local_max_rssi - local_min_rssi) > 8) { + if (local_min_rssi != 0) + p_dm_swat_table->train_time_flag = 3; + else { + if (min_max_rssi > RSSI_CHECK_THRESHOLD) + p_dm_swat_table->train_time_flag = 0; + else + p_dm_swat_table->train_time_flag = 3; + } + } else if ((local_max_rssi - local_min_rssi) > 5) + p_dm_swat_table->train_time_flag = 2; + else if ((local_max_rssi - local_min_rssi) > 2) + p_dm_swat_table->train_time_flag = 1; + else + p_dm_swat_table->train_time_flag = 0; + + } + + /* 2 Select TX Antenna */ + if (target_ant == MAIN_ANT) + p_dm_fat_table->antsel_a[i] = ANT1_2G; + else + p_dm_fat_table->antsel_a[i] = ANT2_2G; + + } + phydm_antdiv_reset_statistic(p_dm_odm, i); + pkt_cnt_total += (main_ant_cnt + aux_ant_cnt); + } + + if (p_dm_swat_table->is_sw_ant_div_by_ctrl_frame) { + odm_s0s1_sw_ant_div_by_ctrl_frame(p_dm_odm, SWAW_STEP_DETERMINE); + is_by_ctrl_frame = true; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Control frame packet counter = %d, data frame packet counter = %llu\n", + p_dm_swat_table->pkt_cnt_sw_ant_div_by_ctrl_frame, pkt_cnt_total)); + + if (min_max_rssi == 0xff || ((pkt_cnt_total < (p_dm_swat_table->pkt_cnt_sw_ant_div_by_ctrl_frame >> 1)) && p_dm_odm->phy_dbg_info.num_qry_beacon_pkt < 2)) { + min_max_rssi = 0; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Check RSSI of control frame because min_max_rssi == 0xff\n")); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("is_by_ctrl_frame = %d\n", is_by_ctrl_frame)); + + if (is_by_ctrl_frame) { + main_rssi = (p_dm_fat_table->main_ant_ctrl_frame_cnt != 0) ? (p_dm_fat_table->main_ant_ctrl_frame_sum / p_dm_fat_table->main_ant_ctrl_frame_cnt) : 0; + aux_rssi = (p_dm_fat_table->aux_ant_ctrl_frame_cnt != 0) ? (p_dm_fat_table->aux_ant_ctrl_frame_sum / p_dm_fat_table->aux_ant_ctrl_frame_cnt) : 0; + + if (p_dm_fat_table->main_ant_ctrl_frame_cnt <= 1 && p_dm_fat_table->cck_ctrl_frame_cnt_main >= 1) + main_rssi = 0; + + if (p_dm_fat_table->aux_ant_ctrl_frame_cnt <= 1 && p_dm_fat_table->cck_ctrl_frame_cnt_aux >= 1) + aux_rssi = 0; + + if (main_rssi != 0 || aux_rssi != 0) { + rx_idle_ant = (main_rssi == aux_rssi) ? p_dm_swat_table->pre_antenna : ((main_rssi >= aux_rssi) ? MAIN_ANT : AUX_ANT); + local_max_rssi = (main_rssi >= aux_rssi) ? main_rssi : aux_rssi; + local_min_rssi = (main_rssi >= aux_rssi) ? aux_rssi : main_rssi; + + if ((local_max_rssi - local_min_rssi) > 8) + p_dm_swat_table->train_time_flag = 3; + else if ((local_max_rssi - local_min_rssi) > 5) + p_dm_swat_table->train_time_flag = 2; + else if ((local_max_rssi - local_min_rssi) > 2) + p_dm_swat_table->train_time_flag = 1; + else + p_dm_swat_table->train_time_flag = 0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Control frame: main_rssi = %d, aux_rssi = %d\n", main_rssi, aux_rssi)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("rx_idle_ant decided by control frame = %s\n", (rx_idle_ant == MAIN_ANT ? "MAIN" : "AUX"))); + } + } + } + + p_dm_fat_table->min_max_rssi = min_max_rssi; + p_dm_swat_table->try_flag = SWAW_STEP_PEEK; + + if (p_dm_swat_table->double_chk_flag == 1) { + p_dm_swat_table->double_chk_flag = 0; + + if (p_dm_fat_table->min_max_rssi > RSSI_CHECK_THRESHOLD) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, (" [Double check] min_max_rssi ((%d)) > %d again!!\n", + p_dm_fat_table->min_max_rssi, RSSI_CHECK_THRESHOLD)); + + odm_update_rx_idle_ant(p_dm_odm, rx_idle_ant); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[reset try_flag = 0] Training accomplished !!!]\n\n\n")); + return; + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, (" [Double check] min_max_rssi ((%d)) <= %d !!\n", + p_dm_fat_table->min_max_rssi, RSSI_CHECK_THRESHOLD)); + + next_ant = (p_dm_fat_table->rx_idle_ant == MAIN_ANT) ? AUX_ANT : MAIN_ANT; + p_dm_swat_table->try_flag = SWAW_STEP_PEEK; + p_dm_swat_table->reset_idx = RSSI_CHECK_RESET_PERIOD; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[set try_flag=0] Normal state: Need to tryg again!!\n\n\n")); + return; + } + } else { + if (p_dm_fat_table->min_max_rssi < RSSI_CHECK_THRESHOLD) + p_dm_swat_table->reset_idx = RSSI_CHECK_RESET_PERIOD; + + p_dm_swat_table->pre_antenna = rx_idle_ant; + odm_update_rx_idle_ant(p_dm_odm, rx_idle_ant); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[reset try_flag = 0] Training accomplished !!!] \n\n\n")); + return; + } + + } + + } + + /* 1 4.Change TRX antenna */ + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("rssi_trying = (( %d )), ant: (( %s )) >>> (( %s ))\n", + p_dm_swat_table->rssi_trying, (p_dm_fat_table->rx_idle_ant == MAIN_ANT ? "MAIN" : "AUX"), (next_ant == MAIN_ANT ? "MAIN" : "AUX"))); + + odm_update_rx_idle_ant(p_dm_odm, next_ant); + + /* 1 5.Reset Statistics */ + + p_dm_fat_table->rx_idle_ant = next_ant; + + /* 1 6.Set next timer (Trying state) */ + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, (" Test ((%s)) ant for (( %d )) ms\n", (next_ant == MAIN_ANT ? "MAIN" : "AUX"), p_dm_swat_table->train_time)); + odm_set_timer(p_dm_odm, &(p_dm_swat_table->phydm_sw_antenna_switch_timer), p_dm_swat_table->train_time); /*ms*/ +} + +void odm_sw_antdiv_workitem_callback(void *p_context) +{ + struct _ADAPTER * p_adapter = (struct _ADAPTER *)p_context; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + + /*dbg_print("SW_antdiv_Workitem_Callback");*/ + odm_s0s1_sw_ant_div(&p_hal_data->odmpriv, SWAW_STEP_DETERMINE); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) +void odm_sw_antdiv_callback(void *function_context) +#else +void odm_sw_antdiv_callback(istruct timer_list *t) +#endif +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)function_context; +#else + struct PHY_DM_STRUCT *p_dm_odm = timer_list(p_dm_odm, t, dm_swat_table.phydm_sw_antenna_switch_timer); +#endif + struct _ADAPTER *padapter = p_dm_odm->adapter; + if (padapter->net_closed == true) + return; + + rtw_run_in_thread_cmd(padapter, odm_sw_antdiv_workitem_callback, padapter); +} + + +#endif + +void +odm_s0s1_sw_ant_div_by_ctrl_frame( + void *p_dm_void, + u8 step +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _sw_antenna_switch_ *p_dm_swat_table = &p_dm_odm->dm_swat_table; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + + switch (step) { + case SWAW_STEP_PEEK: + p_dm_swat_table->pkt_cnt_sw_ant_div_by_ctrl_frame = 0; + p_dm_swat_table->is_sw_ant_div_by_ctrl_frame = true; + p_dm_fat_table->main_ant_ctrl_frame_cnt = 0; + p_dm_fat_table->aux_ant_ctrl_frame_cnt = 0; + p_dm_fat_table->main_ant_ctrl_frame_sum = 0; + p_dm_fat_table->aux_ant_ctrl_frame_sum = 0; + p_dm_fat_table->cck_ctrl_frame_cnt_main = 0; + p_dm_fat_table->cck_ctrl_frame_cnt_aux = 0; + p_dm_fat_table->ofdm_ctrl_frame_cnt_main = 0; + p_dm_fat_table->ofdm_ctrl_frame_cnt_aux = 0; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_S0S1_SwAntDivForAPMode(): Start peek and reset counter\n")); + break; + case SWAW_STEP_DETERMINE: + p_dm_swat_table->is_sw_ant_div_by_ctrl_frame = false; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_S0S1_SwAntDivForAPMode(): Stop peek\n")); + break; + default: + p_dm_swat_table->is_sw_ant_div_by_ctrl_frame = false; + break; + } +} + +void +odm_antsel_statistics_of_ctrl_frame( + void *p_dm_void, + u8 antsel_tr_mux, + u32 rx_pwdb_all + +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + + if (antsel_tr_mux == ANT1_2G) { + p_dm_fat_table->main_ant_ctrl_frame_sum += rx_pwdb_all; + p_dm_fat_table->main_ant_ctrl_frame_cnt++; + } else { + p_dm_fat_table->aux_ant_ctrl_frame_sum += rx_pwdb_all; + p_dm_fat_table->aux_ant_ctrl_frame_cnt++; + } +} + +void +odm_s0s1_sw_ant_div_by_ctrl_frame_process_rssi( + void *p_dm_void, + void *p_phy_info_void, + void *p_pkt_info_void + /* struct _odm_phy_status_info_* p_phy_info, */ + /* struct _odm_per_pkt_info_* p_pktinfo */ +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _odm_phy_status_info_ *p_phy_info = (struct _odm_phy_status_info_ *)p_phy_info_void; + struct _odm_per_pkt_info_ *p_pktinfo = (struct _odm_per_pkt_info_ *)p_pkt_info_void; + struct _sw_antenna_switch_ *p_dm_swat_table = &p_dm_odm->dm_swat_table; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + bool is_cck_rate; + + if (!(p_dm_odm->support_ability & ODM_BB_ANT_DIV)) + return; + + if (p_dm_odm->ant_div_type != S0S1_SW_ANTDIV) + return; + + /* In try state */ + if (!p_dm_swat_table->is_sw_ant_div_by_ctrl_frame) + return; + + /* No HW error and match receiver address */ + if (!p_pktinfo->is_to_self) + return; + + p_dm_swat_table->pkt_cnt_sw_ant_div_by_ctrl_frame++; + is_cck_rate = ((p_pktinfo->data_rate >= DESC_RATE1M) && (p_pktinfo->data_rate <= DESC_RATE11M)) ? true : false; + + if (is_cck_rate) { + p_dm_fat_table->antsel_rx_keep_0 = (p_dm_fat_table->rx_idle_ant == MAIN_ANT) ? ANT1_2G : ANT2_2G; + + if (p_dm_fat_table->antsel_rx_keep_0 == ANT1_2G) + p_dm_fat_table->cck_ctrl_frame_cnt_main++; + else + p_dm_fat_table->cck_ctrl_frame_cnt_aux++; + + odm_antsel_statistics_of_ctrl_frame(p_dm_odm, p_dm_fat_table->antsel_rx_keep_0, p_phy_info->rx_mimo_signal_strength[ODM_RF_PATH_A]); + } else { + if (p_dm_fat_table->antsel_rx_keep_0 == ANT1_2G) + p_dm_fat_table->ofdm_ctrl_frame_cnt_main++; + else + p_dm_fat_table->ofdm_ctrl_frame_cnt_aux++; + + odm_antsel_statistics_of_ctrl_frame(p_dm_odm, p_dm_fat_table->antsel_rx_keep_0, p_phy_info->rx_pwdb_all); + } +} + +#endif /* #if (RTL8723B_SUPPORT == 1) || (RTL8821A_SUPPORT == 1) */ + + + + +void +odm_set_next_mac_addr_target( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + struct sta_info *p_entry; + u32 value32, i; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_set_next_mac_addr_target() ==>\n")); + + if (p_dm_odm->is_linked) { + for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { + + if ((p_dm_fat_table->train_idx + 1) == ODM_ASSOCIATE_ENTRY_NUM) + p_dm_fat_table->train_idx = 0; + else + p_dm_fat_table->train_idx++; + + p_entry = p_dm_odm->p_odm_sta_info[p_dm_fat_table->train_idx]; + + if (IS_STA_VALID(p_entry)) { + + /*Match MAC ADDR*/ + value32 = (p_entry->hwaddr[5] << 8) | p_entry->hwaddr[4]; + + odm_set_mac_reg(p_dm_odm, 0x7b4, 0xFFFF, value32);/*0x7b4~0x7b5*/ + + value32 = (p_entry->hwaddr[3] << 24) | (p_entry->hwaddr[2] << 16) | (p_entry->hwaddr[1] << 8) | p_entry->hwaddr[0]; + odm_set_mac_reg(p_dm_odm, 0x7b0, MASKDWORD, value32);/*0x7b0~0x7b3*/ + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("p_dm_fat_table->train_idx=%d\n", p_dm_fat_table->train_idx)); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Training MAC addr = %x:%x:%x:%x:%x:%x\n", + p_entry->hwaddr[5], p_entry->hwaddr[4], p_entry->hwaddr[3], p_entry->hwaddr[2], p_entry->hwaddr[1], p_entry->hwaddr[0])); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Training MAC addr = %x:%x:%x:%x:%x:%x\n", + p_entry->MacAddr[5], p_entry->MacAddr[4], p_entry->MacAddr[3], p_entry->MacAddr[2], p_entry->MacAddr[1], p_entry->MacAddr[0])); + break; + } + } + } +} + +#if (defined(CONFIG_5G_CG_SMART_ANT_DIVERSITY)) || (defined(CONFIG_2G_CG_SMART_ANT_DIVERSITY)) + +void +odm_fast_ant_training( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + + u32 max_rssi_path_a = 0, pckcnt_path_a = 0; + u8 i, target_ant_path_a = 0; + bool is_pkt_filter_macth_path_a = false; +#if (RTL8192E_SUPPORT == 1) + u32 max_rssi_path_b = 0, pckcnt_path_b = 0; + u8 target_ant_path_b = 0; + bool is_pkt_filter_macth_path_b = false; +#endif + + + if (!p_dm_odm->is_linked) { /* is_linked==False */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[No Link!!!]\n")); + + if (p_dm_fat_table->is_become_linked == true) { + odm_ant_div_on_off(p_dm_odm, ANTDIV_OFF); + phydm_fast_training_enable(p_dm_odm, FAT_OFF); + odm_tx_by_tx_desc_or_reg(p_dm_odm, TX_BY_REG); + p_dm_fat_table->is_become_linked = p_dm_odm->is_linked; + } + return; + } else { + if (p_dm_fat_table->is_become_linked == false) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Linked!!!]\n")); + p_dm_fat_table->is_become_linked = p_dm_odm->is_linked; + } + } + + if (*(p_dm_fat_table->p_force_tx_ant_by_desc) == false) { + if (p_dm_odm->is_one_entry_only == true) + odm_tx_by_tx_desc_or_reg(p_dm_odm, TX_BY_REG); + else + odm_tx_by_tx_desc_or_reg(p_dm_odm, TX_BY_DESC); + } + + + if (p_dm_odm->support_ic_type == ODM_RTL8188E) + odm_set_bb_reg(p_dm_odm, 0x864, BIT(2) | BIT(1) | BIT(0), ((p_dm_odm->fat_comb_a) - 1)); +#if (RTL8192E_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8192E) { + odm_set_bb_reg(p_dm_odm, 0xB38, BIT(2) | BIT1 | BIT0, ((p_dm_odm->fat_comb_a) - 1)); /* path-A */ /* ant combination=regB38[2:0]+1 */ + odm_set_bb_reg(p_dm_odm, 0xB38, BIT(18) | BIT17 | BIT16, ((p_dm_odm->fat_comb_b) - 1)); /* path-B */ /* ant combination=regB38[18:16]+1 */ + } +#endif + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("==>odm_fast_ant_training()\n")); + + /* 1 TRAINING STATE */ + if (p_dm_fat_table->fat_state == FAT_TRAINING_STATE) { + /* 2 Caculate RSSI per Antenna */ + + /* 3 [path-A]--------------------------- */ + for (i = 0; i < (p_dm_odm->fat_comb_a); i++) { /* i : antenna index */ + if (p_dm_fat_table->ant_rssi_cnt[i] == 0) + p_dm_fat_table->ant_ave_rssi[i] = 0; + else { + p_dm_fat_table->ant_ave_rssi[i] = p_dm_fat_table->ant_sum_rssi[i] / p_dm_fat_table->ant_rssi_cnt[i]; + is_pkt_filter_macth_path_a = true; + } + + if (p_dm_fat_table->ant_ave_rssi[i] > max_rssi_path_a) { + max_rssi_path_a = p_dm_fat_table->ant_ave_rssi[i]; + pckcnt_path_a = p_dm_fat_table->ant_rssi_cnt[i]; + target_ant_path_a = i ; + } else if (p_dm_fat_table->ant_ave_rssi[i] == max_rssi_path_a) { + if ((p_dm_fat_table->ant_rssi_cnt[i]) > pckcnt_path_a) { + max_rssi_path_a = p_dm_fat_table->ant_ave_rssi[i]; + pckcnt_path_a = p_dm_fat_table->ant_rssi_cnt[i]; + target_ant_path_a = i ; + } + } + + ODM_RT_TRACE("*** ant-index : [ %d ], counter = (( %d )), Avg RSSI = (( %d ))\n", i, p_dm_fat_table->ant_rssi_cnt[i], p_dm_fat_table->ant_ave_rssi[i]); + } + + /* 1 DECISION STATE */ + + /* 2 Select TRX Antenna */ + + phydm_fast_training_enable(p_dm_odm, FAT_OFF); + + /* 3 [path-A]--------------------------- */ + if (is_pkt_filter_macth_path_a == false) { + /* ODM_RT_TRACE(p_dm_odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("{path-A}: None Packet is matched\n")); */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("{path-A}: None Packet is matched\n")); + odm_ant_div_on_off(p_dm_odm, ANTDIV_OFF); + } else { + ODM_RT_TRACE("target_ant_path_a = (( %d )) , max_rssi_path_a = (( %d ))\n", target_ant_path_a, max_rssi_path_a); + + /* 3 [ update RX-optional ant ] Default RX is Omni, Optional RX is the best decision by FAT */ + if (p_dm_odm->support_ic_type == ODM_RTL8188E) + odm_set_bb_reg(p_dm_odm, 0x864, BIT(8) | BIT(7) | BIT(6), target_ant_path_a); + else if (p_dm_odm->support_ic_type == ODM_RTL8192E) { + odm_set_bb_reg(p_dm_odm, 0xB38, BIT(8) | BIT7 | BIT6, target_ant_path_a); /* Optional RX [pth-A] */ + } + /* 3 [ update TX ant ] */ + odm_update_tx_ant(p_dm_odm, target_ant_path_a, (p_dm_fat_table->train_idx)); + + if (target_ant_path_a == 0) + odm_ant_div_on_off(p_dm_odm, ANTDIV_OFF); + } + + /* 2 Reset counter */ + for (i = 0; i < (p_dm_odm->fat_comb_a); i++) { + p_dm_fat_table->ant_sum_rssi[i] = 0; + p_dm_fat_table->ant_rssi_cnt[i] = 0; + } + + p_dm_fat_table->fat_state = FAT_PREPARE_STATE; + return; + } + + /* 1 NORMAL STATE */ + if (p_dm_fat_table->fat_state == FAT_PREPARE_STATE) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ Start Prepare state ]\n")); + + odm_set_next_mac_addr_target(p_dm_odm); + + /* 2 Prepare Training */ + p_dm_fat_table->fat_state = FAT_TRAINING_STATE; + phydm_fast_training_enable(p_dm_odm, FAT_ON); + odm_ant_div_on_off(p_dm_odm, ANTDIV_ON); /* enable HW AntDiv */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Start Training state]\n")); + + odm_set_timer(p_dm_odm, &p_dm_odm->fast_ant_training_timer, p_dm_odm->antdiv_intvl); /* ms */ + } + +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) +void odm_fast_ant_training_callback(void *p_dm_void) +#else +void odm_fast_ant_training_callback(struct timer_list *t) +#endif +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; +#else + struct PHY_DM_STRUCT *p_dm_odm = from_timer(p_dm_odm, t, fast_ant_training_timer); +#endif + struct _ADAPTER *padapter = p_dm_odm->adapter; + + if (padapter->net_closed == true) + return; + /* if(*p_dm_odm->p_is_net_closed == true) */ + /* return; */ + +#if USE_WORKITEM + odm_schedule_work_item(&p_dm_odm->fast_ant_training_workitem); +#else + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("******odm_fast_ant_training_callback******\n")); + odm_fast_ant_training(p_dm_odm); +#endif +} + +void +odm_fast_ant_training_work_item_callback( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("******odm_fast_ant_training_work_item_callback******\n")); + odm_fast_ant_training(p_dm_odm); +} + +#endif + +#ifdef CONFIG_HL_SMART_ANTENNA_TYPE1 + +u32 +phydm_construct_hl_beam_codeword( + void *p_dm_void, + u32 *beam_pattern_idx, + u32 ant_num +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _SMART_ANTENNA_TRAINNING_ *pdm_sat_table = &(p_dm_odm->dm_sat_table); + u32 codeword = 0; + u32 data_tmp; + u32 i; + u32 break_counter = 0; + + if (ant_num < 8) { + for (i = 0; i < (pdm_sat_table->ant_num_total); i++) { + /*ODM_RT_TRACE(p_dm_odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("beam_pattern_num[%x] = %x\n",i,beam_pattern_num[i] ));*/ + if ((i < (pdm_sat_table->first_train_ant - 1)) /*|| (break_counter >= (pdm_sat_table->ant_num))*/) { + data_tmp = 0; + /**/ + } else { + + break_counter++; + + if (beam_pattern_idx[i] == 0) { + + if (*p_dm_odm->p_band_type == ODM_BAND_5G) + data_tmp = pdm_sat_table->rfu_codeword_table_5g[0]; + else + data_tmp = pdm_sat_table->rfu_codeword_table[0]; + + } else if (beam_pattern_idx[i] == 1) { + + + if (*p_dm_odm->p_band_type == ODM_BAND_5G) + data_tmp = pdm_sat_table->rfu_codeword_table_5g[1]; + else + data_tmp = pdm_sat_table->rfu_codeword_table[1]; + + } else if (beam_pattern_idx[i] == 2) { + + if (*p_dm_odm->p_band_type == ODM_BAND_5G) + data_tmp = pdm_sat_table->rfu_codeword_table_5g[2]; + else + data_tmp = pdm_sat_table->rfu_codeword_table[2]; + + } else if (beam_pattern_idx[i] == 3) { + + if (*p_dm_odm->p_band_type == ODM_BAND_5G) + data_tmp = pdm_sat_table->rfu_codeword_table_5g[3]; + else + data_tmp = pdm_sat_table->rfu_codeword_table[3]; + } + } + + + codeword |= (data_tmp << (i * 4)); + + } + } + + return codeword; +} + +void +phydm_update_beam_pattern( + void *p_dm_void, + u32 codeword, + u32 codeword_length +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _SMART_ANTENNA_TRAINNING_ *pdm_sat_table = &(p_dm_odm->dm_sat_table); + u8 i; + bool beam_ctrl_signal; + u32 one = 0x1; + u32 reg44_tmp_p, reg44_tmp_n, reg44_ori; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ SmartAnt ] Set Beam Pattern =0x%x\n", codeword)); + + reg44_ori = odm_get_mac_reg(p_dm_odm, 0x44, MASKDWORD); + /*ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("reg44_ori =0x%x\n", reg44_ori));*/ + + for (i = 0; i <= (codeword_length - 1); i++) { + beam_ctrl_signal = (bool)((codeword & BIT(i)) >> i); + + if (p_dm_odm->debug_components & ODM_COMP_ANT_DIV) { + + if (i == (codeword_length - 1)) { + dbg_print("%d ]\n", beam_ctrl_signal); + /**/ + } else if (i == 0) { + dbg_print("Send codeword[1:24] ---> [ %d ", beam_ctrl_signal); + /**/ + } else if ((i % 4) == 3) { + dbg_print("%d | ", beam_ctrl_signal); + /**/ + } else { + dbg_print("%d ", beam_ctrl_signal); + /**/ + } + } + + if (p_dm_odm->support_ic_type == ODM_RTL8821) { + } + } +} + +void +phydm_update_rx_idle_beam( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + struct _SMART_ANTENNA_TRAINNING_ *pdm_sat_table = &(p_dm_odm->dm_sat_table); + u32 i; + + pdm_sat_table->update_beam_codeword = phydm_construct_hl_beam_codeword(p_dm_odm, &(pdm_sat_table->rx_idle_beam[0]), pdm_sat_table->ant_num); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Set target beam_pattern codeword = (( 0x%x ))\n", pdm_sat_table->update_beam_codeword)); + + for (i = 0; i < (pdm_sat_table->ant_num); i++) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ Update Rx-Idle-Beam ] RxIdleBeam[%d] =%d\n", i, pdm_sat_table->rx_idle_beam[i])); + /**/ + } + +#if DEV_BUS_TYPE == RT_PCI_INTERFACE + phydm_update_beam_pattern(p_dm_odm, pdm_sat_table->update_beam_codeword, pdm_sat_table->data_codeword_bit_num); +#else + odm_schedule_work_item(&pdm_sat_table->hl_smart_antenna_workitem); + /*odm_stall_execution(1);*/ +#endif + + pdm_sat_table->pre_codeword = pdm_sat_table->update_beam_codeword; +} + +void +phydm_hl_smart_ant_debug( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _SMART_ANTENNA_TRAINNING_ *pdm_sat_table = &(p_dm_odm->dm_sat_table); + u32 used = *_used; + u32 out_len = *_out_len; + u32 one = 0x1; + u32 codeword_length = pdm_sat_table->data_codeword_bit_num; + u32 beam_ctrl_signal, i; + + if (dm_value[0] == 1) { /*fix beam pattern*/ + + pdm_sat_table->fix_beam_pattern_en = dm_value[1]; + + if (pdm_sat_table->fix_beam_pattern_en == 1) { + + pdm_sat_table->fix_beam_pattern_codeword = dm_value[2]; + + if (pdm_sat_table->fix_beam_pattern_codeword > (one << codeword_length)) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ SmartAnt ] Codeword overflow, Current codeword is ((0x%x)), and should be less than ((%d))bit\n", + pdm_sat_table->fix_beam_pattern_codeword, codeword_length)); + (pdm_sat_table->fix_beam_pattern_codeword) &= 0xffffff; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ SmartAnt ] Auto modify to (0x%x)\n", pdm_sat_table->fix_beam_pattern_codeword)); + } + + pdm_sat_table->update_beam_codeword = pdm_sat_table->fix_beam_pattern_codeword; + + /*---------------------------------------------------------*/ + PHYDM_SNPRINTF((output + used, out_len - used, "Fix Beam Pattern\n")); + for (i = 0; i <= (codeword_length - 1); i++) { + beam_ctrl_signal = (bool)((pdm_sat_table->update_beam_codeword & BIT(i)) >> i); + + if (i == (codeword_length - 1)) { + PHYDM_SNPRINTF((output + used, out_len - used, "%d]\n", beam_ctrl_signal)); + /**/ + } else if (i == 0) { + PHYDM_SNPRINTF((output + used, out_len - used, "Send Codeword[1:24] to RFU -> [%d", beam_ctrl_signal)); + /**/ + } else if ((i % 4) == 3) { + PHYDM_SNPRINTF((output + used, out_len - used, "%d|", beam_ctrl_signal)); + /**/ + } else { + PHYDM_SNPRINTF((output + used, out_len - used, "%d", beam_ctrl_signal)); + /**/ + } + } + /*---------------------------------------------------------*/ + + +#if DEV_BUS_TYPE == RT_PCI_INTERFACE + phydm_update_beam_pattern(p_dm_odm, pdm_sat_table->update_beam_codeword, pdm_sat_table->data_codeword_bit_num); +#else + odm_schedule_work_item(&pdm_sat_table->hl_smart_antenna_workitem); + /*odm_stall_execution(1);*/ +#endif + } else if (pdm_sat_table->fix_beam_pattern_en == 0) + PHYDM_SNPRINTF((output + used, out_len - used, "[ SmartAnt ] Smart Antenna: Enable\n")); + + } else if (dm_value[0] == 2) { /*set latch time*/ + + pdm_sat_table->latch_time = dm_value[1]; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ SmartAnt ] latch_time =0x%x\n", pdm_sat_table->latch_time)); + } else if (dm_value[0] == 3) { + + pdm_sat_table->fix_training_num_en = dm_value[1]; + + if (pdm_sat_table->fix_training_num_en == 1) { + pdm_sat_table->per_beam_training_pkt_num = (u8)dm_value[2]; + pdm_sat_table->decision_holding_period = (u8)dm_value[3]; + + PHYDM_SNPRINTF((output + used, out_len - used, "[SmartAnt][Dbg] Fix_train_en = (( %d )), train_pkt_num = (( %d )), holding_period = (( %d )),\n", + pdm_sat_table->fix_training_num_en, pdm_sat_table->per_beam_training_pkt_num, pdm_sat_table->decision_holding_period)); + + } else if (pdm_sat_table->fix_training_num_en == 0) { + PHYDM_SNPRINTF((output + used, out_len - used, "[ SmartAnt ] AUTO per_beam_training_pkt_num\n")); + /**/ + } + } else if (dm_value[0] == 4) { + + if (dm_value[1] == 1) { + pdm_sat_table->ant_num = 1; + pdm_sat_table->first_train_ant = MAIN_ANT; + + } else if (dm_value[1] == 2) { + pdm_sat_table->ant_num = 1; + pdm_sat_table->first_train_ant = AUX_ANT; + + } else if (dm_value[1] == 3) { + pdm_sat_table->ant_num = 2; + pdm_sat_table->first_train_ant = MAIN_ANT; + } + + PHYDM_SNPRINTF((output + used, out_len - used, "[ SmartAnt ] Set ant Num = (( %d )), first_train_ant = (( %d ))\n", + pdm_sat_table->ant_num, (pdm_sat_table->first_train_ant - 1))); + } else if (dm_value[0] == 5) { + + if (dm_value[1] <= 3) { + pdm_sat_table->rfu_codeword_table[dm_value[1]] = dm_value[2]; + PHYDM_SNPRINTF((output + used, out_len - used, "[ SmartAnt ] Set Beam_2G: (( %d )), RFU codeword table = (( 0x%x ))\n", + dm_value[1], dm_value[2])); + } else { + for (i = 0; i < 4; i++) { + PHYDM_SNPRINTF((output + used, out_len - used, "[ SmartAnt ] Show Beam_2G: (( %d )), RFU codeword table = (( 0x%x ))\n", + i, pdm_sat_table->rfu_codeword_table[i])); + } + } + } else if (dm_value[0] == 6) { + + if (dm_value[1] <= 3) { + pdm_sat_table->rfu_codeword_table_5g[dm_value[1]] = dm_value[2]; + PHYDM_SNPRINTF((output + used, out_len - used, "[ SmartAnt ] Set Beam_5G: (( %d )), RFU codeword table = (( 0x%x ))\n", + dm_value[1], dm_value[2])); + } else { + for (i = 0; i < 4; i++) { + PHYDM_SNPRINTF((output + used, out_len - used, "[ SmartAnt ] Show Beam_5G: (( %d )), RFU codeword table = (( 0x%x ))\n", + i, pdm_sat_table->rfu_codeword_table_5g[i])); + } + } + } else if (dm_value[0] == 7) { + + if (dm_value[1] <= 4) { + + pdm_sat_table->beam_patten_num_each_ant = dm_value[1]; + PHYDM_SNPRINTF((output + used, out_len - used, "[ SmartAnt ] Set Beam number = (( %d ))\n", + pdm_sat_table->beam_patten_num_each_ant)); + } else { + + PHYDM_SNPRINTF((output + used, out_len - used, "[ SmartAnt ] Show Beam number = (( %d ))\n", + pdm_sat_table->beam_patten_num_each_ant)); + } + } + +} + + +void +phydm_set_all_ant_same_beam_num( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _SMART_ANTENNA_TRAINNING_ *pdm_sat_table = &(p_dm_odm->dm_sat_table); + + if (p_dm_odm->ant_div_type == HL_SW_SMART_ANT_TYPE1) { /*2ant for 8821A*/ + + pdm_sat_table->rx_idle_beam[0] = pdm_sat_table->fast_training_beam_num; + pdm_sat_table->rx_idle_beam[1] = pdm_sat_table->fast_training_beam_num; + } + + pdm_sat_table->update_beam_codeword = phydm_construct_hl_beam_codeword(p_dm_odm, &(pdm_sat_table->rx_idle_beam[0]), pdm_sat_table->ant_num); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ SmartAnt ] Set all ant beam_pattern: codeword = (( 0x%x ))\n", pdm_sat_table->update_beam_codeword)); + +#if DEV_BUS_TYPE == RT_PCI_INTERFACE + phydm_update_beam_pattern(p_dm_odm, pdm_sat_table->update_beam_codeword, pdm_sat_table->data_codeword_bit_num); +#else + odm_schedule_work_item(&pdm_sat_table->hl_smart_antenna_workitem); + /*odm_stall_execution(1);*/ +#endif +} + +void +odm_fast_ant_training_hl_smart_antenna_type1( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _SMART_ANTENNA_TRAINNING_ *pdm_sat_table = &(p_dm_odm->dm_sat_table); + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &(p_dm_odm->dm_fat_table); + struct _sw_antenna_switch_ *p_dm_swat_table = &p_dm_odm->dm_swat_table; + u32 codeword = 0, i, j; + u32 target_ant; + u32 avg_rssi_tmp, avg_rssi_tmp_ma; + u32 target_ant_beam_max_rssi[SUPPORT_RF_PATH_NUM] = {0}; + u32 max_beam_ant_rssi = 0; + u32 target_ant_beam[SUPPORT_RF_PATH_NUM] = {0}; + u32 beam_tmp; + u8 next_ant; + u32 rssi_sorting_seq[SUPPORT_BEAM_PATTERN_NUM] = {0}; + u32 rank_idx_seq[SUPPORT_BEAM_PATTERN_NUM] = {0}; + u32 rank_idx_out[SUPPORT_BEAM_PATTERN_NUM] = {0}; + u8 per_beam_rssi_diff_tmp = 0, training_pkt_num_offset; + u32 break_counter = 0; + u32 used_ant; + + + if (!p_dm_odm->is_linked) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[No Link!!!]\n")); + + if (p_dm_fat_table->is_become_linked == true) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Link->no Link\n")); + p_dm_fat_table->fat_state = FAT_BEFORE_LINK_STATE; + odm_ant_div_on_off(p_dm_odm, ANTDIV_OFF); + odm_tx_by_tx_desc_or_reg(p_dm_odm, TX_BY_REG); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("change to (( %d )) FAT_state\n", p_dm_fat_table->fat_state)); + + p_dm_fat_table->is_become_linked = p_dm_odm->is_linked; + } + return; + + } else { + if (p_dm_fat_table->is_become_linked == false) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Linked !!!]\n")); + + p_dm_fat_table->fat_state = FAT_PREPARE_STATE; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("change to (( %d )) FAT_state\n", p_dm_fat_table->fat_state)); + + /*pdm_sat_table->fast_training_beam_num = 0;*/ + /*phydm_set_all_ant_same_beam_num(p_dm_odm);*/ + + p_dm_fat_table->is_become_linked = p_dm_odm->is_linked; + } + } + + if (*(p_dm_fat_table->p_force_tx_ant_by_desc) == false) { + if (p_dm_odm->is_one_entry_only == true) + odm_tx_by_tx_desc_or_reg(p_dm_odm, TX_BY_REG); + else + odm_tx_by_tx_desc_or_reg(p_dm_odm, TX_BY_DESC); + } + + /*ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("HL Smart ant Training: state (( %d ))\n", p_dm_fat_table->fat_state));*/ + + /* [DECISION STATE] */ + /*=======================================================================================*/ + if (p_dm_fat_table->fat_state == FAT_DECISION_STATE) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ 3. In Decision state]\n")); + phydm_fast_training_enable(p_dm_odm, FAT_OFF); + + break_counter = 0; + /*compute target beam in each antenna*/ + for (i = (pdm_sat_table->first_train_ant - 1); i < pdm_sat_table->ant_num_total; i++) { + for (j = 0; j < (pdm_sat_table->beam_patten_num_each_ant); j++) { + + if (pdm_sat_table->pkt_rssi_cnt[i][j] == 0) { + avg_rssi_tmp = pdm_sat_table->pkt_rssi_pre[i][j]; + avg_rssi_tmp = (avg_rssi_tmp >= 2) ? (avg_rssi_tmp - 2) : avg_rssi_tmp; + avg_rssi_tmp_ma = avg_rssi_tmp; + } else { + avg_rssi_tmp = (pdm_sat_table->pkt_rssi_sum[i][j]) / (pdm_sat_table->pkt_rssi_cnt[i][j]); + avg_rssi_tmp_ma = (avg_rssi_tmp + pdm_sat_table->pkt_rssi_pre[i][j]) >> 1; + } + + rssi_sorting_seq[j] = avg_rssi_tmp; + pdm_sat_table->pkt_rssi_pre[i][j] = avg_rssi_tmp; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ant[%d], Beam[%d]: pkt_cnt=(( %d )), avg_rssi_MA=(( %d )), avg_rssi=(( %d ))\n", + i, j, pdm_sat_table->pkt_rssi_cnt[i][j], avg_rssi_tmp_ma, avg_rssi_tmp)); + + if (avg_rssi_tmp > target_ant_beam_max_rssi[i]) { + target_ant_beam[i] = j; + target_ant_beam_max_rssi[i] = avg_rssi_tmp; + } + + /*reset counter value*/ + pdm_sat_table->pkt_rssi_sum[i][j] = 0; + pdm_sat_table->pkt_rssi_cnt[i][j] = 0; + + } + pdm_sat_table->rx_idle_beam[i] = target_ant_beam[i]; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("---------> Target of ant[%d]: Beam_num-(( %d )) RSSI= ((%d))\n", + i, target_ant_beam[i], target_ant_beam_max_rssi[i])); + + /*sorting*/ + /* + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Pre]rssi_sorting_seq = [%d, %d, %d, %d]\n", rssi_sorting_seq[0], rssi_sorting_seq[1], rssi_sorting_seq[2], rssi_sorting_seq[3])); + */ + + /*phydm_seq_sorting(p_dm_odm, &rssi_sorting_seq[0], &rank_idx_seq[0], &rank_idx_out[0], SUPPORT_BEAM_PATTERN_NUM);*/ + + /* + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Post]rssi_sorting_seq = [%d, %d, %d, %d]\n", rssi_sorting_seq[0], rssi_sorting_seq[1], rssi_sorting_seq[2], rssi_sorting_seq[3])); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Post]rank_idx_seq = [%d, %d, %d, %d]\n", rank_idx_seq[0], rank_idx_seq[1], rank_idx_seq[2], rank_idx_seq[3])); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Post]rank_idx_out = [%d, %d, %d, %d]\n", rank_idx_out[0], rank_idx_out[1], rank_idx_out[2], rank_idx_out[3])); + */ + + if (target_ant_beam_max_rssi[i] > max_beam_ant_rssi) { + target_ant = i; + max_beam_ant_rssi = target_ant_beam_max_rssi[i]; + /*ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Target of ant = (( %d )) max_beam_ant_rssi = (( %d ))\n", + target_ant, max_beam_ant_rssi));*/ + } + break_counter++; + if (break_counter >= (pdm_sat_table->ant_num)) + break; + } + +#ifdef CONFIG_FAT_PATCH + break_counter = 0; + for (i = (pdm_sat_table->first_train_ant - 1); i < pdm_sat_table->ant_num_total; i++) { + for (j = 0; j < (pdm_sat_table->beam_patten_num_each_ant); j++) { + + per_beam_rssi_diff_tmp = (u8)(max_beam_ant_rssi - pdm_sat_table->pkt_rssi_pre[i][j]); + pdm_sat_table->beam_train_rssi_diff[i][j] = per_beam_rssi_diff_tmp; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ant[%d], Beam[%d]: RSSI_diff= ((%d))\n", + i, j, per_beam_rssi_diff_tmp)); + } + break_counter++; + if (break_counter >= (pdm_sat_table->ant_num)) + break; + } +#endif + + if (target_ant == 0) + target_ant = MAIN_ANT; + else if (target_ant == 1) + target_ant = AUX_ANT; + + if (pdm_sat_table->ant_num > 1) { + /* [ update RX ant ]*/ + odm_update_rx_idle_ant(p_dm_odm, (u8)target_ant); + + /* [ update TX ant ]*/ + odm_update_tx_ant(p_dm_odm, (u8)target_ant, (p_dm_fat_table->train_idx)); + } + + /*set beam in each antenna*/ + phydm_update_rx_idle_beam(p_dm_odm); + + odm_ant_div_on_off(p_dm_odm, ANTDIV_ON); + p_dm_fat_table->fat_state = FAT_PREPARE_STATE; + return; + + } + /* [TRAINING STATE] */ + else if (p_dm_fat_table->fat_state == FAT_TRAINING_STATE) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ 2. In Training state]\n")); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("fat_beam_n = (( %d )), pre_fat_beam_n = (( %d ))\n", + pdm_sat_table->fast_training_beam_num, pdm_sat_table->pre_fast_training_beam_num)); + + if (pdm_sat_table->fast_training_beam_num > pdm_sat_table->pre_fast_training_beam_num) + + pdm_sat_table->force_update_beam_en = 0; + + else { + + pdm_sat_table->force_update_beam_en = 1; + + pdm_sat_table->pkt_counter = 0; + beam_tmp = pdm_sat_table->fast_training_beam_num; + if (pdm_sat_table->fast_training_beam_num >= (pdm_sat_table->beam_patten_num_each_ant - 1)) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Timeout Update] Beam_num (( %d )) -> (( decision ))\n", pdm_sat_table->fast_training_beam_num)); + p_dm_fat_table->fat_state = FAT_DECISION_STATE; + odm_fast_ant_training_hl_smart_antenna_type1(p_dm_odm); + + } else { + pdm_sat_table->fast_training_beam_num++; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Timeout Update] Beam_num (( %d )) -> (( %d ))\n", beam_tmp, pdm_sat_table->fast_training_beam_num)); + phydm_set_all_ant_same_beam_num(p_dm_odm); + p_dm_fat_table->fat_state = FAT_TRAINING_STATE; + + } + } + pdm_sat_table->pre_fast_training_beam_num = pdm_sat_table->fast_training_beam_num; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[prepare state] Update Pre_Beam =(( %d ))\n", pdm_sat_table->pre_fast_training_beam_num)); + } + /* [Prepare state] */ + /*=======================================================================================*/ + else if (p_dm_fat_table->fat_state == FAT_PREPARE_STATE) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("\n\n[ 1. In Prepare state]\n")); + + if (p_dm_odm->pre_traffic_load == (p_dm_odm->traffic_load)) { + if (pdm_sat_table->decision_holding_period != 0) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Holding_period = (( %d )), return!!!\n", pdm_sat_table->decision_holding_period)); + pdm_sat_table->decision_holding_period--; + return; + } + } + + + /* Set training packet number*/ + if (pdm_sat_table->fix_training_num_en == 0) { + + switch (p_dm_odm->traffic_load) { + + case TRAFFIC_HIGH: + pdm_sat_table->per_beam_training_pkt_num = 8; + pdm_sat_table->decision_holding_period = 2; + break; + case TRAFFIC_MID: + pdm_sat_table->per_beam_training_pkt_num = 6; + pdm_sat_table->decision_holding_period = 3; + break; + case TRAFFIC_LOW: + pdm_sat_table->per_beam_training_pkt_num = 3; /*ping 60000*/ + pdm_sat_table->decision_holding_period = 4; + break; + case TRAFFIC_ULTRA_LOW: + pdm_sat_table->per_beam_training_pkt_num = 1; + pdm_sat_table->decision_holding_period = 6; + break; + default: + break; + } + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Fix_training_en = (( %d )), training_pkt_num_base = (( %d )), holding_period = ((%d))\n", + pdm_sat_table->fix_training_num_en, pdm_sat_table->per_beam_training_pkt_num, pdm_sat_table->decision_holding_period)); + + +#ifdef CONFIG_FAT_PATCH + break_counter = 0; + for (i = (pdm_sat_table->first_train_ant - 1); i < pdm_sat_table->ant_num_total; i++) { + for (j = 0; j < (pdm_sat_table->beam_patten_num_each_ant); j++) { + + per_beam_rssi_diff_tmp = pdm_sat_table->beam_train_rssi_diff[i][j]; + training_pkt_num_offset = per_beam_rssi_diff_tmp; + + if ((pdm_sat_table->per_beam_training_pkt_num) > training_pkt_num_offset) + pdm_sat_table->beam_train_cnt[i][j] = pdm_sat_table->per_beam_training_pkt_num - training_pkt_num_offset; + else + pdm_sat_table->beam_train_cnt[i][j] = 1; + + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ant[%d]: Beam_num-(( %d )) training_pkt_num = ((%d))\n", + i, j, pdm_sat_table->beam_train_cnt[i][j])); + } + break_counter++; + if (break_counter >= (pdm_sat_table->ant_num)) + break; + } + + + phydm_fast_training_enable(p_dm_odm, FAT_OFF); + pdm_sat_table->pre_beacon_counter = pdm_sat_table->beacon_counter; + pdm_sat_table->update_beam_idx = 0; + + if (*p_dm_odm->p_band_type == ODM_BAND_5G) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Set 5G ant\n")); + /*used_ant = (pdm_sat_table->first_train_ant == MAIN_ANT) ? AUX_ANT : MAIN_ANT;*/ + used_ant = pdm_sat_table->first_train_ant; + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Set 2.4G ant\n")); + used_ant = pdm_sat_table->first_train_ant; + } + + odm_update_rx_idle_ant(p_dm_odm, (u8)used_ant); + +#else + /* Set training MAC addr. of target */ + odm_set_next_mac_addr_target(p_dm_odm); + phydm_fast_training_enable(p_dm_odm, FAT_ON); +#endif + + odm_ant_div_on_off(p_dm_odm, ANTDIV_OFF); + pdm_sat_table->pkt_counter = 0; + pdm_sat_table->fast_training_beam_num = 0; + phydm_set_all_ant_same_beam_num(p_dm_odm); + pdm_sat_table->pre_fast_training_beam_num = pdm_sat_table->fast_training_beam_num; + p_dm_fat_table->fat_state = FAT_TRAINING_STATE; + } + +} + +#endif /*#ifdef CONFIG_HL_SMART_ANTENNA_TYPE1*/ + +void +odm_ant_div_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + struct _sw_antenna_switch_ *p_dm_swat_table = &p_dm_odm->dm_swat_table; + + + if (!(p_dm_odm->support_ability & ODM_BB_ANT_DIV)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Return!!!] Not Support Antenna Diversity Function\n")); + return; + } + /* --- */ + + /* 2 [--General---] */ + p_dm_odm->antdiv_period = 0; + + p_dm_fat_table->is_become_linked = false; + p_dm_fat_table->ant_div_on_off = 0xff; + + /* 3 - AP - */ + + /* 2 [---Set MAIN_ANT as default antenna if Auto-ant enable---] */ + odm_ant_div_on_off(p_dm_odm, ANTDIV_OFF); + + p_dm_odm->ant_type = ODM_AUTO_ANT; + + p_dm_fat_table->rx_idle_ant = 0xff; /*to make RX-idle-antenna will be updated absolutly*/ + odm_update_rx_idle_ant(p_dm_odm, MAIN_ANT); + phydm_keep_rx_ack_ant_by_tx_ant_time(p_dm_odm, 0); /* Timming issue: keep Rx ant after tx for ACK ( 5 x 3.2 mu = 16mu sec)*/ + + /* 2 [---Set TX Antenna---] */ + if (p_dm_fat_table->p_force_tx_ant_by_desc == NULL) { + p_dm_fat_table->force_tx_ant_by_desc = 0; + p_dm_fat_table->p_force_tx_ant_by_desc = &(p_dm_fat_table->force_tx_ant_by_desc); + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("p_force_tx_ant_by_desc = %d\n", *p_dm_fat_table->p_force_tx_ant_by_desc)); + + if (*(p_dm_fat_table->p_force_tx_ant_by_desc) == true) + odm_tx_by_tx_desc_or_reg(p_dm_odm, TX_BY_DESC); + else + odm_tx_by_tx_desc_or_reg(p_dm_odm, TX_BY_REG); + + + /* 2 [--88E---] */ + if (p_dm_odm->support_ic_type == ODM_RTL8188E) { +#if (RTL8188E_SUPPORT == 1) + /* p_dm_odm->ant_div_type = CGCS_RX_HW_ANTDIV; */ + /* p_dm_odm->ant_div_type = CG_TRX_HW_ANTDIV; */ + /* p_dm_odm->ant_div_type = CG_TRX_SMART_ANTDIV; */ + + if ((p_dm_odm->ant_div_type != CGCS_RX_HW_ANTDIV) && (p_dm_odm->ant_div_type != CG_TRX_HW_ANTDIV) && (p_dm_odm->ant_div_type != CG_TRX_SMART_ANTDIV)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Return!!!] 88E Not Supprrt This AntDiv type\n")); + p_dm_odm->support_ability &= ~(ODM_BB_ANT_DIV); + return; + } + + if (p_dm_odm->ant_div_type == CGCS_RX_HW_ANTDIV) + odm_rx_hw_ant_div_init_88e(p_dm_odm); + else if (p_dm_odm->ant_div_type == CG_TRX_HW_ANTDIV) + odm_trx_hw_ant_div_init_88e(p_dm_odm); +#if (defined(CONFIG_5G_CG_SMART_ANT_DIVERSITY)) || (defined(CONFIG_2G_CG_SMART_ANT_DIVERSITY)) + else if (p_dm_odm->ant_div_type == CG_TRX_SMART_ANTDIV) + odm_smart_hw_ant_div_init_88e(p_dm_odm); +#endif +#endif + } + + /* 2 [--92E---] */ +#if (RTL8192E_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8192E) { + /* p_dm_odm->ant_div_type = CGCS_RX_HW_ANTDIV; */ + /* p_dm_odm->ant_div_type = CG_TRX_HW_ANTDIV; */ + /* p_dm_odm->ant_div_type = CG_TRX_SMART_ANTDIV; */ + + if ((p_dm_odm->ant_div_type != CGCS_RX_HW_ANTDIV) && (p_dm_odm->ant_div_type != CG_TRX_HW_ANTDIV) && (p_dm_odm->ant_div_type != CG_TRX_SMART_ANTDIV)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Return!!!] 8192E Not Supprrt This AntDiv type\n")); + p_dm_odm->support_ability &= ~(ODM_BB_ANT_DIV); + return; + } + + if (p_dm_odm->ant_div_type == CGCS_RX_HW_ANTDIV) + odm_rx_hw_ant_div_init_92e(p_dm_odm); + else if (p_dm_odm->ant_div_type == CG_TRX_HW_ANTDIV) + odm_trx_hw_ant_div_init_92e(p_dm_odm); +#if (defined(CONFIG_5G_CG_SMART_ANT_DIVERSITY)) || (defined(CONFIG_2G_CG_SMART_ANT_DIVERSITY)) + else if (p_dm_odm->ant_div_type == CG_TRX_SMART_ANTDIV) + odm_smart_hw_ant_div_init_92e(p_dm_odm); +#endif + + } +#endif + + /* 2 [--8723B---] */ +#if (RTL8723B_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8723B) { + p_dm_odm->ant_div_type = S0S1_SW_ANTDIV; + /* p_dm_odm->ant_div_type = CG_TRX_HW_ANTDIV; */ + + if (p_dm_odm->ant_div_type != S0S1_SW_ANTDIV && p_dm_odm->ant_div_type != CG_TRX_HW_ANTDIV) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Return!!!] 8723B Not Supprrt This AntDiv type\n")); + p_dm_odm->support_ability &= ~(ODM_BB_ANT_DIV); + return; + } + + if (p_dm_odm->ant_div_type == S0S1_SW_ANTDIV) + odm_s0s1_sw_ant_div_init_8723b(p_dm_odm); + else if (p_dm_odm->ant_div_type == CG_TRX_HW_ANTDIV) + odm_trx_hw_ant_div_init_8723b(p_dm_odm); + } +#endif + /*2 [--8723D---]*/ +#if (RTL8723D_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8723D) { + if (p_dm_fat_table->p_default_s0_s1 == NULL) { + p_dm_fat_table->default_s0_s1 = 1; + p_dm_fat_table->p_default_s0_s1 = &(p_dm_fat_table->default_s0_s1); + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("default_s0_s1 = %d\n", *p_dm_fat_table->p_default_s0_s1)); + + if (*(p_dm_fat_table->p_default_s0_s1) == true) + odm_update_rx_idle_ant(p_dm_odm, MAIN_ANT); + else + odm_update_rx_idle_ant(p_dm_odm, AUX_ANT); + + if (p_dm_odm->ant_div_type == S0S1_TRX_HW_ANTDIV) + odm_trx_hw_ant_div_init_8723d(p_dm_odm); + else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Return!!!] 8723D Not Supprrt This AntDiv type\n")); + p_dm_odm->support_ability &= ~(ODM_BB_ANT_DIV); + return; + } + + } +#endif + /* 2 [--8811A 8821A---] */ +#if (RTL8821A_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8821) { +#ifdef CONFIG_HL_SMART_ANTENNA_TYPE1 + p_dm_odm->ant_div_type = HL_SW_SMART_ANT_TYPE1; + + if (p_dm_odm->ant_div_type == HL_SW_SMART_ANT_TYPE1) { + + odm_trx_hw_ant_div_init_8821a(p_dm_odm); + phydm_hl_smart_ant_type1_init_8821a(p_dm_odm); + } else +#endif + { + /*p_dm_odm->ant_div_type = CG_TRX_HW_ANTDIV;*/ + p_dm_odm->ant_div_type = S0S1_SW_ANTDIV; + + if (p_dm_odm->ant_div_type != CG_TRX_HW_ANTDIV && p_dm_odm->ant_div_type != S0S1_SW_ANTDIV) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Return!!!] 8821A & 8811A Not Supprrt This AntDiv type\n")); + p_dm_odm->support_ability &= ~(ODM_BB_ANT_DIV); + return; + } + if (p_dm_odm->ant_div_type == CG_TRX_HW_ANTDIV) + odm_trx_hw_ant_div_init_8821a(p_dm_odm); + else if (p_dm_odm->ant_div_type == S0S1_SW_ANTDIV) + odm_s0s1_sw_ant_div_init_8821a(p_dm_odm); + } + } +#endif + + /* 2 [--8821C---] */ +#if (RTL8821C_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8821C) { + p_dm_odm->ant_div_type = CG_TRX_HW_ANTDIV; + if (p_dm_odm->ant_div_type != CG_TRX_HW_ANTDIV) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Return!!!] 8821C Not Supprrt This AntDiv type\n")); + p_dm_odm->support_ability &= ~(ODM_BB_ANT_DIV); + return; + } + odm_trx_hw_ant_div_init_8821c(p_dm_odm); + } +#endif + + /* 2 [--8881A---] */ +#if (RTL8881A_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8881A) { + /* p_dm_odm->ant_div_type = CGCS_RX_HW_ANTDIV; */ + /* p_dm_odm->ant_div_type = CG_TRX_HW_ANTDIV; */ + + if (p_dm_odm->ant_div_type == CG_TRX_HW_ANTDIV) { + + odm_trx_hw_ant_div_init_8881a(p_dm_odm); + /**/ + } else { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Return!!!] 8881A Not Supprrt This AntDiv type\n")); + p_dm_odm->support_ability &= ~(ODM_BB_ANT_DIV); + return; + } + + odm_trx_hw_ant_div_init_8881a(p_dm_odm); + } +#endif + + /* 2 [--8812---] */ +#if (RTL8812A_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8812) { + /* p_dm_odm->ant_div_type = CG_TRX_HW_ANTDIV; */ + + if (p_dm_odm->ant_div_type != CG_TRX_HW_ANTDIV) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Return!!!] 8812A Not Supprrt This AntDiv type\n")); + p_dm_odm->support_ability &= ~(ODM_BB_ANT_DIV); + return; + } + odm_trx_hw_ant_div_init_8812a(p_dm_odm); + } +#endif + + /*[--8188F---]*/ +#if (RTL8188F_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8188F) { + + p_dm_odm->ant_div_type = S0S1_SW_ANTDIV; + odm_s0s1_sw_ant_div_init_8188f(p_dm_odm); + } +#endif + +} + +void +odm_ant_div( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTER *p_adapter = p_dm_odm->adapter; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; +#ifdef CONFIG_HL_SMART_ANTENNA_TYPE1 + struct _SMART_ANTENNA_TRAINNING_ *pdm_sat_table = &(p_dm_odm->dm_sat_table); +#endif + + if (*p_dm_odm->p_band_type == ODM_BAND_5G) { + if (p_dm_fat_table->idx_ant_div_counter_5g < p_dm_odm->antdiv_period) { + p_dm_fat_table->idx_ant_div_counter_5g++; + return; + } else + p_dm_fat_table->idx_ant_div_counter_5g = 0; + } else if (*p_dm_odm->p_band_type == ODM_BAND_2_4G) { + if (p_dm_fat_table->idx_ant_div_counter_2g < p_dm_odm->antdiv_period) { + p_dm_fat_table->idx_ant_div_counter_2g++; + return; + } else + p_dm_fat_table->idx_ant_div_counter_2g = 0; + } + + /* ---------- */ + if (!(p_dm_odm->support_ability & ODM_BB_ANT_DIV)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[Return!!!] Not Support Antenna Diversity Function\n")); + return; + } + + /* ---------- */ + + if (p_dm_odm->antdiv_select == 1) + p_dm_odm->ant_type = ODM_FIX_MAIN_ANT; + else if (p_dm_odm->antdiv_select == 2) + p_dm_odm->ant_type = ODM_FIX_AUX_ANT; + else /* if (p_dm_odm->antdiv_select==0) */ + p_dm_odm->ant_type = ODM_AUTO_ANT; + + if (p_dm_odm->ant_type != ODM_AUTO_ANT) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Fix Antenna at (( %s ))\n", (p_dm_odm->ant_type == ODM_FIX_MAIN_ANT) ? "MAIN" : "AUX")); + + if (p_dm_odm->ant_type != p_dm_odm->pre_ant_type) { + odm_ant_div_on_off(p_dm_odm, ANTDIV_OFF); + odm_tx_by_tx_desc_or_reg(p_dm_odm, TX_BY_REG); + + if (p_dm_odm->ant_type == ODM_FIX_MAIN_ANT) + odm_update_rx_idle_ant(p_dm_odm, MAIN_ANT); + else if (p_dm_odm->ant_type == ODM_FIX_AUX_ANT) + odm_update_rx_idle_ant(p_dm_odm, AUX_ANT); + } + p_dm_odm->pre_ant_type = p_dm_odm->ant_type; + return; + } else { + if (p_dm_odm->ant_type != p_dm_odm->pre_ant_type) { + odm_ant_div_on_off(p_dm_odm, ANTDIV_ON); + odm_tx_by_tx_desc_or_reg(p_dm_odm, TX_BY_DESC); + } + p_dm_odm->pre_ant_type = p_dm_odm->ant_type; + } + + + /* 3 ----------------------------------------------------------------------------------------------------------- */ + /* 2 [--88E---] */ + if (p_dm_odm->support_ic_type == ODM_RTL8188E) { +#if (RTL8188E_SUPPORT == 1) + if (p_dm_odm->ant_div_type == CG_TRX_HW_ANTDIV || p_dm_odm->ant_div_type == CGCS_RX_HW_ANTDIV) + odm_hw_ant_div(p_dm_odm); + +#if (defined(CONFIG_5G_CG_SMART_ANT_DIVERSITY)) || (defined(CONFIG_2G_CG_SMART_ANT_DIVERSITY)) + else if (p_dm_odm->ant_div_type == CG_TRX_SMART_ANTDIV) + odm_fast_ant_training(p_dm_odm); +#endif + +#endif + + } + /* 2 [--92E---] */ +#if (RTL8192E_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8192E) { + if (p_dm_odm->ant_div_type == CGCS_RX_HW_ANTDIV || p_dm_odm->ant_div_type == CG_TRX_HW_ANTDIV) + odm_hw_ant_div(p_dm_odm); + +#if (defined(CONFIG_5G_CG_SMART_ANT_DIVERSITY)) || (defined(CONFIG_2G_CG_SMART_ANT_DIVERSITY)) + else if (p_dm_odm->ant_div_type == CG_TRX_SMART_ANTDIV) + odm_fast_ant_training(p_dm_odm); +#endif + + } +#endif + +#if (RTL8723B_SUPPORT == 1) + /* 2 [--8723B---] */ + else if (p_dm_odm->support_ic_type == ODM_RTL8723B) { + if (phydm_is_bt_enable_8723b(p_dm_odm)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[BT is enable!!!]\n")); + if (p_dm_fat_table->is_become_linked == true) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Set REG 948[9:6]=0x0\n")); + if (p_dm_odm->support_ic_type == ODM_RTL8723B) + odm_set_bb_reg(p_dm_odm, 0x948, BIT(9) | BIT(8) | BIT(7) | BIT(6), 0x0); + + p_dm_fat_table->is_become_linked = false; + } + } else { + if (p_dm_odm->ant_div_type == S0S1_SW_ANTDIV) { + +#ifdef CONFIG_S0S1_SW_ANTENNA_DIVERSITY + odm_s0s1_sw_ant_div(p_dm_odm, SWAW_STEP_PEEK); +#endif + } else if (p_dm_odm->ant_div_type == CG_TRX_HW_ANTDIV) + odm_hw_ant_div(p_dm_odm); + } + } +#endif + /*8723D*/ +#if (RTL8723D_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8723D) { + + odm_hw_ant_div(p_dm_odm); + /**/ + } +#endif + + /* 2 [--8821A---] */ +#if (RTL8821A_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8821) { +#ifdef CONFIG_HL_SMART_ANTENNA_TYPE1 + if (p_dm_odm->ant_div_type == HL_SW_SMART_ANT_TYPE1) { + + if (pdm_sat_table->fix_beam_pattern_en != 0) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, (" [ SmartAnt ] Fix SmartAnt Pattern = 0x%x\n", pdm_sat_table->fix_beam_pattern_codeword)); + /*return;*/ + } else { + /*ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[ SmartAnt ] ant_div_type = HL_SW_SMART_ANT_TYPE1\n"));*/ + odm_fast_ant_training_hl_smart_antenna_type1(p_dm_odm); + } + + } else +#endif + { + + if (!p_dm_odm->is_bt_enabled) { /*BT disabled*/ + if (p_dm_odm->ant_div_type == S0S1_SW_ANTDIV) { + p_dm_odm->ant_div_type = CG_TRX_HW_ANTDIV; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, (" [S0S1_SW_ANTDIV] -> [CG_TRX_HW_ANTDIV]\n")); + /*odm_set_bb_reg(p_dm_odm, 0x8D4, BIT24, 1); */ + if (p_dm_fat_table->is_become_linked == true) + odm_ant_div_on_off(p_dm_odm, ANTDIV_ON); + } + + } else { /*BT enabled*/ + + if (p_dm_odm->ant_div_type == CG_TRX_HW_ANTDIV) { + p_dm_odm->ant_div_type = S0S1_SW_ANTDIV; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, (" [CG_TRX_HW_ANTDIV] -> [S0S1_SW_ANTDIV]\n")); + /*odm_set_bb_reg(p_dm_odm, 0x8D4, BIT24, 0);*/ + odm_ant_div_on_off(p_dm_odm, ANTDIV_OFF); + } + } + + if (p_dm_odm->ant_div_type == S0S1_SW_ANTDIV) { + +#ifdef CONFIG_S0S1_SW_ANTENNA_DIVERSITY + odm_s0s1_sw_ant_div(p_dm_odm, SWAW_STEP_PEEK); +#endif + } else if (p_dm_odm->ant_div_type == CG_TRX_HW_ANTDIV) + odm_hw_ant_div(p_dm_odm); + } + } +#endif + + /* 2 [--8821C---] */ +#if (RTL8821C_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8821C) + odm_hw_ant_div(p_dm_odm); +#endif + + /* 2 [--8881A---] */ +#if (RTL8881A_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8881A) + odm_hw_ant_div(p_dm_odm); +#endif + + /* 2 [--8812A---] */ +#if (RTL8812A_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8812) + odm_hw_ant_div(p_dm_odm); +#endif + +#if (RTL8188F_SUPPORT == 1) + /* [--8188F---]*/ + else if (p_dm_odm->support_ic_type == ODM_RTL8188F) { + +#ifdef CONFIG_S0S1_SW_ANTENNA_DIVERSITY + odm_s0s1_sw_ant_div(p_dm_odm, SWAW_STEP_PEEK); +#endif + } +#endif + + /* [--8822B---]*/ +#if (RTL8821A_SUPPORT == 1) + else if (p_dm_odm->support_ic_type == ODM_RTL8822B) { +#ifdef CONFIG_HL_SMART_ANTENNA_TYPE1 + if (p_dm_odm->ant_div_type == HL_SW_SMART_ANT_TYPE1) { + + if (pdm_sat_table->fix_beam_pattern_en != 0) + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, (" [ SmartAnt ] Fix SmartAnt Pattern = 0x%x\n", pdm_sat_table->fix_beam_pattern_codeword)); + else + odm_fast_ant_training_hl_smart_antenna_type1(p_dm_odm); + } +#endif + } +#endif + + +} + + +void +odm_antsel_statistics( + void *p_dm_void, + u8 antsel_tr_mux, + u32 mac_id, + u32 utility, + u8 method, + u8 is_cck_rate + +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + + if (method == RSSI_METHOD) { + + if (is_cck_rate) { + if (antsel_tr_mux == ANT1_2G) { + if (p_dm_fat_table->main_ant_sum_cck[mac_id] > 65435) /*to prevent u16 overflow, max(RSSI)=100, 65435+100 = 65535 (u16)*/ + return; + + p_dm_fat_table->main_ant_sum_cck[mac_id] += (u16)utility; + p_dm_fat_table->main_ant_cnt_cck[mac_id]++; + } else { + if (p_dm_fat_table->aux_ant_sum_cck[mac_id] > 65435) + return; + + p_dm_fat_table->aux_ant_sum_cck[mac_id] += (u16)utility; + p_dm_fat_table->aux_ant_cnt_cck[mac_id]++; + } + + } else { /*ofdm rate*/ + + if (antsel_tr_mux == ANT1_2G) { + if (p_dm_fat_table->main_ant_sum[mac_id] > 65435) + return; + + p_dm_fat_table->main_ant_sum[mac_id] += (u16)utility; + p_dm_fat_table->main_ant_cnt[mac_id]++; + } else { + if (p_dm_fat_table->aux_ant_sum[mac_id] > 65435) + return; + + p_dm_fat_table->aux_ant_sum[mac_id] += (u16)utility; + p_dm_fat_table->aux_ant_cnt[mac_id]++; + } + } + } +#ifdef ODM_EVM_ENHANCE_ANTDIV + else if (method == EVM_METHOD) { + if (antsel_tr_mux == ANT1_2G) { + p_dm_fat_table->main_ant_evm_sum[mac_id] += (utility << 5); + p_dm_fat_table->main_ant_evm_cnt[mac_id]++; + } else { + p_dm_fat_table->aux_ant_evm_sum[mac_id] += (utility << 5); + p_dm_fat_table->aux_ant_evm_cnt[mac_id]++; + } + } else if (method == CRC32_METHOD) { + if (utility == 0) + p_dm_fat_table->crc32_fail_cnt++; + else + p_dm_fat_table->crc32_ok_cnt += utility; + } +#endif +} + + +void +odm_process_rssi_for_ant_div( + void *p_dm_void, + void *p_phy_info_void, + void *p_pkt_info_void + /* struct _odm_phy_status_info_* p_phy_info, */ + /* struct _odm_per_pkt_info_* p_pktinfo */ +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _odm_phy_status_info_ *p_phy_info = (struct _odm_phy_status_info_ *)p_phy_info_void; + struct _odm_per_pkt_info_ *p_pktinfo = (struct _odm_per_pkt_info_ *)p_pkt_info_void; + u8 is_cck_rate = 0, cck_max_rate = ODM_RATE11M; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; +#ifdef CONFIG_HL_SMART_ANTENNA_TYPE1 + struct _SMART_ANTENNA_TRAINNING_ *pdm_sat_table = &(p_dm_odm->dm_sat_table); + u32 beam_tmp; + u8 next_ant; + u8 train_pkt_number; +#endif + + u8 rx_power_ant0, rx_power_ant1; + u8 rx_evm_ant0, rx_evm_ant1; + + cck_max_rate = ODM_RATE11M; + is_cck_rate = (p_pktinfo->data_rate <= cck_max_rate) ? true : false; + + if ((p_dm_odm->support_ic_type & ODM_IC_2SS) && (p_pktinfo->data_rate > cck_max_rate)) { + rx_power_ant0 = p_phy_info->rx_mimo_signal_strength[0]; + rx_power_ant1 = p_phy_info->rx_mimo_signal_strength[1]; + + rx_evm_ant0 = p_phy_info->rx_mimo_signal_quality[0]; + rx_evm_ant1 = p_phy_info->rx_mimo_signal_quality[1]; + } else + rx_power_ant0 = p_phy_info->rx_pwdb_all; + +#ifdef CONFIG_HL_SMART_ANTENNA_TYPE1 +#ifdef CONFIG_FAT_PATCH + if ((p_dm_odm->ant_div_type == HL_SW_SMART_ANT_TYPE1) && (p_dm_fat_table->fat_state == FAT_TRAINING_STATE)) { + + /*[Beacon]*/ + if (p_pktinfo->is_packet_beacon) { + + pdm_sat_table->beacon_counter++; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("MatchBSSID_beacon_counter = ((%d))\n", pdm_sat_table->beacon_counter)); + + if (pdm_sat_table->beacon_counter >= pdm_sat_table->pre_beacon_counter + 2) { + + if (pdm_sat_table->ant_num > 1) { + next_ant = (p_dm_fat_table->rx_idle_ant == MAIN_ANT) ? AUX_ANT : MAIN_ANT; + odm_update_rx_idle_ant(p_dm_odm, next_ant); + } + + pdm_sat_table->update_beam_idx++; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("pre_beacon_counter = ((%d)), pkt_counter = ((%d)), update_beam_idx = ((%d))\n", + pdm_sat_table->pre_beacon_counter, pdm_sat_table->pkt_counter, pdm_sat_table->update_beam_idx)); + + pdm_sat_table->pre_beacon_counter = pdm_sat_table->beacon_counter; + pdm_sat_table->pkt_counter = 0; + } + } + /*[data]*/ + else if (p_pktinfo->is_packet_to_self) { + + if (pdm_sat_table->pkt_skip_statistic_en == 0) { + /* + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("StaID[%d]: antsel_pathA = ((%d)), hw_antsw_occur = ((%d)), Beam_num = ((%d)), RSSI = ((%d))\n", + p_pktinfo->station_id, p_dm_fat_table->antsel_rx_keep_0, p_dm_fat_table->hw_antsw_occur, pdm_sat_table->fast_training_beam_num, rx_power_ant0)); + */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ID[%d][pkt_cnt = %d]: {ANT, Beam} = {%d, %d}, RSSI = ((%d))\n", + p_pktinfo->station_id, pdm_sat_table->pkt_counter, p_dm_fat_table->antsel_rx_keep_0, pdm_sat_table->fast_training_beam_num, rx_power_ant0)); + + pdm_sat_table->pkt_rssi_sum[p_dm_fat_table->antsel_rx_keep_0][pdm_sat_table->fast_training_beam_num] += rx_power_ant0; + pdm_sat_table->pkt_rssi_cnt[p_dm_fat_table->antsel_rx_keep_0][pdm_sat_table->fast_training_beam_num]++; + pdm_sat_table->pkt_counter++; + + train_pkt_number = pdm_sat_table->beam_train_cnt[p_dm_fat_table->rx_idle_ant - 1][pdm_sat_table->fast_training_beam_num]; + + /*Swich Antenna erery N pkts*/ + if (pdm_sat_table->pkt_counter == train_pkt_number) { + + if (pdm_sat_table->ant_num > 1) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("packet enugh ((%d ))pkts ---> Switch antenna\n", train_pkt_number)); + next_ant = (p_dm_fat_table->rx_idle_ant == MAIN_ANT) ? AUX_ANT : MAIN_ANT; + odm_update_rx_idle_ant(p_dm_odm, next_ant); + } + + pdm_sat_table->update_beam_idx++; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("pre_beacon_counter = ((%d)), update_beam_idx_counter = ((%d))\n", + pdm_sat_table->pre_beacon_counter, pdm_sat_table->update_beam_idx)); + + pdm_sat_table->pre_beacon_counter = pdm_sat_table->beacon_counter; + pdm_sat_table->pkt_counter = 0; + } + } + } + + /*Swich Beam after switch "pdm_sat_table->ant_num" antennas*/ + if (pdm_sat_table->update_beam_idx == pdm_sat_table->ant_num) { + + pdm_sat_table->update_beam_idx = 0; + pdm_sat_table->pkt_counter = 0; + beam_tmp = pdm_sat_table->fast_training_beam_num; + + if (pdm_sat_table->fast_training_beam_num >= (pdm_sat_table->beam_patten_num_each_ant - 1)) { + + p_dm_fat_table->fat_state = FAT_DECISION_STATE; + +#if DEV_BUS_TYPE == RT_PCI_INTERFACE + odm_fast_ant_training_hl_smart_antenna_type1(p_dm_odm); +#else + odm_schedule_work_item(&pdm_sat_table->hl_smart_antenna_decision_workitem); +#endif + + + } else { + pdm_sat_table->fast_training_beam_num++; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Update Beam_num (( %d )) -> (( %d ))\n", beam_tmp, pdm_sat_table->fast_training_beam_num)); + phydm_set_all_ant_same_beam_num(p_dm_odm); + + p_dm_fat_table->fat_state = FAT_TRAINING_STATE; + } + } + + } +#else + + if (p_dm_odm->ant_div_type == HL_SW_SMART_ANT_TYPE1) { + if ((p_dm_odm->support_ic_type & ODM_HL_SMART_ANT_TYPE1_SUPPORT) && + (p_pktinfo->is_packet_to_self) && + (p_dm_fat_table->fat_state == FAT_TRAINING_STATE) + ) { + + if (pdm_sat_table->pkt_skip_statistic_en == 0) { + /* + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("StaID[%d]: antsel_pathA = ((%d)), hw_antsw_occur = ((%d)), Beam_num = ((%d)), RSSI = ((%d))\n", + p_pktinfo->station_id, p_dm_fat_table->antsel_rx_keep_0, p_dm_fat_table->hw_antsw_occur, pdm_sat_table->fast_training_beam_num, rx_power_ant0)); + */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("StaID[%d]: antsel_pathA = ((%d)), is_packet_to_self = ((%d)), Beam_num = ((%d)), RSSI = ((%d))\n", + p_pktinfo->station_id, p_dm_fat_table->antsel_rx_keep_0, p_pktinfo->is_packet_to_self, pdm_sat_table->fast_training_beam_num, rx_power_ant0)); + + + pdm_sat_table->pkt_rssi_sum[p_dm_fat_table->antsel_rx_keep_0][pdm_sat_table->fast_training_beam_num] += rx_power_ant0; + pdm_sat_table->pkt_rssi_cnt[p_dm_fat_table->antsel_rx_keep_0][pdm_sat_table->fast_training_beam_num]++; + pdm_sat_table->pkt_counter++; + + /*swich beam every N pkt*/ + if ((pdm_sat_table->pkt_counter) >= (pdm_sat_table->per_beam_training_pkt_num)) { + + pdm_sat_table->pkt_counter = 0; + beam_tmp = pdm_sat_table->fast_training_beam_num; + + if (pdm_sat_table->fast_training_beam_num >= (pdm_sat_table->beam_patten_num_each_ant - 1)) { + + p_dm_fat_table->fat_state = FAT_DECISION_STATE; + +#if DEV_BUS_TYPE == RT_PCI_INTERFACE + odm_fast_ant_training_hl_smart_antenna_type1(p_dm_odm); +#else + odm_schedule_work_item(&pdm_sat_table->hl_smart_antenna_decision_workitem); +#endif + + + } else { + pdm_sat_table->fast_training_beam_num++; + phydm_set_all_ant_same_beam_num(p_dm_odm); + + p_dm_fat_table->fat_state = FAT_TRAINING_STATE; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Update Beam_num (( %d )) -> (( %d ))\n", beam_tmp, pdm_sat_table->fast_training_beam_num)); + } + } + } + } + } +#endif + else +#endif + if (p_dm_odm->ant_div_type == CG_TRX_SMART_ANTDIV) { + if ((p_dm_odm->support_ic_type & ODM_SMART_ANT_SUPPORT) && (p_pktinfo->is_packet_to_self) && (p_dm_fat_table->fat_state == FAT_TRAINING_STATE)) { /* (p_pktinfo->is_packet_match_bssid && (!p_pktinfo->is_packet_beacon)) */ + u8 antsel_tr_mux; + antsel_tr_mux = (p_dm_fat_table->antsel_rx_keep_2 << 2) | (p_dm_fat_table->antsel_rx_keep_1 << 1) | p_dm_fat_table->antsel_rx_keep_0; + p_dm_fat_table->ant_sum_rssi[antsel_tr_mux] += rx_power_ant0; + p_dm_fat_table->ant_rssi_cnt[antsel_tr_mux]++; + } + } else { /* ant_div_type != CG_TRX_SMART_ANTDIV */ + if ((p_dm_odm->support_ic_type & ODM_ANTDIV_SUPPORT) && (p_pktinfo->is_packet_to_self || p_dm_fat_table->use_ctrl_frame_antdiv)) { + + if (p_dm_odm->ant_div_type == S0S1_SW_ANTDIV) { + + if (is_cck_rate) + p_dm_fat_table->antsel_rx_keep_0 = (p_dm_fat_table->rx_idle_ant == MAIN_ANT) ? ANT1_2G : ANT2_2G; + + odm_antsel_statistics(p_dm_odm, p_dm_fat_table->antsel_rx_keep_0, p_pktinfo->station_id, rx_power_ant0, RSSI_METHOD, is_cck_rate); + + } else { + + odm_antsel_statistics(p_dm_odm, p_dm_fat_table->antsel_rx_keep_0, p_pktinfo->station_id, rx_power_ant0, RSSI_METHOD, is_cck_rate); + +#ifdef ODM_EVM_ENHANCE_ANTDIV + if (p_dm_odm->support_ic_type == ODM_RTL8192E) { + if (!is_cck_rate) + odm_antsel_statistics(p_dm_odm, p_dm_fat_table->antsel_rx_keep_0, p_pktinfo->station_id, rx_evm_ant0, EVM_METHOD, is_cck_rate); + + } +#endif + } + } + } + /* ODM_RT_TRACE(p_dm_odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD,("is_cck_rate=%d, PWDB_ALL=%d\n",is_cck_rate, p_phy_info->rx_pwdb_all)); */ + /* ODM_RT_TRACE(p_dm_odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD,("antsel_tr_mux=3'b%d%d%d\n",p_dm_fat_table->antsel_rx_keep_2, p_dm_fat_table->antsel_rx_keep_1, p_dm_fat_table->antsel_rx_keep_0)); */ +} + +void +odm_set_tx_ant_by_tx_info( + void *p_dm_void, + u8 *p_desc, + u8 mac_id + +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + + if (!(p_dm_odm->support_ability & ODM_BB_ANT_DIV)) + return; + + if (p_dm_odm->ant_div_type == CGCS_RX_HW_ANTDIV) + return; + + + if (p_dm_odm->support_ic_type == ODM_RTL8723B) { +#if (RTL8723B_SUPPORT == 1) + SET_TX_DESC_ANTSEL_A_8723B(p_desc, p_dm_fat_table->antsel_a[mac_id]); + /*ODM_RT_TRACE(p_dm_odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[8723B] SetTxAntByTxInfo_WIN: mac_id=%d, antsel_tr_mux=3'b%d%d%d\n", + mac_id, p_dm_fat_table->antsel_c[mac_id], p_dm_fat_table->antsel_b[mac_id], p_dm_fat_table->antsel_a[mac_id]));*/ +#endif + } else if (p_dm_odm->support_ic_type == ODM_RTL8821) { +#if (RTL8821A_SUPPORT == 1) + SET_TX_DESC_ANTSEL_A_8812(p_desc, p_dm_fat_table->antsel_a[mac_id]); + /*ODM_RT_TRACE(p_dm_odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[8821A] SetTxAntByTxInfo_WIN: mac_id=%d, antsel_tr_mux=3'b%d%d%d\n", + mac_id, p_dm_fat_table->antsel_c[mac_id], p_dm_fat_table->antsel_b[mac_id], p_dm_fat_table->antsel_a[mac_id]));*/ +#endif + } else if (p_dm_odm->support_ic_type == ODM_RTL8188E) { +#if (RTL8188E_SUPPORT == 1) + SET_TX_DESC_ANTSEL_A_88E(p_desc, p_dm_fat_table->antsel_a[mac_id]); + SET_TX_DESC_ANTSEL_B_88E(p_desc, p_dm_fat_table->antsel_b[mac_id]); + SET_TX_DESC_ANTSEL_C_88E(p_desc, p_dm_fat_table->antsel_c[mac_id]); + /*ODM_RT_TRACE(p_dm_odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[8188E] SetTxAntByTxInfo_WIN: mac_id=%d, antsel_tr_mux=3'b%d%d%d\n", + mac_id, p_dm_fat_table->antsel_c[mac_id], p_dm_fat_table->antsel_b[mac_id], p_dm_fat_table->antsel_a[mac_id]));*/ +#endif + } else if (p_dm_odm->support_ic_type == ODM_RTL8821C) { +#if (RTL8821C_SUPPORT == 1) + SET_TX_DESC_ANTSEL_A_8821C(p_desc, p_dm_fat_table->antsel_a[mac_id]); + /*ODM_RT_TRACE(p_dm_odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[8821C] SetTxAntByTxInfo_WIN: mac_id=%d, antsel_tr_mux=3'b%d%d%d\n", + mac_id, p_dm_fat_table->antsel_c[mac_id], p_dm_fat_table->antsel_b[mac_id], p_dm_fat_table->antsel_a[mac_id]));*/ +#endif + } +} + +void +odm_ant_div_config( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("CE Config Antenna Diversity\n")); + + if (p_dm_odm->support_ic_type == ODM_RTL8723B) + p_dm_odm->ant_div_type = S0S1_SW_ANTDIV; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[AntDiv Config Info] AntDiv_SupportAbility = (( %x ))\n", ((p_dm_odm->support_ability & ODM_BB_ANT_DIV) ? 1 : 0))); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("[AntDiv Config Info] be_fix_tx_ant = ((%d))\n", p_dm_odm->dm_fat_table.b_fix_tx_ant)); + +} + + +void +odm_ant_div_timers( + void *p_dm_void, + u8 state +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + if (state == INIT_ANTDIV_TIMMER) { +#ifdef CONFIG_S0S1_SW_ANTENNA_DIVERSITY +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) + odm_initialize_timer(p_dm_odm, &(p_dm_odm->dm_swat_table.phydm_sw_antenna_switch_timer), + (void *)odm_sw_antdiv_callback, NULL, "phydm_sw_antenna_switch_timer"); +#else + timer_setup(&p_dm_odm->dm_swat_table.phydm_sw_antenna_switch_timer, odm_sw_antdiv_callback, 0); +#endif +#elif (defined(CONFIG_5G_CG_SMART_ANT_DIVERSITY)) || (defined(CONFIG_2G_CG_SMART_ANT_DIVERSITY)) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) + odm_initialize_timer(p_dm_odm, &p_dm_odm->fast_ant_training_timer, + (void *)odm_fast_ant_training_callback, NULL, "fast_ant_training_timer"); +#else + timer_setup(&p_dm_odm->fast_ant_training_timer, odm_fast_ant_training_callback, 0); +#endif +#endif + +#ifdef ODM_EVM_ENHANCE_ANTDIV +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) + odm_initialize_timer(p_dm_odm, &p_dm_odm->evm_fast_ant_training_timer, + (void *)odm_evm_fast_ant_training_callback, NULL, "evm_fast_ant_training_timer"); +#else + timer_setup(&p_dm_odm->evm_fast_ant_training_timer, odm_evm_fast_ant_training_callback, 0); +#endif +#endif + } else if (state == CANCEL_ANTDIV_TIMMER) { +#ifdef CONFIG_S0S1_SW_ANTENNA_DIVERSITY + odm_cancel_timer(p_dm_odm, &(p_dm_odm->dm_swat_table.phydm_sw_antenna_switch_timer)); +#elif (defined(CONFIG_5G_CG_SMART_ANT_DIVERSITY)) || (defined(CONFIG_2G_CG_SMART_ANT_DIVERSITY)) + odm_cancel_timer(p_dm_odm, &p_dm_odm->fast_ant_training_timer); +#endif + +#ifdef ODM_EVM_ENHANCE_ANTDIV + odm_cancel_timer(p_dm_odm, &p_dm_odm->evm_fast_ant_training_timer); +#endif + } else if (state == RELEASE_ANTDIV_TIMMER) { +#ifdef CONFIG_S0S1_SW_ANTENNA_DIVERSITY + odm_release_timer(p_dm_odm, &(p_dm_odm->dm_swat_table.phydm_sw_antenna_switch_timer)); +#elif (defined(CONFIG_5G_CG_SMART_ANT_DIVERSITY)) || (defined(CONFIG_2G_CG_SMART_ANT_DIVERSITY)) + odm_release_timer(p_dm_odm, &p_dm_odm->fast_ant_training_timer); +#endif + +#ifdef ODM_EVM_ENHANCE_ANTDIV + odm_release_timer(p_dm_odm, &p_dm_odm->evm_fast_ant_training_timer); +#endif + } + +} + +void +phydm_antdiv_debug( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + /*struct _FAST_ANTENNA_TRAINNING_* p_dm_fat_table = &p_dm_odm->dm_fat_table;*/ + u32 used = *_used; + u32 out_len = *_out_len; + + if (dm_value[0] == 1) { /*fixed or auto antenna*/ + + if (dm_value[1] == 0) { + p_dm_odm->antdiv_select = 0; + PHYDM_SNPRINTF((output + used, out_len - used, "AntDiv: Auto\n")); + } else if (dm_value[1] == 1) { + p_dm_odm->antdiv_select = 1; + PHYDM_SNPRINTF((output + used, out_len - used, "AntDiv: Fix MAin\n")); + } else if (dm_value[1] == 2) { + p_dm_odm->antdiv_select = 2; + PHYDM_SNPRINTF((output + used, out_len - used, "AntDiv: Fix Aux\n")); + } + } else if (dm_value[0] == 2) { /*dynamic period for AntDiv*/ + + p_dm_odm->antdiv_period = (u8)dm_value[1]; + PHYDM_SNPRINTF((output + used, out_len - used, "AntDiv_period = ((%d))\n", p_dm_odm->antdiv_period)); + } +} + +#endif /*#if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY))*/ + +void +odm_ant_div_reset( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (p_dm_odm->ant_div_type == S0S1_SW_ANTDIV) { +#ifdef CONFIG_S0S1_SW_ANTENNA_DIVERSITY + odm_s0s1_sw_ant_div_reset(p_dm_odm); +#endif + } + +} + +void +odm_antenna_diversity_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + +#if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY)) + odm_ant_div_config(p_dm_odm); + odm_ant_div_init(p_dm_odm); +#endif +} + +void +odm_antenna_diversity( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + if (p_dm_odm->mp_mode == true) + return; + +#if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY)) + odm_ant_div(p_dm_odm); +#endif +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_antdiv.h b/drivers/staging/rtl8188eu/hal/phydm_antdiv.h new file mode 100644 index 000000000000..14fc9c1df824 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_antdiv.h @@ -0,0 +1,516 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDMANTDIV_H__ +#define __PHYDMANTDIV_H__ + +/*#define ANTDIV_VERSION "2.0" //2014.11.04*/ +/*#define ANTDIV_VERSION "2.1" //2015.01.13 Dino*/ +/*#define ANTDIV_VERSION "2.2" 2015.01.16 Dino*/ +/*#define ANTDIV_VERSION "3.1" 2015.07.29 YuChen, remove 92c 92d 8723a*/ +/*#define ANTDIV_VERSION "3.2" 2015.08.11 Stanley, disable antenna diversity when BT is enable for 8723B*/ +/*#define ANTDIV_VERSION "3.3" 2015.08.12 Stanley. 8723B does not need to check the antenna is control by BT, + because antenna diversity only works when BT is disable or radio off*/ +/*#define ANTDIV_VERSION "3.4" 2015.08.28 Dino 1.Add 8821A Smart Antenna 2. Add 8188F SW S0S1 Antenna Diversity*/ +/*#define ANTDIV_VERSION "3.5" 2015.10.07 Stanley Always check antenna detection result from BT-coex. for 8723B, not from PHYDM*/ +/*#define ANTDIV_VERSION "3.6"*/ /*2015.11.16 Stanley */ +/*#define ANTDIV_VERSION "3.7"*/ /*2015.11.20 Dino Add SmartAnt FAT Patch */ +/*#define ANTDIV_VERSION "3.8" 2015.12.21 Dino, Add SmartAnt dynamic training packet num */ +#define ANTDIV_VERSION "3.9" /*2016.01.05 Dino, Add SmartAnt cmd for converting single & two smtant, and add cmd for adjust truth table */ + +/* 1 ============================================================ + * 1 Definition + * 1 ============================================================ */ + +#define ANTDIV_INIT 0xff +#define MAIN_ANT 1 /*ant A or ant Main or S1*/ +#define AUX_ANT 2 /*AntB or ant Aux or S0*/ +#define MAX_ANT 3 /* 3 for AP using*/ + +#define ANT1_2G 0 /* = ANT2_5G for 8723D BTG S1 RX S0S1 diversity for 8723D, TX fixed at S1 */ +#define ANT2_2G 1 /* = ANT1_5G for 8723D BTG S0 RX S0S1 diversity for 8723D, TX fixed at S1 */ +/*smart antenna*/ +#define SUPPORT_RF_PATH_NUM 4 +#define SUPPORT_BEAM_PATTERN_NUM 4 +#define NUM_ANTENNA_8821A 2 + +#define NO_FIX_TX_ANT 0 +#define FIX_TX_AT_MAIN 1 +#define FIX_AUX_AT_MAIN 2 + +/* Antenna Diversty Control type */ +#define ODM_AUTO_ANT 0 +#define ODM_FIX_MAIN_ANT 1 +#define ODM_FIX_AUX_ANT 2 + +#define ODM_N_ANTDIV_SUPPORT (ODM_RTL8188E | ODM_RTL8192E | ODM_RTL8723B | ODM_RTL8188F | ODM_RTL8723D | ODM_RTL8195A) +#define ODM_AC_ANTDIV_SUPPORT (ODM_RTL8821 | ODM_RTL8881A | ODM_RTL8812 | ODM_RTL8821C | ODM_RTL8822B | ODM_RTL8814B) +#define ODM_ANTDIV_SUPPORT (ODM_N_ANTDIV_SUPPORT | ODM_AC_ANTDIV_SUPPORT) +#define ODM_SMART_ANT_SUPPORT (ODM_RTL8188E | ODM_RTL8192E) +#define ODM_HL_SMART_ANT_TYPE1_SUPPORT (ODM_RTL8821 | ODM_RTL8822B) + +#define ODM_ANTDIV_2G_SUPPORT_IC (ODM_RTL8188E | ODM_RTL8192E | ODM_RTL8723B | ODM_RTL8881A | ODM_RTL8188F | ODM_RTL8723D) +#define ODM_ANTDIV_5G_SUPPORT_IC (ODM_RTL8821 | ODM_RTL8881A | ODM_RTL8812 | ODM_RTL8821C) + +#define ODM_EVM_ENHANCE_ANTDIV_SUPPORT_IC (ODM_RTL8192E) + +#define ODM_ANTDIV_2G BIT(0) +#define ODM_ANTDIV_5G BIT(1) + +#define ANTDIV_ON 1 +#define ANTDIV_OFF 0 + +#define FAT_ON 1 +#define FAT_OFF 0 + +#define TX_BY_DESC 1 +#define TX_BY_REG 0 + +#define RSSI_METHOD 0 +#define EVM_METHOD 1 +#define CRC32_METHOD 2 + +#define INIT_ANTDIV_TIMMER 0 +#define CANCEL_ANTDIV_TIMMER 1 +#define RELEASE_ANTDIV_TIMMER 2 + +#define CRC32_FAIL 1 +#define CRC32_OK 0 + +#define evm_rssi_th_high 25 +#define evm_rssi_th_low 20 + +#define NORMAL_STATE_MIAN 1 +#define NORMAL_STATE_AUX 2 +#define TRAINING_STATE 3 + +#define FORCE_RSSI_DIFF 10 + +#define CSI_ON 1 +#define CSI_OFF 0 + +#define DIVON_CSIOFF 1 +#define DIVOFF_CSION 2 + +#define BDC_DIV_TRAIN_STATE 0 +#define bdc_bfer_train_state 1 +#define BDC_DECISION_STATE 2 +#define BDC_BF_HOLD_STATE 3 +#define BDC_DIV_HOLD_STATE 4 + +#define BDC_MODE_1 1 +#define BDC_MODE_2 2 +#define BDC_MODE_3 3 +#define BDC_MODE_4 4 +#define BDC_MODE_NULL 0xff + +/*SW S0S1 antenna diversity*/ +#define SWAW_STEP_INIT 0xff +#define SWAW_STEP_PEEK 0 +#define SWAW_STEP_DETERMINE 1 + +#define RSSI_CHECK_RESET_PERIOD 10 +#define RSSI_CHECK_THRESHOLD 50 + +/*Hong Lin Smart antenna*/ +#define HL_SMTANT_2WIRE_DATA_LEN 24 + +/* 1 ============================================================ + * 1 structure + * 1 ============================================================ */ + + +struct _sw_antenna_switch_ { + u8 double_chk_flag; /*If current antenna RSSI > "RSSI_CHECK_THRESHOLD", than check this antenna again*/ + u8 try_flag; + s32 pre_rssi; + u8 cur_antenna; + u8 pre_antenna; + u8 rssi_trying; + u8 reset_idx; + u8 train_time; + u8 train_time_flag; /*base on RSSI difference between two antennas*/ + struct timer_list phydm_sw_antenna_switch_timer; + u32 pkt_cnt_sw_ant_div_by_ctrl_frame; + bool is_sw_ant_div_by_ctrl_frame; + + /* AntDect (Before link Antenna Switch check) need to be moved*/ + u16 single_ant_counter; + u16 dual_ant_counter; + u16 aux_fail_detec_counter; + u16 retry_counter; + u8 swas_no_link_state; + u32 swas_no_link_bk_reg948; + bool ANTA_ON; /*To indicate ant A is or not*/ + bool ANTB_ON; /*To indicate ant B is on or not*/ + bool pre_aux_fail_detec; + bool rssi_ant_dect_result; + u8 ant_5g; + u8 ant_2g; +}; + +#ifdef CONFIG_HL_SMART_ANTENNA_TYPE1 +struct _SMART_ANTENNA_TRAINNING_ { + u32 latch_time; + bool pkt_skip_statistic_en; + u32 fix_beam_pattern_en; + u32 fix_training_num_en; + u32 fix_beam_pattern_codeword; + u32 update_beam_codeword; + u32 ant_num; /*number of used smart beam antenna*/ + u32 ant_num_total;/*number of total smart beam antenna*/ + u32 first_train_ant; /*decide witch antenna to train first*/ + u32 rfu_codeword_table[4]; /*2G beam truth table*/ + u32 rfu_codeword_table_5g[4]; /*5G beam truth table*/ + u32 beam_patten_num_each_ant;/*number of beam can be switched in each antenna*/ + u32 data_codeword_bit_num; + u8 per_beam_training_pkt_num; + u8 decision_holding_period; + u8 pkt_counter; + u32 fast_training_beam_num; + u32 pre_fast_training_beam_num; + u32 pkt_rssi_pre[SUPPORT_RF_PATH_NUM][SUPPORT_BEAM_PATTERN_NUM]; + u8 beam_train_cnt[SUPPORT_RF_PATH_NUM][SUPPORT_BEAM_PATTERN_NUM]; + u8 beam_train_rssi_diff[SUPPORT_RF_PATH_NUM][SUPPORT_BEAM_PATTERN_NUM]; + u32 pkt_rssi_sum[8][SUPPORT_BEAM_PATTERN_NUM]; + u32 pkt_rssi_cnt[8][SUPPORT_BEAM_PATTERN_NUM]; + u32 rx_idle_beam[SUPPORT_RF_PATH_NUM]; + u32 pre_codeword; + bool force_update_beam_en; + u32 beacon_counter; + u32 pre_beacon_counter; + u8 update_beam_idx; +}; +#endif + +struct _FAST_ANTENNA_TRAINNING_ { + u8 bssid[6]; + u8 antsel_rx_keep_0; + u8 antsel_rx_keep_1; + u8 antsel_rx_keep_2; + u8 antsel_rx_keep_3; + u32 ant_sum_rssi[7]; + u32 ant_rssi_cnt[7]; + u32 ant_ave_rssi[7]; + u8 fat_state; + u32 train_idx; + u8 antsel_a[ODM_ASSOCIATE_ENTRY_NUM]; + u8 antsel_b[ODM_ASSOCIATE_ENTRY_NUM]; + u8 antsel_c[ODM_ASSOCIATE_ENTRY_NUM]; + u16 main_ant_sum[ODM_ASSOCIATE_ENTRY_NUM]; + u16 aux_ant_sum[ODM_ASSOCIATE_ENTRY_NUM]; + u16 main_ant_cnt[ODM_ASSOCIATE_ENTRY_NUM]; + u16 aux_ant_cnt[ODM_ASSOCIATE_ENTRY_NUM]; + u16 main_ant_sum_cck[ODM_ASSOCIATE_ENTRY_NUM]; + u16 aux_ant_sum_cck[ODM_ASSOCIATE_ENTRY_NUM]; + u16 main_ant_cnt_cck[ODM_ASSOCIATE_ENTRY_NUM]; + u16 aux_ant_cnt_cck[ODM_ASSOCIATE_ENTRY_NUM]; + u8 rx_idle_ant; + u8 ant_div_on_off; + bool is_become_linked; + u32 min_max_rssi; + u8 idx_ant_div_counter_2g; + u8 idx_ant_div_counter_5g; + u8 ant_div_2g_5g; + +#ifdef ODM_EVM_ENHANCE_ANTDIV + u32 main_ant_evm_sum[ODM_ASSOCIATE_ENTRY_NUM]; + u32 aux_ant_evm_sum[ODM_ASSOCIATE_ENTRY_NUM]; + u32 main_ant_evm_cnt[ODM_ASSOCIATE_ENTRY_NUM]; + u32 aux_ant_evm_cnt[ODM_ASSOCIATE_ENTRY_NUM]; + bool EVM_method_enable; + u8 target_ant_evm; + u8 target_ant_crc32; + u8 target_ant_enhance; + u8 pre_target_ant_enhance; + u16 main_mpdu_ok_cnt; + u16 aux_mpdu_ok_cnt; + + u32 crc32_ok_cnt; + u32 crc32_fail_cnt; + u32 main_crc32_ok_cnt; + u32 aux_crc32_ok_cnt; + u32 main_crc32_fail_cnt; + u32 aux_crc32_fail_cnt; +#endif + u32 cck_ctrl_frame_cnt_main; + u32 cck_ctrl_frame_cnt_aux; + u32 ofdm_ctrl_frame_cnt_main; + u32 ofdm_ctrl_frame_cnt_aux; + u32 main_ant_ctrl_frame_sum; + u32 aux_ant_ctrl_frame_sum; + u32 main_ant_ctrl_frame_cnt; + u32 aux_ant_ctrl_frame_cnt; + u8 b_fix_tx_ant; + bool fix_ant_bfee; + bool enable_ctrl_frame_antdiv; + bool use_ctrl_frame_antdiv; + u8 hw_antsw_occur; + u8 *p_force_tx_ant_by_desc; + u8 force_tx_ant_by_desc; /*A temp value, will hook to driver team's outer parameter later*/ + u8 *p_default_s0_s1; + u8 default_s0_s1; +}; + + +/* 1 ============================================================ + * 1 enumeration + * 1 ============================================================ */ + + + +enum fat_state_e /*Fast antenna training*/ +{ + FAT_BEFORE_LINK_STATE = 0, + FAT_PREPARE_STATE = 1, + FAT_TRAINING_STATE = 2, + FAT_DECISION_STATE = 3 +}; + +enum ant_div_type_e { + NO_ANTDIV = 0xFF, + CG_TRX_HW_ANTDIV = 0x01, + CGCS_RX_HW_ANTDIV = 0x02, + FIXED_HW_ANTDIV = 0x03, + CG_TRX_SMART_ANTDIV = 0x04, + CGCS_RX_SW_ANTDIV = 0x05, + S0S1_SW_ANTDIV = 0x06, /*8723B intrnal switch S0 S1*/ + S0S1_TRX_HW_ANTDIV = 0x07, /*TRX S0S1 diversity for 8723D*/ + HL_SW_SMART_ANT_TYPE1 = 0x10 /*Hong-Lin Smart antenna use for 8821AE which is a 2 ant. entitys, and each ant. is equipped with 4 antenna patterns*/ +}; + + +/* 1 ============================================================ + * 1 function prototype + * 1 ============================================================ */ + + +void +odm_stop_antenna_switch_dm( + void *p_dm_void +); + +void +phydm_enable_antenna_diversity( + void *p_dm_void +); + +void +odm_set_ant_config( + void *p_dm_void, + u8 ant_setting /* 0=A, 1=B, 2=C, .... */ +); + + +#define sw_ant_div_rest_after_link odm_sw_ant_div_rest_after_link + +void odm_sw_ant_div_rest_after_link( + void *p_dm_void +); + +#if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY)) + +void +phydm_antdiv_reset_statistic( + void *p_dm_void, + u32 macid +); + +void +odm_update_rx_idle_ant( + void *p_dm_void, + u8 ant +); + +#if (RTL8723B_SUPPORT == 1) +void +odm_update_rx_idle_ant_8723b( + void *p_dm_void, + u8 ant, + u32 default_ant, + u32 optional_ant +); +#endif + +#if (RTL8188F_SUPPORT == 1) +void +phydm_update_rx_idle_antenna_8188F( + void *p_dm_void, + u32 default_ant +); +#endif + +#if (RTL8723D_SUPPORT == 1) + +void +phydm_set_tx_ant_pwr_8723d( + void *p_dm_void, + u8 ant +); + +#endif + +#ifdef CONFIG_S0S1_SW_ANTENNA_DIVERSITY + +void +odm_sw_antdiv_workitem_callback( + void *p_context +); + +void +odm_sw_antdiv_callback( + void *function_context +); + +void +odm_s0s1_sw_ant_div_by_ctrl_frame( + void *p_dm_void, + u8 step +); + +void +odm_antsel_statistics_of_ctrl_frame( + void *p_dm_void, + u8 antsel_tr_mux, + u32 rx_pwdb_all +); + +void +odm_s0s1_sw_ant_div_by_ctrl_frame_process_rssi( + void *p_dm_void, + void *p_phy_info_void, + void *p_pkt_info_void +); + +#endif + +#ifdef ODM_EVM_ENHANCE_ANTDIV +void +odm_evm_fast_ant_training_callback( + void *p_dm_void +); +#endif + +void +odm_hw_ant_div( + void *p_dm_void +); + +#if (defined(CONFIG_5G_CG_SMART_ANT_DIVERSITY)) || (defined(CONFIG_2G_CG_SMART_ANT_DIVERSITY)) +void +odm_fast_ant_training( + void *p_dm_void +); + +void +odm_fast_ant_training_callback( + void *p_dm_void +); + +void +odm_fast_ant_training_work_item_callback( + void *p_dm_void +); +#endif + + +#ifdef CONFIG_HL_SMART_ANTENNA_TYPE1 + +void +phydm_update_beam_pattern( + void *p_dm_void, + u32 codeword, + u32 codeword_length +); + +void +phydm_set_all_ant_same_beam_num( + void *p_dm_void +); + +void +phydm_hl_smart_ant_debug( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +); + +#endif/*#ifdef CONFIG_HL_SMART_ANTENNA_TYPE1*/ + +void +odm_ant_div_init( + void *p_dm_void +); + +void +odm_ant_div( + void *p_dm_void +); + +void +odm_antsel_statistics( + void *p_dm_void, + u8 antsel_tr_mux, + u32 mac_id, + u32 utility, + u8 method, + u8 is_cck_rate +); + +void +odm_process_rssi_for_ant_div( + void *p_dm_void, + void *p_phy_info_void, + void *p_pkt_info_void +); + + + +void +odm_set_tx_ant_by_tx_info( + void *p_dm_void, + u8 *p_desc, + u8 mac_id +); + +void +odm_ant_div_config( + void *p_dm_void +); + +void +odm_ant_div_timers( + void *p_dm_void, + u8 state +); + +void +phydm_antdiv_debug( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +); + +#endif /*#if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY))*/ + +void +odm_ant_div_reset( + void *p_dm_void +); + +void +odm_antenna_diversity_init( + void *p_dm_void +); + +void +odm_antenna_diversity( + void *p_dm_void +); + +#endif /*#ifndef __ODMANTDIV_H__*/ diff --git a/drivers/staging/rtl8188eu/hal/phydm_beamforming.h b/drivers/staging/rtl8188eu/hal/phydm_beamforming.h new file mode 100644 index 000000000000..e3413f682948 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_beamforming.h @@ -0,0 +1,27 @@ +#ifndef __INC_PHYDM_BEAMFORMING_H +#define __INC_PHYDM_BEAMFORMING_H + +#ifndef BEAMFORMING_SUPPORT + #define BEAMFORMING_SUPPORT 0 +#endif + +/*Beamforming Related*/ +#include "halcomtxbf.h" +#include "haltxbfjaguar.h" +#include "haltxbfinterface.h" + +#define beamforming_gid_paid(adapter, p_tcb) +#define phydm_acting_determine(p_dm_odm, type) false +#define beamforming_enter(p_dm_odm, sta_idx) +#define beamforming_leave(p_dm_odm, RA) +#define beamforming_end_fw(p_dm_odm) +#define beamforming_control_v1(p_dm_odm, RA, AID, mode, BW, rate) true +#define beamforming_control_v2(p_dm_odm, idx, mode, BW, period) true +#define phydm_beamforming_end_sw(p_dm_odm, _status) +#define beamforming_timer_callback(p_dm_odm) +#define phydm_beamforming_init(p_dm_odm) +#define phydm_beamforming_control_v2(p_dm_odm, _idx, _mode, _BW, _period) false +#define beamforming_watchdog(p_dm_odm) +#define phydm_beamforming_watchdog(p_dm_odm) + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_ccx.c b/drivers/staging/rtl8188eu/hal/phydm_ccx.c new file mode 100644 index 000000000000..e8417490e7e2 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_ccx.c @@ -0,0 +1,389 @@ +#include "mp_precomp.h" +#include "phydm_precomp.h" + +/*Set NHM period, threshold, disable ignore cca or not, disable ignore txon or not*/ +void +phydm_nhm_setting( + void *p_dm_void, + u8 nhm_setting +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _CCX_INFO *ccx_info = &p_dm_odm->dm_ccx_info; + + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + + if (nhm_setting == SET_NHM_SETTING) { + + /*Set inexclude_cca, inexclude_txon*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, BIT(9), ccx_info->nhm_inexclude_cca); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, BIT(10), ccx_info->nhm_inexclude_txon); + + /*Set NHM period*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_CCX_PERIOD_11AC, MASKHWORD, ccx_info->NHM_period); + + /*Set NHM threshold*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11AC, MASKBYTE0, ccx_info->NHM_th[0]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11AC, MASKBYTE1, ccx_info->NHM_th[1]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11AC, MASKBYTE2, ccx_info->NHM_th[2]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11AC, MASKBYTE3, ccx_info->NHM_th[3]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11AC, MASKBYTE0, ccx_info->NHM_th[4]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11AC, MASKBYTE1, ccx_info->NHM_th[5]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11AC, MASKBYTE2, ccx_info->NHM_th[6]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11AC, MASKBYTE3, ccx_info->NHM_th[7]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH8_11AC, MASKBYTE0, ccx_info->NHM_th[8]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, MASKBYTE2, ccx_info->NHM_th[9]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, MASKBYTE3, ccx_info->NHM_th[10]); + + /*CCX EN*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, BIT(8), CCX_EN); + + } else if (nhm_setting == STORE_NHM_SETTING) { + + /*Store pervious disable_ignore_cca, disable_ignore_txon*/ + ccx_info->NHM_inexclude_cca_restore = (enum nhm_inexclude_cca)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, BIT(9)); + ccx_info->NHM_inexclude_txon_restore = (enum nhm_inexclude_txon)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, BIT(10)); + + /*Store pervious NHM period*/ + ccx_info->NHM_period_restore = (u16)odm_get_bb_reg(p_dm_odm, ODM_REG_CCX_PERIOD_11AC, MASKHWORD); + + /*Store NHM threshold*/ + ccx_info->NHM_th_restore[0] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11AC, MASKBYTE0); + ccx_info->NHM_th_restore[1] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11AC, MASKBYTE1); + ccx_info->NHM_th_restore[2] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11AC, MASKBYTE2); + ccx_info->NHM_th_restore[3] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11AC, MASKBYTE3); + ccx_info->NHM_th_restore[4] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11AC, MASKBYTE0); + ccx_info->NHM_th_restore[5] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11AC, MASKBYTE1); + ccx_info->NHM_th_restore[6] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11AC, MASKBYTE2); + ccx_info->NHM_th_restore[7] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11AC, MASKBYTE3); + ccx_info->NHM_th_restore[8] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH8_11AC, MASKBYTE0); + ccx_info->NHM_th_restore[9] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, MASKBYTE2); + ccx_info->NHM_th_restore[10] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, MASKBYTE3); + } else if (nhm_setting == RESTORE_NHM_SETTING) { + + /*Set disable_ignore_cca, disable_ignore_txon*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, BIT(9), ccx_info->NHM_inexclude_cca_restore); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, BIT(10), ccx_info->NHM_inexclude_txon_restore); + + /*Set NHM period*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_CCX_PERIOD_11AC, MASKHWORD, ccx_info->NHM_period); + + /*Set NHM threshold*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11AC, MASKBYTE0, ccx_info->NHM_th_restore[0]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11AC, MASKBYTE1, ccx_info->NHM_th_restore[1]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11AC, MASKBYTE2, ccx_info->NHM_th_restore[2]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11AC, MASKBYTE3, ccx_info->NHM_th_restore[3]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11AC, MASKBYTE0, ccx_info->NHM_th_restore[4]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11AC, MASKBYTE1, ccx_info->NHM_th_restore[5]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11AC, MASKBYTE2, ccx_info->NHM_th_restore[6]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11AC, MASKBYTE3, ccx_info->NHM_th_restore[7]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH8_11AC, MASKBYTE0, ccx_info->NHM_th_restore[8]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, MASKBYTE2, ccx_info->NHM_th_restore[9]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, MASKBYTE3, ccx_info->NHM_th_restore[10]); + } else + return; + } + + else if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + + if (nhm_setting == SET_NHM_SETTING) { + + /*Set disable_ignore_cca, disable_ignore_txon*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, BIT(9), ccx_info->nhm_inexclude_cca); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, BIT(10), ccx_info->nhm_inexclude_txon); + + /*Set NHM period*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_CCX_PERIOD_11N, MASKHWORD, ccx_info->NHM_period); + + /*Set NHM threshold*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11N, MASKBYTE0, ccx_info->NHM_th[0]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11N, MASKBYTE1, ccx_info->NHM_th[1]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11N, MASKBYTE2, ccx_info->NHM_th[2]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11N, MASKBYTE3, ccx_info->NHM_th[3]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11N, MASKBYTE0, ccx_info->NHM_th[4]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11N, MASKBYTE1, ccx_info->NHM_th[5]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11N, MASKBYTE2, ccx_info->NHM_th[6]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11N, MASKBYTE3, ccx_info->NHM_th[7]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH8_11N, MASKBYTE0, ccx_info->NHM_th[8]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, MASKBYTE2, ccx_info->NHM_th[9]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, MASKBYTE3, ccx_info->NHM_th[10]); + + /*CCX EN*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, BIT(8), CCX_EN); + } else if (nhm_setting == STORE_NHM_SETTING) { + + /*Store pervious disable_ignore_cca, disable_ignore_txon*/ + ccx_info->NHM_inexclude_cca_restore = (enum nhm_inexclude_cca)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, BIT(9)); + ccx_info->NHM_inexclude_txon_restore = (enum nhm_inexclude_txon)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, BIT(10)); + + /*Store pervious NHM period*/ + ccx_info->NHM_period_restore = (u16)odm_get_bb_reg(p_dm_odm, ODM_REG_CCX_PERIOD_11N, MASKHWORD); + + /*Store NHM threshold*/ + ccx_info->NHM_th_restore[0] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11N, MASKBYTE0); + ccx_info->NHM_th_restore[1] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11N, MASKBYTE1); + ccx_info->NHM_th_restore[2] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11N, MASKBYTE2); + ccx_info->NHM_th_restore[3] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11N, MASKBYTE3); + ccx_info->NHM_th_restore[4] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11N, MASKBYTE0); + ccx_info->NHM_th_restore[5] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11N, MASKBYTE1); + ccx_info->NHM_th_restore[6] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11N, MASKBYTE2); + ccx_info->NHM_th_restore[7] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11N, MASKBYTE3); + ccx_info->NHM_th_restore[8] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH8_11N, MASKBYTE0); + ccx_info->NHM_th_restore[9] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, MASKBYTE2); + ccx_info->NHM_th_restore[10] = (u8)odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, MASKBYTE3); + + } else if (nhm_setting == RESTORE_NHM_SETTING) { + + /*Set disable_ignore_cca, disable_ignore_txon*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, BIT(9), ccx_info->NHM_inexclude_cca_restore); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, BIT(10), ccx_info->NHM_inexclude_txon_restore); + + /*Set NHM period*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_CCX_PERIOD_11N, MASKHWORD, ccx_info->NHM_period_restore); + + /*Set NHM threshold*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11N, MASKBYTE0, ccx_info->NHM_th_restore[0]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11N, MASKBYTE1, ccx_info->NHM_th_restore[1]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11N, MASKBYTE2, ccx_info->NHM_th_restore[2]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH3_TO_TH0_11N, MASKBYTE3, ccx_info->NHM_th_restore[3]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11N, MASKBYTE0, ccx_info->NHM_th_restore[4]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11N, MASKBYTE1, ccx_info->NHM_th_restore[5]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11N, MASKBYTE2, ccx_info->NHM_th_restore[6]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH7_TO_TH4_11N, MASKBYTE3, ccx_info->NHM_th_restore[7]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH8_11N, MASKBYTE0, ccx_info->NHM_th_restore[8]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, MASKBYTE2, ccx_info->NHM_th_restore[9]); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, MASKBYTE3, ccx_info->NHM_th_restore[10]); + } else + return; + + } +} + +void +phydm_nhm_trigger( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _CCX_INFO *ccx_info = &p_dm_odm->dm_ccx_info; + + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + + /*Trigger NHM*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, BIT(1), 0); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11AC, BIT(1), 1); + } else if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + + /*Trigger NHM*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, BIT(1), 0); + odm_set_bb_reg(p_dm_odm, ODM_REG_NHM_TH9_TH10_11N, BIT(1), 1); + } +} + +void +phydm_get_nhm_result( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 value32; + struct _CCX_INFO *ccx_info = &p_dm_odm->dm_ccx_info; + + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + + value32 = odm_read_4byte(p_dm_odm, ODM_REG_NHM_CNT_11AC); + ccx_info->NHM_result[0] = (u8)(value32 & MASKBYTE0); + ccx_info->NHM_result[1] = (u8)((value32 & MASKBYTE1) >> 8); + ccx_info->NHM_result[2] = (u8)((value32 & MASKBYTE2) >> 16); + ccx_info->NHM_result[3] = (u8)((value32 & MASKBYTE3) >> 24); + + value32 = odm_read_4byte(p_dm_odm, ODM_REG_NHM_CNT7_TO_CNT4_11AC); + ccx_info->NHM_result[4] = (u8)(value32 & MASKBYTE0); + ccx_info->NHM_result[5] = (u8)((value32 & MASKBYTE1) >> 8); + ccx_info->NHM_result[6] = (u8)((value32 & MASKBYTE2) >> 16); + ccx_info->NHM_result[7] = (u8)((value32 & MASKBYTE3) >> 24); + + value32 = odm_read_4byte(p_dm_odm, ODM_REG_NHM_CNT11_TO_CNT8_11AC); + ccx_info->NHM_result[8] = (u8)(value32 & MASKBYTE0); + ccx_info->NHM_result[9] = (u8)((value32 & MASKBYTE1) >> 8); + ccx_info->NHM_result[10] = (u8)((value32 & MASKBYTE2) >> 16); + ccx_info->NHM_result[11] = (u8)((value32 & MASKBYTE3) >> 24); + + /*Get NHM duration*/ + value32 = odm_read_4byte(p_dm_odm, ODM_REG_NHM_DUR_READY_11AC); + ccx_info->NHM_duration = (u16)(value32 & MASKLWORD); + + } + + else if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + + value32 = odm_read_4byte(p_dm_odm, ODM_REG_NHM_CNT_11N); + ccx_info->NHM_result[0] = (u8)(value32 & MASKBYTE0); + ccx_info->NHM_result[1] = (u8)((value32 & MASKBYTE1) >> 8); + ccx_info->NHM_result[2] = (u8)((value32 & MASKBYTE2) >> 16); + ccx_info->NHM_result[3] = (u8)((value32 & MASKBYTE3) >> 24); + + value32 = odm_read_4byte(p_dm_odm, ODM_REG_NHM_CNT7_TO_CNT4_11N); + ccx_info->NHM_result[4] = (u8)(value32 & MASKBYTE0); + ccx_info->NHM_result[5] = (u8)((value32 & MASKBYTE1) >> 8); + ccx_info->NHM_result[6] = (u8)((value32 & MASKBYTE2) >> 16); + ccx_info->NHM_result[7] = (u8)((value32 & MASKBYTE3) >> 24); + + value32 = odm_read_4byte(p_dm_odm, ODM_REG_NHM_CNT9_TO_CNT8_11N); + ccx_info->NHM_result[8] = (u8)((value32 & MASKBYTE2) >> 16); + ccx_info->NHM_result[9] = (u8)((value32 & MASKBYTE3) >> 24); + + value32 = odm_read_4byte(p_dm_odm, ODM_REG_NHM_CNT10_TO_CNT11_11N); + ccx_info->NHM_result[10] = (u8)((value32 & MASKBYTE2) >> 16); + ccx_info->NHM_result[11] = (u8)((value32 & MASKBYTE3) >> 24); + + /*Get NHM duration*/ + value32 = odm_read_4byte(p_dm_odm, ODM_REG_NHM_CNT10_TO_CNT11_11N); + ccx_info->NHM_duration = (u16)(value32 & MASKLWORD); + + } + +} + +bool +phydm_check_nhm_ready( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 value32 = 0; + u8 i; + bool ret = false; + + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_CLM_RESULT_11AC, MASKDWORD); + + for (i = 0; i < 200; i++) { + + ODM_delay_ms(1); + if (odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_DUR_READY_11AC, BIT(17))) { + ret = 1; + break; + } + } + } + + else if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_CLM_READY_11N, MASKDWORD); + + for (i = 0; i < 200; i++) { + + ODM_delay_ms(1); + if (odm_get_bb_reg(p_dm_odm, ODM_REG_NHM_DUR_READY_11AC, BIT(17))) { + ret = 1; + break; + } + } + } + return ret; +} + +static void phydm_store_nhm_setting(void *p_dm_void) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _CCX_INFO *ccx_info = &p_dm_odm->dm_ccx_info; + + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + + + } else if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + + + + } +} + +void +phydm_clm_setting( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _CCX_INFO *ccx_info = &p_dm_odm->dm_ccx_info; + + + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + + odm_set_bb_reg(p_dm_odm, ODM_REG_CCX_PERIOD_11AC, MASKLWORD, ccx_info->CLM_period); /*4us sample 1 time*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_CLM_11AC, BIT(8), 0x1); /*Enable CCX for CLM*/ + + } else if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + + odm_set_bb_reg(p_dm_odm, ODM_REG_CCX_PERIOD_11N, MASKLWORD, ccx_info->CLM_period); /*4us sample 1 time*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_CLM_11N, BIT(8), 0x1); /*Enable CCX for CLM*/ + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CCX, ODM_DBG_LOUD, ("[%s] : CLM period = %dus\n", __func__, ccx_info->CLM_period * 4)); + +} + +void +phydm_clm_trigger( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + odm_set_bb_reg(p_dm_odm, ODM_REG_CLM_11AC, BIT(0), 0x0); /*Trigger CLM*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_CLM_11AC, BIT(0), 0x1); + } else if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + odm_set_bb_reg(p_dm_odm, ODM_REG_CLM_11N, BIT(0), 0x0); /*Trigger CLM*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_CLM_11N, BIT(0), 0x1); + } +} + +bool +phydm_check_cl_mready( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 value32 = 0; + bool ret = false; + + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_CLM_RESULT_11AC, MASKDWORD); /*make sure CLM calc is ready*/ + else if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_CLM_READY_11N, MASKDWORD); /*make sure CLM calc is ready*/ + + if ((p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) && (value32 & BIT(16))) + ret = true; + else if ((p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) && (value32 & BIT(16))) + ret = true; + else + ret = false; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CCX, ODM_DBG_LOUD, ("[%s] : CLM ready = %d\n", __func__, ret)); + + return ret; +} + +void +phydm_get_cl_mresult( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _CCX_INFO *ccx_info = &p_dm_odm->dm_ccx_info; + + u32 value32 = 0; + u16 results = 0; + + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_CLM_RESULT_11AC, MASKDWORD); /*read CLM calc result*/ + else if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_CLM_RESULT_11N, MASKDWORD); /*read CLM calc result*/ + + ccx_info->CLM_result = (u16)(value32 & MASKLWORD); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CCX, ODM_DBG_LOUD, ("[%s] : CLM result = %dus\n", __func__, ccx_info->CLM_result * 4)); + +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_ccx.h b/drivers/staging/rtl8188eu/hal/phydm_ccx.h new file mode 100644 index 000000000000..d9adf6332e30 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_ccx.h @@ -0,0 +1,102 @@ +#ifndef __PHYDMCCX_H__ +#define __PHYDMCCX_H__ + +#define CCX_EN 1 + +#define SET_NHM_SETTING 0 +#define STORE_NHM_SETTING 1 +#define RESTORE_NHM_SETTING 2 + +/* +#define NHM_EXCLUDE_CCA 0 +#define NHM_INCLUDE_CCA 1 +#define NHM_EXCLUDE_TXON 0 +#define NHM_INCLUDE_TXON 1 +*/ + +enum nhm_inexclude_cca { + NHM_EXCLUDE_CCA, + NHM_INCLUDE_CCA +}; + +enum nhm_inexclude_txon { + NHM_EXCLUDE_TXON, + NHM_INCLUDE_TXON +}; + + +struct _CCX_INFO { + + /*Settings*/ + u8 NHM_th[11]; + u16 NHM_period; /* 4us per unit */ + u16 CLM_period; /* 4us per unit */ + enum nhm_inexclude_txon nhm_inexclude_txon; + enum nhm_inexclude_cca nhm_inexclude_cca; + + /*Previous Settings*/ + u8 NHM_th_restore[11]; + u16 NHM_period_restore; /* 4us per unit */ + u16 CLM_period_restore; /* 4us per unit */ + enum nhm_inexclude_txon NHM_inexclude_txon_restore; + enum nhm_inexclude_cca NHM_inexclude_cca_restore; + + /*Report*/ + u8 NHM_result[12]; + u16 NHM_duration; + u16 CLM_result; + + + bool echo_NHM_en; + bool echo_CLM_en; + u8 echo_IGI; + +}; + +/*NHM*/ + +void +phydm_nhm_setting( + void *p_dm_void, + u8 nhm_setting +); + +void +phydm_nhm_trigger( + void *p_dm_void +); + +void +phydm_get_nhm_result( + void *p_dm_void +); + +bool +phydm_check_nhm_ready( + void *p_dm_void +); + +/*CLM*/ + +void +phydm_clm_setting( + void *p_dm_void +); + +void +phydm_clm_trigger( + void *p_dm_void +); + +bool +phydm_check_cl_mready( + void *p_dm_void +); + +void +phydm_get_cl_mresult( + void *p_dm_void +); + + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_cfotracking.c b/drivers/staging/rtl8188eu/hal/phydm_cfotracking.c new file mode 100644 index 000000000000..b8782d1ac6db --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_cfotracking.c @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#include "mp_precomp.h" +#include "phydm_precomp.h" + +static void +odm_set_crystal_cap( + void *p_dm_void, + u8 crystal_cap +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK); + + if (p_cfo_track->crystal_cap == crystal_cap) + return; + + p_cfo_track->crystal_cap = crystal_cap; + + if (p_dm_odm->support_ic_type & (ODM_RTL8188E | ODM_RTL8188F)) { + /* write 0x24[22:17] = 0x24[16:11] = crystal_cap */ + crystal_cap = crystal_cap & 0x3F; + odm_set_bb_reg(p_dm_odm, REG_AFE_XTAL_CTRL, 0x007ff800, (crystal_cap | (crystal_cap << 6))); + } else if (p_dm_odm->support_ic_type & ODM_RTL8812) { + /* write 0x2C[30:25] = 0x2C[24:19] = crystal_cap */ + crystal_cap = crystal_cap & 0x3F; + odm_set_bb_reg(p_dm_odm, REG_MAC_PHY_CTRL, 0x7FF80000, (crystal_cap | (crystal_cap << 6))); + } else if ((p_dm_odm->support_ic_type & (ODM_RTL8703B | ODM_RTL8723B | ODM_RTL8192E | ODM_RTL8821))) { + /* 0x2C[23:18] = 0x2C[17:12] = crystal_cap */ + crystal_cap = crystal_cap & 0x3F; + odm_set_bb_reg(p_dm_odm, REG_MAC_PHY_CTRL, 0x00FFF000, (crystal_cap | (crystal_cap << 6))); + } else if (p_dm_odm->support_ic_type & ODM_RTL8814A) { + /* write 0x2C[26:21] = 0x2C[20:15] = crystal_cap */ + crystal_cap = crystal_cap & 0x3F; + odm_set_bb_reg(p_dm_odm, REG_MAC_PHY_CTRL, 0x07FF8000, (crystal_cap | (crystal_cap << 6))); + } else if (p_dm_odm->support_ic_type & (ODM_RTL8822B | ODM_RTL8821C)) { + /* write 0x24[30:25] = 0x28[6:1] = crystal_cap */ + crystal_cap = crystal_cap & 0x3F; + odm_set_bb_reg(p_dm_odm, REG_AFE_XTAL_CTRL, 0x7e000000, crystal_cap); + odm_set_bb_reg(p_dm_odm, REG_AFE_PLL_CTRL, 0x7e, crystal_cap); + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_set_crystal_cap(): Use default setting.\n")); + odm_set_bb_reg(p_dm_odm, REG_MAC_PHY_CTRL, 0xFFF000, (crystal_cap | (crystal_cap << 6))); + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_set_crystal_cap(): crystal_cap = 0x%x\n", crystal_cap)); +} + +static u8 +odm_get_default_crytaltal_cap( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 crystal_cap = 0x20; + + struct _ADAPTER *adapter = p_dm_odm->adapter; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(adapter); + + crystal_cap = p_hal_data->crystal_cap; + + crystal_cap = crystal_cap & 0x3f; + + return crystal_cap; +} + +static void +odm_set_atc_status( + void *p_dm_void, + bool atc_status +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK); + + if (p_cfo_track->is_atc_status == atc_status) + return; + + odm_set_bb_reg(p_dm_odm, ODM_REG(BB_ATC, p_dm_odm), ODM_BIT(BB_ATC, p_dm_odm), atc_status); + p_cfo_track->is_atc_status = atc_status; +} + +static bool +odm_get_atc_status( + void *p_dm_void +) +{ + bool atc_status; + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + atc_status = (bool)odm_get_bb_reg(p_dm_odm, ODM_REG(BB_ATC, p_dm_odm), ODM_BIT(BB_ATC, p_dm_odm)); + return atc_status; +} + +void +odm_cfo_tracking_reset( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK); + + p_cfo_track->def_x_cap = odm_get_default_crytaltal_cap(p_dm_odm); + p_cfo_track->is_adjust = true; + + if (p_cfo_track->crystal_cap > p_cfo_track->def_x_cap) { + odm_set_crystal_cap(p_dm_odm, p_cfo_track->crystal_cap - 1); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, + ("odm_cfo_tracking_reset(): approch default value (0x%x)\n", p_cfo_track->crystal_cap)); + } else if (p_cfo_track->crystal_cap < p_cfo_track->def_x_cap) { + odm_set_crystal_cap(p_dm_odm, p_cfo_track->crystal_cap + 1); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, + ("odm_cfo_tracking_reset(): approch default value (0x%x)\n", p_cfo_track->crystal_cap)); + } + odm_set_atc_status(p_dm_odm, true); +} + +void +odm_cfo_tracking_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK); + + p_cfo_track->def_x_cap = p_cfo_track->crystal_cap = odm_get_default_crytaltal_cap(p_dm_odm); + p_cfo_track->is_atc_status = odm_get_atc_status(p_dm_odm); + p_cfo_track->is_adjust = true; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("ODM_CfoTracking_init()=========>\n")); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("ODM_CfoTracking_init(): is_atc_status = %d, crystal_cap = 0x%x\n", p_cfo_track->is_atc_status, p_cfo_track->def_x_cap)); +} + +void +odm_cfo_tracking( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK); + s32 CFO_ave = 0; + u32 CFO_rpt_sum, cfo_khz_avg[4] = {0}; + s32 CFO_ave_diff; + s8 crystal_cap = p_cfo_track->crystal_cap; + u8 adjust_xtal = 1, i, valid_path_cnt = 0; + + /* 4 Support ability */ + if (!(p_dm_odm->support_ability & ODM_BB_CFO_TRACKING)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Return: support_ability ODM_BB_CFO_TRACKING is disabled\n")); + return; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking()=========>\n")); + + if (!p_dm_odm->is_linked || !p_dm_odm->is_one_entry_only) { + /* 4 No link or more than one entry */ + odm_cfo_tracking_reset(p_dm_odm); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Reset: is_linked = %d, is_one_entry_only = %d\n", + p_dm_odm->is_linked, p_dm_odm->is_one_entry_only)); + } else { + /* 3 1. CFO Tracking */ + /* 4 1.1 No new packet */ + if (p_cfo_track->packet_count == p_cfo_track->packet_count_pre) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): packet counter doesn't change\n")); + return; + } + p_cfo_track->packet_count_pre = p_cfo_track->packet_count; + + /* 4 1.2 Calculate CFO */ + for (i = 0; i < p_dm_odm->num_rf_path; i++) { + + if (p_cfo_track->CFO_cnt[i] == 0) + continue; + + valid_path_cnt++; + CFO_rpt_sum = (u32)((p_cfo_track->CFO_tail[i] < 0) ? (0 - p_cfo_track->CFO_tail[i]) : p_cfo_track->CFO_tail[i]); + cfo_khz_avg[i] = CFO_HW_RPT_2_MHZ(CFO_rpt_sum) / p_cfo_track->CFO_cnt[i]; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("[path %d] CFO_rpt_sum = (( %d )), CFO_cnt = (( %d )) , CFO_avg= (( %s%d )) kHz\n", + i, CFO_rpt_sum, p_cfo_track->CFO_cnt[i], ((p_cfo_track->CFO_tail[i] < 0) ? "-" : " "), cfo_khz_avg[i])); + } + + for (i = 0; i < valid_path_cnt; i++) { + + /* ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("path [%d], p_cfo_track->CFO_tail = %d\n", i, p_cfo_track->CFO_tail[i])); */ + if (p_cfo_track->CFO_tail[i] < 0) { + CFO_ave += (0 - (s32)cfo_khz_avg[i]); + /* ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("CFO_ave = %d\n", CFO_ave)); */ + } else + CFO_ave += (s32)cfo_khz_avg[i]; + } + + if (valid_path_cnt >= 2) + CFO_ave = CFO_ave / valid_path_cnt; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("valid_path_cnt = ((%d)), CFO_ave = ((%d kHz))\n", valid_path_cnt, CFO_ave)); + + /*reset counter*/ + for (i = 0; i < p_dm_odm->num_rf_path; i++) { + p_cfo_track->CFO_tail[i] = 0; + p_cfo_track->CFO_cnt[i] = 0; + } + + /* 4 1.3 Avoid abnormal large CFO */ + CFO_ave_diff = (p_cfo_track->CFO_ave_pre >= CFO_ave) ? (p_cfo_track->CFO_ave_pre - CFO_ave) : (CFO_ave - p_cfo_track->CFO_ave_pre); + if (CFO_ave_diff > 20 && p_cfo_track->large_cfo_hit == 0 && !p_cfo_track->is_adjust) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): first large CFO hit\n")); + p_cfo_track->large_cfo_hit = 1; + return; + } else + p_cfo_track->large_cfo_hit = 0; + p_cfo_track->CFO_ave_pre = CFO_ave; + + /* 4 1.4 Dynamic Xtal threshold */ + if (p_cfo_track->is_adjust == false) { + if (CFO_ave > CFO_TH_XTAL_HIGH || CFO_ave < (-CFO_TH_XTAL_HIGH)) + p_cfo_track->is_adjust = true; + } else { + if (CFO_ave < CFO_TH_XTAL_LOW && CFO_ave > (-CFO_TH_XTAL_LOW)) + p_cfo_track->is_adjust = false; + } + + /* 4 1.5 BT case: Disable CFO tracking */ + if (p_dm_odm->is_bt_enabled) { + p_cfo_track->is_adjust = false; + odm_set_crystal_cap(p_dm_odm, p_cfo_track->def_x_cap); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Disable CFO tracking for BT!!\n")); + } + + /* 4 1.7 Adjust Crystal Cap. */ + if (p_cfo_track->is_adjust) { + if (CFO_ave > CFO_TH_XTAL_LOW) + crystal_cap = crystal_cap + adjust_xtal; + else if (CFO_ave < (-CFO_TH_XTAL_LOW)) + crystal_cap = crystal_cap - adjust_xtal; + + if (crystal_cap > 0x3f) + crystal_cap = 0x3f; + else if (crystal_cap < 0) + crystal_cap = 0; + + odm_set_crystal_cap(p_dm_odm, (u8)crystal_cap); + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Crystal cap = 0x%x, Default Crystal cap = 0x%x\n", + p_cfo_track->crystal_cap, p_cfo_track->def_x_cap)); + + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) + return; + + /* 3 2. Dynamic ATC switch */ + if (CFO_ave < CFO_TH_ATC && CFO_ave > -CFO_TH_ATC) { + odm_set_atc_status(p_dm_odm, false); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Disable ATC!!\n")); + } else { + odm_set_atc_status(p_dm_odm, true); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Enable ATC!!\n")); + } + } +} + +void +odm_parsing_cfo( + void *p_dm_void, + void *p_pktinfo_void, + s8 *pcfotail, + u8 num_ss +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _odm_per_pkt_info_ *p_pktinfo = (struct _odm_per_pkt_info_ *)p_pktinfo_void; + struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK); + u8 i; + + if (!(p_dm_odm->support_ability & ODM_BB_CFO_TRACKING)) + return; + + if (p_pktinfo->is_packet_match_bssid) { + if (num_ss > p_dm_odm->num_rf_path) /*For fool proof*/ + num_ss = p_dm_odm->num_rf_path; + + /* 3 Update CFO report for path-A & path-B */ + /* Only paht-A and path-B have CFO tail and short CFO */ + for (i = 0; i < num_ss; i++) { + p_cfo_track->CFO_tail[i] += pcfotail[i]; + p_cfo_track->CFO_cnt[i]++; + /*ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("[ID %d][path %d][rate 0x%x] CFO_tail = ((%d)), CFO_tail_sum = ((%d)), CFO_cnt = ((%d))\n", + p_pktinfo->station_id, i, p_pktinfo->data_rate, pcfotail[i], p_cfo_track->CFO_tail[i], p_cfo_track->CFO_cnt[i])); + */ + } + + /* 3 Update packet counter */ + if (p_cfo_track->packet_count == 0xffffffff) + p_cfo_track->packet_count = 0; + else + p_cfo_track->packet_count++; + } +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_cfotracking.h b/drivers/staging/rtl8188eu/hal/phydm_cfotracking.h new file mode 100644 index 000000000000..f59da576653f --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_cfotracking.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDMCFOTRACK_H__ +#define __PHYDMCFOTRACK_H__ + +#define CFO_TRACKING_VERSION "1.4" /*2015.10.01 Stanley, Modify for 8822B*/ + +#define CFO_TH_XTAL_HIGH 20 /* kHz */ +#define CFO_TH_XTAL_LOW 10 /* kHz */ +#define CFO_TH_ATC 80 /* kHz */ + +struct _CFO_TRACKING_ { + bool is_atc_status; + bool large_cfo_hit; + bool is_adjust; + u8 crystal_cap; + u8 def_x_cap; + s32 CFO_tail[4]; + u32 CFO_cnt[4]; + s32 CFO_ave_pre; + u32 packet_count; + u32 packet_count_pre; + + bool is_force_xtal_cap; + bool is_reset; +}; + +void +odm_cfo_tracking_reset( + void *p_dm_void +); + +void +odm_cfo_tracking_init( + void *p_dm_void +); + +void +odm_cfo_tracking( + void *p_dm_void +); + +void +odm_parsing_cfo( + void *p_dm_void, + void *p_pktinfo_void, + s8 *pcfotail, + u8 num_ss +); + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_debug.c b/drivers/staging/rtl8188eu/hal/phydm_debug.c new file mode 100644 index 000000000000..81361eeafb49 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_debug.c @@ -0,0 +1,2357 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* ************************************************************ + * include files + * ************************************************************ */ + +#include "mp_precomp.h" +#include "phydm_precomp.h" + +void +phydm_init_debug_setting( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + p_dm_odm->debug_level = ODM_DBG_TRACE; + + p_dm_odm->fw_debug_components = 0; + p_dm_odm->debug_components = + \ +#if DBG + /*BB Functions*/ + /* ODM_COMP_DIG |*/ + /* ODM_COMP_RA_MASK |*/ + /* ODM_COMP_DYNAMIC_TXPWR |*/ + /* ODM_COMP_FA_CNT |*/ + /* ODM_COMP_RSSI_MONITOR |*/ + /* ODM_COMP_SNIFFER |*/ + /* ODM_COMP_ANT_DIV |*/ + /* ODM_COMP_NOISY_DETECT |*/ + /* ODM_COMP_RATE_ADAPTIVE |*/ + /* ODM_COMP_PATH_DIV |*/ + /* ODM_COMP_DYNAMIC_PRICCA |*/ + /* ODM_COMP_MP |*/ + /* ODM_COMP_CFO_TRACKING |*/ + /* ODM_COMP_ACS |*/ + /* PHYDM_COMP_ADAPTIVITY |*/ + /* PHYDM_COMP_RA_DBG |*/ + /* PHYDM_COMP_TXBF |*/ + + /*MAC Functions*/ + /* ODM_COMP_EDCA_TURBO |*/ + /* ODM_COMP_DYNAMIC_RX_PATH |*/ + /* ODM_FW_DEBUG_TRACE |*/ + + /*RF Functions*/ + /* ODM_COMP_TX_PWR_TRACK |*/ + /* ODM_COMP_CALIBRATION |*/ + + /*Common*/ + /* ODM_PHY_CONFIG |*/ + /* ODM_COMP_INIT |*/ + /* ODM_COMP_COMMON |*/ + /* ODM_COMP_API |*/ + + +#endif + 0; + + p_dm_odm->fw_buff_is_enpty = true; + p_dm_odm->pre_c2h_seq = 0; +} + +#if CONFIG_PHYDM_DEBUG_FUNCTION +static void +phydm_bb_rx_hang_info( + void *p_dm_void, + u32 *_used, + char *output, + u32 *_out_len +) +{ + u32 value32 = 0; + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 used = *_used; + u32 out_len = *_out_len; + + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) + return; + + value32 = odm_get_bb_reg(p_dm_odm, 0xF80, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "rptreg of sc/bw/ht/...", value32)); + + if (p_dm_odm->support_ic_type & ODM_RTL8822B) + odm_set_bb_reg(p_dm_odm, 0x198c, BIT(2) | BIT(1) | BIT(0), 7); + + /* dbg_port = basic state machine */ + { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0x000); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "0x8fc", value32)); + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "basic state machine", value32)); + } + + /* dbg_port = state machine */ + { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0x007); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "0x8fc", value32)); + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "state machine", value32)); + } + + /* dbg_port = CCA-related*/ + { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0x204); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "0x8fc", value32)); + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "CCA-related", value32)); + } + + + /* dbg_port = edcca/rxd*/ + { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0x278); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "0x8fc", value32)); + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "edcca/rxd", value32)); + } + + /* dbg_port = rx_state/mux_state/ADC_MASK_OFDM*/ + { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0x290); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "0x8fc", value32)); + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "rx_state/mux_state/ADC_MASK_OFDM", value32)); + } + + /* dbg_port = bf-related*/ + { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0x2B2); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "0x8fc", value32)); + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "bf-related", value32)); + } + + /* dbg_port = bf-related*/ + { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0x2B8); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "0x8fc", value32)); + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "bf-related", value32)); + } + + /* dbg_port = txon/rxd*/ + { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0xA03); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "0x8fc", value32)); + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "txon/rxd", value32)); + } + + /* dbg_port = l_rate/l_length*/ + { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0xA0B); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "0x8fc", value32)); + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "l_rate/l_length", value32)); + } + + /* dbg_port = rxd/rxd_hit*/ + { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0xA0D); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "0x8fc", value32)); + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "rxd/rxd_hit", value32)); + } + + /* dbg_port = dis_cca*/ + { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0xAA0); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "0x8fc", value32)); + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "dis_cca", value32)); + } + + + /* dbg_port = tx*/ + { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0xAB0); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "0x8fc", value32)); + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "tx", value32)); + } + + /* dbg_port = rx plcp*/ + { + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0xAD0); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "0x8fc", value32)); + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "rx plcp", value32)); + + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0xAD1); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "0x8fc", value32)); + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "rx plcp", value32)); + + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0xAD2); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "0x8fc", value32)); + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "rx plcp", value32)); + + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0xAD3); + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "0x8fc", value32)); + + value32 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = 0x%x", "rx plcp", value32)); + } + +} + +static void +phydm_bb_debug_info_n_series( + void *p_dm_void, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 used = *_used; + u32 out_len = *_out_len; + + u32 value32 = 0, value32_1 = 0, value32_2 = 0, value32_3 = 0; + u8 rf_gain_a = 0, rf_gain_b = 0, rf_gain_c = 0, rf_gain_d = 0; + u8 rx_snr_a = 0, rx_snr_b = 0, rx_snr_c = 0, rx_snr_d = 0; + + s8 rxevm_0 = 0, rxevm_1 = 0; + s32 short_cfo_a = 0, short_cfo_b = 0, long_cfo_a = 0, long_cfo_b = 0; + s32 scfo_a = 0, scfo_b = 0, avg_cfo_a = 0, avg_cfo_b = 0; + s32 cfo_end_a = 0, cfo_end_b = 0, acq_cfo_a = 0, acq_cfo_b = 0; + + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s\n", "BB Report Info")); + + /*AGC result*/ + value32 = odm_get_bb_reg(p_dm_odm, 0xdd0, MASKDWORD); + rf_gain_a = (u8)(value32 & 0x3f); + rf_gain_a = rf_gain_a << 1; + + rf_gain_b = (u8)((value32 >> 8) & 0x3f); + rf_gain_b = rf_gain_b << 1; + + rf_gain_c = (u8)((value32 >> 16) & 0x3f); + rf_gain_c = rf_gain_c << 1; + + rf_gain_d = (u8)((value32 >> 24) & 0x3f); + rf_gain_d = rf_gain_d << 1; + + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d / %d / %d", "OFDM RX RF Gain(A/B/C/D)", rf_gain_a, rf_gain_b, rf_gain_c, rf_gain_d)); + + /*SNR report*/ + value32 = odm_get_bb_reg(p_dm_odm, 0xdd4, MASKDWORD); + rx_snr_a = (u8)(value32 & 0xff); + rx_snr_a = rx_snr_a >> 1; + + rx_snr_b = (u8)((value32 >> 8) & 0xff); + rx_snr_b = rx_snr_b >> 1; + + rx_snr_c = (u8)((value32 >> 16) & 0xff); + rx_snr_c = rx_snr_c >> 1; + + rx_snr_d = (u8)((value32 >> 24) & 0xff); + rx_snr_d = rx_snr_d >> 1; + + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d / %d / %d", "RXSNR(A/B/C/D, dB)", rx_snr_a, rx_snr_b, rx_snr_c, rx_snr_d)); + + /* PostFFT related info*/ + value32 = odm_get_bb_reg(p_dm_odm, 0xdd8, MASKDWORD); + + rxevm_0 = (s8)((value32 & MASKBYTE2) >> 16); + rxevm_0 /= 2; + if (rxevm_0 < -63) + rxevm_0 = 0; + + rxevm_1 = (s8)((value32 & MASKBYTE3) >> 24); + rxevm_1 /= 2; + if (rxevm_1 < -63) + rxevm_1 = 0; + + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d", "RXEVM (1ss/2ss)", rxevm_0, rxevm_1)); + + /*CFO Report Info*/ + odm_set_bb_reg(p_dm_odm, 0xd00, BIT(26), 1); + + /*Short CFO*/ + value32 = odm_get_bb_reg(p_dm_odm, 0xdac, MASKDWORD); + value32_1 = odm_get_bb_reg(p_dm_odm, 0xdb0, MASKDWORD); + + short_cfo_b = (s32)(value32 & 0xfff); /*S(12,11)*/ + short_cfo_a = (s32)((value32 & 0x0fff0000) >> 16); + + long_cfo_b = (s32)(value32_1 & 0x1fff); /*S(13,12)*/ + long_cfo_a = (s32)((value32_1 & 0x1fff0000) >> 16); + + /*SFO 2's to dec*/ + if (short_cfo_a > 2047) + short_cfo_a = short_cfo_a - 4096; + if (short_cfo_b > 2047) + short_cfo_b = short_cfo_b - 4096; + + short_cfo_a = (short_cfo_a * 312500) / 2048; + short_cfo_b = (short_cfo_b * 312500) / 2048; + + /*LFO 2's to dec*/ + + if (long_cfo_a > 4095) + long_cfo_a = long_cfo_a - 8192; + + if (long_cfo_b > 4095) + long_cfo_b = long_cfo_b - 8192; + + long_cfo_a = long_cfo_a * 312500 / 4096; + long_cfo_b = long_cfo_b * 312500 / 4096; + + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s", "CFO Report Info")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d", "Short CFO(Hz) ", short_cfo_a, short_cfo_b)); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d", "Long CFO(Hz) ", long_cfo_a, long_cfo_b)); + + /*SCFO*/ + value32 = odm_get_bb_reg(p_dm_odm, 0xdb8, MASKDWORD); + value32_1 = odm_get_bb_reg(p_dm_odm, 0xdb4, MASKDWORD); + + scfo_b = (s32)(value32 & 0x7ff); /*S(11,10)*/ + scfo_a = (s32)((value32 & 0x07ff0000) >> 16); + + if (scfo_a > 1023) + scfo_a = scfo_a - 2048; + + if (scfo_b > 1023) + scfo_b = scfo_b - 2048; + + scfo_a = scfo_a * 312500 / 1024; + scfo_b = scfo_b * 312500 / 1024; + + avg_cfo_b = (s32)(value32_1 & 0x1fff); /*S(13,12)*/ + avg_cfo_a = (s32)((value32_1 & 0x1fff0000) >> 16); + + if (avg_cfo_a > 4095) + avg_cfo_a = avg_cfo_a - 8192; + + if (avg_cfo_b > 4095) + avg_cfo_b = avg_cfo_b - 8192; + + avg_cfo_a = avg_cfo_a * 312500 / 4096; + avg_cfo_b = avg_cfo_b * 312500 / 4096; + + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d", "value SCFO(Hz) ", scfo_a, scfo_b)); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d", "Avg CFO(Hz) ", avg_cfo_a, avg_cfo_b)); + + value32 = odm_get_bb_reg(p_dm_odm, 0xdbc, MASKDWORD); + value32_1 = odm_get_bb_reg(p_dm_odm, 0xde0, MASKDWORD); + + cfo_end_b = (s32)(value32 & 0x1fff); /*S(13,12)*/ + cfo_end_a = (s32)((value32 & 0x1fff0000) >> 16); + + if (cfo_end_a > 4095) + cfo_end_a = cfo_end_a - 8192; + + if (cfo_end_b > 4095) + cfo_end_b = cfo_end_b - 8192; + + cfo_end_a = cfo_end_a * 312500 / 4096; + cfo_end_b = cfo_end_b * 312500 / 4096; + + acq_cfo_b = (s32)(value32_1 & 0x1fff); /*S(13,12)*/ + acq_cfo_a = (s32)((value32_1 & 0x1fff0000) >> 16); + + if (acq_cfo_a > 4095) + acq_cfo_a = acq_cfo_a - 8192; + + if (acq_cfo_b > 4095) + acq_cfo_b = acq_cfo_b - 8192; + + acq_cfo_a = acq_cfo_a * 312500 / 4096; + acq_cfo_b = acq_cfo_b * 312500 / 4096; + + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d", "End CFO(Hz) ", cfo_end_a, cfo_end_b)); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d", "ACQ CFO(Hz) ", acq_cfo_a, acq_cfo_b)); + +} + + +static void +phydm_bb_debug_info( + void *p_dm_void, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 used = *_used; + u32 out_len = *_out_len; + + char *tmp_string = NULL; + + u8 RX_HT_BW, RX_VHT_BW, RXSC, RX_HT, RX_BW; + static u8 v_rx_bw ; + u32 value32, value32_1, value32_2, value32_3; + s32 SFO_A, SFO_B, SFO_C, SFO_D; + s32 LFO_A, LFO_B, LFO_C, LFO_D; + static u8 MCSS, tail, parity, rsv, vrsv, idx, smooth, htsound, agg, stbc, vstbc, fec, fecext, sgi, sgiext, htltf, vgid, v_nsts, vtxops, vrsv2, vbrsv, bf, vbcrc; + static u16 h_length, htcrc8, length; + static u16 vpaid; + static u16 v_length, vhtcrc8, v_mcss, v_tail, vb_tail; + static u8 HMCSS, HRX_BW; + + u8 pwdb; + s8 RXEVM_0, RXEVM_1, RXEVM_2 ; + u8 rf_gain_path_a, rf_gain_path_b, rf_gain_path_c, rf_gain_path_d; + u8 rx_snr_path_a, rx_snr_path_b, rx_snr_path_c, rx_snr_path_d; + s32 sig_power; + const char *L_rate[8] = {"6M", "9M", "12M", "18M", "24M", "36M", "48M", "54M"}; + + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + phydm_bb_debug_info_n_series(p_dm_odm, &used, output, &out_len); + return; + } + + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s\n", "BB Report Info")); + + /*BW & mode Detection*/ + + value32 = odm_get_bb_reg(p_dm_odm, 0xf80, MASKDWORD); + value32_2 = value32; + RX_HT_BW = (u8)(value32 & 0x1); + RX_VHT_BW = (u8)((value32 >> 1) & 0x3); + RXSC = (u8)(value32 & 0x78); + value32_1 = (value32 & 0x180) >> 7; + RX_HT = (u8)(value32_1); + + RX_BW = 0; + + if (RX_HT == 2) { + if (RX_VHT_BW == 0) + tmp_string = "20M"; + else if (RX_VHT_BW == 1) + tmp_string = "40M"; + else + tmp_string = "80M"; + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s %s %s", "mode", "VHT", tmp_string)); + RX_BW = RX_VHT_BW; + } else if (RX_HT == 1) { + if (RX_HT_BW == 0) + tmp_string = "20M"; + else if (RX_HT_BW == 1) + tmp_string = "40M"; + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s %s %s", "mode", "HT", tmp_string)); + RX_BW = RX_HT_BW; + } else + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s %s", "mode", "Legacy")); + + if (RX_HT != 0) { + if (RXSC == 0) + tmp_string = "duplicate/full bw"; + else if (RXSC == 1) + tmp_string = "usc20-1"; + else if (RXSC == 2) + tmp_string = "lsc20-1"; + else if (RXSC == 3) + tmp_string = "usc20-2"; + else if (RXSC == 4) + tmp_string = "lsc20-2"; + else if (RXSC == 9) + tmp_string = "usc40"; + else if (RXSC == 10) + tmp_string = "lsc40"; + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s", tmp_string)); + } + + /* RX signal power and AGC related info*/ + + value32 = odm_get_bb_reg(p_dm_odm, 0xF90, MASKDWORD); + pwdb = (u8)((value32 & MASKBYTE1) >> 8); + pwdb = pwdb >> 1; + sig_power = -110 + pwdb; + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d", "OFDM RX Signal Power(dB)", sig_power)); + + value32 = odm_get_bb_reg(p_dm_odm, 0xd14, MASKDWORD); + rx_snr_path_a = (u8)(value32 & 0xFF) >> 1; + rf_gain_path_a = (s8)((value32 & MASKBYTE1) >> 8); + rf_gain_path_a *= 2; + value32 = odm_get_bb_reg(p_dm_odm, 0xd54, MASKDWORD); + rx_snr_path_b = (u8)(value32 & 0xFF) >> 1; + rf_gain_path_b = (s8)((value32 & MASKBYTE1) >> 8); + rf_gain_path_b *= 2; + value32 = odm_get_bb_reg(p_dm_odm, 0xd94, MASKDWORD); + rx_snr_path_c = (u8)(value32 & 0xFF) >> 1; + rf_gain_path_c = (s8)((value32 & MASKBYTE1) >> 8); + rf_gain_path_c *= 2; + value32 = odm_get_bb_reg(p_dm_odm, 0xdd4, MASKDWORD); + rx_snr_path_d = (u8)(value32 & 0xFF) >> 1; + rf_gain_path_d = (s8)((value32 & MASKBYTE1) >> 8); + rf_gain_path_d *= 2; + + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d / %d / %d", "OFDM RX RF Gain(A/B/C/D)", rf_gain_path_a, rf_gain_path_b, rf_gain_path_c, rf_gain_path_d)); + + + /* RX counter related info*/ + + value32 = odm_get_bb_reg(p_dm_odm, 0xF08, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d", "OFDM CCA counter", ((value32 & 0xFFFF0000) >> 16))); + + value32 = odm_get_bb_reg(p_dm_odm, 0xFD0, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d", "OFDM SBD Fail counter", value32 & 0xFFFF)); + + value32 = odm_get_bb_reg(p_dm_odm, 0xFC4, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d", "VHT SIGA/SIGB CRC8 Fail counter", value32 & 0xFFFF, ((value32 & 0xFFFF0000) >> 16))); + + value32 = odm_get_bb_reg(p_dm_odm, 0xFCC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d", "CCK CCA counter", value32 & 0xFFFF)); + + value32 = odm_get_bb_reg(p_dm_odm, 0xFBC, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d", "LSIG (parity Fail/rate Illegal) counter", value32 & 0xFFFF, ((value32 & 0xFFFF0000) >> 16))); + + value32_1 = odm_get_bb_reg(p_dm_odm, 0xFC8, MASKDWORD); + value32_2 = odm_get_bb_reg(p_dm_odm, 0xFC0, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d", "HT/VHT MCS NOT SUPPORT counter", ((value32_2 & 0xFFFF0000) >> 16), value32_1 & 0xFFFF)); + + /* PostFFT related info*/ + value32 = odm_get_bb_reg(p_dm_odm, 0xF8c, MASKDWORD); + RXEVM_0 = (s8)((value32 & MASKBYTE2) >> 16); + RXEVM_0 /= 2; + if (RXEVM_0 < -63) + RXEVM_0 = 0; + + RXEVM_1 = (s8)((value32 & MASKBYTE3) >> 24); + RXEVM_1 /= 2; + value32 = odm_get_bb_reg(p_dm_odm, 0xF88, MASKDWORD); + RXEVM_2 = (s8)((value32 & MASKBYTE2) >> 16); + RXEVM_2 /= 2; + + if (RXEVM_1 < -63) + RXEVM_1 = 0; + if (RXEVM_2 < -63) + RXEVM_2 = 0; + + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d / %d", "RXEVM (1ss/2ss/3ss)", RXEVM_0, RXEVM_1, RXEVM_2)); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d / %d / %d", "RXSNR(A/B/C/D, dB)", rx_snr_path_a, rx_snr_path_b, rx_snr_path_c, rx_snr_path_d)); + + value32 = odm_get_bb_reg(p_dm_odm, 0xF8C, MASKDWORD); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d", "CSI_1st /CSI_2nd", value32 & 0xFFFF, ((value32 & 0xFFFF0000) >> 16))); + + /*BW & mode Detection*/ + + /*Reset Page F counter*/ + odm_set_bb_reg(p_dm_odm, 0xB58, BIT(0), 1); + odm_set_bb_reg(p_dm_odm, 0xB58, BIT(0), 0); + + /*CFO Report Info*/ + /*Short CFO*/ + value32 = odm_get_bb_reg(p_dm_odm, 0xd0c, MASKDWORD); + value32_1 = odm_get_bb_reg(p_dm_odm, 0xd4c, MASKDWORD); + value32_2 = odm_get_bb_reg(p_dm_odm, 0xd8c, MASKDWORD); + value32_3 = odm_get_bb_reg(p_dm_odm, 0xdcc, MASKDWORD); + + SFO_A = (s32)(value32 & 0xfff); + SFO_B = (s32)(value32_1 & 0xfff); + SFO_C = (s32)(value32_2 & 0xfff); + SFO_D = (s32)(value32_3 & 0xfff); + + LFO_A = (s32)(value32 >> 16); + LFO_B = (s32)(value32_1 >> 16); + LFO_C = (s32)(value32_2 >> 16); + LFO_D = (s32)(value32_3 >> 16); + + /*SFO 2's to dec*/ + if (SFO_A > 2047) + SFO_A = SFO_A - 4096; + SFO_A = (SFO_A * 312500) / 2048; + if (SFO_B > 2047) + SFO_B = SFO_B - 4096; + SFO_B = (SFO_B * 312500) / 2048; + if (SFO_C > 2047) + SFO_C = SFO_C - 4096; + SFO_C = (SFO_C * 312500) / 2048; + if (SFO_D > 2047) + SFO_D = SFO_D - 4096; + SFO_D = (SFO_D * 312500) / 2048; + + /*LFO 2's to dec*/ + + if (LFO_A > 4095) + LFO_A = LFO_A - 8192; + + if (LFO_B > 4095) + LFO_B = LFO_B - 8192; + + if (LFO_C > 4095) + LFO_C = LFO_C - 8192; + + if (LFO_D > 4095) + LFO_D = LFO_D - 8192; + LFO_A = LFO_A * 312500 / 4096; + LFO_B = LFO_B * 312500 / 4096; + LFO_C = LFO_C * 312500 / 4096; + LFO_D = LFO_D * 312500 / 4096; + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s", "CFO Report Info")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d / %d /%d", "Short CFO(Hz) ", SFO_A, SFO_B, SFO_C, SFO_D)); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d / %d /%d", "Long CFO(Hz) ", LFO_A, LFO_B, LFO_C, LFO_D)); + + /*SCFO*/ + value32 = odm_get_bb_reg(p_dm_odm, 0xd10, MASKDWORD); + value32_1 = odm_get_bb_reg(p_dm_odm, 0xd50, MASKDWORD); + value32_2 = odm_get_bb_reg(p_dm_odm, 0xd90, MASKDWORD); + value32_3 = odm_get_bb_reg(p_dm_odm, 0xdd0, MASKDWORD); + + SFO_A = (s32)(value32 & 0x7ff); + SFO_B = (s32)(value32_1 & 0x7ff); + SFO_C = (s32)(value32_2 & 0x7ff); + SFO_D = (s32)(value32_3 & 0x7ff); + + if (SFO_A > 1023) + SFO_A = SFO_A - 2048; + + if (SFO_B > 2047) + SFO_B = SFO_B - 4096; + + if (SFO_C > 2047) + SFO_C = SFO_C - 4096; + + if (SFO_D > 2047) + SFO_D = SFO_D - 4096; + + SFO_A = SFO_A * 312500 / 1024; + SFO_B = SFO_B * 312500 / 1024; + SFO_C = SFO_C * 312500 / 1024; + SFO_D = SFO_D * 312500 / 1024; + + LFO_A = (s32)(value32 >> 16); + LFO_B = (s32)(value32_1 >> 16); + LFO_C = (s32)(value32_2 >> 16); + LFO_D = (s32)(value32_3 >> 16); + + if (LFO_A > 4095) + LFO_A = LFO_A - 8192; + + if (LFO_B > 4095) + LFO_B = LFO_B - 8192; + + if (LFO_C > 4095) + LFO_C = LFO_C - 8192; + + if (LFO_D > 4095) + LFO_D = LFO_D - 8192; + LFO_A = LFO_A * 312500 / 4096; + LFO_B = LFO_B * 312500 / 4096; + LFO_C = LFO_C * 312500 / 4096; + LFO_D = LFO_D * 312500 / 4096; + + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d / %d /%d", "value SCFO(Hz) ", SFO_A, SFO_B, SFO_C, SFO_D)); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d / %d /%d", "ACQ CFO(Hz) ", LFO_A, LFO_B, LFO_C, LFO_D)); + + value32 = odm_get_bb_reg(p_dm_odm, 0xd14, MASKDWORD); + value32_1 = odm_get_bb_reg(p_dm_odm, 0xd54, MASKDWORD); + value32_2 = odm_get_bb_reg(p_dm_odm, 0xd94, MASKDWORD); + value32_3 = odm_get_bb_reg(p_dm_odm, 0xdd4, MASKDWORD); + + LFO_A = (s32)(value32 >> 16); + LFO_B = (s32)(value32_1 >> 16); + LFO_C = (s32)(value32_2 >> 16); + LFO_D = (s32)(value32_3 >> 16); + + if (LFO_A > 4095) + LFO_A = LFO_A - 8192; + + if (LFO_B > 4095) + LFO_B = LFO_B - 8192; + + if (LFO_C > 4095) + LFO_C = LFO_C - 8192; + + if (LFO_D > 4095) + LFO_D = LFO_D - 8192; + + LFO_A = LFO_A * 312500 / 4096; + LFO_B = LFO_B * 312500 / 4096; + LFO_C = LFO_C * 312500 / 4096; + LFO_D = LFO_D * 312500 / 4096; + + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d / %d / %d /%d", "End CFO(Hz) ", LFO_A, LFO_B, LFO_C, LFO_D)); + + value32 = odm_get_bb_reg(p_dm_odm, 0xf20, MASKDWORD); /*L SIG*/ + + tail = (u8)((value32 & 0xfc0000) >> 16); + parity = (u8)((value32 & 0x20000) >> 16); + length = (u16)((value32 & 0x1ffe00) >> 8); + rsv = (u8)(value32 & 0x10); + MCSS = (u8)(value32 & 0x0f); + + switch (MCSS) { + case 0x0b: + idx = 0; + break; + case 0x0f: + idx = 1; + break; + case 0x0a: + idx = 2; + break; + case 0x0e: + idx = 3; + break; + case 0x09: + idx = 4; + break; + case 0x08: + idx = 5; + break; + case 0x0c: + idx = 6; + break; + default: + idx = 6; + break; + + } + + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s", "L-SIG")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s : %s", "rate", L_rate[idx])); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %x / %x / %x", "Rsv/length/parity", rsv, RX_BW, length)); + + value32 = odm_get_bb_reg(p_dm_odm, 0xf2c, MASKDWORD); /*HT SIG*/ + if (RX_HT == 1) { + + HMCSS = (u8)(value32 & 0x7F); + HRX_BW = (u8)(value32 & 0x80); + h_length = (u16)((value32 >> 8) & 0xffff); + } + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s", "HT-SIG1")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %x / %x / %x", "MCS/BW/length", HMCSS, HRX_BW, h_length)); + + value32 = odm_get_bb_reg(p_dm_odm, 0xf30, MASKDWORD); /*HT SIG*/ + + if (RX_HT == 1) { + smooth = (u8)(value32 & 0x01); + htsound = (u8)(value32 & 0x02); + rsv = (u8)(value32 & 0x04); + agg = (u8)(value32 & 0x08); + stbc = (u8)(value32 & 0x30); + fec = (u8)(value32 & 0x40); + sgi = (u8)(value32 & 0x80); + htltf = (u8)((value32 & 0x300) >> 8); + htcrc8 = (u16)((value32 & 0x3fc00) >> 8); + tail = (u8)((value32 & 0xfc0000) >> 16); + } + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s", "HT-SIG2")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %x / %x / %x / %x / %x / %x", "Smooth/NoSound/Rsv/Aggregate/STBC/LDPC", smooth, htsound, rsv, agg, stbc, fec)); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %x / %x / %x / %x", "SGI/E-HT-LTFs/CRC/tail", sgi, htltf, htcrc8, tail)); + + value32 = odm_get_bb_reg(p_dm_odm, 0xf2c, MASKDWORD); /*VHT SIG A1*/ + if (RX_HT == 2) { + /* value32 = odm_get_bb_reg(p_dm_odm, 0xf2c,MASKDWORD);*/ + v_rx_bw = (u8)(value32 & 0x03); + vrsv = (u8)(value32 & 0x04); + vstbc = (u8)(value32 & 0x08); + vgid = (u8)((value32 & 0x3f0) >> 4); + v_nsts = (u8)(((value32 & 0x1c00) >> 8) + 1); + vpaid = (u16)(value32 & 0x3fe); + vtxops = (u8)((value32 & 0x400000) >> 20); + vrsv2 = (u8)((value32 & 0x800000) >> 20); + } + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s", "VHT-SIG-A1")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %x / %x / %x / %x / %x / %x / %x / %x", "BW/Rsv1/STBC/GID/Nsts/PAID/TXOPPS/Rsv2", v_rx_bw, vrsv, vstbc, vgid, v_nsts, vpaid, vtxops, vrsv2)); + + value32 = odm_get_bb_reg(p_dm_odm, 0xf30, MASKDWORD); /*VHT SIG*/ + + if (RX_HT == 2) { + /*value32 = odm_get_bb_reg(p_dm_odm, 0xf30,MASKDWORD); */ /*VHT SIG*/ + + /* sgi=(u8)(value32&0x01); */ + sgiext = (u8)(value32 & 0x03); + /* fec = (u8)(value32&0x04); */ + fecext = (u8)(value32 & 0x0C); + + v_mcss = (u8)(value32 & 0xf0); + bf = (u8)((value32 & 0x100) >> 8); + vrsv = (u8)((value32 & 0x200) >> 8); + vhtcrc8 = (u16)((value32 & 0x3fc00) >> 8); + v_tail = (u8)((value32 & 0xfc0000) >> 16); + } + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s", "VHT-SIG-A2")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %x / %x / %x / %x / %x / %x / %x", "SGI/FEC/MCS/BF/Rsv/CRC/tail", sgiext, fecext, v_mcss, bf, vrsv, vhtcrc8, v_tail)); + + value32 = odm_get_bb_reg(p_dm_odm, 0xf34, MASKDWORD); /*VHT SIG*/ + { + v_length = (u16)(value32 & 0x1fffff); + vbrsv = (u8)((value32 & 0x600000) >> 20); + vb_tail = (u16)((value32 & 0x1f800000) >> 20); + vbcrc = (u8)((value32 & 0x80000000) >> 28); + + } + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s", "VHT-SIG-B")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %x / %x / %x / %x", "length/Rsv/tail/CRC", v_length, vbrsv, vb_tail, vbcrc)); + + /*for Condition number*/ + if (p_dm_odm->support_ic_type & ODM_RTL8822B) { + s32 condition_num = 0; + char *factor = NULL; + + odm_set_bb_reg(p_dm_odm, 0x1988, BIT(22), 0x1); /*enable report condition number*/ + + condition_num = odm_get_bb_reg(p_dm_odm, 0xf84, MASKDWORD); + condition_num = (condition_num & 0x3ffff) >> 4; + + if (*p_dm_odm->p_band_width == ODM_BW80M) + factor = "256/234"; + else if (*p_dm_odm->p_band_width == ODM_BW40M) + factor = "128/108"; + else if (*p_dm_odm->p_band_width == ODM_BW20M) { + if (RX_HT != 2 || RX_HT != 1) + factor = "64/52"; /*HT or VHT*/ + else + factor = "64/48"; /*legacy*/ + } + + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = %d (factor = %s)", "Condition number", condition_num, factor)); + + } + +} +#endif /*#if CONFIG_PHYDM_DEBUG_FUNCTION*/ + +void +phydm_basic_dbg_message +( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct false_ALARM_STATISTICS *false_alm_cnt = (struct false_ALARM_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDMfalseALMCNT); + struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK); + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + u16 macid, phydm_macid, client_cnt = 0; + struct sta_info *p_entry; + s32 tmp_val = 0; + u8 tmp_val_u1 = 0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("[PHYDM Common MSG] System up time: ((%d sec))----->\n", p_dm_odm->phydm_sys_up_time)); + + if (p_dm_odm->is_linked) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("Curr_STA_ID = 0x%x\n", p_dm_odm->curr_station_id)); + + /*Print RX rate*/ + if (p_dm_odm->rx_rate <= ODM_RATE11M) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("[CCK AGC Report] LNA_idx = 0x%x, VGA_idx = 0x%x\n", + p_dm_odm->cck_lna_idx, p_dm_odm->cck_vga_idx)); + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("[OFDM AGC Report] { 0x%x, 0x%x, 0x%x, 0x%x }\n", + p_dm_odm->ofdm_agc_idx[0], p_dm_odm->ofdm_agc_idx[1], p_dm_odm->ofdm_agc_idx[2], p_dm_odm->ofdm_agc_idx[3])); + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("RSSI: { %d, %d, %d, %d }, rx_rate:", + (p_dm_odm->RSSI_A == 0xff) ? 0 : p_dm_odm->RSSI_A, + (p_dm_odm->RSSI_B == 0xff) ? 0 : p_dm_odm->RSSI_B, + (p_dm_odm->RSSI_C == 0xff) ? 0 : p_dm_odm->RSSI_C, + (p_dm_odm->RSSI_D == 0xff) ? 0 : p_dm_odm->RSSI_D)); + + phydm_print_rate(p_dm_odm, p_dm_odm->rx_rate, ODM_COMP_COMMON); + + /*Print TX rate*/ + for (macid = 0; macid < ODM_ASSOCIATE_ENTRY_NUM; macid++) { + + p_entry = p_dm_odm->p_odm_sta_info[macid]; + if (IS_STA_VALID(p_entry)) { + + phydm_macid = (p_dm_odm->platform2phydm_macid_table[macid]); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("TXRate [%d]:", macid)); + phydm_print_rate(p_dm_odm, p_ra_table->link_tx_rate[macid], ODM_COMP_COMMON); + + client_cnt++; + + if (client_cnt == p_dm_odm->number_linked_client) + break; + } + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("TP { TX, RX, total} = {%d, %d, %d }Mbps, traffic_load = (%d))\n", + p_dm_odm->tx_tp, p_dm_odm->rx_tp, p_dm_odm->total_tp, p_dm_odm->traffic_load)); + + tmp_val_u1 = (p_cfo_track->crystal_cap > p_cfo_track->def_x_cap) ? (p_cfo_track->crystal_cap - p_cfo_track->def_x_cap) : (p_cfo_track->def_x_cap - p_cfo_track->crystal_cap); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("CFO_avg = ((%d kHz)) , CrystalCap_tracking = ((%s%d))\n", + p_cfo_track->CFO_ave_pre, ((p_cfo_track->crystal_cap > p_cfo_track->def_x_cap) ? "+" : "-"), tmp_val_u1)); + +#if (ODM_PHY_STATUS_NEW_TYPE_SUPPORT == 1) + /*STBC or LDPC pkt*/ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("LDPC = %s, STBC = %s\n", (p_dm_odm->phy_dbg_info.is_ldpc_pkt) ? "Y" : "N", (p_dm_odm->phy_dbg_info.is_stbc_pkt) ? "Y" : "N")); +#endif + } else + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("No Link !!!\n")); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("[CCA Cnt] {CCK, OFDM, Total} = {%d, %d, %d}\n", + false_alm_cnt->cnt_cck_cca, false_alm_cnt->cnt_ofdm_cca, false_alm_cnt->cnt_cca_all)); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("[FA Cnt] {CCK, OFDM, Total} = {%d, %d, %d}\n", + false_alm_cnt->cnt_cck_fail, false_alm_cnt->cnt_ofdm_fail, false_alm_cnt->cnt_all)); + +#if (ODM_IC_11N_SERIES_SUPPORT == 1) + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("[OFDM FA Detail] Parity_Fail = (( %d )), Rate_Illegal = (( %d )), CRC8_fail = (( %d )), Mcs_fail = (( %d )), Fast_Fsync = (( %d )), SB_Search_fail = (( %d ))\n", + false_alm_cnt->cnt_parity_fail, false_alm_cnt->cnt_rate_illegal, false_alm_cnt->cnt_crc8_fail, false_alm_cnt->cnt_mcs_fail, false_alm_cnt->cnt_fast_fsync, false_alm_cnt->cnt_sb_search_fail)); + } +#endif + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("is_linked = %d, Num_client = %d, rssi_min = %d, current_igi = 0x%x, bNoisy=%d\n\n", + p_dm_odm->is_linked, p_dm_odm->number_linked_client, p_dm_odm->rssi_min, p_dm_dig_table->cur_ig_value, p_dm_odm->noisy_decision)); +} + +void phydm_basic_profile( + void *p_dm_void, + u32 *_used, + char *output, + u32 *_out_len +) +{ +#if CONFIG_PHYDM_DEBUG_FUNCTION + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + char *cut = NULL; + char *ic_type = NULL; + u32 used = *_used; + u32 out_len = *_out_len; + u32 commit_ver = 0; + u32 date = 0; + char *commit_by = NULL; + u32 release_ver = 0; + + PHYDM_SNPRINTF((output + used, out_len - used, "%-35s\n", "% Basic Profile %")); + + if (p_dm_odm->support_ic_type == ODM_RTL8188E) { + ic_type = "RTL8188E"; + date = RELEASE_DATE_8188E; + commit_by = COMMIT_BY_8188E; + release_ver = RELEASE_VERSION_8188E; + } + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s (MP Chip: %s)\n", "IC type", ic_type, p_dm_odm->is_mp_chip ? "Yes" : "No")); + + if (p_dm_odm->cut_version == ODM_CUT_A) + cut = "A"; + else if (p_dm_odm->cut_version == ODM_CUT_B) + cut = "B"; + else if (p_dm_odm->cut_version == ODM_CUT_C) + cut = "C"; + else if (p_dm_odm->cut_version == ODM_CUT_D) + cut = "D"; + else if (p_dm_odm->cut_version == ODM_CUT_E) + cut = "E"; + else if (p_dm_odm->cut_version == ODM_CUT_F) + cut = "F"; + else if (p_dm_odm->cut_version == ODM_CUT_I) + cut = "I"; + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "cut version", cut)); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %d\n", "PHY Parameter version", odm_get_hw_img_version(p_dm_odm))); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %d\n", "PHY Parameter Commit date", date)); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "PHY Parameter Commit by", commit_by)); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %d\n", "PHY Parameter Release version", release_ver)); + + { + struct _ADAPTER *adapter = p_dm_odm->adapter; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(adapter); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %d (Subversion: %d)\n", "FW version", p_hal_data->firmware_version, p_hal_data->firmware_sub_version)); + } + /* 1 PHY DM version List */ + PHYDM_SNPRINTF((output + used, out_len - used, "%-35s\n", "% PHYDM version %")); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "Code base", PHYDM_CODE_BASE)); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "Release Date", PHYDM_RELEASE_DATE)); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "adaptivity", ADAPTIVITY_VERSION)); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "DIG", DIG_VERSION)); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "Dynamic BB PowerSaving", DYNAMIC_BBPWRSAV_VERSION)); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "CFO Tracking", CFO_TRACKING_VERSION)); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "Antenna Diversity", ANTDIV_VERSION)); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "Power Tracking", POWRTRACKING_VERSION)); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "Dynamic TxPower", DYNAMIC_TXPWR_VERSION)); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "RA Info", RAINFO_VERSION)); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "Auto channel Selection", ACS_VERSION)); +#if PHYDM_SUPPORT_EDCA + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "EDCA Turbo", EDCATURBO_VERSION)); +#endif + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "path Diversity", PATHDIV_VERSION)); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "LA mode", DYNAMIC_LA_MODE)); + PHYDM_SNPRINTF((output + used, out_len - used, " %-35s: %s\n", "Dynamic RX path", DYNAMIC_RX_PATH_VERSION)); + + *_used = used; + *_out_len = out_len; +#endif /*#if CONFIG_PHYDM_DEBUG_FUNCTION*/ +} + +#if CONFIG_PHYDM_DEBUG_FUNCTION +void +phydm_fw_trace_en_h2c( + void *p_dm_void, + bool enable, + u32 fw_debug_component, + u32 monitor_mode, + u32 macid +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 h2c_parameter[7] = {0}; + u8 cmd_length; + + if (p_dm_odm->support_ic_type & PHYDM_IC_3081_SERIES) { + + h2c_parameter[0] = enable; + h2c_parameter[1] = (u8)(fw_debug_component & MASKBYTE0); + h2c_parameter[2] = (u8)((fw_debug_component & MASKBYTE1) >> 8); + h2c_parameter[3] = (u8)((fw_debug_component & MASKBYTE2) >> 16); + h2c_parameter[4] = (u8)((fw_debug_component & MASKBYTE3) >> 24); + h2c_parameter[5] = (u8)monitor_mode; + h2c_parameter[6] = (u8)macid; + cmd_length = 7; + + } else { + + h2c_parameter[0] = enable; + h2c_parameter[1] = (u8)monitor_mode; + h2c_parameter[2] = (u8)macid; + cmd_length = 3; + } + + + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("---->\n")); + if (monitor_mode == 0) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[H2C] FW_debug_en: (( %d ))\n", enable)); + else + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[H2C] FW_debug_en: (( %d )), mode: (( %d )), macid: (( %d ))\n", enable, monitor_mode, macid)); + odm_fill_h2c_cmd(p_dm_odm, PHYDM_H2C_FW_TRACE_EN, cmd_length, h2c_parameter); +} + +static void +phydm_get_per_path_txagc( + void *p_dm_void, + u8 path, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 rate_idx; + u8 txagc; + u32 used = *_used; + u32 out_len = *_out_len; + +} + +static void +phydm_get_txagc( + void *p_dm_void, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 used = *_used; + u32 out_len = *_out_len; + + /* path-A */ + PHYDM_SNPRINTF((output + used, out_len - used, "%-35s\n", "path-A====================")); + phydm_get_per_path_txagc(p_dm_odm, ODM_RF_PATH_A, _used, output, _out_len); + + /* path-B */ + PHYDM_SNPRINTF((output + used, out_len - used, "\n%-35s\n", "path-B====================")); + phydm_get_per_path_txagc(p_dm_odm, ODM_RF_PATH_B, _used, output, _out_len); + + /* path-C */ + PHYDM_SNPRINTF((output + used, out_len - used, "\n%-35s\n", "path-C====================")); + phydm_get_per_path_txagc(p_dm_odm, ODM_RF_PATH_C, _used, output, _out_len); + + /* path-D */ + PHYDM_SNPRINTF((output + used, out_len - used, "\n%-35s\n", "path-D====================")); + phydm_get_per_path_txagc(p_dm_odm, ODM_RF_PATH_D, _used, output, _out_len); + +} + +static void +phydm_set_txagc( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 used = *_used; + u32 out_len = *_out_len; + + /*dm_value[1] = path*/ + /*dm_value[2] = hw_rate*/ + /*dm_value[3] = power_index*/ +} + +static void +phydm_debug_trace( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 pre_debug_components, one = 1; + u32 used = *_used; + u32 out_len = *_out_len; + + pre_debug_components = p_dm_odm->debug_components; + + PHYDM_SNPRINTF((output + used, out_len - used, "\n%s\n", "================================")); + if (dm_value[0] == 100) { + PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "[Debug Message] PhyDM Selection")); + PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "================================")); + PHYDM_SNPRINTF((output + used, out_len - used, "00. (( %s ))DIG\n", ((p_dm_odm->debug_components & ODM_COMP_DIG) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "01. (( %s ))RA_MASK\n", ((p_dm_odm->debug_components & ODM_COMP_RA_MASK) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "02. (( %s ))DYNAMIC_TXPWR\n", ((p_dm_odm->debug_components & ODM_COMP_DYNAMIC_TXPWR) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "03. (( %s ))FA_CNT\n", ((p_dm_odm->debug_components & ODM_COMP_FA_CNT) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "04. (( %s ))RSSI_MONITOR\n", ((p_dm_odm->debug_components & ODM_COMP_RSSI_MONITOR) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "05. (( %s ))SNIFFER\n", ((p_dm_odm->debug_components & ODM_COMP_SNIFFER) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "06. (( %s ))ANT_DIV\n", ((p_dm_odm->debug_components & ODM_COMP_ANT_DIV) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "07. (( %s ))DFS\n", ((p_dm_odm->debug_components & ODM_COMP_DFS) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "08. (( %s ))NOISY_DETECT\n", ((p_dm_odm->debug_components & ODM_COMP_NOISY_DETECT) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "09. (( %s ))RATE_ADAPTIVE\n", ((p_dm_odm->debug_components & ODM_COMP_RATE_ADAPTIVE) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "10. (( %s ))PATH_DIV\n", ((p_dm_odm->debug_components & ODM_COMP_PATH_DIV) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "12. (( %s ))DYNAMIC_PRICCA\n", ((p_dm_odm->debug_components & ODM_COMP_DYNAMIC_PRICCA) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "14. (( %s ))MP\n", ((p_dm_odm->debug_components & ODM_COMP_MP) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "15. (( %s ))struct _CFO_TRACKING_\n", ((p_dm_odm->debug_components & ODM_COMP_CFO_TRACKING) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "16. (( %s ))struct _ACS_\n", ((p_dm_odm->debug_components & ODM_COMP_ACS) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "17. (( %s ))ADAPTIVITY\n", ((p_dm_odm->debug_components & PHYDM_COMP_ADAPTIVITY) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "18. (( %s ))RA_DBG\n", ((p_dm_odm->debug_components & PHYDM_COMP_RA_DBG) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "19. (( %s ))TXBF\n", ((p_dm_odm->debug_components & PHYDM_COMP_TXBF) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "20. (( %s ))EDCA_TURBO\n", ((p_dm_odm->debug_components & ODM_COMP_EDCA_TURBO) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "22. (( %s ))FW_DEBUG_TRACE\n", ((p_dm_odm->debug_components & ODM_FW_DEBUG_TRACE) ? ("V") : (".")))); + + PHYDM_SNPRINTF((output + used, out_len - used, "24. (( %s ))TX_PWR_TRACK\n", ((p_dm_odm->debug_components & ODM_COMP_TX_PWR_TRACK) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "26. (( %s ))CALIBRATION\n", ((p_dm_odm->debug_components & ODM_COMP_CALIBRATION) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "28. (( %s ))PHY_CONFIG\n", ((p_dm_odm->debug_components & ODM_PHY_CONFIG) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "29. (( %s ))INIT\n", ((p_dm_odm->debug_components & ODM_COMP_INIT) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "30. (( %s ))COMMON\n", ((p_dm_odm->debug_components & ODM_COMP_COMMON) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "31. (( %s ))API\n", ((p_dm_odm->debug_components & ODM_COMP_API) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "================================")); + + } else if (dm_value[0] == 101) { + p_dm_odm->debug_components = 0; + PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "Disable all debug components")); + } else { + if (dm_value[1] == 1) /*enable*/ + p_dm_odm->debug_components |= (one << dm_value[0]); + else if (dm_value[1] == 2) /*disable*/ + p_dm_odm->debug_components &= ~(one << dm_value[0]); + else + PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "[Warning!!!] 1:enable, 2:disable")); + } + PHYDM_SNPRINTF((output + used, out_len - used, "pre-DbgComponents = 0x%x\n", pre_debug_components)); + PHYDM_SNPRINTF((output + used, out_len - used, "Curr-DbgComponents = 0x%x\n", p_dm_odm->debug_components)); + PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "================================")); +} + +static void +phydm_fw_debug_trace( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 pre_fw_debug_components, one = 1; + u32 used = *_used; + u32 out_len = *_out_len; + + pre_fw_debug_components = p_dm_odm->fw_debug_components; + + PHYDM_SNPRINTF((output + used, out_len - used, "\n%s\n", "================================")); + if (dm_value[0] == 100) { + PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "[FW Debug Component]")); + PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "================================")); + PHYDM_SNPRINTF((output + used, out_len - used, "00. (( %s ))RA\n", ((p_dm_odm->fw_debug_components & PHYDM_FW_COMP_RA) ? ("V") : (".")))); + + if (p_dm_odm->support_ic_type & PHYDM_IC_3081_SERIES) { + PHYDM_SNPRINTF((output + used, out_len - used, "01. (( %s ))MU\n", ((p_dm_odm->fw_debug_components & PHYDM_FW_COMP_MU) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "02. (( %s ))path Div\n", ((p_dm_odm->fw_debug_components & PHYDM_FW_COMP_PHY_CONFIG) ? ("V") : (".")))); + PHYDM_SNPRINTF((output + used, out_len - used, "03. (( %s ))Phy Config\n", ((p_dm_odm->fw_debug_components & PHYDM_FW_COMP_PHY_CONFIG) ? ("V") : (".")))); + } + PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "================================")); + + } else { + if (dm_value[0] == 101) { + p_dm_odm->fw_debug_components = 0; + PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "Clear all fw debug components")); + } else { + if (dm_value[1] == 1) /*enable*/ + p_dm_odm->fw_debug_components |= (one << dm_value[0]); + else if (dm_value[1] == 2) /*disable*/ + p_dm_odm->fw_debug_components &= ~(one << dm_value[0]); + else + PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "[Warning!!!] 1:enable, 2:disable")); + } + + if (p_dm_odm->fw_debug_components == 0) { + p_dm_odm->debug_components &= ~ODM_FW_DEBUG_TRACE; + phydm_fw_trace_en_h2c(p_dm_odm, false, p_dm_odm->fw_debug_components, dm_value[2], dm_value[3]); /*H2C to enable C2H Msg*/ + } else { + p_dm_odm->debug_components |= ODM_FW_DEBUG_TRACE; + phydm_fw_trace_en_h2c(p_dm_odm, true, p_dm_odm->fw_debug_components, dm_value[2], dm_value[3]); /*H2C to enable C2H Msg*/ + } + } +} + +static void +phydm_dump_bb_reg( + void *p_dm_void, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 addr = 0; + u32 used = *_used; + u32 out_len = *_out_len; + + + /* BB Reg, For Nseries IC we only need to dump page8 to pageF using 3 digits*/ + for (addr = 0x800; addr < 0xfff; addr += 4) { + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "0x%03x 0x%08x\n", addr, odm_get_bb_reg(p_dm_odm, addr, MASKDWORD))); + else + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "0x%04x 0x%08x\n", addr, odm_get_bb_reg(p_dm_odm, addr, MASKDWORD))); + } + + if (p_dm_odm->support_ic_type & (ODM_RTL8822B | ODM_RTL8814A | ODM_RTL8821C)) { + + if (p_dm_odm->rf_type > ODM_2T2R) { + for (addr = 0x1800; addr < 0x18ff; addr += 4) + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "0x%04x 0x%08x\n", addr, odm_get_bb_reg(p_dm_odm, addr, MASKDWORD))); + } + + if (p_dm_odm->rf_type > ODM_3T3R) { + for (addr = 0x1a00; addr < 0x1aff; addr += 4) + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "0x%04x 0x%08x\n", addr, odm_get_bb_reg(p_dm_odm, addr, MASKDWORD))); + } + + for (addr = 0x1900; addr < 0x19ff; addr += 4) + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "0x%04x 0x%08x\n", addr, odm_get_bb_reg(p_dm_odm, addr, MASKDWORD))); + + for (addr = 0x1c00; addr < 0x1cff; addr += 4) + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "0x%04x 0x%08x\n", addr, odm_get_bb_reg(p_dm_odm, addr, MASKDWORD))); + + for (addr = 0x1f00; addr < 0x1fff; addr += 4) + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "0x%04x 0x%08x\n", addr, odm_get_bb_reg(p_dm_odm, addr, MASKDWORD))); + } +} + +static void +phydm_dump_all_reg( + void *p_dm_void, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 addr = 0; + u32 used = *_used; + u32 out_len = *_out_len; + + /* dump MAC register */ + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "MAC==========\n")); + for (addr = 0; addr < 0x7ff; addr += 4) + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "0x%04x 0x%08x\n", addr, odm_get_bb_reg(p_dm_odm, addr, MASKDWORD))); + + for (addr = 0x1000; addr < 0x17ff; addr += 4) + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "0x%04x 0x%08x\n", addr, odm_get_bb_reg(p_dm_odm, addr, MASKDWORD))); + + /* dump BB register */ + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "BB==========\n")); + phydm_dump_bb_reg(p_dm_odm, &used, output, &out_len); + + /* dump RF register */ + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "RF-A==========\n")); + for (addr = 0; addr < 0xFF; addr++) + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "0x%02x 0x%05x\n", addr, odm_get_rf_reg(p_dm_odm, ODM_RF_PATH_A, addr, RFREGOFFSETMASK))); + + if (p_dm_odm->rf_type > ODM_1T1R) { + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "RF-B==========\n")); + for (addr = 0; addr < 0xFF; addr++) + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "0x%02x 0x%05x\n", addr, odm_get_rf_reg(p_dm_odm, ODM_RF_PATH_B, addr, RFREGOFFSETMASK))); + } + + if (p_dm_odm->rf_type > ODM_2T2R) { + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "RF-C==========\n")); + for (addr = 0; addr < 0xFF; addr++) + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "0x%02x 0x%05x\n", addr, odm_get_rf_reg(p_dm_odm, ODM_RF_PATH_C, addr, RFREGOFFSETMASK))); + } + + if (p_dm_odm->rf_type > ODM_3T3R) { + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "RF-D==========\n")); + for (addr = 0; addr < 0xFF; addr++) + PHYDM_VAST_INFO_SNPRINTF((output + used, out_len - used, "0x%02x 0x%05x\n", addr, odm_get_rf_reg(p_dm_odm, ODM_RF_PATH_D, addr, RFREGOFFSETMASK))); + } +} + +static void +phydm_enable_big_jump( + struct PHY_DM_STRUCT *p_dm_odm, + bool state +) +{ +} + +struct _PHYDM_COMMAND { + char name[16]; + u8 id; +}; + +enum PHYDM_CMD_ID { + PHYDM_HELP, + PHYDM_DEMO, + PHYDM_RA, + PHYDM_PROFILE, + PHYDM_ANTDIV, + PHYDM_PATHDIV, + PHYDM_DEBUG, + PHYDM_FW_DEBUG, + PHYDM_SUPPORT_ABILITY, + PHYDM_GET_TXAGC, + PHYDM_SET_TXAGC, + PHYDM_SMART_ANT, + PHYDM_API, + PHYDM_TRX_PATH, + PHYDM_LA_MODE, + PHYDM_DUMP_REG, + PHYDM_MU_MIMO, + PHYDM_HANG, + PHYDM_BIG_JUMP, + PHYDM_SHOW_RXRATE, + PHYDM_NBI_EN, + PHYDM_CSI_MASK_EN, + PHYDM_DFS, + PHYDM_IQK, + PHYDM_NHM, + PHYDM_CLM, + PHYDM_BB_INFO, + PHYDM_TXBF, + PHYDM_PAUSE_DIG_EN, + PHYDM_H2C, + PHYDM_ANT_SWITCH, + PHYDM_DYNAMIC_RA_PATH +}; + +static struct _PHYDM_COMMAND phy_dm_ary[] = { + {"-h", PHYDM_HELP}, /*do not move this element to other position*/ + {"demo", PHYDM_DEMO}, /*do not move this element to other position*/ + {"ra", PHYDM_RA}, + {"profile", PHYDM_PROFILE}, + {"antdiv", PHYDM_ANTDIV}, + {"pathdiv", PHYDM_PATHDIV}, + {"dbg", PHYDM_DEBUG}, + {"fw_dbg", PHYDM_FW_DEBUG}, + {"ability", PHYDM_SUPPORT_ABILITY}, + {"get_txagc", PHYDM_GET_TXAGC}, + {"set_txagc", PHYDM_SET_TXAGC}, + {"smtant", PHYDM_SMART_ANT}, + {"api", PHYDM_API}, + {"trxpath", PHYDM_TRX_PATH}, + {"lamode", PHYDM_LA_MODE}, + {"dumpreg", PHYDM_DUMP_REG}, + {"mu", PHYDM_MU_MIMO}, + {"hang", PHYDM_HANG}, + {"bigjump", PHYDM_BIG_JUMP}, + {"rxrate", PHYDM_SHOW_RXRATE}, + {"nbi", PHYDM_NBI_EN}, + {"csi_mask", PHYDM_CSI_MASK_EN}, + {"dfs", PHYDM_DFS}, + {"iqk", PHYDM_IQK}, + {"nhm", PHYDM_NHM}, + {"clm", PHYDM_CLM}, + {"bbinfo", PHYDM_BB_INFO}, + {"txbf", PHYDM_TXBF}, + {"pause_dig", PHYDM_PAUSE_DIG_EN}, + {"h2c", PHYDM_H2C}, + {"ant_switch", PHYDM_ANT_SWITCH}, + {"drp", PHYDM_DYNAMIC_RA_PATH} +}; + +#endif /*#if CONFIG_PHYDM_DEBUG_FUNCTION*/ + +void +phydm_cmd_parser( + struct PHY_DM_STRUCT *p_dm_odm, + char input[][MAX_ARGV], + u32 input_num, + u8 flag, + char *output, + u32 out_len +) +{ +#if CONFIG_PHYDM_DEBUG_FUNCTION + u32 used = 0; + u8 id = 0; + int var1[10] = {0}; + int i, input_idx = 0, phydm_ary_size; + char help[] = "-h"; + + if (flag == 0) { + PHYDM_SNPRINTF((output + used, out_len - used, "GET, nothing to print\n")); + return; + } + + PHYDM_SNPRINTF((output + used, out_len - used, "\n")); + + /* Parsing Cmd ID */ + if (input_num) { + + phydm_ary_size = sizeof(phy_dm_ary) / sizeof(struct _PHYDM_COMMAND); + for (i = 0; i < phydm_ary_size; i++) { + if (strcmp(phy_dm_ary[i].name, input[0]) == 0) { + id = phy_dm_ary[i].id; + break; + } + } + if (i == phydm_ary_size) { + PHYDM_SNPRINTF((output + used, out_len - used, "SET, command not found!\n")); + return; + } + } + + switch (id) { + + case PHYDM_HELP: + { + PHYDM_SNPRINTF((output + used, out_len - used, "BB cmd ==>\n")); + for (i = 0; i < phydm_ary_size - 2; i++) { + + PHYDM_SNPRINTF((output + used, out_len - used, " %-5d: %s\n", i, phy_dm_ary[i + 2].name)); + /**/ + } + } + break; + + case PHYDM_DEMO: { /*echo demo 10 0x3a z abcde >cmd*/ + u32 directory = 0; + char char_temp; + + PHYDM_SSCANF(input[1], DCMD_DECIMAL, &directory); + PHYDM_SNPRINTF((output + used, out_len - used, "Decimal value = %d\n", directory)); + PHYDM_SSCANF(input[2], DCMD_HEX, &directory); + PHYDM_SNPRINTF((output + used, out_len - used, "Hex value = 0x%x\n", directory)); + PHYDM_SSCANF(input[3], DCMD_CHAR, &char_temp); + PHYDM_SNPRINTF((output + used, out_len - used, "Char = %c\n", char_temp)); + PHYDM_SNPRINTF((output + used, out_len - used, "String = %s\n", input[4])); + } + break; + + case PHYDM_RA: + + for (i = 0; i < 5; i++) { + if (input[i + 1]) { + PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL, &var1[i]); + + /*PHYDM_SNPRINTF((output + used, out_len - used, "new SET, RA_var[%d]= (( %d ))\n", i, var1[i]));*/ + input_idx++; + } + } + + if (input_idx >= 1) { + /*PHYDM_SNPRINTF((output+used, out_len-used, "odm_RA_debug\n"));*/ +#if (defined(CONFIG_RA_DBG_CMD)) + odm_RA_debug((void *)p_dm_odm, (u32 *) var1); +#else + phydm_RA_debug_PCR(p_dm_odm, (u32 *)var1, &used, output, &out_len); +#endif + } + + + break; + + case PHYDM_ANTDIV: + + for (i = 0; i < 5; i++) { + if (input[i + 1]) { + PHYDM_SSCANF(input[i + 1], DCMD_HEX, &var1[i]); + + /*PHYDM_SNPRINTF((output+used, out_len-used, "new SET, PATHDIV_var[%d]= (( %d ))\n", i, var1[i]));*/ + input_idx++; + } + } + + if (input_idx >= 1) { + /*PHYDM_SNPRINTF((output+used, out_len-used, "odm_PATHDIV_debug\n"));*/ +#if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY)) + phydm_antdiv_debug(p_dm_odm, (u32 *)var1, &used, output, &out_len); +#endif + } + + break; + + case PHYDM_PATHDIV: + + for (i = 0; i < 5; i++) { + if (input[i + 1]) { + PHYDM_SSCANF(input[i + 1], DCMD_HEX, &var1[i]); + + /*PHYDM_SNPRINTF((output+used, out_len-used, "new SET, PATHDIV_var[%d]= (( %d ))\n", i, var1[i]));*/ + input_idx++; + } + } + + if (input_idx >= 1) { + /*PHYDM_SNPRINTF((output+used, out_len-used, "odm_PATHDIV_debug\n"));*/ +#if (defined(CONFIG_PATH_DIVERSITY)) + odm_pathdiv_debug(p_dm_odm, (u32 *)var1, &used, output, &out_len); +#endif + } + + break; + + case PHYDM_DEBUG: + + for (i = 0; i < 5; i++) { + if (input[i + 1]) { + PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL, &var1[i]); + + /*PHYDM_SNPRINTF((output+used, out_len-used, "new SET, Debug_var[%d]= (( %d ))\n", i, var1[i]));*/ + input_idx++; + } + } + + if (input_idx >= 1) { + /*PHYDM_SNPRINTF((output+used, out_len-used, "odm_debug_comp\n"));*/ + phydm_debug_trace(p_dm_odm, (u32 *)var1, &used, output, &out_len); + } + + + break; + + case PHYDM_FW_DEBUG: + + for (i = 0; i < 5; i++) { + if (input[i + 1]) { + PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL, &var1[i]); + input_idx++; + } + } + + if (input_idx >= 1) + phydm_fw_debug_trace(p_dm_odm, (u32 *)var1, &used, output, &out_len); + + break; + + case PHYDM_SUPPORT_ABILITY: + + for (i = 0; i < 5; i++) { + if (input[i + 1]) { + PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL, &var1[i]); + + /*PHYDM_SNPRINTF((output+used, out_len-used, "new SET, support ablity_var[%d]= (( %d ))\n", i, var1[i]));*/ + input_idx++; + } + } + + if (input_idx >= 1) { + /*PHYDM_SNPRINTF((output+used, out_len-used, "support ablity\n"));*/ + phydm_support_ability_debug(p_dm_odm, (u32 *)var1, &used, output, &out_len); + } + + break; + + case PHYDM_SMART_ANT: + + for (i = 0; i < 5; i++) { + if (input[i + 1]) { + PHYDM_SSCANF(input[i + 1], DCMD_HEX, &var1[i]); + input_idx++; + } + } + + if (input_idx >= 1) { +#if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY)) +#ifdef CONFIG_HL_SMART_ANTENNA_TYPE1 + phydm_hl_smart_ant_debug(p_dm_odm, (u32 *)var1, &used, output, &out_len); +#endif +#endif + } + + break; + + case PHYDM_API: + PHYDM_SNPRINTF((output + used, out_len - used, "This IC doesn't support PHYDM API function\n")); + break; + case PHYDM_PROFILE: /*echo profile, >cmd*/ + phydm_basic_profile(p_dm_odm, &used, output, &out_len); + break; + case PHYDM_GET_TXAGC: + phydm_get_txagc(p_dm_odm, &used, output, &out_len); + break; + case PHYDM_SET_TXAGC: + { + bool is_enable_dbg_mode; + + for (i = 0; i < 5; i++) { + if (input[i + 1]) { + PHYDM_SSCANF(input[i + 1], DCMD_HEX, &var1[i]); + input_idx++; + } + } + + if ((strcmp(input[1], help) == 0)) { + PHYDM_SNPRINTF((output + used, out_len - used, "{En} {pathA~D(0~3)} {rate_idx(Hex), All_rate:0xff} {txagc_idx (Hex)}\n")); + /**/ + + } else { + + is_enable_dbg_mode = (bool)var1[0]; + if (is_enable_dbg_mode) { + p_dm_odm->is_disable_phy_api = false; + phydm_set_txagc(p_dm_odm, (u32 *)var1, &used, output, &out_len); + p_dm_odm->is_disable_phy_api = true; + } else { + p_dm_odm->is_disable_phy_api = false; + PHYDM_SNPRINTF((output + used, out_len - used, "Disable API debug mode\n")); + } + } + } + break; + + case PHYDM_TRX_PATH: + + for (i = 0; i < 4; i++) { + if (input[i + 1]) + PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL, &var1[i]); + } + phydm_config_trx_path(p_dm_odm, (u32 *)var1, &used, output, &out_len); + break; + + case PHYDM_LA_MODE: + +#if (PHYDM_LA_MODE_SUPPORT == 1) + p_dm_odm->support_ability &= ~(ODM_BB_FA_CNT); + phydm_lamode_trigger_setting(p_dm_odm, &input[0], &used, output, &out_len, input_num); + p_dm_odm->support_ability |= ODM_BB_FA_CNT; +#else + PHYDM_SNPRINTF((output + used, out_len - used, "This IC doesn't support LA mode\n")); +#endif + + break; + + case PHYDM_DUMP_REG: + { + u8 type = 0; + + if (input[1]) { + PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]); + type = (u8)var1[0]; + } + + if (type == 0) + phydm_dump_bb_reg(p_dm_odm, &used, output, &out_len); + else if (type == 1) + phydm_dump_all_reg(p_dm_odm, &used, output, &out_len); + } + break; + + case PHYDM_MU_MIMO: + break; + case PHYDM_BIG_JUMP: + PHYDM_SNPRINTF((output + used, out_len - used, "The command is only for 8822B!\n")); + break; + case PHYDM_HANG: + phydm_bb_rx_hang_info(p_dm_odm, &used, output, &out_len); + break; + case PHYDM_SHOW_RXRATE: + break; + case PHYDM_NBI_EN: + for (i = 0; i < 5; i++) { + if (input[i + 1]) { + PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL, &var1[i]); + input_idx++; + } + } + + if (input_idx >= 1) { + + phydm_api_debug(p_dm_odm, PHYDM_API_NBI, (u32 *)var1, &used, output, &out_len); + /**/ + } + + + break; + + case PHYDM_CSI_MASK_EN: + + for (i = 0; i < 5; i++) { + if (input[i + 1]) { + PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL, &var1[i]); + input_idx++; + } + } + + if (input_idx >= 1) { + + phydm_api_debug(p_dm_odm, PHYDM_API_CSI_MASK, (u32 *)var1, &used, output, &out_len); + /**/ + } + + + break; + + case PHYDM_DFS: + { + u32 var[6] = {0}; + + for (i = 0; i < 6; i++) { + if (input[i + 1]) { + PHYDM_SSCANF(input[i + 1], DCMD_HEX, &var[i]); + input_idx++; + } + } + + if (input_idx >= 1) + phydm_dfs_debug(p_dm_odm, var, &used, output, &out_len); + } + break; + case PHYDM_IQK: + break; + case PHYDM_NHM: + { + u8 target_rssi; + u32 value32; + u16 nhm_period = 0xC350; /* 200ms */ + u8 IGI; + struct _CCX_INFO *ccx_info = &p_dm_odm->dm_ccx_info; + + PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]); + + if (input_num == 1) { + + ccx_info->echo_NHM_en = false; + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n Trigger NHM: echo nhm 1\n")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r (Exclude CCA)\n")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r Trigger NHM: echo nhm 2\n")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r (Include CCA)\n")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r Get NHM results: echo nhm 3\n")); + + return; + } + + /* NMH trigger */ + if ((var1[0] <= 2) && (var1[0] != 0)) { + + ccx_info->echo_NHM_en = true; + ccx_info->echo_IGI = (u8)odm_get_bb_reg(p_dm_odm, 0xC50, MASKBYTE0); + + target_rssi = ccx_info->echo_IGI - 10; + + ccx_info->NHM_th[0] = (target_rssi - 15 + 10) * 2; + + for (i = 1; i <= 10; i++) + ccx_info->NHM_th[i] = ccx_info->NHM_th[0] + 6 * i; + + /* 4 1. store previous NHM setting */ + phydm_nhm_setting(p_dm_odm, STORE_NHM_SETTING); + + /* 4 2. Set NHM period, 0x990[31:16]=0xC350, Time duration for NHM unit: 4us, 0xC350=200ms */ + ccx_info->NHM_period = nhm_period; + + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n Monitor NHM for %d us", nhm_period * 4)); + + /* 4 3. Set NHM inexclude_txon, inexclude_cca, ccx_en */ + + + ccx_info->nhm_inexclude_cca = (var1[0] == 1) ? NHM_EXCLUDE_CCA : NHM_INCLUDE_CCA; + ccx_info->nhm_inexclude_txon = NHM_EXCLUDE_TXON; + + phydm_nhm_setting(p_dm_odm, SET_NHM_SETTING); + + for (i = 0; i <= 10; i++) { + + if (i == 5) + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n NHM_th[%d] = 0x%x, echo_IGI = 0x%x", i, ccx_info->NHM_th[i], ccx_info->echo_IGI)); + else if (i == 10) + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n NHM_th[%d] = 0x%x\n", i, ccx_info->NHM_th[i])); + else + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n NHM_th[%d] = 0x%x", i, ccx_info->NHM_th[i])); + } + + /* 4 4. Trigger NHM */ + phydm_nhm_trigger(p_dm_odm); + + } + + /*Get NHM results*/ + else if (var1[0] == 3) { + + IGI = (u8)odm_get_bb_reg(p_dm_odm, 0xC50, MASKBYTE0); + + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n Cur_IGI = 0x%x", IGI)); + + phydm_get_nhm_result(p_dm_odm); + + /* 4 Resotre NHM setting */ + phydm_nhm_setting(p_dm_odm, RESTORE_NHM_SETTING); + + for (i = 0; i <= 11; i++) { + + if (i == 5) + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n nhm_result[%d] = %d, echo_IGI = 0x%x", i, ccx_info->NHM_result[i], ccx_info->echo_IGI)); + else if (i == 11) + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n nhm_result[%d] = %d\n", i, ccx_info->NHM_result[i])); + else + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n nhm_result[%d] = %d", i, ccx_info->NHM_result[i])); + } + + ccx_info->echo_NHM_en = false; + } else { + + ccx_info->echo_NHM_en = false; + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n Trigger NHM: echo nhm 1\n")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r (Exclude CCA)\n")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r Trigger NHM: echo nhm 2\n")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r (Include CCA)\n")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r Get NHM results: echo nhm 3\n")); + + return; + } + } + break; + + case PHYDM_CLM: + { + struct _CCX_INFO *ccx_info = &p_dm_odm->dm_ccx_info; + PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]); + + /* PHYDM_SNPRINTF((output + used, out_len - used, "\r\n input_num = %d\n", input_num)); */ + + if (input_num == 1) { + + ccx_info->echo_CLM_en = false; + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n Trigger CLM: echo clm 1\n")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r Get CLM results: echo clm 2\n")); + return; + } + + /* Set & trigger CLM */ + if (var1[0] == 1) { + + ccx_info->echo_CLM_en = true; + ccx_info->CLM_period = 0xC350; /*100ms*/ + phydm_clm_setting(p_dm_odm); + phydm_clm_trigger(p_dm_odm); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n Monitor CLM for 200ms\n")); + } + + /* Get CLM results */ + else if (var1[0] == 2) { + + ccx_info->echo_CLM_en = false; + phydm_get_cl_mresult(p_dm_odm); + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n CLM_result = %d us\n", ccx_info->CLM_result * 4)); + + } else { + + ccx_info->echo_CLM_en = false; + PHYDM_SNPRINTF((output + used, out_len - used, "\n\r Error command !\n")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r Trigger CLM: echo clm 1\n")); + PHYDM_SNPRINTF((output + used, out_len - used, "\r Get CLM results: echo clm 2\n")); + } + } + break; + + case PHYDM_BB_INFO: + { + s32 value32 = 0; + + phydm_bb_debug_info(p_dm_odm, &used, output, &out_len); + + if (p_dm_odm->support_ic_type & ODM_RTL8822B && input[1]) { + PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]); + odm_set_bb_reg(p_dm_odm, 0x1988, 0x003fff00, var1[0]); + value32 = odm_get_bb_reg(p_dm_odm, 0xf84, MASKDWORD); + value32 = (value32 & 0xff000000) >> 24; + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n %-35s = condition num = %d, subcarriers = %d\n", "Over condition num subcarrier", var1[0], value32)); + odm_set_bb_reg(p_dm_odm, 0x1988, BIT(22), 0x0); /*disable report condition number*/ + } + } + break; + + case PHYDM_TXBF: + { +#if (BEAMFORMING_SUPPORT == 1) + struct _RT_BEAMFORMING_INFO *p_beamforming_info = &p_dm_odm->beamforming_info; + + PHYDM_SSCANF(input[1], DCMD_DECIMAL, &var1[0]); + if (var1[0] == 1) { + p_beamforming_info->apply_v_matrix = true; + p_beamforming_info->snding3ss = false; + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n apply V matrix and 3SS 789 dont snding\n")); + } else if (var1[0] == 0) { + p_beamforming_info->apply_v_matrix = false; + p_beamforming_info->snding3ss = true; + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n dont apply V matrix and 3SS 789 snding\n")); + } else + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n unknown cmd!!\n")); +#else + PHYDM_SNPRINTF((output + used, out_len - used, "\r\n no TxBF !!\n")); +#endif + } + break; + + case PHYDM_PAUSE_DIG_EN: + + + for (i = 0; i < 5; i++) { + if (input[i + 1]) { + PHYDM_SSCANF(input[i + 1], DCMD_HEX, &var1[i]); + input_idx++; + } + } + + if (input_idx >= 1) { + if (var1[0] == 0) { + odm_pause_dig(p_dm_odm, PHYDM_PAUSE, PHYDM_PAUSE_LEVEL_7, (u8)var1[1]); + PHYDM_SNPRINTF((output + used, out_len - used, "Set IGI_value = ((%x))\n", var1[1])); + } else if (var1[0] == 1) { + odm_pause_dig(p_dm_odm, PHYDM_RESUME, PHYDM_PAUSE_LEVEL_7, (u8)var1[1]); + PHYDM_SNPRINTF((output + used, out_len - used, "Resume IGI_value\n")); + } else + PHYDM_SNPRINTF((output + used, out_len - used, "echo (1:pause, 2resume) (IGI_value)\n")); + } + + break; + + case PHYDM_H2C: + + for (i = 0; i < 8; i++) { + if (input[i + 1]) { + PHYDM_SSCANF(input[i + 1], DCMD_HEX, &var1[i]); + input_idx++; + } + } + + if (input_idx >= 1) + phydm_h2C_debug(p_dm_odm, (u32 *)var1, &used, output, &out_len); + + + break; + + case PHYDM_ANT_SWITCH: + + for (i = 0; i < 8; i++) { + if (input[i + 1]) { + PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL, &var1[i]); + input_idx++; + } + } + + if (input_idx >= 1) { + +#if (RTL8821A_SUPPORT == 1) + phydm_set_ext_switch(p_dm_odm, (u32 *)var1, &used, output, &out_len); +#else + PHYDM_SNPRINTF((output + used, out_len - used, "Not Support IC")); +#endif + } + + + break; + + case PHYDM_DYNAMIC_RA_PATH: + +#if (CONFIG_DYNAMIC_RX_PATH == 1) + for (i = 0; i < 8; i++) { + if (input[i + 1]) { + PHYDM_SSCANF(input[i + 1], DCMD_DECIMAL, &var1[i]); + input_idx++; + } + } + + if (input_idx >= 1) + phydm_drp_debug(p_dm_odm, (u32 *)var1, &used, output, &out_len); + +#else + PHYDM_SNPRINTF((output + used, out_len - used, "Not Support IC")); +#endif + + break; + + default: + PHYDM_SNPRINTF((output + used, out_len - used, "SET, unknown command!\n")); + break; + + } +#endif /*#if CONFIG_PHYDM_DEBUG_FUNCTION*/ +} + +#ifdef __ECOS +char *strsep(char **s, const char *ct) +{ + char *sbegin = *s; + char *end; + + if (sbegin == NULL) + return NULL; + + end = strpbrk(sbegin, ct); + if (end) + *end++ = '\0'; + *s = end; + return sbegin; +} +#endif + +s32 +phydm_cmd( + struct PHY_DM_STRUCT *p_dm_odm, + char *input, + u32 in_len, + u8 flag, + char *output, + u32 out_len +) +{ + char *token; + u32 argc = 0; + char argv[MAX_ARGC][MAX_ARGV]; + + do { + token = strsep(&input, ", "); + if (token) { + strcpy(argv[argc], token); + argc++; + } else + break; + } while (argc < MAX_ARGC); + + if (argc == 1) + argv[0][strlen(argv[0]) - 1] = '\0'; + + phydm_cmd_parser(p_dm_odm, argv, argc, flag, output, out_len); + + return 0; +} + +void +phydm_fw_trace_handler( + void *p_dm_void, + u8 *cmd_buf, + u8 cmd_len +) +{ +#if CONFIG_PHYDM_DEBUG_FUNCTION + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + /*u8 debug_trace_11byte[60];*/ + u8 freg_num, c2h_seq, buf_0 = 0; + + if (!(p_dm_odm->support_ic_type & PHYDM_IC_3081_SERIES)) + return; + + if (cmd_len > 12) + return; + + buf_0 = cmd_buf[0]; + freg_num = (buf_0 & 0xf); + c2h_seq = (buf_0 & 0xf0) >> 4; + /*ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE,ODM_DBG_LOUD,("[FW debug message] freg_num = (( %d )), c2h_seq = (( %d ))\n", freg_num,c2h_seq ));*/ + + /*strncpy(debug_trace_11byte,&cmd_buf[1],(cmd_len-1));*/ + /*debug_trace_11byte[cmd_len-1] = '\0';*/ + /*ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE,ODM_DBG_LOUD,("[FW debug message] %s\n", debug_trace_11byte));*/ + /*ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE,ODM_DBG_LOUD,("[FW debug message] cmd_len = (( %d ))\n", cmd_len));*/ + /*ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE,ODM_DBG_LOUD,("[FW debug message] c2h_cmd_start = (( %d ))\n", p_dm_odm->c2h_cmd_start));*/ + + + + /*ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE,ODM_DBG_LOUD,("pre_seq = (( %d )), current_seq = (( %d ))\n", p_dm_odm->pre_c2h_seq, c2h_seq));*/ + /*ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE,ODM_DBG_LOUD,("fw_buff_is_enpty = (( %d ))\n", p_dm_odm->fw_buff_is_enpty));*/ + + if ((c2h_seq != p_dm_odm->pre_c2h_seq) && p_dm_odm->fw_buff_is_enpty == false) { + p_dm_odm->fw_debug_trace[p_dm_odm->c2h_cmd_start] = '\0'; + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW Dbg Queue Overflow] %s\n", p_dm_odm->fw_debug_trace)); + p_dm_odm->c2h_cmd_start = 0; + } + + if ((cmd_len - 1) > (60 - p_dm_odm->c2h_cmd_start)) { + p_dm_odm->fw_debug_trace[p_dm_odm->c2h_cmd_start] = '\0'; + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW Dbg Queue error: wrong C2H length] %s\n", p_dm_odm->fw_debug_trace)); + p_dm_odm->c2h_cmd_start = 0; + return; + } + + strncpy((char *)&(p_dm_odm->fw_debug_trace[p_dm_odm->c2h_cmd_start]), (char *)&cmd_buf[1], (cmd_len - 1)); + p_dm_odm->c2h_cmd_start += (cmd_len - 1); + p_dm_odm->fw_buff_is_enpty = false; + + if (freg_num == 0 || p_dm_odm->c2h_cmd_start >= 60) { + if (p_dm_odm->c2h_cmd_start < 60) + p_dm_odm->fw_debug_trace[p_dm_odm->c2h_cmd_start] = '\0'; + else + p_dm_odm->fw_debug_trace[59] = '\0'; + + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW DBG Msg] %s\n", p_dm_odm->fw_debug_trace)); + /*dbg_print("[FW DBG Msg] %s\n", p_dm_odm->fw_debug_trace);*/ + p_dm_odm->c2h_cmd_start = 0; + p_dm_odm->fw_buff_is_enpty = true; + } + + p_dm_odm->pre_c2h_seq = c2h_seq; +#endif /*#if CONFIG_PHYDM_DEBUG_FUNCTION*/ +} + +void +phydm_fw_trace_handler_code( + void *p_dm_void, + u8 *buffer, + u8 cmd_len +) +{ +#if CONFIG_PHYDM_DEBUG_FUNCTION + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 function = buffer[0]; + u8 dbg_num = buffer[1]; + u16 content_0 = (((u16)buffer[3]) << 8) | ((u16)buffer[2]); + u16 content_1 = (((u16)buffer[5]) << 8) | ((u16)buffer[4]); + u16 content_2 = (((u16)buffer[7]) << 8) | ((u16)buffer[6]); + u16 content_3 = (((u16)buffer[9]) << 8) | ((u16)buffer[8]); + u16 content_4 = (((u16)buffer[11]) << 8) | ((u16)buffer[10]); + + if (cmd_len > 12) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW Msg] Invalid cmd length (( %d )) >12\n", cmd_len)); + + /* ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE,ODM_DBG_LOUD,("[FW Msg] Func=((%d)), num=((%d)), ct_0=((%d)), ct_1=((%d)), ct_2=((%d)), ct_3=((%d)), ct_4=((%d))\n", */ + /* function, dbg_num, content_0, content_1, content_2, content_3, content_4)); */ + + /*--------------------------------------------*/ +#if (CONFIG_RA_FW_DBG_CODE) + if (function == RATE_DECISION) { + if (dbg_num == 0) { + if (content_0 == 1) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] RA_CNT=((%d)) Max_device=((%d))--------------------------->\n", content_1, content_2)); + else if (content_0 == 2) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] Check RA macid= ((%d)), MediaStatus=((%d)), Dis_RA=((%d)), try_bit=((0x%x))\n", content_1, content_2, content_3, content_4)); + else if (content_0 == 3) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] Check RA total=((%d)), drop=((0x%x)), TXRPT_TRY_bit=((%x)), bNoisy=((%x))\n", content_1, content_2, content_3, content_4)); + } else if (dbg_num == 1) { + if (content_0 == 1) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] RTY[0,1,2,3]=[ %d , %d , %d , %d ]\n", content_1, content_2, content_3, content_4)); + else if (content_0 == 2) { + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] RTY[4]=[ %d ], drop=(( %d )), total=(( %d )), current_rate=((0x %x ))", content_1, content_2, content_3, content_4)); + phydm_print_rate(p_dm_odm, (u8)content_4, ODM_FW_DEBUG_TRACE); + } else if (content_0 == 3) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] penality_idx=(( %d ))\n", content_1)); + else if (content_0 == 4) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] RSSI=(( %d )), ra_stage = (( %d ))\n", content_1, content_2)); + } + + else if (dbg_num == 3) { + if (content_0 == 1) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] Fast_RA (( DOWN )) total=((%d)), total>>1=((%d)), R4+R3+R2 = ((%d)), RateDownHold = ((%d))\n", content_1, content_2, content_3, content_4)); + else if (content_0 == 2) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] Fast_RA (( UP )) total_acc=((%d)), total_acc>>1=((%d)), R4+R3+R2 = ((%d)), RateDownHold = ((%d))\n", content_1, content_2, content_3, content_4)); + else if (content_0 == 3) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] Fast_RA (( UP )) ((rate Down Hold)) RA_CNT=((%d))\n", content_1)); + else if (content_0 == 4) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] Fast_RA (( UP )) ((tota_accl<5 skip)) RA_CNT=((%d))\n", content_1)); + else if (content_0 == 8) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] Fast_RA (( Reset Tx Rpt )) RA_CNT=((%d))\n", content_1)); + } + + else if (dbg_num == 4) { + if (content_0 == 3) { + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] RER_CNT PCR_ori =(( %d )), ratio_ori =(( %d )), pcr_updown_bitmap =(( 0x%x )), pcr_var_diff =(( %d ))\n", content_1, content_2, content_3, content_4)); + /**/ + } else if (content_0 == 4) { + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] pcr_shift_value =(( %s%d )), rate_down_threshold =(( %d )), rate_up_threshold =(( %d ))\n", ((content_1) ? "+" : "-"), content_2, content_3, content_4)); + /**/ + } else if (content_0 == 5) { + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] pcr_mean =(( %d )), PCR_VAR =(( %d )), offset =(( %d )), decision_offset_p =(( %d ))\n", content_1, content_2, content_3, content_4)); + /**/ + } + } + + else if (dbg_num == 5) { + if (content_0 == 1) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] (( UP)) Nsc=(( %d )), N_High=(( %d )), RateUp_Waiting=(( %d )), RateUp_Fail=(( %d ))\n", content_1, content_2, content_3, content_4)); + else if (content_0 == 2) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] ((DOWN)) Nsc=(( %d )), N_Low=(( %d ))\n", content_1, content_2)); + else if (content_0 == 3) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] ((HOLD)) Nsc=((%d)), N_High=((%d)), N_Low=((%d)), Reset_CNT=((%d))\n", content_1, content_2, content_3, content_4)); + } else if (dbg_num == 0x60) { + if (content_0 == 1) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] ((AP RPT)) macid=((%d)), BUPDATE[macid]=((%d))\n", content_1, content_2)); + else if (content_0 == 4) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] ((AP RPT)) pass=((%d)), rty_num=((%d)), drop=((%d)), total=((%d))\n", content_1, content_2, content_3, content_4)); + else if (content_0 == 5) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW] ((AP RPT)) PASS=((%d)), RTY_NUM=((%d)), DROP=((%d)), TOTAL=((%d))\n", content_1, content_2, content_3, content_4)); + } + } + /*--------------------------------------------*/ + else if (function == INIT_RA_TABLE) { + if (dbg_num == 3) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW][INIT_RA_INFO] Ra_init, RA_SKIP_CNT = (( %d ))\n", content_0)); + + } + /*--------------------------------------------*/ + else if (function == RATE_UP) { + if (dbg_num == 2) { + if (content_0 == 1) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW][RateUp] ((Highest rate->return)), macid=((%d)) Nsc=((%d))\n", content_1, content_2)); + } else if (dbg_num == 5) { + if (content_0 == 0) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW][RateUp] ((rate UP)), up_rate_tmp=((0x%x)), rate_idx=((0x%x)), SGI_en=((%d)), SGI=((%d))\n", content_1, content_2, content_3, content_4)); + else if (content_0 == 1) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW][RateUp] ((rate UP)), rate_1=((0x%x)), rate_2=((0x%x)), BW=((%d)), Try_Bit=((%d))\n", content_1, content_2, content_3, content_4)); + } + + } + /*--------------------------------------------*/ + else if (function == RATE_DOWN) { + if (dbg_num == 5) { + if (content_0 == 1) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW][RateDownStep] ((rate Down)), macid=((%d)), rate1=((0x%x)), rate2=((0x%x)), BW=((%d))\n", content_1, content_2, content_3, content_4)); + } + } else if (function == TRY_DONE) { + if (dbg_num == 1) { + if (content_0 == 1) { + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW][Try Done] ((try succsess )) macid=((%d)), Try_Done_cnt=((%d))\n", content_1, content_2)); + /**/ + } + } else if (dbg_num == 2) { + if (content_0 == 1) { + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW][Try Done] ((try)) macid=((%d)), Try_Done_cnt=((%d)), rate_2=((%d)), try_succes=((%d))\n", content_1, content_2, content_3, content_4)); + /**/ + } + } + } + /*--------------------------------------------*/ + else if (function == RA_H2C) { + if (dbg_num == 1) { + if (content_0 == 0) { + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW][H2C=0x49] fw_trace_en=((%d)), mode =((%d)), macid=((%d))\n", content_1, content_2, content_3)); + /**/ + /*C2H_RA_Dbg_code(F_RA_H2C,1,0, SysMib.ODM.DEBUG.fw_trace_en, mode, macid, 0); //RA MASK*/ + } + } + } + /*--------------------------------------------*/ + else if (function == F_RATE_AP_RPT) { + if (dbg_num == 1) { + if (content_0 == 1) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW][AP RPT] ((1)), SPE_STATIS=((0x%x))---------->\n", content_3)); + } else if (dbg_num == 2) { + if (content_0 == 1) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW][AP RPT] RTY_all=((%d))\n", content_1)); + } else if (dbg_num == 3) { + if (content_0 == 1) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW][AP RPT] MACID1[%d], TOTAL=((%d)), RTY=((%d))\n", content_3, content_1, content_2)); + } else if (dbg_num == 4) { + if (content_0 == 1) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW][AP RPT] MACID2[%d], TOTAL=((%d)), RTY=((%d))\n", content_3, content_1, content_2)); + } else if (dbg_num == 5) { + if (content_0 == 1) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW][AP RPT] MACID1[%d], PASS=((%d)), DROP=((%d))\n", content_3, content_1, content_2)); + } else if (dbg_num == 6) { + if (content_0 == 1) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW][AP RPT] MACID2[%d],, PASS=((%d)), DROP=((%d))\n", content_3, content_1, content_2)); + } + } else { + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW][general][%d, %d, %d] = {%d, %d, %d, %d}\n", function, dbg_num, content_0, content_1, content_2, content_3, content_4)); + /**/ + } +#else + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW][general][%d, %d, %d] = {%d, %d, %d, %d}\n", function, dbg_num, content_0, content_1, content_2, content_3, content_4)); +#endif + /*--------------------------------------------*/ + +#endif /*#if CONFIG_PHYDM_DEBUG_FUNCTION*/ +} + +void +phydm_fw_trace_handler_8051( + void *p_dm_void, + u8 *buffer, + u8 cmd_len +) +{ +#if CONFIG_PHYDM_DEBUG_FUNCTION + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + int i = 0; + u8 extend_c2h_sub_id = 0, extend_c2h_dbg_len = 0, extend_c2h_dbg_seq = 0; + u8 fw_debug_trace[128]; + u8 *extend_c2h_dbg_content = NULL; + + if (cmd_len > 127) + return; + + extend_c2h_sub_id = buffer[0]; + extend_c2h_dbg_len = buffer[1]; + extend_c2h_dbg_content = buffer + 2; /*DbgSeq+DbgContent for show HEX*/ + +go_backfor_aggre_dbg_pkt: + i = 0; + extend_c2h_dbg_seq = buffer[2]; + extend_c2h_dbg_content = buffer + 3; + + for (; ; i++) { + fw_debug_trace[i] = extend_c2h_dbg_content[i]; + if (extend_c2h_dbg_content[i + 1] == '\0') { + fw_debug_trace[i + 1] = '\0'; + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW DBG Msg] %s", &(fw_debug_trace[0]))); + break; + } else if (extend_c2h_dbg_content[i] == '\n') { + fw_debug_trace[i + 1] = '\0'; + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("[FW DBG Msg] %s", &(fw_debug_trace[0]))); + buffer = extend_c2h_dbg_content + i + 3; + goto go_backfor_aggre_dbg_pkt; + } + } + + +#endif /*#if CONFIG_PHYDM_DEBUG_FUNCTION*/ +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_debug.h b/drivers/staging/rtl8188eu/hal/phydm_debug.h new file mode 100644 index 000000000000..661139551cf0 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_debug.h @@ -0,0 +1,294 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + + +#ifndef __ODM_DBG_H__ +#define __ODM_DBG_H__ + +/*#define DEBUG_VERSION "1.1"*/ /*2015.07.29 YuChen*/ +/*#define DEBUG_VERSION "1.2"*/ /*2015.08.28 Dino*/ +#define DEBUG_VERSION "1.3" /*2016.04.28 YuChen*/ +/* ----------------------------------------------------------------------------- + * Define the debug levels + * + * 1. DBG_TRACE and DBG_LOUD are used for normal cases. + * So that, they can help SW engineer to develope or trace states changed + * and also help HW enginner to trace every operation to and from HW, + * e.g IO, Tx, Rx. + * + * 2. DBG_WARNNING and DBG_SERIOUS are used for unusual or error cases, + * which help us to debug SW or HW. + * + * ----------------------------------------------------------------------------- + * + * Never used in a call to ODM_RT_TRACE()! + * */ +#define ODM_DBG_OFF 1 + +/* + * Fatal bug. + * For example, Tx/Rx/IO locked up, OS hangs, memory access violation, + * resource allocation failed, unexpected HW behavior, HW BUG and so on. + * */ +#define ODM_DBG_SERIOUS 2 + +/* + * Abnormal, rare, or unexpeted cases. + * For example, IRP/Packet/OID canceled, device suprisely unremoved and so on. + * */ +#define ODM_DBG_WARNING 3 + +/* + * Normal case with useful information about current SW or HW state. + * For example, Tx/Rx descriptor to fill, Tx/Rx descriptor completed status, + * SW protocol state change, dynamic mechanism state change and so on. + * */ +#define ODM_DBG_LOUD 4 + +/* + * Normal case with detail execution flow or information. + * */ +#define ODM_DBG_TRACE 5 + +/*FW DBG MSG*/ +#define RATE_DECISION BIT(0) +#define INIT_RA_TABLE BIT(1) +#define RATE_UP BIT(2) +#define RATE_DOWN BIT(3) +#define TRY_DONE BIT(4) +#define RA_H2C BIT(5) +#define F_RATE_AP_RPT BIT(7) + +/* ----------------------------------------------------------------------------- + * Define the tracing components + * + * ----------------------------------------------------------------------------- + *BB FW Functions*/ +#define PHYDM_FW_COMP_RA BIT(0) +#define PHYDM_FW_COMP_MU BIT(1) +#define PHYDM_FW_COMP_PATH_DIV BIT(2) +#define PHYDM_FW_COMP_PHY_CONFIG BIT(3) + + +/*BB Driver Functions*/ +#define ODM_COMP_DIG BIT(0) +#define ODM_COMP_RA_MASK BIT(1) +#define ODM_COMP_DYNAMIC_TXPWR BIT(2) +#define ODM_COMP_FA_CNT BIT(3) +#define ODM_COMP_RSSI_MONITOR BIT(4) +#define ODM_COMP_SNIFFER BIT(5) +#define ODM_COMP_ANT_DIV BIT(6) +#define ODM_COMP_DFS BIT(7) +#define ODM_COMP_NOISY_DETECT BIT(8) +#define ODM_COMP_RATE_ADAPTIVE BIT(9) +#define ODM_COMP_PATH_DIV BIT(10) +#define ODM_COMP_CCX BIT(11) + +#define ODM_COMP_DYNAMIC_PRICCA BIT(12) +/*BIT13 TBD*/ +#define ODM_COMP_MP BIT(14) +#define ODM_COMP_CFO_TRACKING BIT(15) +#define ODM_COMP_ACS BIT(16) +#define PHYDM_COMP_ADAPTIVITY BIT(17) +#define PHYDM_COMP_RA_DBG BIT(18) +#define PHYDM_COMP_TXBF BIT(19) +/* MAC Functions */ +#define ODM_COMP_EDCA_TURBO BIT(20) +#define ODM_COMP_DYNAMIC_RX_PATH BIT(21) +#define ODM_FW_DEBUG_TRACE BIT(22) +/* RF Functions */ +/*BIT23 TBD*/ +#define ODM_COMP_TX_PWR_TRACK BIT(24) +/*BIT25 TBD*/ +#define ODM_COMP_CALIBRATION BIT(26) +/* Common Functions */ +/*BIT27 TBD*/ +#define ODM_PHY_CONFIG BIT(28) +#define ODM_COMP_INIT BIT(29) +#define ODM_COMP_COMMON BIT(30) +#define ODM_COMP_API BIT(31) + + +/*------------------------Export Marco Definition---------------------------*/ + +#define config_phydm_read_txagc_check(data) (data != INVALID_TXAGC_DATA) + +#define dbg_print printk +#define RT_PRINTK(fmt, args...) dbg_print("%s(): " fmt, __func__, ## args); +#define RT_DISP(dbgtype, dbgflag, printstr) + +#ifndef ASSERT + #define ASSERT(expr) +#endif + +#if DBG +#define ODM_RT_TRACE(p_dm_odm, comp, level, fmt) \ + do { \ + if (((comp) & p_dm_odm->debug_components) && (level <= p_dm_odm->debug_level || level == ODM_DBG_SERIOUS)) { \ + \ + if (p_dm_odm->support_ic_type == ODM_RTL8188E) \ + dbg_print("[PhyDM-8188E] "); \ + else if (p_dm_odm->support_ic_type == ODM_RTL8192E) \ + dbg_print("[PhyDM-8192E] "); \ + else if (p_dm_odm->support_ic_type == ODM_RTL8812) \ + dbg_print("[PhyDM-8812A] "); \ + else if (p_dm_odm->support_ic_type == ODM_RTL8821) \ + dbg_print("[PhyDM-8821A] "); \ + else if (p_dm_odm->support_ic_type == ODM_RTL8814A) \ + dbg_print("[PhyDM-8814A] "); \ + else if (p_dm_odm->support_ic_type == ODM_RTL8703B) \ + dbg_print("[PhyDM-8703B] "); \ + else if (p_dm_odm->support_ic_type == ODM_RTL8822B) \ + dbg_print("[PhyDM-8822B] "); \ + else if (p_dm_odm->support_ic_type == ODM_RTL8188F) \ + dbg_print("[PhyDM-8188F] "); \ + RT_PRINTK fmt; \ + } \ + } while (0) + +#define ODM_RT_TRACE_F(p_dm_odm, comp, level, fmt) do {\ + if (((comp) & p_dm_odm->debug_components) && (level <= p_dm_odm->debug_level)) { \ + \ + RT_PRINTK fmt; \ + } \ + } while (0) + + +#define ODM_RT_ASSERT(p_dm_odm, expr, fmt) do {\ + if (!(expr)) { \ + dbg_print("Assertion failed! %s at ......\n", #expr); \ + dbg_print(" ......%s,%s, line=%d\n", __FILE__, __func__, __LINE__); \ + RT_PRINTK fmt; \ + ASSERT(false); \ + } \ + } while (0) + +#define ODM_dbg_enter() { dbg_print(" == > %s\n", __func__); } +#define ODM_dbg_exit() { dbg_print("< == %s\n", __func__); } +#define ODM_dbg_trace(str) { dbg_print("%s:%s\n", __func__, str); } + +#define ODM_PRINT_ADDR(p_dm_odm, comp, level, title_str, ptr) do {\ + if (((comp) & p_dm_odm->debug_components) && (level <= p_dm_odm->debug_level)) { \ + \ + int __i; \ + u8 *__ptr = (u8 *)ptr; \ + dbg_print("[ODM] "); \ + dbg_print(title_str); \ + dbg_print(" "); \ + for (__i = 0; __i < 6; __i++) \ + dbg_print("%02X%s", __ptr[__i], (__i == 5) ? "" : "-"); \ + dbg_print("\n"); \ + } \ + } while (0) + +#else +#define ODM_RT_TRACE(p_dm_odm, comp, level, fmt) +#define ODM_RT_TRACE_F(p_dm_odm, comp, level, fmt) +#define ODM_RT_ASSERT(p_dm_odm, expr, fmt) +#define ODM_dbg_enter() +#define ODM_dbg_exit() +#define ODM_dbg_trace(str) +#define ODM_PRINT_ADDR(p_dm_odm, comp, level, title_str, ptr) +#endif + + +void +phydm_init_debug_setting(struct PHY_DM_STRUCT *p_dm_odm); + +void phydm_basic_dbg_message(void *p_dm_void); + +#define PHYDM_DBGPRINT 0 +#define MAX_ARGC 20 +#define MAX_ARGV 16 +#define DCMD_DECIMAL "%d" +#define DCMD_CHAR "%c" +#define DCMD_HEX "%x" + +#define PHYDM_SSCANF(x, y, z) sscanf(x, y, z) + +#define PHYDM_VAST_INFO_SNPRINTF(msg)\ + do {\ + snprintf msg;\ + dbg_print(output);\ + } while (0) + +#if (PHYDM_DBGPRINT == 1) +#define PHYDM_SNPRINTF(msg)\ + do {\ + snprintf msg;\ + dbg_print(output);\ + } while (0) +#else +#define PHYDM_SNPRINTF(msg)\ + do {\ + if (out_len > used)\ + used += snprintf msg;\ + } while (0) +#endif + +void phydm_basic_profile( + void *p_dm_void, + u32 *_used, + char *output, + u32 *_out_len +); +s32 +phydm_cmd( + struct PHY_DM_STRUCT *p_dm_odm, + char *input, + u32 in_len, + u8 flag, + char *output, + u32 out_len +); + +void +phydm_cmd_parser( + struct PHY_DM_STRUCT *p_dm_odm, + char input[][16], + u32 input_num, + u8 flag, + char *output, + u32 out_len +); + +bool +phydm_api_trx_mode( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_rf_path_e tx_path, + enum odm_rf_path_e rx_path, + bool is_tx2_path +); + +void +phydm_fw_trace_en_h2c( + void *p_dm_void, + bool enable, + u32 fw_debug_component, + u32 monitor_mode, + u32 macid +); + +void +phydm_fw_trace_handler( + void *p_dm_void, + u8 *cmd_buf, + u8 cmd_len +); + +void +phydm_fw_trace_handler_code( + void *p_dm_void, + u8 *buffer, + u8 cmd_len +); + +void +phydm_fw_trace_handler_8051( + void *p_dm_void, + u8 *cmd_buf, + u8 cmd_len +); + +#endif /* __ODM_DBG_H__ */ diff --git a/drivers/staging/rtl8188eu/hal/phydm_dfs.c b/drivers/staging/rtl8188eu/hal/phydm_dfs.c new file mode 100644 index 000000000000..5b1f6f45d3cd --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_dfs.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* +============================================================ + include files +============================================================ +*/ + +#include "mp_precomp.h" +#include "phydm_precomp.h" + +#if defined(CONFIG_PHYDM_DFS_MASTER) +void phydm_radar_detect_reset(void *p_dm_void) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + odm_set_bb_reg(p_dm_odm, 0x924, BIT(15), 0); + odm_set_bb_reg(p_dm_odm, 0x924, BIT(15), 1); +} + +void phydm_radar_detect_disable(void *p_dm_void) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + odm_set_bb_reg(p_dm_odm, 0x924, BIT(15), 0); +} + +static void phydm_radar_detect_with_dbg_parm(void *p_dm_void) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + odm_set_bb_reg(p_dm_odm, 0x918, MASKDWORD, p_dm_odm->radar_detect_reg_918); + odm_set_bb_reg(p_dm_odm, 0x91c, MASKDWORD, p_dm_odm->radar_detect_reg_91c); + odm_set_bb_reg(p_dm_odm, 0x920, MASKDWORD, p_dm_odm->radar_detect_reg_920); + odm_set_bb_reg(p_dm_odm, 0x924, MASKDWORD, p_dm_odm->radar_detect_reg_924); +} + +/* Init radar detection parameters, called after ch, bw is set */ +void phydm_radar_detect_enable(void *p_dm_void) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 region_domain = p_dm_odm->dfs_region_domain; + u8 c_channel = *(p_dm_odm->p_channel); + + if (region_domain == PHYDM_DFS_DOMAIN_UNKNOWN) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DFS, ODM_DBG_LOUD, ("PHYDM_DFS_DOMAIN_UNKNOWN\n")); + return; + } + + if (p_dm_odm->support_ic_type & (ODM_RTL8821 | ODM_RTL8812 | ODM_RTL8881A)) { + + odm_set_bb_reg(p_dm_odm, 0x814, 0x3fffffff, 0x04cc4d10); + odm_set_bb_reg(p_dm_odm, 0x834, MASKBYTE0, 0x06); + + if (p_dm_odm->radar_detect_dbg_parm_en) { + phydm_radar_detect_with_dbg_parm(p_dm_odm); + goto exit; + } + + if (region_domain == PHYDM_DFS_DOMAIN_ETSI) { + odm_set_bb_reg(p_dm_odm, 0x918, MASKDWORD, 0x1c17ecdf); + odm_set_bb_reg(p_dm_odm, 0x924, MASKDWORD, 0x01528500); + odm_set_bb_reg(p_dm_odm, 0x91c, MASKDWORD, 0x0fa21a20); + odm_set_bb_reg(p_dm_odm, 0x920, MASKDWORD, 0xe0f69204); + + } else if (region_domain == PHYDM_DFS_DOMAIN_MKK) { + odm_set_bb_reg(p_dm_odm, 0x924, MASKDWORD, 0x01528500); + odm_set_bb_reg(p_dm_odm, 0x920, MASKDWORD, 0xe0d67234); + + if (c_channel >= 52 && c_channel <= 64) { + odm_set_bb_reg(p_dm_odm, 0x918, MASKDWORD, 0x1c16ecdf); + odm_set_bb_reg(p_dm_odm, 0x91c, MASKDWORD, 0x0f141a20); + } else { + odm_set_bb_reg(p_dm_odm, 0x918, MASKDWORD, 0x1c16acdf); + if (p_dm_odm->p_band_width == ODM_BW20M) + odm_set_bb_reg(p_dm_odm, 0x91c, MASKDWORD, 0x64721a20); + else + odm_set_bb_reg(p_dm_odm, 0x91c, MASKDWORD, 0x68721a20); + } + + } else if (region_domain == PHYDM_DFS_DOMAIN_FCC) { + odm_set_bb_reg(p_dm_odm, 0x918, MASKDWORD, 0x1c16acdf); + odm_set_bb_reg(p_dm_odm, 0x924, MASKDWORD, 0x01528500); + odm_set_bb_reg(p_dm_odm, 0x920, MASKDWORD, 0xe0d67231); + if (p_dm_odm->p_band_width == ODM_BW20M) + odm_set_bb_reg(p_dm_odm, 0x91c, MASKDWORD, 0x64741a20); + else + odm_set_bb_reg(p_dm_odm, 0x91c, MASKDWORD, 0x68741a20); + } else { + /* not supported */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DFS, ODM_DBG_LOUD, ("Unsupported dfs_region_domain:%d\n", region_domain)); + } + + } else if (p_dm_odm->support_ic_type & (ODM_RTL8814A | ODM_RTL8822B)) { + + odm_set_bb_reg(p_dm_odm, 0x814, 0x3fffffff, 0x04cc4d10); + odm_set_bb_reg(p_dm_odm, 0x834, MASKBYTE0, 0x06); + + /* 8822B only, when BW = 20M, DFIR output is 40Mhz, but DFS input is 80MMHz, so it need to upgrade to 80MHz */ + if (p_dm_odm->support_ic_type & ODM_RTL8822B) { + if (p_dm_odm->p_band_width == ODM_BW20M) + odm_set_bb_reg(p_dm_odm, 0x1984, BIT(26), 1); + else + odm_set_bb_reg(p_dm_odm, 0x1984, BIT(26), 0); + } + + if (p_dm_odm->radar_detect_dbg_parm_en) { + phydm_radar_detect_with_dbg_parm(p_dm_odm); + goto exit; + } + + if (region_domain == PHYDM_DFS_DOMAIN_ETSI) { + odm_set_bb_reg(p_dm_odm, 0x918, MASKDWORD, 0x1c16acdf); + odm_set_bb_reg(p_dm_odm, 0x924, MASKDWORD, 0x095a8500); + odm_set_bb_reg(p_dm_odm, 0x91c, MASKDWORD, 0x0fa21a20); + odm_set_bb_reg(p_dm_odm, 0x920, MASKDWORD, 0xe0f57204); + + } else if (region_domain == PHYDM_DFS_DOMAIN_MKK) { + odm_set_bb_reg(p_dm_odm, 0x924, MASKDWORD, 0x095a8500); + odm_set_bb_reg(p_dm_odm, 0x920, MASKDWORD, 0xe0d67234); + + if (c_channel >= 52 && c_channel <= 64) { + odm_set_bb_reg(p_dm_odm, 0x918, MASKDWORD, 0x1c16ecdf); + odm_set_bb_reg(p_dm_odm, 0x91c, MASKDWORD, 0x0f141a20); + } else { + odm_set_bb_reg(p_dm_odm, 0x918, MASKDWORD, 0x1c166cdf); + if (p_dm_odm->p_band_width == ODM_BW20M) + odm_set_bb_reg(p_dm_odm, 0x91c, MASKDWORD, 0x64721a20); + else + odm_set_bb_reg(p_dm_odm, 0x91c, MASKDWORD, 0x68721a20); + } + } else if (region_domain == PHYDM_DFS_DOMAIN_FCC) { + odm_set_bb_reg(p_dm_odm, 0x918, MASKDWORD, 0x1c166cdf); + odm_set_bb_reg(p_dm_odm, 0x924, MASKDWORD, 0x095a8500); + odm_set_bb_reg(p_dm_odm, 0x920, MASKDWORD, 0xe0d67231); + if (p_dm_odm->p_band_width == ODM_BW20M) + odm_set_bb_reg(p_dm_odm, 0x91c, MASKDWORD, 0x64741a20); + else + odm_set_bb_reg(p_dm_odm, 0x91c, MASKDWORD, 0x68741a20); + } else { + /* not supported */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DFS, ODM_DBG_LOUD, ("Unsupported dfs_region_domain:%d\n", region_domain)); + } + } else { + /* not supported IC type*/ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DFS, ODM_DBG_LOUD, ("Unsupported IC type:%d\n", p_dm_odm->support_ic_type)); + } + +exit: + phydm_radar_detect_reset(p_dm_odm); +} + +bool phydm_radar_detect(void *p_dm_void) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + bool enable_DFS = false; + bool radar_detected = false; + u8 region_domain = p_dm_odm->dfs_region_domain; + + if (region_domain == PHYDM_DFS_DOMAIN_UNKNOWN) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DFS, ODM_DBG_LOUD, ("PHYDM_DFS_DOMAIN_UNKNOWN\n")); + return false; + } + + if (odm_get_bb_reg(p_dm_odm, 0x924, BIT(15))) + enable_DFS = true; + + if ((odm_get_bb_reg(p_dm_odm, 0xf98, BIT(17))) + || (!(region_domain == PHYDM_DFS_DOMAIN_ETSI) && (odm_get_bb_reg(p_dm_odm, 0xf98, BIT(19))))) + radar_detected = true; + + if (enable_DFS && radar_detected) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DFS, ODM_DBG_LOUD + , ("Radar detect: enable_DFS:%d, radar_detected:%d\n" + , enable_DFS, radar_detected)); + + phydm_radar_detect_reset(p_dm_odm); + } + +exit: + return enable_DFS && radar_detected; +} +#endif /* defined(CONFIG_PHYDM_DFS_MASTER) */ + +bool +phydm_dfs_master_enabled( + void *p_dm_void +) +{ +#ifdef CONFIG_PHYDM_DFS_MASTER + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + return *p_dm_odm->dfs_master_enabled ? true : false; +#else + return false; +#endif +} + +void +phydm_dfs_debug( + void *p_dm_void, + u32 *const argv, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 used = *_used; + u32 out_len = *_out_len; + + switch (argv[0]) { + case 1: +#if defined(CONFIG_PHYDM_DFS_MASTER) + /* set dbg parameters for radar detection instead of the default value */ + if (argv[1] == 1) { + p_dm_odm->radar_detect_reg_918 = argv[2]; + p_dm_odm->radar_detect_reg_91c = argv[3]; + p_dm_odm->radar_detect_reg_920 = argv[4]; + p_dm_odm->radar_detect_reg_924 = argv[5]; + p_dm_odm->radar_detect_dbg_parm_en = 1; + + PHYDM_SNPRINTF((output + used, out_len - used, "Radar detection with dbg parameter\n")); + PHYDM_SNPRINTF((output + used, out_len - used, "reg918:0x%08X\n", p_dm_odm->radar_detect_reg_918)); + PHYDM_SNPRINTF((output + used, out_len - used, "reg91c:0x%08X\n", p_dm_odm->radar_detect_reg_91c)); + PHYDM_SNPRINTF((output + used, out_len - used, "reg920:0x%08X\n", p_dm_odm->radar_detect_reg_920)); + PHYDM_SNPRINTF((output + used, out_len - used, "reg924:0x%08X\n", p_dm_odm->radar_detect_reg_924)); + } else { + p_dm_odm->radar_detect_dbg_parm_en = 0; + PHYDM_SNPRINTF((output + used, out_len - used, "Radar detection with default parameter\n")); + } + phydm_radar_detect_enable(p_dm_odm); +#endif /* defined(CONFIG_PHYDM_DFS_MASTER) */ + + break; + default: + break; + } +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_dfs.h b/drivers/staging/rtl8188eu/hal/phydm_dfs.h new file mode 100644 index 000000000000..b89ccea0d6f5 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_dfs.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDM_DFS_H__ +#define __PHYDM_DFS_H__ + +#define DFS_VERSION "0.0" + +/* ============================================================ + Definition + ============================================================ +*/ + +/* +============================================================ +1 structure + ============================================================ +*/ + +/* ============================================================ + enumeration + ============================================================ +*/ + +enum phydm_dfs_region_domain { + PHYDM_DFS_DOMAIN_UNKNOWN = 0, + PHYDM_DFS_DOMAIN_FCC = 1, + PHYDM_DFS_DOMAIN_MKK = 2, + PHYDM_DFS_DOMAIN_ETSI = 3, +}; + +/* +============================================================ + function prototype +============================================================ +*/ +#if defined(CONFIG_PHYDM_DFS_MASTER) + void phydm_radar_detect_reset(void *p_dm_void); + void phydm_radar_detect_disable(void *p_dm_void); + void phydm_radar_detect_enable(void *p_dm_void); + bool phydm_radar_detect(void *p_dm_void); +#endif /* defined(CONFIG_PHYDM_DFS_MASTER) */ + +bool +phydm_dfs_master_enabled( + void *p_dm_void +); + +void +phydm_dfs_debug( + void *p_dm_void, + u32 *const argv, + u32 *_used, + char *output, + u32 *_out_len +); + +#endif /*#ifndef __PHYDM_DFS_H__ */ diff --git a/drivers/staging/rtl8188eu/hal/phydm_dig.c b/drivers/staging/rtl8188eu/hal/phydm_dig.c new file mode 100644 index 000000000000..f13f77c05ef0 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_dig.c @@ -0,0 +1,1305 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* ************************************************************ + * include files + * ************************************************************ */ +#include "mp_precomp.h" +#include "phydm_precomp.h" + + +void +odm_change_dynamic_init_gain_thresh( + void *p_dm_void, + u32 dm_type, + u32 dm_value +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + + if (dm_type == DIG_TYPE_THRESH_HIGH) + p_dm_dig_table->rssi_high_thresh = dm_value; + else if (dm_type == DIG_TYPE_THRESH_LOW) + p_dm_dig_table->rssi_low_thresh = dm_value; + else if (dm_type == DIG_TYPE_ENABLE) + p_dm_dig_table->dig_enable_flag = true; + else if (dm_type == DIG_TYPE_DISABLE) + p_dm_dig_table->dig_enable_flag = false; + else if (dm_type == DIG_TYPE_BACKOFF) { + if (dm_value > 30) + dm_value = 30; + p_dm_dig_table->backoff_val = (u8)dm_value; + } else if (dm_type == DIG_TYPE_RX_GAIN_MIN) { + if (dm_value == 0) + dm_value = 0x1; + p_dm_dig_table->rx_gain_range_min = (u8)dm_value; + } else if (dm_type == DIG_TYPE_RX_GAIN_MAX) { + if (dm_value > 0x50) + dm_value = 0x50; + p_dm_dig_table->rx_gain_range_max = (u8)dm_value; + } +} /* dm_change_dynamic_init_gain_thresh */ + +static int +get_igi_for_diff(int value_IGI) +{ +#define ONERCCA_LOW_TH 0x30 +#define ONERCCA_LOW_DIFF 8 + + if (value_IGI < ONERCCA_LOW_TH) { + if ((ONERCCA_LOW_TH - value_IGI) < ONERCCA_LOW_DIFF) + return ONERCCA_LOW_TH; + else + return value_IGI + ONERCCA_LOW_DIFF; + } else + return value_IGI; +} + +static void +odm_fa_threshold_check( + void *p_dm_void, + bool is_dfs_band, + bool is_performance, + u32 rx_tp, + u32 tx_tp, + u32 *dm_FA_thres +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (p_dm_odm->is_linked && (is_performance || is_dfs_band)) { + /*For NIC*/ + dm_FA_thres[0] = DM_DIG_FA_TH0; + dm_FA_thres[1] = DM_DIG_FA_TH1; + dm_FA_thres[2] = DM_DIG_FA_TH2; + } else { + if (is_dfs_band) { + /* For DFS band and no link */ + dm_FA_thres[0] = 250; + dm_FA_thres[1] = 1000; + dm_FA_thres[2] = 2000; + } else { + dm_FA_thres[0] = 2000; + dm_FA_thres[1] = 4000; + dm_FA_thres[2] = 5000; + } + } + return; +} + +static u8 +odm_forbidden_igi_check( + void *p_dm_void, + u8 dig_dynamic_min, + u8 current_igi +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + struct false_ALARM_STATISTICS *p_false_alm_cnt = (struct false_ALARM_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDMfalseALMCNT); + u8 rx_gain_range_min = p_dm_dig_table->rx_gain_range_min; + + if (p_dm_dig_table->large_fa_timeout) { + if (--p_dm_dig_table->large_fa_timeout == 0) + p_dm_dig_table->large_fa_hit = 0; + } + + if (p_false_alm_cnt->cnt_all > 10000) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Abnormally false alarm case.\n")); + + if (p_dm_dig_table->large_fa_hit != 3) + p_dm_dig_table->large_fa_hit++; + + if (p_dm_dig_table->forbidden_igi < current_igi) { /* if(p_dm_dig_table->forbidden_igi < p_dm_dig_table->cur_ig_value) */ + p_dm_dig_table->forbidden_igi = current_igi;/* p_dm_dig_table->forbidden_igi = p_dm_dig_table->cur_ig_value; */ + p_dm_dig_table->large_fa_hit = 1; + p_dm_dig_table->large_fa_timeout = LARGE_FA_TIMEOUT; + } + + if (p_dm_dig_table->large_fa_hit >= 3) { + if ((p_dm_dig_table->forbidden_igi + 2) > p_dm_dig_table->rx_gain_range_max) + rx_gain_range_min = p_dm_dig_table->rx_gain_range_max; + else + rx_gain_range_min = (p_dm_dig_table->forbidden_igi + 2); + p_dm_dig_table->recover_cnt = 1800; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Abnormally false alarm case: recover_cnt = %d\n", p_dm_dig_table->recover_cnt)); + } + } + + else if (p_false_alm_cnt->cnt_all > 2000) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("Abnormally false alarm case.\n")); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("cnt_all=%d, cnt_all_pre=%d, current_igi=0x%x, pre_ig_value=0x%x\n", + p_false_alm_cnt->cnt_all, p_false_alm_cnt->cnt_all_pre, current_igi, p_dm_dig_table->pre_ig_value)); + + /* p_false_alm_cnt->cnt_all = 1.1875*p_false_alm_cnt->cnt_all_pre */ + if ((p_false_alm_cnt->cnt_all > (p_false_alm_cnt->cnt_all_pre + (p_false_alm_cnt->cnt_all_pre >> 3) + (p_false_alm_cnt->cnt_all_pre >> 4))) && (current_igi < p_dm_dig_table->pre_ig_value)) { + if (p_dm_dig_table->large_fa_hit != 3) + p_dm_dig_table->large_fa_hit++; + + if (p_dm_dig_table->forbidden_igi < current_igi) { /*if(p_dm_dig_table->forbidden_igi < p_dm_dig_table->cur_ig_value)*/ + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("Updating forbidden_igi by current_igi, forbidden_igi=0x%x, current_igi=0x%x\n", + p_dm_dig_table->forbidden_igi, current_igi)); + + p_dm_dig_table->forbidden_igi = current_igi; /*p_dm_dig_table->forbidden_igi = p_dm_dig_table->cur_ig_value;*/ + p_dm_dig_table->large_fa_hit = 1; + p_dm_dig_table->large_fa_timeout = LARGE_FA_TIMEOUT; + } + + } + + if (p_dm_dig_table->large_fa_hit >= 3) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("FaHit is greater than 3, rx_gain_range_max=0x%x, rx_gain_range_min=0x%x, forbidden_igi=0x%x\n", + p_dm_dig_table->rx_gain_range_max, rx_gain_range_min, p_dm_dig_table->forbidden_igi)); + + if ((p_dm_dig_table->forbidden_igi + 1) > p_dm_dig_table->rx_gain_range_max) + rx_gain_range_min = p_dm_dig_table->rx_gain_range_max; + else + rx_gain_range_min = (p_dm_dig_table->forbidden_igi + 1); + + p_dm_dig_table->recover_cnt = 1200; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("Abnormally false alarm case: recover_cnt = %d, rx_gain_range_min = 0x%x\n", p_dm_dig_table->recover_cnt, rx_gain_range_min)); + } + } + + else { + if (p_dm_dig_table->recover_cnt != 0) { + + p_dm_dig_table->recover_cnt--; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Normal Case: recover_cnt = %d\n", p_dm_dig_table->recover_cnt)); + } else { + if (p_dm_dig_table->large_fa_hit < 3) { + if ((p_dm_dig_table->forbidden_igi - 2) < dig_dynamic_min) { /* DM_DIG_MIN) */ + p_dm_dig_table->forbidden_igi = dig_dynamic_min; /* DM_DIG_MIN; */ + rx_gain_range_min = dig_dynamic_min; /* DM_DIG_MIN; */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Normal Case: At Lower Bound\n")); + } else { + if (p_dm_dig_table->large_fa_hit == 0) { + p_dm_dig_table->forbidden_igi -= 2; + rx_gain_range_min = (p_dm_dig_table->forbidden_igi + 2); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Normal Case: Approach Lower Bound\n")); + } + } + } else + p_dm_dig_table->large_fa_hit = 0; + } + } + + return rx_gain_range_min; + +} + +static void +odm_inband_noise_calculate( + void *p_dm_void +) +{ +} + +static void +odm_dig_for_bt_hs_mode( + void *p_dm_void +) +{ +} + +static void +phydm_set_big_jump_step( + void *p_dm_void, + u8 current_igi +) +{ +} + +void +odm_write_dig( + void *p_dm_void, + u8 current_igi +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + + if (p_dm_dig_table->is_stop_dig) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_write_dig(): Stop Writing IGI\n")); + return; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_TRACE, ("odm_write_dig(): ODM_REG(IGI_A,p_dm_odm)=0x%x, ODM_BIT(IGI,p_dm_odm)=0x%x\n", + ODM_REG(IGI_A, p_dm_odm), ODM_BIT(IGI, p_dm_odm))); + + /* 1 Check initial gain by upper bound */ + if ((!p_dm_dig_table->is_psd_in_progress) && p_dm_odm->is_linked) { + if (current_igi > p_dm_dig_table->rx_gain_range_max) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_TRACE, ("odm_write_dig(): current_igi(0x%02x) is larger than upper bound !!\n", current_igi)); + current_igi = p_dm_dig_table->rx_gain_range_max; + } + if (p_dm_odm->support_ability & ODM_BB_ADAPTIVITY && p_dm_odm->adaptivity_flag == true) { + if (current_igi > p_dm_odm->adaptivity_igi_upper) + current_igi = p_dm_odm->adaptivity_igi_upper; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_write_dig(): adaptivity case: Force upper bound to 0x%x !!!!!!\n", current_igi)); + } + } + + if (p_dm_dig_table->cur_ig_value != current_igi) { + +#if (ODM_PHY_STATUS_NEW_TYPE_SUPPORT == 1) + /* Set IGI value of CCK for new CCK AGC */ + if (p_dm_odm->cck_new_agc) { + if (p_dm_odm->support_ic_type & ODM_IC_PHY_STATUE_NEW_TYPE) + odm_set_bb_reg(p_dm_odm, 0xa0c, 0x00003f00, (current_igi >> 1)); + } +#endif + + /*Add by YuChen for USB IO too slow issue*/ + if ((p_dm_odm->support_ability & ODM_BB_ADAPTIVITY) && (current_igi > p_dm_dig_table->cur_ig_value)) { + p_dm_dig_table->cur_ig_value = current_igi; + phydm_adaptivity(p_dm_odm); + } + + /* 1 Set IGI value */ + if (p_dm_odm->support_platform & (ODM_WIN | ODM_CE)) { + odm_set_bb_reg(p_dm_odm, ODM_REG(IGI_A, p_dm_odm), ODM_BIT(IGI, p_dm_odm), current_igi); + + if (p_dm_odm->rf_type > ODM_1T1R) + odm_set_bb_reg(p_dm_odm, ODM_REG(IGI_B, p_dm_odm), ODM_BIT(IGI, p_dm_odm), current_igi); + +#if (RTL8814A_SUPPORT == 1) + if (p_dm_odm->support_ic_type & ODM_RTL8814A) { + odm_set_bb_reg(p_dm_odm, ODM_REG(IGI_C, p_dm_odm), ODM_BIT(IGI, p_dm_odm), current_igi); + odm_set_bb_reg(p_dm_odm, ODM_REG(IGI_D, p_dm_odm), ODM_BIT(IGI, p_dm_odm), current_igi); + } +#endif + } else if (p_dm_odm->support_platform & (ODM_AP)) { + switch (*(p_dm_odm->p_one_path_cca)) { + case ODM_CCA_2R: + odm_set_bb_reg(p_dm_odm, ODM_REG(IGI_A, p_dm_odm), ODM_BIT(IGI, p_dm_odm), current_igi); + + if (p_dm_odm->rf_type > ODM_1T1R) + odm_set_bb_reg(p_dm_odm, ODM_REG(IGI_B, p_dm_odm), ODM_BIT(IGI, p_dm_odm), current_igi); +#if (RTL8814A_SUPPORT == 1) + if (p_dm_odm->support_ic_type & ODM_RTL8814A) { + odm_set_bb_reg(p_dm_odm, ODM_REG(IGI_C, p_dm_odm), ODM_BIT(IGI, p_dm_odm), current_igi); + odm_set_bb_reg(p_dm_odm, ODM_REG(IGI_D, p_dm_odm), ODM_BIT(IGI, p_dm_odm), current_igi); + } +#endif + break; + case ODM_CCA_1R_A: + odm_set_bb_reg(p_dm_odm, ODM_REG(IGI_A, p_dm_odm), ODM_BIT(IGI, p_dm_odm), current_igi); + if (p_dm_odm->rf_type != ODM_1T1R) + odm_set_bb_reg(p_dm_odm, ODM_REG(IGI_B, p_dm_odm), ODM_BIT(IGI, p_dm_odm), get_igi_for_diff(current_igi)); + break; + case ODM_CCA_1R_B: + odm_set_bb_reg(p_dm_odm, ODM_REG(IGI_B, p_dm_odm), ODM_BIT(IGI, p_dm_odm), get_igi_for_diff(current_igi)); + if (p_dm_odm->rf_type != ODM_1T1R) + odm_set_bb_reg(p_dm_odm, ODM_REG(IGI_A, p_dm_odm), ODM_BIT(IGI, p_dm_odm), current_igi); + break; + } + } + + p_dm_dig_table->cur_ig_value = current_igi; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_TRACE, ("odm_write_dig(): current_igi(0x%02x).\n", current_igi)); + +} + +void +odm_pause_dig( + void *p_dm_void, + enum phydm_pause_type pause_type, + enum phydm_pause_level pause_level, + u8 igi_value +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_dig()=========> level = %d\n", pause_level)); + + if ((p_dm_dig_table->pause_dig_level == 0) && (!(p_dm_odm->support_ability & ODM_BB_DIG) || !(p_dm_odm->support_ability & ODM_BB_FA_CNT))) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, + ("odm_pause_dig(): Return: support_ability DIG or FA is disabled !!\n")); + return; + } + + if (pause_level > DM_DIG_MAX_PAUSE_TYPE) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, + ("odm_pause_dig(): Return: Wrong pause level !!\n")); + return; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_dig(): pause level = 0x%x, Current value = 0x%x\n", p_dm_dig_table->pause_dig_level, igi_value)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_dig(): pause value = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + p_dm_dig_table->pause_dig_value[7], p_dm_dig_table->pause_dig_value[6], p_dm_dig_table->pause_dig_value[5], p_dm_dig_table->pause_dig_value[4], + p_dm_dig_table->pause_dig_value[3], p_dm_dig_table->pause_dig_value[2], p_dm_dig_table->pause_dig_value[1], p_dm_dig_table->pause_dig_value[0])); + + switch (pause_type) { + /* Pause DIG */ + case PHYDM_PAUSE: + { + /* Disable DIG */ + odm_cmn_info_update(p_dm_odm, ODM_CMNINFO_ABILITY, p_dm_odm->support_ability & (~ODM_BB_DIG)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_dig(): Pause DIG !!\n")); + + /* Backup IGI value */ + if (p_dm_dig_table->pause_dig_level == 0) { + p_dm_dig_table->igi_backup = p_dm_dig_table->cur_ig_value; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_dig(): Backup IGI = 0x%x, new IGI = 0x%x\n", p_dm_dig_table->igi_backup, igi_value)); + } + + /* Record IGI value */ + p_dm_dig_table->pause_dig_value[pause_level] = igi_value; + + /* Update pause level */ + p_dm_dig_table->pause_dig_level = (p_dm_dig_table->pause_dig_level | BIT(pause_level)); + + /* Write new IGI value */ + if (BIT(pause_level + 1) > p_dm_dig_table->pause_dig_level) { + odm_write_dig(p_dm_odm, igi_value); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_dig(): IGI of higher level = 0x%x\n", igi_value)); + } + break; + } + /* Resume DIG */ + case PHYDM_RESUME: + { + /* check if the level is illegal or not */ + if ((p_dm_dig_table->pause_dig_level & (BIT(pause_level))) != 0) { + p_dm_dig_table->pause_dig_level = p_dm_dig_table->pause_dig_level & (~(BIT(pause_level))); + p_dm_dig_table->pause_dig_value[pause_level] = 0; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_dig(): Resume DIG !!\n")); + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_dig(): Wrong resume level !!\n")); + break; + } + + /* Resume DIG */ + if (p_dm_dig_table->pause_dig_level == 0) { + /* Write backup IGI value */ + odm_write_dig(p_dm_odm, p_dm_dig_table->igi_backup); + p_dm_dig_table->is_ignore_dig = true; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_dig(): Write original IGI = 0x%x\n", p_dm_dig_table->igi_backup)); + + /* Enable DIG */ + odm_cmn_info_update(p_dm_odm, ODM_CMNINFO_ABILITY, p_dm_odm->support_ability | ODM_BB_DIG); + break; + } + + if (BIT(pause_level) > p_dm_dig_table->pause_dig_level) { + s8 max_level; + + /* Calculate the maximum level now */ + for (max_level = (pause_level - 1); max_level >= 0; max_level--) { + if ((p_dm_dig_table->pause_dig_level & BIT(max_level)) > 0) + break; + } + + /* write IGI of lower level */ + odm_write_dig(p_dm_odm, p_dm_dig_table->pause_dig_value[max_level]); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_dig(): Write IGI (0x%x) of level (%d)\n", + p_dm_dig_table->pause_dig_value[max_level], max_level)); + break; + } + break; + } + default: + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_dig(): Wrong type !!\n")); + break; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_dig(): pause level = 0x%x, Current value = 0x%x\n", p_dm_dig_table->pause_dig_level, igi_value)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_dig(): pause value = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + p_dm_dig_table->pause_dig_value[7], p_dm_dig_table->pause_dig_value[6], p_dm_dig_table->pause_dig_value[5], p_dm_dig_table->pause_dig_value[4], + p_dm_dig_table->pause_dig_value[3], p_dm_dig_table->pause_dig_value[2], p_dm_dig_table->pause_dig_value[1], p_dm_dig_table->pause_dig_value[0])); + +} + +static bool +odm_dig_abort( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + + /* support_ability */ + if (!(p_dm_odm->support_ability & ODM_BB_FA_CNT)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Return: support_ability ODM_BB_FA_CNT is disabled\n")); + return true; + } + + /* support_ability */ + if (!(p_dm_odm->support_ability & ODM_BB_DIG)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Return: support_ability ODM_BB_DIG is disabled\n")); + return true; + } + + /* ScanInProcess */ + if (*(p_dm_odm->p_is_scan_in_process)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Return: In Scan Progress\n")); + return true; + } + + if (p_dm_dig_table->is_ignore_dig) { + p_dm_dig_table->is_ignore_dig = false; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Return: Ignore DIG\n")); + return true; + } + + /* add by Neil Chen to avoid PSD is processing */ + if (p_dm_odm->is_dm_initial_gain_enable == false) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Return: PSD is Processing\n")); + return true; + } + +#ifdef CONFIG_SPECIAL_SETTING_FOR_FUNAI_TV + if ((p_dm_odm->is_linked) && (p_dm_odm->adapter->registrypriv.force_igi != 0)) { + printk("p_dm_odm->rssi_min=%d\n", p_dm_odm->rssi_min); + odm_write_dig(p_dm_odm, p_dm_odm->adapter->registrypriv.force_igi); + return true; + } +#endif + return false; +} + +void +odm_dig_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + u32 ret_value; + u8 i; + + p_dm_dig_table->is_stop_dig = false; + p_dm_dig_table->is_ignore_dig = false; + p_dm_dig_table->is_psd_in_progress = false; + p_dm_dig_table->cur_ig_value = (u8) odm_get_bb_reg(p_dm_odm, ODM_REG(IGI_A, p_dm_odm), ODM_BIT(IGI, p_dm_odm)); + p_dm_dig_table->pre_ig_value = 0; + p_dm_dig_table->rssi_low_thresh = DM_DIG_THRESH_LOW; + p_dm_dig_table->rssi_high_thresh = DM_DIG_THRESH_HIGH; + p_dm_dig_table->fa_low_thresh = DMfalseALARM_THRESH_LOW; + p_dm_dig_table->fa_high_thresh = DMfalseALARM_THRESH_HIGH; + p_dm_dig_table->backoff_val = DM_DIG_BACKOFF_DEFAULT; + p_dm_dig_table->backoff_val_range_max = DM_DIG_BACKOFF_MAX; + p_dm_dig_table->backoff_val_range_min = DM_DIG_BACKOFF_MIN; + p_dm_dig_table->pre_cck_cca_thres = 0xFF; + p_dm_dig_table->cur_cck_cca_thres = 0x83; + p_dm_dig_table->forbidden_igi = DM_DIG_MIN_NIC; + p_dm_dig_table->large_fa_hit = 0; + p_dm_dig_table->large_fa_timeout = 0; + p_dm_dig_table->recover_cnt = 0; + p_dm_dig_table->is_media_connect_0 = false; + p_dm_dig_table->is_media_connect_1 = false; + + /* To Initialize p_dm_odm->is_dm_initial_gain_enable == false to avoid DIG error */ + p_dm_odm->is_dm_initial_gain_enable = true; + + p_dm_dig_table->dig_dynamic_min_0 = DM_DIG_MIN_NIC; + p_dm_dig_table->dig_dynamic_min_1 = DM_DIG_MIN_NIC; + + /* To Initi BT30 IGI */ + p_dm_dig_table->bt30_cur_igi = 0x32; + + odm_memory_set(p_dm_odm, p_dm_dig_table->pause_dig_value, 0, (DM_DIG_MAX_PAUSE_TYPE + 1)); + p_dm_dig_table->pause_dig_level = 0; + odm_memory_set(p_dm_odm, p_dm_dig_table->pause_cckpd_value, 0, (DM_DIG_MAX_PAUSE_TYPE + 1)); + p_dm_dig_table->pause_cckpd_level = 0; + + if (p_dm_odm->board_type & (ODM_BOARD_EXT_PA | ODM_BOARD_EXT_LNA)) { + p_dm_dig_table->rx_gain_range_max = DM_DIG_MAX_NIC; + p_dm_dig_table->rx_gain_range_min = DM_DIG_MIN_NIC; + } else { + p_dm_dig_table->rx_gain_range_max = DM_DIG_MAX_NIC; + p_dm_dig_table->rx_gain_range_min = DM_DIG_MIN_NIC; + } +} + + +void +odm_DIG( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + /* Common parameters */ + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + struct false_ALARM_STATISTICS *p_false_alm_cnt = (struct false_ALARM_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDMfalseALMCNT); + bool first_connect, first_dis_connect; + u8 dig_max_of_min, dig_dynamic_min; + u8 dm_dig_max, dm_dig_min; + u8 current_igi = p_dm_dig_table->cur_ig_value; + u8 offset; + u32 dm_FA_thres[3]; + u32 tx_tp = 0, rx_tp = 0; + bool dig_go_up_check = true; + bool is_dfs_band = false; + bool is_performance = true, is_first_tp_target = false, is_first_coverage = false; + + if (odm_dig_abort(p_dm_odm) == true) + return; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG()===========================>\n\n")); + + + /* 1 Update status */ + { + dig_dynamic_min = p_dm_dig_table->dig_dynamic_min_0; + first_connect = (p_dm_odm->is_linked) && (p_dm_dig_table->is_media_connect_0 == false); + first_dis_connect = (!p_dm_odm->is_linked) && (p_dm_dig_table->is_media_connect_0 == true); + } + + + /* 1 Boundary Decision */ + { + /* 2 For WIN\CE */ + if (p_dm_odm->support_ic_type >= ODM_RTL8188E) + dm_dig_max = 0x5A; + else + dm_dig_max = DM_DIG_MAX_NIC; + + if (p_dm_odm->support_ic_type != ODM_RTL8821) + dm_dig_min = DM_DIG_MIN_NIC; + else + dm_dig_min = 0x1C; + + dig_max_of_min = DM_DIG_MAX_AP; + + /* Modify lower bound for DFS band */ + if ((((*p_dm_odm->p_channel >= 52) && (*p_dm_odm->p_channel <= 64)) || + ((*p_dm_odm->p_channel >= 100) && (*p_dm_odm->p_channel <= 140))) + && phydm_dfs_master_enabled(p_dm_odm) == true + ) { + is_dfs_band = true; + if (*p_dm_odm->p_band_width == ODM_BW20M) + dm_dig_min = DM_DIG_MIN_AP_DFS + 2; + else + dm_dig_min = DM_DIG_MIN_AP_DFS; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): ====== In DFS band ======\n")); + } + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Absolutly upper bound = 0x%x, lower bound = 0x%x\n", dm_dig_max, dm_dig_min)); + + if (p_dm_odm->pu1_forced_igi_lb && (0 < *p_dm_odm->pu1_forced_igi_lb)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Force IGI lb to: 0x%02x !!!!!!\n", *p_dm_odm->pu1_forced_igi_lb)); + dm_dig_min = *p_dm_odm->pu1_forced_igi_lb; + dm_dig_max = (dm_dig_min <= dm_dig_max) ? (dm_dig_max) : (dm_dig_min + 1); + } + + /* 1 Adjust boundary by RSSI */ + if (p_dm_odm->is_linked && is_performance) { + /* 2 Modify DIG upper bound */ + /* 4 Modify DIG upper bound for 92E, 8723A\B, 8821 & 8812 BT */ + if ((p_dm_odm->support_ic_type & (ODM_RTL8192E | ODM_RTL8723B | ODM_RTL8812 | ODM_RTL8821)) && (p_dm_odm->is_bt_limited_dig == 1)) { + offset = 10; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Coex. case: Force upper bound to RSSI + %d !!!!!!\n", offset)); + } else + offset = 15; + + if ((p_dm_odm->rssi_min + offset) > dm_dig_max) + p_dm_dig_table->rx_gain_range_max = dm_dig_max; + else if ((p_dm_odm->rssi_min + offset) < dm_dig_min) + p_dm_dig_table->rx_gain_range_max = dm_dig_min; + else + p_dm_dig_table->rx_gain_range_max = p_dm_odm->rssi_min + offset; + + /* 2 Modify DIG lower bound */ + /* if(p_dm_odm->is_one_entry_only) */ + { + if (p_dm_odm->rssi_min < dm_dig_min) + dig_dynamic_min = dm_dig_min; + else if (p_dm_odm->rssi_min > dig_max_of_min) + dig_dynamic_min = dig_max_of_min; + else + dig_dynamic_min = p_dm_odm->rssi_min; + + if (is_dfs_band) { + dig_dynamic_min = dm_dig_min; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): DFS band: Force lower bound to 0x%x after link !!!!!!\n", dm_dig_min)); + } + } + } else { + if (is_performance && is_dfs_band) { + p_dm_dig_table->rx_gain_range_max = 0x28; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): DFS band: Force upper bound to 0x%x before link !!!!!!\n", p_dm_dig_table->rx_gain_range_max)); + } else { + if (is_performance) + p_dm_dig_table->rx_gain_range_max = DM_DIG_MAX_OF_MIN; + else + p_dm_dig_table->rx_gain_range_max = dm_dig_max; + } + dig_dynamic_min = dm_dig_min; + } + + /* 1 Force Lower Bound for AntDiv */ + if (p_dm_odm->is_linked && !p_dm_odm->is_one_entry_only) { + if ((p_dm_odm->support_ic_type & ODM_ANTDIV_SUPPORT) && (p_dm_odm->support_ability & ODM_BB_ANT_DIV)) { + if (p_dm_odm->ant_div_type == CG_TRX_HW_ANTDIV || p_dm_odm->ant_div_type == CG_TRX_SMART_ANTDIV) { + if (p_dm_dig_table->ant_div_rssi_max > dig_max_of_min) + dig_dynamic_min = dig_max_of_min; + else + dig_dynamic_min = (u8) p_dm_dig_table->ant_div_rssi_max; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Antenna diversity case: Force lower bound to 0x%x !!!!!!\n", dig_dynamic_min)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Antenna diversity case: RSSI_max = 0x%x !!!!!!\n", p_dm_dig_table->ant_div_rssi_max)); + } + } + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Adjust boundary by RSSI Upper bound = 0x%x, Lower bound = 0x%x\n", + p_dm_dig_table->rx_gain_range_max, dig_dynamic_min)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Link status: is_linked = %d, RSSI = %d, bFirstConnect = %d, bFirsrDisConnect = %d\n\n", + p_dm_odm->is_linked, p_dm_odm->rssi_min, first_connect, first_dis_connect)); + + /* 1 Modify DIG lower bound, deal with abnormal case */ + /* 2 Abnormal false alarm case */ + if (is_dfs_band) + p_dm_dig_table->rx_gain_range_min = dig_dynamic_min; + else + { + if (!p_dm_odm->is_linked) { + p_dm_dig_table->rx_gain_range_min = dig_dynamic_min; + + if (first_dis_connect) + p_dm_dig_table->forbidden_igi = dig_dynamic_min; + } else + p_dm_dig_table->rx_gain_range_min = odm_forbidden_igi_check(p_dm_odm, dig_dynamic_min, current_igi); + } + + /* 2 Abnormal # beacon case */ + if (p_dm_odm->is_linked && !first_connect) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("Beacon Num (%d)\n", p_dm_odm->phy_dbg_info.num_qry_beacon_pkt)); + if ((p_dm_odm->phy_dbg_info.num_qry_beacon_pkt < 5) && (p_dm_odm->bsta_state)) { + p_dm_dig_table->rx_gain_range_min = 0x1c; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Abnrormal #beacon (%d) case in STA mode: Force lower bound to 0x%x !!!!!!\n\n", + p_dm_odm->phy_dbg_info.num_qry_beacon_pkt, p_dm_dig_table->rx_gain_range_min)); + } + } + + /* 2 Abnormal lower bound case */ + if (p_dm_dig_table->rx_gain_range_min > p_dm_dig_table->rx_gain_range_max) { + p_dm_dig_table->rx_gain_range_min = p_dm_dig_table->rx_gain_range_max; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Abnrormal lower bound case: Force lower bound to 0x%x !!!!!!\n\n", p_dm_dig_table->rx_gain_range_min)); + } + + + /* 1 False alarm threshold decision */ + odm_fa_threshold_check(p_dm_odm, is_dfs_band, is_performance, rx_tp, tx_tp, dm_FA_thres); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): False alarm threshold = %d, %d, %d \n\n", dm_FA_thres[0], dm_FA_thres[1], dm_FA_thres[2])); + + /* 1 Adjust initial gain by false alarm */ + if (p_dm_odm->is_linked && is_performance) { + /* 2 After link */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Adjust IGI after link\n")); + + if (is_first_tp_target || (first_connect && is_performance)) { + p_dm_dig_table->large_fa_hit = 0; + + if (is_dfs_band) { + if (p_dm_odm->rssi_min > 0x28) + current_igi = 0x28; + else + current_igi = p_dm_odm->rssi_min; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): DFS band: One-shot to 0x28 upmost!!!!!!\n")); + } else { + if (p_dm_odm->rssi_min < dig_max_of_min) { + if (current_igi < p_dm_odm->rssi_min) + current_igi = p_dm_odm->rssi_min; + } else { + if (current_igi < dig_max_of_min) + current_igi = dig_max_of_min; + } + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): First connect case: IGI does on-shot to 0x%x\n", current_igi)); + + } else { + if ((p_false_alm_cnt->cnt_all > dm_FA_thres[2]) && dig_go_up_check) + current_igi = current_igi + 4; + else if ((p_false_alm_cnt->cnt_all > dm_FA_thres[1]) && dig_go_up_check) + current_igi = current_igi + 2; + else if (p_false_alm_cnt->cnt_all < dm_FA_thres[0]) + current_igi = current_igi - 2; + + /* 4 Abnormal # beacon case */ + if ((p_dm_odm->phy_dbg_info.num_qry_beacon_pkt < 5) && (p_false_alm_cnt->cnt_all < DM_DIG_FA_TH1) && (p_dm_odm->bsta_state)) { + current_igi = p_dm_dig_table->rx_gain_range_min; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Abnormal #beacon (%d) case: IGI does one-shot to 0x%x\n", + p_dm_odm->phy_dbg_info.num_qry_beacon_pkt, current_igi)); + } + } + } else { + /* 2 Before link */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Adjust IGI before link\n")); + + if (first_dis_connect || is_first_coverage) { + current_igi = dm_dig_min; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): First disconnect case: IGI does on-shot to lower bound\n")); + } else { + if ((p_false_alm_cnt->cnt_all > dm_FA_thres[2]) && dig_go_up_check) + current_igi = current_igi + 4; + else if ((p_false_alm_cnt->cnt_all > dm_FA_thres[1]) && dig_go_up_check) + current_igi = current_igi + 2; + else if (p_false_alm_cnt->cnt_all < dm_FA_thres[0]) + current_igi = current_igi - 2; + } + } + + /* 1 Check initial gain by upper/lower bound */ + if (current_igi < p_dm_dig_table->rx_gain_range_min) + current_igi = p_dm_dig_table->rx_gain_range_min; + + if (current_igi > p_dm_dig_table->rx_gain_range_max) + current_igi = p_dm_dig_table->rx_gain_range_max; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): cur_ig_value=0x%x, TotalFA = %d\n\n", current_igi, p_false_alm_cnt->cnt_all)); + + /* 1 Update status */ + { +#if (((ODM_CONFIG_BT_COEXIST == 1))) + if (p_dm_odm->is_bt_hs_operation) { + if (p_dm_odm->is_linked) { + if (p_dm_dig_table->bt30_cur_igi > (current_igi)) + odm_write_dig(p_dm_odm, current_igi); + else + odm_write_dig(p_dm_odm, p_dm_dig_table->bt30_cur_igi); + + p_dm_dig_table->is_media_connect_0 = p_dm_odm->is_linked; + p_dm_dig_table->dig_dynamic_min_0 = dig_dynamic_min; + } else { + if (p_dm_odm->is_link_in_process) + odm_write_dig(p_dm_odm, 0x1c); + else if (p_dm_odm->is_bt_connect_process) + odm_write_dig(p_dm_odm, 0x28); + else + odm_write_dig(p_dm_odm, p_dm_dig_table->bt30_cur_igi);/* odm_write_dig(p_dm_odm, p_dm_dig_table->cur_ig_value); */ + } + } else /* BT is not using */ +#endif + { + odm_write_dig(p_dm_odm, current_igi);/* odm_write_dig(p_dm_odm, p_dm_dig_table->cur_ig_value); */ + p_dm_dig_table->is_media_connect_0 = p_dm_odm->is_linked; + p_dm_dig_table->dig_dynamic_min_0 = dig_dynamic_min; + } + } +} + +void +odm_dig_by_rssi_lps( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct false_ALARM_STATISTICS *p_false_alm_cnt = (struct false_ALARM_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDMfalseALMCNT); + + u8 rssi_lower = DM_DIG_MIN_NIC; /* 0x1E or 0x1C */ + u8 current_igi = p_dm_odm->rssi_min; + + if (odm_dig_abort(p_dm_odm) == true) + return; + + current_igi = current_igi + RSSI_OFFSET_DIG; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_dig_by_rssi_lps()==>\n")); + + /* Using FW PS mode to make IGI */ + /* Adjust by FA in LPS MODE */ + if (p_false_alm_cnt->cnt_all > DM_DIG_FA_TH2_LPS) + current_igi = current_igi + 4; + else if (p_false_alm_cnt->cnt_all > DM_DIG_FA_TH1_LPS) + current_igi = current_igi + 2; + else if (p_false_alm_cnt->cnt_all < DM_DIG_FA_TH0_LPS) + current_igi = current_igi - 2; + + + /* Lower bound checking */ + + /* RSSI Lower bound check */ + if ((p_dm_odm->rssi_min - 10) > DM_DIG_MIN_NIC) + rssi_lower = (p_dm_odm->rssi_min - 10); + else + rssi_lower = DM_DIG_MIN_NIC; + + /* Upper and Lower Bound checking */ + if (current_igi > DM_DIG_MAX_NIC) + current_igi = DM_DIG_MAX_NIC; + else if (current_igi < rssi_lower) + current_igi = rssi_lower; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_dig_by_rssi_lps(): p_false_alm_cnt->cnt_all = %d\n", p_false_alm_cnt->cnt_all)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_dig_by_rssi_lps(): p_dm_odm->rssi_min = %d\n", p_dm_odm->rssi_min)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_dig_by_rssi_lps(): current_igi = 0x%x\n", current_igi)); + + odm_write_dig(p_dm_odm, current_igi);/* odm_write_dig(p_dm_odm, p_dm_dig_table->cur_ig_value); */ +} + +/* 3============================================================ + * 3 FASLE ALARM CHECK + * 3============================================================ */ + +void +odm_false_alarm_counter_statistics( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct false_ALARM_STATISTICS *false_alm_cnt = (struct false_ALARM_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDMfalseALMCNT); +#if (PHYDM_LA_MODE_SUPPORT == 1) + struct _RT_ADCSMP *adc_smp = &(p_dm_odm->adcsmp); +#endif + u32 ret_value; + + if (!(p_dm_odm->support_ability & ODM_BB_FA_CNT)) + return; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics()======>\n")); + +#if (ODM_IC_11N_SERIES_SUPPORT == 1) + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) { + + /* hold ofdm counter */ + odm_set_bb_reg(p_dm_odm, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1); /* hold page C counter */ + odm_set_bb_reg(p_dm_odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), 1); /* hold page D counter */ + + ret_value = odm_get_bb_reg(p_dm_odm, ODM_REG_OFDM_FA_TYPE1_11N, MASKDWORD); + false_alm_cnt->cnt_fast_fsync = (ret_value & 0xffff); + false_alm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = odm_get_bb_reg(p_dm_odm, ODM_REG_OFDM_FA_TYPE2_11N, MASKDWORD); + false_alm_cnt->cnt_ofdm_cca = (ret_value & 0xffff); + false_alm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = odm_get_bb_reg(p_dm_odm, ODM_REG_OFDM_FA_TYPE3_11N, MASKDWORD); + false_alm_cnt->cnt_rate_illegal = (ret_value & 0xffff); + false_alm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = odm_get_bb_reg(p_dm_odm, ODM_REG_OFDM_FA_TYPE4_11N, MASKDWORD); + false_alm_cnt->cnt_mcs_fail = (ret_value & 0xffff); + + false_alm_cnt->cnt_ofdm_fail = false_alm_cnt->cnt_parity_fail + false_alm_cnt->cnt_rate_illegal + + false_alm_cnt->cnt_crc8_fail + false_alm_cnt->cnt_mcs_fail + + false_alm_cnt->cnt_fast_fsync + false_alm_cnt->cnt_sb_search_fail; + + /* read CCK CRC32 counter */ + false_alm_cnt->cnt_cck_crc32_error = odm_get_bb_reg(p_dm_odm, ODM_REG_CCK_CRC32_ERROR_CNT_11N, MASKDWORD); + false_alm_cnt->cnt_cck_crc32_ok = odm_get_bb_reg(p_dm_odm, ODM_REG_CCK_CRC32_OK_CNT_11N, MASKDWORD); + + /* read OFDM CRC32 counter */ + ret_value = odm_get_bb_reg(p_dm_odm, ODM_REG_OFDM_CRC32_CNT_11N, MASKDWORD); + false_alm_cnt->cnt_ofdm_crc32_error = (ret_value & 0xffff0000) >> 16; + false_alm_cnt->cnt_ofdm_crc32_ok = ret_value & 0xffff; + + /* read HT CRC32 counter */ + ret_value = odm_get_bb_reg(p_dm_odm, ODM_REG_HT_CRC32_CNT_11N, MASKDWORD); + false_alm_cnt->cnt_ht_crc32_error = (ret_value & 0xffff0000) >> 16; + false_alm_cnt->cnt_ht_crc32_ok = ret_value & 0xffff; + + /* read VHT CRC32 counter */ + false_alm_cnt->cnt_vht_crc32_error = 0; + false_alm_cnt->cnt_vht_crc32_ok = 0; + +#if (RTL8188E_SUPPORT == 1) + if (p_dm_odm->support_ic_type == ODM_RTL8188E) { + ret_value = odm_get_bb_reg(p_dm_odm, ODM_REG_SC_CNT_11N, MASKDWORD); + false_alm_cnt->cnt_bw_lsc = (ret_value & 0xffff); + false_alm_cnt->cnt_bw_usc = ((ret_value & 0xffff0000) >> 16); + } +#endif + + { + /* hold cck counter */ + odm_set_bb_reg(p_dm_odm, ODM_REG_CCK_FA_RST_11N, BIT(12), 1); + odm_set_bb_reg(p_dm_odm, ODM_REG_CCK_FA_RST_11N, BIT(14), 1); + + ret_value = odm_get_bb_reg(p_dm_odm, ODM_REG_CCK_FA_LSB_11N, MASKBYTE0); + false_alm_cnt->cnt_cck_fail = ret_value; + + ret_value = odm_get_bb_reg(p_dm_odm, ODM_REG_CCK_FA_MSB_11N, MASKBYTE3); + false_alm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; + + ret_value = odm_get_bb_reg(p_dm_odm, ODM_REG_CCK_CCA_CNT_11N, MASKDWORD); + false_alm_cnt->cnt_cck_cca = ((ret_value & 0xFF) << 8) | ((ret_value & 0xFF00) >> 8); + } + + false_alm_cnt->cnt_all_pre = false_alm_cnt->cnt_all; + + false_alm_cnt->cnt_all = (false_alm_cnt->cnt_fast_fsync + + false_alm_cnt->cnt_sb_search_fail + + false_alm_cnt->cnt_parity_fail + + false_alm_cnt->cnt_rate_illegal + + false_alm_cnt->cnt_crc8_fail + + false_alm_cnt->cnt_mcs_fail + + false_alm_cnt->cnt_cck_fail); + + false_alm_cnt->cnt_cca_all = false_alm_cnt->cnt_ofdm_cca + false_alm_cnt->cnt_cck_cca; + + if (p_dm_odm->support_ic_type >= ODM_RTL8188E) { + /*reset false alarm counter registers*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_OFDM_FA_RSTC_11N, BIT(31), 1); + odm_set_bb_reg(p_dm_odm, ODM_REG_OFDM_FA_RSTC_11N, BIT(31), 0); + odm_set_bb_reg(p_dm_odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(27), 1); + odm_set_bb_reg(p_dm_odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(27), 0); + + /*update ofdm counter*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0); /*update page C counter*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), 0); /*update page D counter*/ + + /*reset CCK CCA counter*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 0); + odm_set_bb_reg(p_dm_odm, ODM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 2); + + /*reset CCK FA counter*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 0); + odm_set_bb_reg(p_dm_odm, ODM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 2); + + /*reset CRC32 counter*/ + odm_set_bb_reg(p_dm_odm, ODM_REG_PAGE_F_RST_11N, BIT(16), 1); + odm_set_bb_reg(p_dm_odm, ODM_REG_PAGE_F_RST_11N, BIT(16), 0); + } + + /* Get debug port 0 */ + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11N, MASKDWORD, 0x0); + false_alm_cnt->dbg_port0 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11N, MASKDWORD); + + /* Get EDCCA flag */ + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11N, MASKDWORD, 0x208); + false_alm_cnt->edcca_flag = (bool)odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11N, BIT(30)); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): cnt_fast_fsync=%d, cnt_sb_search_fail=%d\n", + false_alm_cnt->cnt_fast_fsync, false_alm_cnt->cnt_sb_search_fail)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): cnt_parity_fail=%d, cnt_rate_illegal=%d\n", + false_alm_cnt->cnt_parity_fail, false_alm_cnt->cnt_rate_illegal)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): cnt_crc8_fail=%d, cnt_mcs_fail=%d\n", + false_alm_cnt->cnt_crc8_fail, false_alm_cnt->cnt_mcs_fail)); + } +#endif + +#if (ODM_IC_11AC_SERIES_SUPPORT == 1) + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) { + u32 cck_enable; + + /* read OFDM FA counter */ + false_alm_cnt->cnt_ofdm_fail = odm_get_bb_reg(p_dm_odm, ODM_REG_OFDM_FA_11AC, MASKLWORD); + + /* Read CCK FA counter */ + false_alm_cnt->cnt_cck_fail = odm_get_bb_reg(p_dm_odm, ODM_REG_CCK_FA_11AC, MASKLWORD); + + /* read CCK/OFDM CCA counter */ + ret_value = odm_get_bb_reg(p_dm_odm, ODM_REG_CCK_CCA_CNT_11AC, MASKDWORD); + false_alm_cnt->cnt_ofdm_cca = (ret_value & 0xffff0000) >> 16; + false_alm_cnt->cnt_cck_cca = ret_value & 0xffff; + + /* read CCK CRC32 counter */ + ret_value = odm_get_bb_reg(p_dm_odm, ODM_REG_CCK_CRC32_CNT_11AC, MASKDWORD); + false_alm_cnt->cnt_cck_crc32_error = (ret_value & 0xffff0000) >> 16; + false_alm_cnt->cnt_cck_crc32_ok = ret_value & 0xffff; + + /* read OFDM CRC32 counter */ + ret_value = odm_get_bb_reg(p_dm_odm, ODM_REG_OFDM_CRC32_CNT_11AC, MASKDWORD); + false_alm_cnt->cnt_ofdm_crc32_error = (ret_value & 0xffff0000) >> 16; + false_alm_cnt->cnt_ofdm_crc32_ok = ret_value & 0xffff; + + /* read HT CRC32 counter */ + ret_value = odm_get_bb_reg(p_dm_odm, ODM_REG_HT_CRC32_CNT_11AC, MASKDWORD); + false_alm_cnt->cnt_ht_crc32_error = (ret_value & 0xffff0000) >> 16; + false_alm_cnt->cnt_ht_crc32_ok = ret_value & 0xffff; + + /* read VHT CRC32 counter */ + ret_value = odm_get_bb_reg(p_dm_odm, ODM_REG_VHT_CRC32_CNT_11AC, MASKDWORD); + false_alm_cnt->cnt_vht_crc32_error = (ret_value & 0xffff0000) >> 16; + false_alm_cnt->cnt_vht_crc32_ok = ret_value & 0xffff; + +#if (RTL8881A_SUPPORT == 1) + /* For 8881A */ + if (p_dm_odm->support_ic_type == ODM_RTL8881A) { + u32 cnt_ofdm_fail_temp = 0; + + if (false_alm_cnt->cnt_ofdm_fail >= false_alm_cnt->cnt_ofdm_fail_pre) { + cnt_ofdm_fail_temp = false_alm_cnt->cnt_ofdm_fail_pre; + false_alm_cnt->cnt_ofdm_fail_pre = false_alm_cnt->cnt_ofdm_fail; + false_alm_cnt->cnt_ofdm_fail = false_alm_cnt->cnt_ofdm_fail - cnt_ofdm_fail_temp; + } else + false_alm_cnt->cnt_ofdm_fail_pre = false_alm_cnt->cnt_ofdm_fail; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): cnt_ofdm_fail=%d\n", false_alm_cnt->cnt_ofdm_fail_pre)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): cnt_ofdm_fail_pre=%d\n", cnt_ofdm_fail_temp)); + + /* Reset FA counter by enable/disable OFDM */ + if (false_alm_cnt->cnt_ofdm_fail_pre >= 0x7fff) { + /* reset OFDM */ + odm_set_bb_reg(p_dm_odm, ODM_REG_BB_RX_PATH_11AC, BIT(29), 0); + odm_set_bb_reg(p_dm_odm, ODM_REG_BB_RX_PATH_11AC, BIT(29), 1); + false_alm_cnt->cnt_ofdm_fail_pre = 0; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): Reset false alarm counter\n")); + } + } +#endif + + /* reset OFDM FA coutner */ + odm_set_bb_reg(p_dm_odm, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 1); + odm_set_bb_reg(p_dm_odm, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 0); + + /* reset CCK FA counter */ + odm_set_bb_reg(p_dm_odm, ODM_REG_CCK_FA_RST_11AC, BIT(15), 0); + odm_set_bb_reg(p_dm_odm, ODM_REG_CCK_FA_RST_11AC, BIT(15), 1); + + /* reset CCA counter */ + odm_set_bb_reg(p_dm_odm, ODM_REG_RST_RPT_11AC, BIT(0), 1); + odm_set_bb_reg(p_dm_odm, ODM_REG_RST_RPT_11AC, BIT(0), 0); + + cck_enable = odm_get_bb_reg(p_dm_odm, ODM_REG_BB_RX_PATH_11AC, BIT(28)); + if (cck_enable) { /* if(*p_dm_odm->p_band_type == ODM_BAND_2_4G) */ + false_alm_cnt->cnt_all = false_alm_cnt->cnt_ofdm_fail + false_alm_cnt->cnt_cck_fail; + false_alm_cnt->cnt_cca_all = false_alm_cnt->cnt_cck_cca + false_alm_cnt->cnt_ofdm_cca; + } else { + false_alm_cnt->cnt_all = false_alm_cnt->cnt_ofdm_fail; + false_alm_cnt->cnt_cca_all = false_alm_cnt->cnt_ofdm_cca; + } + +#if (PHYDM_LA_MODE_SUPPORT == 1) + if (adc_smp->adc_smp_state == ADCSMP_STATE_IDLE) +#endif + { + /* Get debug port 0 */ + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0x0); + false_alm_cnt->dbg_port0 = odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, MASKDWORD); + + /* Get EDCCA flag */ + odm_set_bb_reg(p_dm_odm, ODM_REG_DBG_RPT_11AC, MASKDWORD, 0x209); + false_alm_cnt->edcca_flag = (bool)odm_get_bb_reg(p_dm_odm, ODM_REG_RPT_11AC, BIT(30)); + } + + } +#endif + + + false_alm_cnt->cnt_crc32_error_all = false_alm_cnt->cnt_vht_crc32_error + false_alm_cnt->cnt_ht_crc32_error + false_alm_cnt->cnt_ofdm_crc32_error + false_alm_cnt->cnt_cck_crc32_error; + false_alm_cnt->cnt_crc32_ok_all = false_alm_cnt->cnt_vht_crc32_ok + false_alm_cnt->cnt_ht_crc32_ok + false_alm_cnt->cnt_ofdm_crc32_ok + false_alm_cnt->cnt_cck_crc32_ok; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): cnt_ofdm_cca=%d\n", false_alm_cnt->cnt_ofdm_cca)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): cnt_cck_cca=%d\n", false_alm_cnt->cnt_cck_cca)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): cnt_cca_all=%d\n", false_alm_cnt->cnt_cca_all)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): cnt_ofdm_fail=%d\n", false_alm_cnt->cnt_ofdm_fail)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): cnt_cck_fail=%d\n", false_alm_cnt->cnt_cck_fail)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): cnt_ofdm_fail=%d\n", false_alm_cnt->cnt_ofdm_fail)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): Total False Alarm=%d\n", false_alm_cnt->cnt_all)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): CCK CRC32 fail: %d, ok: %d\n", false_alm_cnt->cnt_cck_crc32_error, false_alm_cnt->cnt_cck_crc32_ok)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): OFDM CRC32 fail: %d, ok: %d\n", false_alm_cnt->cnt_ofdm_crc32_error, false_alm_cnt->cnt_ofdm_crc32_ok)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): HT CRC32 fail: %d, ok: %d\n", false_alm_cnt->cnt_ht_crc32_error, false_alm_cnt->cnt_ht_crc32_ok)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): VHT CRC32 fail: %d, ok: %d\n", false_alm_cnt->cnt_vht_crc32_error, false_alm_cnt->cnt_vht_crc32_ok)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): Total CRC32 fail: %d, ok: %d\n", false_alm_cnt->cnt_crc32_error_all, false_alm_cnt->cnt_crc32_ok_all)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("odm_false_alarm_counter_statistics(): dbg port 0x0 = 0x%x, EDCCA = %d\n\n", false_alm_cnt->dbg_port0, false_alm_cnt->edcca_flag)); +} + +/* 3============================================================ + * 3 CCK Packet Detect threshold + * 3============================================================ */ + +void +odm_pause_cck_packet_detection( + void *p_dm_void, + enum phydm_pause_type pause_type, + enum phydm_pause_level pause_level, + u8 cck_pd_threshold +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_cck_packet_detection()=========> level = %d\n", pause_level)); + + if ((p_dm_dig_table->pause_cckpd_level == 0) && (!(p_dm_odm->support_ability & ODM_BB_CCK_PD) || !(p_dm_odm->support_ability & ODM_BB_FA_CNT))) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("Return: support_ability ODM_BB_CCK_PD or ODM_BB_FA_CNT is disabled\n")); + return; + } + + if (pause_level > DM_DIG_MAX_PAUSE_TYPE) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, + ("odm_pause_cck_packet_detection(): Return: Wrong pause level !!\n")); + return; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_cck_packet_detection(): pause level = 0x%x, Current value = 0x%x\n", p_dm_dig_table->pause_cckpd_level, cck_pd_threshold)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_cck_packet_detection(): pause value = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + p_dm_dig_table->pause_cckpd_value[7], p_dm_dig_table->pause_cckpd_value[6], p_dm_dig_table->pause_cckpd_value[5], p_dm_dig_table->pause_cckpd_value[4], + p_dm_dig_table->pause_cckpd_value[3], p_dm_dig_table->pause_cckpd_value[2], p_dm_dig_table->pause_cckpd_value[1], p_dm_dig_table->pause_cckpd_value[0])); + + switch (pause_type) { + /* Pause CCK Packet Detection threshold */ + case PHYDM_PAUSE: + { + /* Disable CCK PD */ + odm_cmn_info_update(p_dm_odm, ODM_CMNINFO_ABILITY, p_dm_odm->support_ability & (~ODM_BB_CCK_PD)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_cck_packet_detection(): Pause CCK packet detection threshold !!\n")); + + /* Backup original CCK PD threshold decided by CCK PD mechanism */ + if (p_dm_dig_table->pause_cckpd_level == 0) { + p_dm_dig_table->cck_pd_backup = p_dm_dig_table->cur_cck_cca_thres; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, + ("odm_pause_cck_packet_detection(): Backup CCKPD = 0x%x, new CCKPD = 0x%x\n", p_dm_dig_table->cck_pd_backup, cck_pd_threshold)); + } + + /* Update pause level */ + p_dm_dig_table->pause_cckpd_level = (p_dm_dig_table->pause_cckpd_level | BIT(pause_level)); + + /* Record CCK PD threshold */ + p_dm_dig_table->pause_cckpd_value[pause_level] = cck_pd_threshold; + + /* Write new CCK PD threshold */ + if (BIT(pause_level + 1) > p_dm_dig_table->pause_cckpd_level) { + odm_write_cck_cca_thres(p_dm_odm, cck_pd_threshold); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_cck_packet_detection(): CCKPD of higher level = 0x%x\n", cck_pd_threshold)); + } + break; + } + /* Resume CCK Packet Detection threshold */ + case PHYDM_RESUME: + { + /* check if the level is illegal or not */ + if ((p_dm_dig_table->pause_cckpd_level & (BIT(pause_level))) != 0) { + p_dm_dig_table->pause_cckpd_level = p_dm_dig_table->pause_cckpd_level & (~(BIT(pause_level))); + p_dm_dig_table->pause_cckpd_value[pause_level] = 0; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_cck_packet_detection(): Resume CCK PD !!\n")); + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_cck_packet_detection(): Wrong resume level !!\n")); + break; + } + + /* Resume DIG */ + if (p_dm_dig_table->pause_cckpd_level == 0) { + /* Write backup IGI value */ + odm_write_cck_cca_thres(p_dm_odm, p_dm_dig_table->cck_pd_backup); + /* p_dm_dig_table->is_ignore_dig = true; */ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_cck_packet_detection(): Write original CCKPD = 0x%x\n", p_dm_dig_table->cck_pd_backup)); + + /* Enable DIG */ + odm_cmn_info_update(p_dm_odm, ODM_CMNINFO_ABILITY, p_dm_odm->support_ability | ODM_BB_CCK_PD); + break; + } + + if (BIT(pause_level) > p_dm_dig_table->pause_cckpd_level) { + s8 max_level; + + /* Calculate the maximum level now */ + for (max_level = (pause_level - 1); max_level >= 0; max_level--) { + if ((p_dm_dig_table->pause_cckpd_level & BIT(max_level)) > 0) + break; + } + + /* write CCKPD of lower level */ + odm_write_cck_cca_thres(p_dm_odm, p_dm_dig_table->pause_cckpd_value[max_level]); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_cck_packet_detection(): Write CCKPD (0x%x) of level (%d)\n", + p_dm_dig_table->pause_cckpd_value[max_level], max_level)); + break; + } + break; + } + default: + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_cck_packet_detection(): Wrong type !!\n")); + break; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_cck_packet_detection(): pause level = 0x%x, Current value = 0x%x\n", p_dm_dig_table->pause_cckpd_level, cck_pd_threshold)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_pause_cck_packet_detection(): pause value = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + p_dm_dig_table->pause_cckpd_value[7], p_dm_dig_table->pause_cckpd_value[6], p_dm_dig_table->pause_cckpd_value[5], p_dm_dig_table->pause_cckpd_value[4], + p_dm_dig_table->pause_cckpd_value[3], p_dm_dig_table->pause_cckpd_value[2], p_dm_dig_table->pause_cckpd_value[1], p_dm_dig_table->pause_cckpd_value[0])); +} + + +void +odm_cck_packet_detection_thresh( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + struct false_ALARM_STATISTICS *false_alm_cnt = (struct false_ALARM_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDMfalseALMCNT); + u8 cur_cck_cca_thres = p_dm_dig_table->cur_cck_cca_thres, RSSI_thd = 35; + + if ((!(p_dm_odm->support_ability & ODM_BB_CCK_PD)) || (!(p_dm_odm->support_ability & ODM_BB_FA_CNT))) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_cck_packet_detection_thresh() return==========\n")); +#ifdef MCR_WIRELESS_EXTEND + odm_write_cck_cca_thres(p_dm_odm, 0x43); +#endif + return; + } + + if (p_dm_odm->ext_lna) + return; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_cck_packet_detection_thresh() ==========>\n")); + + if (p_dm_dig_table->cck_fa_ma == 0xffffffff) + p_dm_dig_table->cck_fa_ma = false_alm_cnt->cnt_cck_fail; + else + p_dm_dig_table->cck_fa_ma = ((p_dm_dig_table->cck_fa_ma << 1) + p_dm_dig_table->cck_fa_ma + false_alm_cnt->cnt_cck_fail) >> 2; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_cck_packet_detection_thresh(): CCK FA moving average = %d\n", p_dm_dig_table->cck_fa_ma)); + + if (p_dm_odm->is_linked) { + if (p_dm_odm->rssi_min > RSSI_thd) + cur_cck_cca_thres = 0xcd; + else if (p_dm_odm->rssi_min > 20) { + if (p_dm_dig_table->cck_fa_ma > ((DM_DIG_FA_TH1 >> 1) + (DM_DIG_FA_TH1 >> 3))) + cur_cck_cca_thres = 0xcd; + else if (p_dm_dig_table->cck_fa_ma < (DM_DIG_FA_TH0 >> 1)) + cur_cck_cca_thres = 0x83; + } else if (p_dm_odm->rssi_min > 7) + cur_cck_cca_thres = 0x83; + else + cur_cck_cca_thres = 0x40; + } else { + if (p_dm_dig_table->cck_fa_ma > 0x400) + cur_cck_cca_thres = 0x83; + else if (p_dm_dig_table->cck_fa_ma < 0x200) + cur_cck_cca_thres = 0x40; + } + + odm_write_cck_cca_thres(p_dm_odm, cur_cck_cca_thres); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_cck_packet_detection_thresh() cur_cck_cca_thres = 0x%x\n", cur_cck_cca_thres)); +} + +void +odm_write_cck_cca_thres( + void *p_dm_void, + u8 cur_cck_cca_thres +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + + if (p_dm_dig_table->cur_cck_cca_thres != cur_cck_cca_thres) { /* modify by Guo.Mingzhi 2012-01-03 */ + odm_write_1byte(p_dm_odm, ODM_REG(CCK_CCA, p_dm_odm), cur_cck_cca_thres); + p_dm_dig_table->cck_fa_ma = 0xffffffff; + } + p_dm_dig_table->pre_cck_cca_thres = p_dm_dig_table->cur_cck_cca_thres; + p_dm_dig_table->cur_cck_cca_thres = cur_cck_cca_thres; +} + +bool +phydm_dig_go_up_check( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _CCX_INFO *ccx_info = &p_dm_odm->dm_ccx_info; + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = &p_dm_odm->dm_dig_table; + u8 cur_ig_value = p_dm_dig_table->cur_ig_value; + u8 max_DIG_cover_bond; + u8 current_igi_max_up_resolution; + u8 rx_gain_range_max; + u8 i = 0; + + u32 total_NHM_cnt; + u32 DIG_cover_cnt; + u32 over_DIG_cover_cnt; + bool ret = true; + + return ret; +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_dig.h b/drivers/staging/rtl8188eu/hal/phydm_dig.h new file mode 100644 index 000000000000..bf7659530bdd --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_dig.h @@ -0,0 +1,292 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDMDIG_H__ +#define __PHYDMDIG_H__ + +#define DIG_VERSION "1.3" /* 2016.08.16 YuChen. Modify IGI lower bound to 0x1e for 8197F asked by RF Arthur*/ + +/* Pause DIG & CCKPD */ +#define DM_DIG_MAX_PAUSE_TYPE 0x7 + +enum dig_goupcheck_level { + + DIG_GOUPCHECK_LEVEL_0, + DIG_GOUPCHECK_LEVEL_1, + DIG_GOUPCHECK_LEVEL_2 + +}; + +struct _dynamic_initial_gain_threshold_ { + bool is_stop_dig; /* for debug */ + bool is_ignore_dig; + bool is_psd_in_progress; + + u8 dig_enable_flag; + u8 dig_ext_port_stage; + + int rssi_low_thresh; + int rssi_high_thresh; + + u32 fa_low_thresh; + u32 fa_high_thresh; + + u8 cur_sta_connect_state; + u8 pre_sta_connect_state; + u8 cur_multi_sta_connect_state; + + u8 pre_ig_value; + u8 cur_ig_value; + u8 backup_ig_value; /* MP DIG */ + u8 bt30_cur_igi; + u8 igi_backup; + + s8 backoff_val; + s8 backoff_val_range_max; + s8 backoff_val_range_min; + u8 rx_gain_range_max; + u8 rx_gain_range_min; + u8 rssi_val_min; + + u8 pre_cck_cca_thres; + u8 cur_cck_cca_thres; + u8 pre_cck_pd_state; + u8 cur_cck_pd_state; + u8 cck_pd_backup; + u8 pause_cckpd_level; + u8 pause_cckpd_value[DM_DIG_MAX_PAUSE_TYPE + 1]; + + u8 large_fa_hit; + u8 large_fa_timeout; /*if (large_fa_hit), monitor "large_fa_timeout" sec, if timeout, large_fa_hit=0*/ + u8 forbidden_igi; + u32 recover_cnt; + + u8 dig_dynamic_min_0; + u8 dig_dynamic_min_1; + bool is_media_connect_0; + bool is_media_connect_1; + + u32 ant_div_rssi_max; + u32 RSSI_max; + + u8 *is_p2p_in_process; + + u8 pause_dig_level; + u8 pause_dig_value[DM_DIG_MAX_PAUSE_TYPE + 1]; + + u32 cck_fa_ma; + enum dig_goupcheck_level dig_go_up_check_level; +}; + +struct false_ALARM_STATISTICS { + u32 cnt_parity_fail; + u32 cnt_rate_illegal; + u32 cnt_crc8_fail; + u32 cnt_mcs_fail; + u32 cnt_ofdm_fail; + u32 cnt_ofdm_fail_pre; /* For RTL8881A */ + u32 cnt_cck_fail; + u32 cnt_all; + u32 cnt_all_pre; + u32 cnt_fast_fsync; + u32 cnt_sb_search_fail; + u32 cnt_ofdm_cca; + u32 cnt_cck_cca; + u32 cnt_cca_all; + u32 cnt_bw_usc; /* Gary */ + u32 cnt_bw_lsc; /* Gary */ + u32 cnt_cck_crc32_error; + u32 cnt_cck_crc32_ok; + u32 cnt_ofdm_crc32_error; + u32 cnt_ofdm_crc32_ok; + u32 cnt_ht_crc32_error; + u32 cnt_ht_crc32_ok; + u32 cnt_vht_crc32_error; + u32 cnt_vht_crc32_ok; + u32 cnt_crc32_error_all; + u32 cnt_crc32_ok_all; + bool cck_block_enable; + bool ofdm_block_enable; + u32 dbg_port0; + bool edcca_flag; +}; + +enum dm_dig_op_e { + DIG_TYPE_THRESH_HIGH = 0, + DIG_TYPE_THRESH_LOW = 1, + DIG_TYPE_BACKOFF = 2, + DIG_TYPE_RX_GAIN_MIN = 3, + DIG_TYPE_RX_GAIN_MAX = 4, + DIG_TYPE_ENABLE = 5, + DIG_TYPE_DISABLE = 6, + DIG_OP_TYPE_MAX +}; + +/* +enum dm_cck_pdth_e +{ + CCK_PD_STAGE_LowRssi = 0, + CCK_PD_STAGE_HighRssi = 1, + CCK_PD_STAGE_MAX = 3, +}; + +enum dm_dig_ext_port_alg_e +{ + DIG_EXT_PORT_STAGE_0 = 0, + DIG_EXT_PORT_STAGE_1 = 1, + DIG_EXT_PORT_STAGE_2 = 2, + DIG_EXT_PORT_STAGE_3 = 3, + DIG_EXT_PORT_STAGE_MAX = 4, +}; + +enum dm_dig_connect_e +{ + DIG_STA_DISCONNECT = 0, + DIG_STA_CONNECT = 1, + DIG_STA_BEFORE_CONNECT = 2, + dig_multi_sta_disconnect = 3, + dig_multi_sta_connect = 4, + DIG_CONNECT_MAX +}; + + +#define DM_MultiSTA_InitGainChangeNotify(Event) {dm_dig_table.cur_multi_sta_connect_state = Event;} + +#define DM_MultiSTA_InitGainChangeNotify_CONNECT(_ADAPTER) \ + DM_MultiSTA_InitGainChangeNotify(dig_multi_sta_connect) + +#define DM_MultiSTA_InitGainChangeNotify_DISCONNECT(_ADAPTER) \ + DM_MultiSTA_InitGainChangeNotify(dig_multi_sta_disconnect) +*/ + +enum phydm_pause_type { + PHYDM_PAUSE = BIT(0), + PHYDM_RESUME = BIT(1) +}; + +enum phydm_pause_level { + /* number of pause level can't exceed DM_DIG_MAX_PAUSE_TYPE */ + PHYDM_PAUSE_LEVEL_0 = 0, + PHYDM_PAUSE_LEVEL_1 = 1, + PHYDM_PAUSE_LEVEL_2 = 2, + PHYDM_PAUSE_LEVEL_3 = 3, + PHYDM_PAUSE_LEVEL_4 = 4, + PHYDM_PAUSE_LEVEL_5 = 5, + PHYDM_PAUSE_LEVEL_6 = 6, + PHYDM_PAUSE_LEVEL_7 = DM_DIG_MAX_PAUSE_TYPE /* maximum level */ +}; + +#define DM_DIG_THRESH_HIGH 40 +#define DM_DIG_THRESH_LOW 35 + +#define DMfalseALARM_THRESH_LOW 400 +#define DMfalseALARM_THRESH_HIGH 1000 + +#define DM_DIG_MAX_NIC 0x3e +#define DM_DIG_MIN_NIC 0x20 +#define DM_DIG_MAX_OF_MIN_NIC 0x3e + +#define DM_DIG_MAX_AP 0x3e +#define DM_DIG_MIN_AP 0x20 +#define DM_DIG_MAX_OF_MIN 0x2A /* 0x32 */ +#define DM_DIG_MIN_AP_DFS 0x20 + +#define DM_DIG_MAX_NIC_HP 0x46 +#define DM_DIG_MIN_NIC_HP 0x2e + +#define DM_DIG_MAX_AP_HP 0x42 +#define DM_DIG_MIN_AP_HP 0x30 + +/* vivi 92c&92d has different definition, 20110504 + * this is for 92c */ +#ifdef CONFIG_SPECIAL_SETTING_FOR_FUNAI_TV + #define DM_DIG_FA_TH0 0x80/* 0x20 */ +#else + #define DM_DIG_FA_TH0 0x200/* 0x20 */ +#endif + +#define DM_DIG_FA_TH1 0x300 +#define DM_DIG_FA_TH2 0x400 +/* this is for 92d */ +#define DM_DIG_FA_TH0_92D 0x100 +#define DM_DIG_FA_TH1_92D 0x400 +#define DM_DIG_FA_TH2_92D 0x600 + +#define DM_DIG_BACKOFF_MAX 12 +#define DM_DIG_BACKOFF_MIN -4 +#define DM_DIG_BACKOFF_DEFAULT 10 + +#define DM_DIG_FA_TH0_LPS 4 /* -> 4 in lps */ +#define DM_DIG_FA_TH1_LPS 15 /* -> 15 lps */ +#define DM_DIG_FA_TH2_LPS 30 /* -> 30 lps */ +#define RSSI_OFFSET_DIG 0x05 +#define LARGE_FA_TIMEOUT 60 + + +void +odm_change_dynamic_init_gain_thresh( + void *p_dm_void, + u32 dm_type, + u32 dm_value +); + +void +odm_write_dig( + void *p_dm_void, + u8 current_igi +); + +void +odm_pause_dig( + void *p_dm_void, + enum phydm_pause_type pause_type, + enum phydm_pause_level pause_level, + u8 igi_value +); + +void +odm_dig_init( + void *p_dm_void +); + +void +odm_DIG( + void *p_dm_void +); + +void +odm_dig_by_rssi_lps( + void *p_dm_void +); + +void +odm_false_alarm_counter_statistics( + void *p_dm_void +); + +void +odm_pause_cck_packet_detection( + void *p_dm_void, + enum phydm_pause_type pause_type, + enum phydm_pause_level pause_level, + u8 cck_pd_threshold +); + +void +odm_cck_packet_detection_thresh( + void *p_dm_void +); + +void +odm_write_cck_cca_thres( + void *p_dm_void, + u8 cur_cck_cca_thres +); + +bool +phydm_dig_go_up_check( + void *p_dm_void +); + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_dynamic_rx_path.c b/drivers/staging/rtl8188eu/hal/phydm_dynamic_rx_path.c new file mode 100644 index 000000000000..f68783fe4b72 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_dynamic_rx_path.c @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* ************************************************************ + * include files + * ************************************************************ */ +#include "mp_precomp.h" +#include "phydm_precomp.h" + +#if (CONFIG_DYNAMIC_RX_PATH == 1) + +void +phydm_process_phy_status_for_dynamic_rx_path( + void *p_dm_void, + void *p_phy_info_void, + void *p_pkt_info_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _odm_phy_status_info_ *p_phy_info = (struct _odm_phy_status_info_ *)p_phy_info_void; + struct _odm_per_pkt_info_ *p_pktinfo = (struct _odm_per_pkt_info_ *)p_pkt_info_void; + struct _DYNAMIC_RX_PATH_ *p_dm_drp_table = &(p_dm_odm->dm_drp_table); + /*u8 is_cck_rate=0;*/ + + + +} + +void +phydm_drp_get_statistic( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _DYNAMIC_RX_PATH_ *p_dm_drp_table = &(p_dm_odm->dm_drp_table); + struct false_ALARM_STATISTICS *false_alm_cnt = (struct false_ALARM_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDMfalseALMCNT); + + odm_false_alarm_counter_statistics(p_dm_odm); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[CCA Cnt] {CCK, OFDM, Total} = {%d, %d, %d}\n", + false_alm_cnt->cnt_cck_cca, false_alm_cnt->cnt_ofdm_cca, false_alm_cnt->cnt_cca_all)); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[FA Cnt] {CCK, OFDM, Total} = {%d, %d, %d}\n", + false_alm_cnt->cnt_cck_fail, false_alm_cnt->cnt_ofdm_fail, false_alm_cnt->cnt_all)); +} + +void +phydm_dynamic_rx_path( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _DYNAMIC_RX_PATH_ *p_dm_drp_table = &(p_dm_odm->dm_drp_table); + u8 training_set_timmer_en; + u8 curr_drp_state; + u32 rx_ok_cal; + u32 RSSI = 0; + struct false_ALARM_STATISTICS *false_alm_cnt = (struct false_ALARM_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDMfalseALMCNT); + + if (!(p_dm_odm->support_ability & ODM_BB_DYNAMIC_RX_PATH)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[Return Init] Not Support Dynamic RX PAth\n")); + return; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("Current drp_state = ((%d))\n", p_dm_drp_table->drp_state)); + + curr_drp_state = p_dm_drp_table->drp_state; + + if (p_dm_drp_table->drp_state == DRP_INIT_STATE) { + + phydm_drp_get_statistic(p_dm_odm); + + if (false_alm_cnt->cnt_crc32_ok_all > 20) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[Stop DRP Training] cnt_crc32_ok_all = ((%d))\n", false_alm_cnt->cnt_crc32_ok_all)); + p_dm_drp_table->drp_state = DRP_INIT_STATE; + training_set_timmer_en = false; + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[Start DRP Training] cnt_crc32_ok_all = ((%d))\n", false_alm_cnt->cnt_crc32_ok_all)); + p_dm_drp_table->drp_state = DRP_TRAINING_STATE_0; + p_dm_drp_table->curr_rx_path = PHYDM_AB; + training_set_timmer_en = true; + } + + } else if (p_dm_drp_table->drp_state == DRP_TRAINING_STATE_0) { + + phydm_drp_get_statistic(p_dm_odm); + + p_dm_drp_table->curr_cca_all_cnt_0 = false_alm_cnt->cnt_cca_all; + p_dm_drp_table->curr_fa_all_cnt_0 = false_alm_cnt->cnt_all; + + p_dm_drp_table->drp_state = DRP_TRAINING_STATE_1; + p_dm_drp_table->curr_rx_path = PHYDM_B; + training_set_timmer_en = true; + + } else if (p_dm_drp_table->drp_state == DRP_TRAINING_STATE_1) { + phydm_drp_get_statistic(p_dm_odm); + p_dm_drp_table->curr_cca_all_cnt_1 = false_alm_cnt->cnt_cca_all; + p_dm_drp_table->curr_fa_all_cnt_1 = false_alm_cnt->cnt_all; + p_dm_drp_table->drp_state = DRP_DECISION_STATE; + } else if (p_dm_drp_table->drp_state == DRP_TRAINING_STATE_2) { + + phydm_drp_get_statistic(p_dm_odm); + + p_dm_drp_table->curr_cca_all_cnt_2 = false_alm_cnt->cnt_cca_all; + p_dm_drp_table->curr_fa_all_cnt_2 = false_alm_cnt->cnt_all; + p_dm_drp_table->drp_state = DRP_DECISION_STATE; + } + + if (p_dm_drp_table->drp_state == DRP_DECISION_STATE) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("Current drp_state = ((%d))\n", p_dm_drp_table->drp_state)); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[0] {CCA, FA} = {%d, %d}\n", p_dm_drp_table->curr_cca_all_cnt_0, p_dm_drp_table->curr_fa_all_cnt_0)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[1] {CCA, FA} = {%d, %d}\n", p_dm_drp_table->curr_cca_all_cnt_1, p_dm_drp_table->curr_fa_all_cnt_1)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[2] {CCA, FA} = {%d, %d}\n", p_dm_drp_table->curr_cca_all_cnt_2, p_dm_drp_table->curr_fa_all_cnt_2)); + + if (p_dm_drp_table->curr_fa_all_cnt_1 < p_dm_drp_table->curr_fa_all_cnt_0) { + + if ((p_dm_drp_table->curr_fa_all_cnt_0 - p_dm_drp_table->curr_fa_all_cnt_1) > p_dm_drp_table->fa_diff_threshold) + p_dm_drp_table->curr_rx_path = PHYDM_B; + else + p_dm_drp_table->curr_rx_path = PHYDM_AB; + } else + p_dm_drp_table->curr_rx_path = PHYDM_AB; + + phydm_config_ofdm_rx_path(p_dm_odm, p_dm_drp_table->curr_rx_path); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[Training Result] curr_rx_path = ((%s%s)),\n", + ((p_dm_drp_table->curr_rx_path & PHYDM_A) ? "A" : " "), ((p_dm_drp_table->curr_rx_path & PHYDM_B) ? "B" : " "))); + + p_dm_drp_table->drp_state = DRP_INIT_STATE; + training_set_timmer_en = false; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("DRP_state: ((%d)) -> ((%d))\n", curr_drp_state, p_dm_drp_table->drp_state)); + + if (training_set_timmer_en) { + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[Training en] curr_rx_path = ((%s%s)), training_time = ((%d ms))\n", + ((p_dm_drp_table->curr_rx_path & PHYDM_A) ? "A" : " "), ((p_dm_drp_table->curr_rx_path & PHYDM_B) ? "B" : " "), p_dm_drp_table->training_time)); + + phydm_config_ofdm_rx_path(p_dm_odm, p_dm_drp_table->curr_rx_path); + odm_set_timer(p_dm_odm, &(p_dm_drp_table->phydm_dynamic_rx_path_timer), p_dm_drp_table->training_time); /*ms*/ + } else + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("DRP period end\n\n", curr_drp_state, p_dm_drp_table->drp_state)); + +} + +void +phydm_dynamic_rx_path_callback( + void *function_context +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)function_context; + struct _ADAPTER *padapter = p_dm_odm->adapter; + + if (padapter->net_closed == true) + return; +} + +void +phydm_dynamic_rx_path_timers( + void *p_dm_void, + u8 state +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _DYNAMIC_RX_PATH_ *p_dm_drp_table = &(p_dm_odm->dm_drp_table); + + if (state == INIT_DRP_TIMMER) { + + odm_initialize_timer(p_dm_odm, &(p_dm_drp_table->phydm_dynamic_rx_path_timer), + (void *)phydm_dynamic_rx_path_callback, NULL, "phydm_sw_antenna_switch_timer"); + } else if (state == CANCEL_DRP_TIMMER) + + odm_cancel_timer(p_dm_odm, &(p_dm_drp_table->phydm_dynamic_rx_path_timer)); + + else if (state == RELEASE_DRP_TIMMER) + + odm_release_timer(p_dm_odm, &(p_dm_drp_table->phydm_dynamic_rx_path_timer)); + +} + +void +phydm_dynamic_rx_path_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _DYNAMIC_RX_PATH_ *p_dm_drp_table = &(p_dm_odm->dm_drp_table); + bool ret_value; + + if (!(p_dm_odm->support_ability & ODM_BB_DYNAMIC_RX_PATH)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[Return] Not Support Dynamic RX PAth\n")); + return; + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("phydm_dynamic_rx_path_init\n")); + + p_dm_drp_table->drp_state = DRP_INIT_STATE; + p_dm_drp_table->rssi_threshold = DRP_RSSI_TH; + p_dm_drp_table->fa_count_thresold = 50; + p_dm_drp_table->fa_diff_threshold = 50; + p_dm_drp_table->training_time = 100; /*ms*/ + p_dm_drp_table->drp_skip_counter = 0; + p_dm_drp_table->drp_period = 0; + p_dm_drp_table->drp_init_finished = true; + + ret_value = phydm_api_trx_mode(p_dm_odm, (enum odm_rf_path_e)(ODM_RF_A | ODM_RF_B), (enum odm_rf_path_e)(ODM_RF_A | ODM_RF_B), true); + +} + +void +phydm_drp_debug( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 used = *_used; + u32 out_len = *_out_len; + struct _DYNAMIC_RX_PATH_ *p_dm_drp_table = &(p_dm_odm->dm_drp_table); + + switch (dm_value[0]) { + + case DRP_TRAINING_TIME: + p_dm_drp_table->training_time = (u16)dm_value[1]; + break; + case DRP_TRAINING_PERIOD: + p_dm_drp_table->drp_period = (u8)dm_value[1]; + break; + case DRP_RSSI_THRESHOLD: + p_dm_drp_table->rssi_threshold = (u8)dm_value[1]; + break; + case DRP_FA_THRESHOLD: + p_dm_drp_table->fa_count_thresold = dm_value[1]; + break; + case DRP_FA_DIFF_THRESHOLD: + p_dm_drp_table->fa_diff_threshold = dm_value[1]; + break; + default: + PHYDM_SNPRINTF((output + used, out_len - used, "[DRP] unknown command\n")); + break; +} +} + +void +phydm_dynamic_rx_path_caller( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _DYNAMIC_RX_PATH_ *p_dm_drp_table = &(p_dm_odm->dm_drp_table); + + if (p_dm_drp_table->drp_skip_counter < p_dm_drp_table->drp_period) + p_dm_drp_table->drp_skip_counter++; + else + p_dm_drp_table->drp_skip_counter = 0; + + if (p_dm_drp_table->drp_skip_counter != 0) + return; + + if (p_dm_drp_table->drp_init_finished != true) + return; + + phydm_dynamic_rx_path(p_dm_odm); + +} +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_dynamic_rx_path.h b/drivers/staging/rtl8188eu/hal/phydm_dynamic_rx_path.h new file mode 100644 index 000000000000..0502cf96d770 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_dynamic_rx_path.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDMDYMICRXPATH_H__ +#define __PHYDMDYMICRXPATH_H__ + +#define DYNAMIC_RX_PATH_VERSION "1.0" /*2016.07.15 Dino */ + + +#define DRP_RSSI_TH 35 + +#define INIT_DRP_TIMMER 0 +#define CANCEL_DRP_TIMMER 1 +#define RELEASE_DRP_TIMMER 2 + +#if (CONFIG_DYNAMIC_RX_PATH == 1) + +enum drp_state_e { + DRP_INIT_STATE = 0, + DRP_TRAINING_STATE_0 = 1, + DRP_TRAINING_STATE_1 = 2, + DRP_TRAINING_STATE_2 = 3, + DRP_DECISION_STATE = 4 +}; + +enum adjustable_value_e { + DRP_TRAINING_TIME = 0, + DRP_TRAINING_PERIOD = 1, + DRP_RSSI_THRESHOLD = 2, + DRP_FA_THRESHOLD = 3, + DRP_FA_DIFF_THRESHOLD = 4 +}; + +struct _DYNAMIC_RX_PATH_ { + u8 curr_rx_path; + u8 drp_state; + u16 training_time; + u8 rssi_threshold; + u32 fa_count_thresold; + u32 fa_diff_threshold; + u32 curr_cca_all_cnt_0; + u32 curr_fa_all_cnt_0; + u32 curr_cca_all_cnt_1; + u32 curr_fa_all_cnt_1; + u32 curr_cca_all_cnt_2; + u32 curr_fa_all_cnt_2; + u8 drp_skip_counter; + u8 drp_period; + u8 drp_init_finished; + struct timer_list phydm_dynamic_rx_path_timer; +}; + + + +void +phydm_process_phy_status_for_dynamic_rx_path( + void *p_dm_void, + void *p_phy_info_void, + void *p_pkt_info_void +); + +void phydm_dynamic_rx_path(void *p_dm_void); + +void phydm_dynamic_rx_path_callback(void *function_context); + +void +phydm_dynamic_rx_path_timers( + void *p_dm_void, + u8 state +); + +void +phydm_dynamic_rx_path_init( + void *p_dm_void +); + +void +phydm_drp_debug( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +); + +void +phydm_dynamic_rx_path_caller( + void *p_dm_void +); + +#endif +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_dynamicbbpowersaving.c b/drivers/staging/rtl8188eu/hal/phydm_dynamicbbpowersaving.c new file mode 100644 index 000000000000..7544d20741dd --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_dynamicbbpowersaving.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* ************************************************************ + * include files + * ************************************************************ */ +#include "mp_precomp.h" +#include "phydm_precomp.h" + +#if (defined(CONFIG_BB_POWER_SAVING)) + +void +odm_dynamic_bb_power_saving_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _dynamic_power_saving *p_dm_ps_table = &p_dm_odm->dm_ps_table; + + p_dm_ps_table->pre_cca_state = CCA_MAX; + p_dm_ps_table->cur_cca_state = CCA_MAX; + p_dm_ps_table->pre_rf_state = RF_MAX; + p_dm_ps_table->cur_rf_state = RF_MAX; + p_dm_ps_table->rssi_val_min = 0; + p_dm_ps_table->initialize = 0; +} + +void +odm_rf_saving( + void *p_dm_void, + u8 is_force_in_normal +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _dynamic_power_saving *p_dm_ps_table = &p_dm_odm->dm_ps_table; + u8 rssi_up_bound = 30 ; + u8 rssi_low_bound = 25; + if (p_dm_odm->patch_id == 40) { /* RT_CID_819x_FUNAI_TV */ + rssi_up_bound = 50 ; + rssi_low_bound = 45; + } + if (p_dm_ps_table->initialize == 0) { + p_dm_ps_table->reg874 = (odm_get_bb_reg(p_dm_odm, 0x874, MASKDWORD) & 0x1CC000) >> 14; + p_dm_ps_table->regc70 = (odm_get_bb_reg(p_dm_odm, 0xc70, MASKDWORD) & BIT(3)) >> 3; + p_dm_ps_table->reg85c = (odm_get_bb_reg(p_dm_odm, 0x85c, MASKDWORD) & 0xFF000000) >> 24; + p_dm_ps_table->rega74 = (odm_get_bb_reg(p_dm_odm, 0xa74, MASKDWORD) & 0xF000) >> 12; + /* Reg818 = phy_query_bb_reg(p_adapter, 0x818, MASKDWORD); */ + p_dm_ps_table->initialize = 1; + } + + if (!is_force_in_normal) { + if (p_dm_odm->rssi_min != 0xFF) { + if (p_dm_ps_table->pre_rf_state == rf_normal) { + if (p_dm_odm->rssi_min >= rssi_up_bound) + p_dm_ps_table->cur_rf_state = rf_save; + else + p_dm_ps_table->cur_rf_state = rf_normal; + } else { + if (p_dm_odm->rssi_min <= rssi_low_bound) + p_dm_ps_table->cur_rf_state = rf_normal; + else + p_dm_ps_table->cur_rf_state = rf_save; + } + } else + p_dm_ps_table->cur_rf_state = RF_MAX; + } else + p_dm_ps_table->cur_rf_state = rf_normal; + + if (p_dm_ps_table->pre_rf_state != p_dm_ps_table->cur_rf_state) { + if (p_dm_ps_table->cur_rf_state == rf_save) { + odm_set_bb_reg(p_dm_odm, 0x874, 0x1C0000, 0x2); /* reg874[20:18]=3'b010 */ + odm_set_bb_reg(p_dm_odm, 0xc70, BIT(3), 0); /* regc70[3]=1'b0 */ + odm_set_bb_reg(p_dm_odm, 0x85c, 0xFF000000, 0x63); /* reg85c[31:24]=0x63 */ + odm_set_bb_reg(p_dm_odm, 0x874, 0xC000, 0x2); /* reg874[15:14]=2'b10 */ + odm_set_bb_reg(p_dm_odm, 0xa74, 0xF000, 0x3); /* RegA75[7:4]=0x3 */ + odm_set_bb_reg(p_dm_odm, 0x818, BIT(28), 0x0); /* Reg818[28]=1'b0 */ + odm_set_bb_reg(p_dm_odm, 0x818, BIT(28), 0x1); /* Reg818[28]=1'b1 */ + } else { + odm_set_bb_reg(p_dm_odm, 0x874, 0x1CC000, p_dm_ps_table->reg874); + odm_set_bb_reg(p_dm_odm, 0xc70, BIT(3), p_dm_ps_table->regc70); + odm_set_bb_reg(p_dm_odm, 0x85c, 0xFF000000, p_dm_ps_table->reg85c); + odm_set_bb_reg(p_dm_odm, 0xa74, 0xF000, p_dm_ps_table->rega74); + odm_set_bb_reg(p_dm_odm, 0x818, BIT(28), 0x0); + } + p_dm_ps_table->pre_rf_state = p_dm_ps_table->cur_rf_state; + } +} + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_dynamicbbpowersaving.h b/drivers/staging/rtl8188eu/hal/phydm_dynamicbbpowersaving.h new file mode 100644 index 000000000000..fe5f1564b6fe --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_dynamicbbpowersaving.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDMDYNAMICBBPOWERSAVING_H__ +#define __PHYDMDYNAMICBBPOWERSAVING_H__ + +#define DYNAMIC_BBPWRSAV_VERSION "1.1" + +#if (defined(CONFIG_BB_POWER_SAVING)) + +struct _dynamic_power_saving { + u8 pre_cca_state; + u8 cur_cca_state; + + u8 pre_rf_state; + u8 cur_rf_state; + + int rssi_val_min; + + u8 initialize; + u32 reg874, regc70, reg85c, rega74; + +}; + +#define dm_rf_saving odm_rf_saving + +void odm_rf_saving( + void *p_dm_void, + u8 is_force_in_normal +); + +void +odm_dynamic_bb_power_saving_init( + void *p_dm_void +); +#else +#define dm_rf_saving(p_dm_void, is_force_in_normal) +#endif + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_dynamictxpower.c b/drivers/staging/rtl8188eu/hal/phydm_dynamictxpower.c new file mode 100644 index 000000000000..6829d1b3e6f8 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_dynamictxpower.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* ************************************************************ + * include files + * ************************************************************ */ +#include "mp_precomp.h" +#include "phydm_precomp.h" + +void +odm_dynamic_tx_power_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + p_dm_odm->last_dtp_lvl = tx_high_pwr_level_normal; + p_dm_odm->dynamic_tx_high_power_lvl = tx_high_pwr_level_normal; + p_dm_odm->tx_agc_ofdm_18_6 = odm_get_bb_reg(p_dm_odm, 0xC24, MASKDWORD); /*TXAGC {18M 12M 9M 6M}*/ +} + +void +odm_dynamic_tx_power_save_power_index( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 index; + u32 power_index_reg[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a}; + +} + +void +odm_dynamic_tx_power_restore_power_index( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 index; + struct _ADAPTER *adapter = p_dm_odm->adapter; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(adapter); + u32 power_index_reg[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a}; +} + +void +odm_dynamic_tx_power_write_power_index( + void *p_dm_void, + u8 value) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 index; + u32 power_index_reg[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a}; + + for (index = 0; index < 6; index++) + /* platform_efio_write_1byte(adapter, power_index_reg[index], value); */ + odm_write_1byte(p_dm_odm, power_index_reg[index], value); + +} + +static void +odm_dynamic_tx_power_nic_ce( + void *p_dm_void +) +{ +} + +void +odm_dynamic_tx_power( + void *p_dm_void +) +{ + /* */ + /* For AP/ADSL use struct rtl8192cd_priv* */ + /* For CE/NIC use struct _ADAPTER* */ + /* */ + /* struct _ADAPTER* p_adapter = p_dm_odm->adapter; + * struct rtl8192cd_priv* priv = p_dm_odm->priv; */ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + if (!(p_dm_odm->support_ability & ODM_BB_DYNAMIC_TXPWR)) + return; + /* */ + /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */ + /* at the same time. In the stage2/3, we need to prive universal interface and merge all */ + /* HW dynamic mechanism. */ + /* */ + switch (p_dm_odm->support_platform) { + case ODM_WIN: + odm_dynamic_tx_power_nic(p_dm_odm); + break; + case ODM_CE: + odm_dynamic_tx_power_nic_ce(p_dm_odm); + break; + case ODM_AP: + odm_dynamic_tx_power_ap(p_dm_odm); + break; + default: + break; + } + + +} + + +void +odm_dynamic_tx_power_nic( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (!(p_dm_odm->support_ability & ODM_BB_DYNAMIC_TXPWR)) + return; +} + +void +odm_dynamic_tx_power_ap( + void *p_dm_void + +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; +} + +void +odm_dynamic_tx_power_8821( + void *p_dm_void, + u8 *p_desc, + u8 mac_id +) +{ +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_dynamictxpower.h b/drivers/staging/rtl8188eu/hal/phydm_dynamictxpower.h new file mode 100644 index 000000000000..b8a82c54be5c --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_dynamictxpower.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDMDYNAMICTXPOWER_H__ +#define __PHYDMDYNAMICTXPOWER_H__ + +/*#define DYNAMIC_TXPWR_VERSION "1.0"*/ +/*#define DYNAMIC_TXPWR_VERSION "1.3" */ /*2015.08.26, Add 8814 Dynamic TX power*/ +#define DYNAMIC_TXPWR_VERSION "1.4" /*2015.11.06, Add CE 8821A Dynamic TX power*/ + +#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 +#define TX_POWER_NEAR_FIELD_THRESH_LVL1 60 + +#define tx_high_pwr_level_normal 0 +#define tx_high_pwr_level_level1 1 +#define tx_high_pwr_level_level2 2 + +#define tx_high_pwr_level_bt1 3 +#define tx_high_pwr_level_bt2 4 +#define tx_high_pwr_level_15 5 +#define tx_high_pwr_level_35 6 +#define tx_high_pwr_level_50 7 +#define tx_high_pwr_level_70 8 +#define tx_high_pwr_level_100 9 + +void +odm_dynamic_tx_power_init( + void *p_dm_void +); + +void +odm_dynamic_tx_power_restore_power_index( + void *p_dm_void +); + +void +odm_dynamic_tx_power_nic( + void *p_dm_void +); + +void +odm_dynamic_tx_power_save_power_index( + void *p_dm_void +); + +void +odm_dynamic_tx_power_write_power_index( + void *p_dm_void, + u8 value); + +void +odm_dynamic_tx_power_8821( + void *p_dm_void, + u8 *p_desc, + u8 mac_id +); + +void +odm_dynamic_tx_power( + void *p_dm_void +); + +void +odm_dynamic_tx_power_ap( + void *p_dm_void +); + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_edcaturbocheck.c b/drivers/staging/rtl8188eu/hal/phydm_edcaturbocheck.c new file mode 100644 index 000000000000..2da41a0ebc91 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_edcaturbocheck.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* ************************************************************ + * include files + * ************************************************************ */ +#include "mp_precomp.h" +#include "phydm_precomp.h" + +#if PHYDM_SUPPORT_EDCA + +void +odm_edca_turbo_init( + void *p_dm_void) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + struct _ADAPTER *adapter = p_dm_odm->adapter; + p_dm_odm->dm_edca_table.is_current_turbo_edca = false; + p_dm_odm->dm_edca_table.is_cur_rdl_state = false; + adapter->recvpriv.is_any_non_be_pkts = false; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial VO PARAM: 0x%x\n", odm_read_4byte(p_dm_odm, ODM_EDCA_VO_PARAM))); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial VI PARAM: 0x%x\n", odm_read_4byte(p_dm_odm, ODM_EDCA_VI_PARAM))); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial BE PARAM: 0x%x\n", odm_read_4byte(p_dm_odm, ODM_EDCA_BE_PARAM))); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial BK PARAM: 0x%x\n", odm_read_4byte(p_dm_odm, ODM_EDCA_BK_PARAM))); +} /* ODM_InitEdcaTurbo */ + +void +odm_edca_turbo_check( + void *p_dm_void +) +{ + /* */ + /* For AP/ADSL use struct rtl8192cd_priv* */ + /* For CE/NIC use struct _ADAPTER* */ + /* */ + + /* */ + /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */ + /* at the same time. In the stage2/3, we need to prive universal interface and merge all */ + /* HW dynamic mechanism. */ + /* */ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("odm_edca_turbo_check========================>\n")); + + if (!(p_dm_odm->support_ability & ODM_MAC_EDCA_TURBO)) + return; + + switch (p_dm_odm->support_platform) { + case ODM_WIN: + break; + case ODM_CE: + odm_edca_turbo_check_ce(p_dm_odm); + break; + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("<========================odm_edca_turbo_check\n")); + +} /* odm_CheckEdcaTurbo */ + +void +odm_edca_turbo_check_ce( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTER *adapter = p_dm_odm->adapter; + u32 EDCA_BE_UL = 0x5ea42b;/* Parameter suggested by Scott */ /* edca_setting_UL[p_mgnt_info->iot_peer]; */ + u32 EDCA_BE_DL = 0x00a42b;/* Parameter suggested by Scott */ /* edca_setting_DL[p_mgnt_info->iot_peer]; */ + u32 ic_type = p_dm_odm->support_ic_type; + u32 iot_peer = 0; + u8 wireless_mode = 0xFF; /* invalid value */ + u32 traffic_index; + u32 edca_param; + u64 cur_tx_bytes = 0; + u64 cur_rx_bytes = 0; + u8 bbtchange = true; + u8 is_bias_on_rx = false; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(adapter); + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter); + struct xmit_priv *pxmitpriv = &(adapter->xmitpriv); + struct recv_priv *precvpriv = &(adapter->recvpriv); + struct registry_priv *pregpriv = &adapter->registrypriv; + struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + if (p_dm_odm->is_linked != true) { + precvpriv->is_any_non_be_pkts = false; + return; + } + + if ((pregpriv->wifi_spec == 1)) { /* || (pmlmeinfo->HT_enable == 0)) */ + precvpriv->is_any_non_be_pkts = false; + return; + } + + if (p_dm_odm->p_wireless_mode != NULL) + wireless_mode = *(p_dm_odm->p_wireless_mode); + + iot_peer = pmlmeinfo->assoc_AP_vendor; + + if (iot_peer >= HT_IOT_PEER_MAX) { + precvpriv->is_any_non_be_pkts = false; + return; + } + + if (p_dm_odm->support_ic_type & ODM_RTL8188E) { + if ((iot_peer == HT_IOT_PEER_RALINK) || (iot_peer == HT_IOT_PEER_ATHEROS)) + is_bias_on_rx = true; + } + + /* Check if the status needs to be changed. */ + if ((bbtchange) || (!precvpriv->is_any_non_be_pkts)) { + cur_tx_bytes = pdvobjpriv->traffic_stat.cur_tx_bytes; + cur_rx_bytes = pdvobjpriv->traffic_stat.cur_rx_bytes; + + /* traffic, TX or RX */ + if (is_bias_on_rx) { + if (cur_tx_bytes > (cur_rx_bytes << 2)) { + /* Uplink TP is present. */ + traffic_index = UP_LINK; + } else { + /* Balance TP is present. */ + traffic_index = DOWN_LINK; + } + } else { + if (cur_rx_bytes > (cur_tx_bytes << 2)) { + /* Downlink TP is present. */ + traffic_index = DOWN_LINK; + } else { + /* Balance TP is present. */ + traffic_index = UP_LINK; + } + } + + /* if ((p_dm_odm->dm_edca_table.prv_traffic_idx != traffic_index) || (!p_dm_odm->dm_edca_table.is_current_turbo_edca)) */ + { + if (p_dm_odm->support_interface == ODM_ITRF_PCIE) { + EDCA_BE_UL = 0x6ea42b; + EDCA_BE_DL = 0x6ea42b; + } + + /* 92D txop can't be set to 0x3e for cisco1250 */ + if ((iot_peer == HT_IOT_PEER_CISCO) && (wireless_mode == ODM_WM_N24G)) { + EDCA_BE_DL = edca_setting_DL[iot_peer]; + EDCA_BE_UL = edca_setting_UL[iot_peer]; + } + /* merge from 92s_92c_merge temp brunch v2445 20120215 */ + else if ((iot_peer == HT_IOT_PEER_CISCO) && ((wireless_mode == ODM_WM_G) || (wireless_mode == (ODM_WM_B | ODM_WM_G)) || (wireless_mode == ODM_WM_A) || (wireless_mode == ODM_WM_B))) + EDCA_BE_DL = edca_setting_dl_g_mode[iot_peer]; + else if ((iot_peer == HT_IOT_PEER_AIRGO) && ((wireless_mode == ODM_WM_G) || (wireless_mode == ODM_WM_A))) + EDCA_BE_DL = 0xa630; + else if (iot_peer == HT_IOT_PEER_MARVELL) { + EDCA_BE_DL = edca_setting_DL[iot_peer]; + EDCA_BE_UL = edca_setting_UL[iot_peer]; + } else if (iot_peer == HT_IOT_PEER_ATHEROS) { + /* Set DL EDCA for Atheros peer to 0x3ea42b. Suggested by SD3 Wilson for ASUS TP issue. */ + EDCA_BE_DL = edca_setting_DL[iot_peer]; + } + + if ((ic_type == ODM_RTL8812) || (ic_type == ODM_RTL8821) || (ic_type == ODM_RTL8192E)) { /* add 8812AU/8812AE */ + EDCA_BE_UL = 0x5ea42b; + EDCA_BE_DL = 0x5ea42b; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("8812A: EDCA_BE_UL=0x%x EDCA_BE_DL =0x%x", EDCA_BE_UL, EDCA_BE_DL)); + } + + if (traffic_index == DOWN_LINK) + edca_param = EDCA_BE_DL; + else + edca_param = EDCA_BE_UL; + + rtw_write32(adapter, REG_EDCA_BE_PARAM, edca_param); + + p_dm_odm->dm_edca_table.prv_traffic_idx = traffic_index; + } + + p_dm_odm->dm_edca_table.is_current_turbo_edca = true; + } else { + /* */ + /* Turn Off EDCA turbo here. */ + /* Restore original EDCA according to the declaration of AP. */ + /* */ + if (p_dm_odm->dm_edca_table.is_current_turbo_edca) { + rtw_write32(adapter, REG_EDCA_BE_PARAM, p_hal_data->ac_param_be); + p_dm_odm->dm_edca_table.is_current_turbo_edca = false; + } + } +} + +#endif /*PHYDM_SUPPORT_EDCA*/ diff --git a/drivers/staging/rtl8188eu/hal/phydm_edcaturbocheck.h b/drivers/staging/rtl8188eu/hal/phydm_edcaturbocheck.h new file mode 100644 index 000000000000..82ccd733e2db --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_edcaturbocheck.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDMEDCATURBOCHECK_H__ +#define __PHYDMEDCATURBOCHECK_H__ + +#if PHYDM_SUPPORT_EDCA +/*#define EDCATURBO_VERSION "2.1"*/ +#define EDCATURBO_VERSION "2.3" /*2015.07.29 by YuChen*/ + +struct _EDCA_TURBO_ { + bool is_current_turbo_edca; + bool is_cur_rdl_state; + + u32 prv_traffic_idx; /* edca turbo */ + +}; + +static u32 edca_setting_UL[HT_IOT_PEER_MAX] = + /* UNKNOWN REALTEK_90 REALTEK_92SE BROADCOM RALINK ATHEROS CISCO MERU MARVELL 92U_AP SELF_AP(DownLink/Tx) */ +{ 0x5e4322, 0xa44f, 0x5e4322, 0x5ea32b, 0x5ea422, 0x5ea322, 0x3ea430, 0x5ea42b, 0x5ea44f, 0x5e4322, 0x5e4322}; + + +static u32 edca_setting_DL[HT_IOT_PEER_MAX] = + /* UNKNOWN REALTEK_90 REALTEK_92SE BROADCOM RALINK ATHEROS CISCO MERU, MARVELL 92U_AP SELF_AP(UpLink/Rx) */ +{ 0xa44f, 0x5ea44f, 0x5e4322, 0x5ea42b, 0xa44f, 0xa630, 0x5ea630, 0x5ea42b, 0xa44f, 0xa42b, 0xa42b}; + +static u32 edca_setting_dl_g_mode[HT_IOT_PEER_MAX] = + /* UNKNOWN REALTEK_90 REALTEK_92SE BROADCOM RALINK ATHEROS CISCO MERU, MARVELL 92U_AP SELF_AP */ +{ 0x4322, 0xa44f, 0x5e4322, 0xa42b, 0x5e4322, 0x4322, 0xa42b, 0x5ea42b, 0xa44f, 0x5e4322, 0x5ea42b}; + +void +odm_edca_turbo_check( + void *p_dm_void +); +void +odm_edca_turbo_init( + void *p_dm_void +); + +void +odm_edca_turbo_check_ce( + void *p_dm_void +); + +#endif /*PHYDM_SUPPORT_EDCA*/ + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_features.h b/drivers/staging/rtl8188eu/hal/phydm_features.h new file mode 100644 index 000000000000..6339c4b25839 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_features.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDM_FEATURES_H__ +#define __PHYDM_FEATURES + +#define ODM_RECEIVER_BLOCKING_SUPPORT (ODM_RTL8188E | ODM_RTL8192E) +#define PHYDM_LA_MODE_SUPPORT 0 + +/*phydm debyg report & tools*/ +#define CONFIG_PHYDM_DEBUG_FUNCTION 1 + +#define CONFIG_DYNAMIC_RX_PATH 0 + +#define PHYDM_SUPPORT_EDCA 1 +#define SUPPORTABLITY_PHYDMLIZE 1 +#define RA_MASK_PHYDMLIZE_CE 1 + +/*Antenna Diversity*/ +#ifdef CONFIG_ANTENNA_DIVERSITY + #define CONFIG_PHYDM_ANTENNA_DIVERSITY +#endif + +#ifdef CONFIG_DFS_MASTER + #define CONFIG_PHYDM_DFS_MASTER +#endif + +#define CONFIG_RECEIVER_BLOCKING +#define CONFIG_RA_FW_DBG_CODE 0 +#define CONFIG_BB_POWER_SAVING +#define CONFIG_BB_TXBF_API + +#ifdef CONFIG_BT_COEXIST + #define BT_SUPPORT 1 +#endif + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_hal_txbf_api.c b/drivers/staging/rtl8188eu/hal/phydm_hal_txbf_api.c new file mode 100644 index 000000000000..36ccbde9feb0 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_hal_txbf_api.c @@ -0,0 +1,72 @@ +#include "mp_precomp.h" +#include "phydm_precomp.h" + +#if (defined(CONFIG_BB_TXBF_API)) +u8 beamforming_get_htndp_tx_rate( + void *p_dm_void, + u8 comp_steering_num_of_bfer +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 nr_index = 0; + u8 ndp_tx_rate; + /*Find nr*/ + nr_index = tx_bf_nr(1, comp_steering_num_of_bfer); + + switch (nr_index) { + case 1: + ndp_tx_rate = ODM_MGN_MCS8; + break; + + case 2: + ndp_tx_rate = ODM_MGN_MCS16; + break; + + case 3: + ndp_tx_rate = ODM_MGN_MCS24; + break; + + default: + ndp_tx_rate = ODM_MGN_MCS8; + break; + } + + return ndp_tx_rate; + +} + +u8 +beamforming_get_vht_ndp_tx_rate( + void *p_dm_void, + u8 comp_steering_num_of_bfer +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 nr_index = 0; + u8 ndp_tx_rate; + /*Find nr*/ + nr_index = tx_bf_nr(1, comp_steering_num_of_bfer); + + switch (nr_index) { + case 1: + ndp_tx_rate = ODM_MGN_VHT2SS_MCS0; + break; + + case 2: + ndp_tx_rate = ODM_MGN_VHT3SS_MCS0; + break; + + case 3: + ndp_tx_rate = ODM_MGN_VHT4SS_MCS0; + break; + + default: + ndp_tx_rate = ODM_MGN_VHT2SS_MCS0; + break; + } + + return ndp_tx_rate; + +} + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_hal_txbf_api.h b/drivers/staging/rtl8188eu/hal/phydm_hal_txbf_api.h new file mode 100644 index 000000000000..b91a6deaff0d --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_hal_txbf_api.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#ifndef __PHYDM_HAL_TXBF_API_H__ +#define __PHYDM_HAL_TXBF_API_H__ + +#if (defined(CONFIG_BB_TXBF_API)) + +#define tx_bf_nr(a, b) ((a > b) ? (b) : (a)) + +u8 +beamforming_get_htndp_tx_rate( + void *p_dm_void, + u8 comp_steering_num_of_bfer +); + +u8 +beamforming_get_vht_ndp_tx_rate( + void *p_dm_void, + u8 comp_steering_num_of_bfer +); + +#define phydm_get_beamforming_sounding_info(p_dm_void, troughput, total_bfee_num, tx_rate) +#define phydm_get_ndpa_rate(p_dm_void) +#define phydm_get_mu_bfee_snding_decision(p_dm_void, troughput) + +#endif +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_hwconfig.c b/drivers/staging/rtl8188eu/hal/phydm_hwconfig.c new file mode 100644 index 000000000000..321743dfb50e --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_hwconfig.c @@ -0,0 +1,2102 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* ************************************************************ + * include files + * ************************************************************ */ + +#include "mp_precomp.h" +#include "phydm_precomp.h" + +#define READ_AND_CONFIG_MP(ic, txt) (odm_read_and_config_mp_##ic##txt(p_dm_odm)) +#define READ_AND_CONFIG_TC(ic, txt) (odm_read_and_config_tc_##ic##txt(p_dm_odm)) + +#if (PHYDM_TESTCHIP_SUPPORT == 1) +#define READ_AND_CONFIG(ic, txt) do {\ + if (p_dm_odm->is_mp_chip)\ + READ_AND_CONFIG_MP(ic, txt);\ + else\ + READ_AND_CONFIG_TC(ic, txt);\ + } while (0) +#else +#define READ_AND_CONFIG READ_AND_CONFIG_MP +#endif + +#define READ_FIRMWARE_MP(ic, txt) (odm_read_firmware_mp_##ic##txt(p_dm_odm, p_firmware, p_size)) +#define READ_FIRMWARE_TC(ic, txt) (odm_read_firmware_tc_##ic##txt(p_dm_odm, p_firmware, p_size)) + +#if (PHYDM_TESTCHIP_SUPPORT == 1) +#define READ_FIRMWARE(ic, txt) do {\ + if (p_dm_odm->is_mp_chip)\ + READ_FIRMWARE_MP(ic, txt);\ + else\ + READ_FIRMWARE_TC(ic, txt);\ + } while (0) +#else +#define READ_FIRMWARE READ_FIRMWARE_MP +#endif + +#define GET_VERSION_MP(ic, txt) (odm_get_version_mp_##ic##txt()) +#define GET_VERSION_TC(ic, txt) (odm_get_version_tc_##ic##txt()) + +#if (PHYDM_TESTCHIP_SUPPORT == 1) + #define GET_VERSION(ic, txt) (p_dm_odm->is_mp_chip ? GET_VERSION_MP(ic, txt) : GET_VERSION_TC(ic, txt)) +#else + #define GET_VERSION(ic, txt) GET_VERSION_MP(ic, txt) +#endif + +static u8 +odm_query_rx_pwr_percentage( + s8 ant_power +) +{ + if ((ant_power <= -100) || (ant_power >= 20)) + return 0; + else if (ant_power >= 0) + return 100; + else + return 100 + ant_power; +} + +/* + * 2012/01/12 MH MOve some signal strength smooth method to MP HAL layer. + * IF other SW team do not support the feature, remove this section.?? + * */ +static s32 +odm_signal_scale_mapping_92c_series_patch_rt_cid_819x_lenovo( + struct PHY_DM_STRUCT *p_dm_odm, + s32 curr_sig +) +{ + s32 ret_sig = 0; + return ret_sig; +} + +static s32 +odm_signal_scale_mapping_92c_series_patch_rt_cid_819x_netcore( + struct PHY_DM_STRUCT *p_dm_odm, + s32 curr_sig +) +{ + s32 ret_sig = 0; + return ret_sig; +} + +static s32 +odm_signal_scale_mapping_92c_series( + struct PHY_DM_STRUCT *p_dm_odm, + s32 curr_sig +) +{ + s32 ret_sig = 0; + + if ((p_dm_odm->support_interface == ODM_ITRF_USB) || (p_dm_odm->support_interface == ODM_ITRF_SDIO)) { + if (curr_sig >= 51 && curr_sig <= 100) + ret_sig = 100; + else if (curr_sig >= 41 && curr_sig <= 50) + ret_sig = 80 + ((curr_sig - 40) * 2); + else if (curr_sig >= 31 && curr_sig <= 40) + ret_sig = 66 + (curr_sig - 30); + else if (curr_sig >= 21 && curr_sig <= 30) + ret_sig = 54 + (curr_sig - 20); + else if (curr_sig >= 10 && curr_sig <= 20) + ret_sig = 42 + (((curr_sig - 10) * 2) / 3); + else if (curr_sig >= 5 && curr_sig <= 9) + ret_sig = 22 + (((curr_sig - 5) * 3) / 2); + else if (curr_sig >= 1 && curr_sig <= 4) + ret_sig = 6 + (((curr_sig - 1) * 3) / 2); + else + ret_sig = curr_sig; + } + + return ret_sig; +} +s32 +odm_signal_scale_mapping( + struct PHY_DM_STRUCT *p_dm_odm, + s32 curr_sig +) +{ + { +#ifdef CONFIG_SIGNAL_SCALE_MAPPING + return odm_signal_scale_mapping_92c_series(p_dm_odm, curr_sig); +#else + return curr_sig; +#endif + } + +} + +static u8 odm_sq_process_patch_rt_cid_819x_lenovo( + struct PHY_DM_STRUCT *p_dm_odm, + u8 is_cck_rate, + u8 PWDB_ALL, + u8 path, + u8 RSSI +) +{ + u8 SQ = 0; + return SQ; +} + +static u8 odm_sq_process_patch_rt_cid_819x_acer( + struct PHY_DM_STRUCT *p_dm_odm, + u8 is_cck_rate, + u8 PWDB_ALL, + u8 path, + u8 RSSI +) +{ + u8 SQ = 0; + + return SQ; +} + +static u8 +odm_evm_db_to_percentage( + s8 value +) +{ + /* */ + /* -33dB~0dB to 0%~99% */ + /* */ + s8 ret_val; + + ret_val = value; + ret_val /= 2; + + /*dbg_print("value=%d\n", value);*/ + /*ODM_RT_DISP(FRX, RX_PHY_SQ, ("EVMdbToPercentage92C value=%d / %x\n", ret_val, ret_val));*/ +#ifdef ODM_EVM_ENHANCE_ANTDIV + if (ret_val >= 0) + ret_val = 0; + + if (ret_val <= -40) + ret_val = -40; + + ret_val = 0 - ret_val; + ret_val *= 3; +#else + if (ret_val >= 0) + ret_val = 0; + + if (ret_val <= -33) + ret_val = -33; + + ret_val = 0 - ret_val; + ret_val *= 3; + + if (ret_val == 99) + ret_val = 100; +#endif + + return (u8)ret_val; +} + +static u8 +odm_evm_dbm_jaguar_series( + s8 value +) +{ + s8 ret_val = value; + + /* -33dB~0dB to 33dB ~ 0dB */ + if (ret_val == -128) + ret_val = 127; + else if (ret_val < 0) + ret_val = 0 - ret_val; + + ret_val = ret_val >> 1; + return (u8)ret_val; +} + +static s16 +odm_cfo( + s8 value +) +{ + s16 ret_val; + + if (value < 0) { + ret_val = 0 - value; + ret_val = (ret_val << 1) + (ret_val >> 1) ; /* *2.5~=312.5/2^7 */ + ret_val = ret_val | BIT(12); /* set bit12 as 1 for negative cfo */ + } else { + ret_val = value; + ret_val = (ret_val << 1) + (ret_val >> 1) ; /* *2.5~=312.5/2^7 */ + } + return ret_val; +} + +static u8 +phydm_rate_to_num_ss( + struct PHY_DM_STRUCT *p_dm_odm, + u8 data_rate +) +{ + u8 num_ss = 1; + + if (data_rate <= ODM_RATE54M) + num_ss = 1; + else if (data_rate <= ODM_RATEMCS31) + num_ss = ((data_rate - ODM_RATEMCS0) >> 3) + 1; + else if (data_rate <= ODM_RATEVHTSS1MCS9) + num_ss = 1; + else if (data_rate <= ODM_RATEVHTSS2MCS9) + num_ss = 2; + else if (data_rate <= ODM_RATEVHTSS3MCS9) + num_ss = 3; + else if (data_rate <= ODM_RATEVHTSS4MCS9) + num_ss = 4; + + return num_ss; +} + +#if (ODM_IC_11N_SERIES_SUPPORT == 1) + +#if (RTL8703B_SUPPORT == 1) +s8 +odm_CCKRSSI_8703B( + u16 LNA_idx, + u8 VGA_idx +) +{ + s8 rx_pwr_all = 0x00; + + switch (LNA_idx) { + case 0xf: + rx_pwr_all = -48 - (2 * VGA_idx); + break; + case 0xb: + rx_pwr_all = -42 - (2 * VGA_idx); /*TBD*/ + break; + case 0xa: + rx_pwr_all = -36 - (2 * VGA_idx); + break; + case 8: + rx_pwr_all = -32 - (2 * VGA_idx); + break; + case 7: + rx_pwr_all = -19 - (2 * VGA_idx); + break; + case 4: + rx_pwr_all = -6 - (2 * VGA_idx); + break; + case 0: + rx_pwr_all = -2 - (2 * VGA_idx); + break; + default: + /*rx_pwr_all = -53+(2*(31-VGA_idx));*/ + /*dbg_print("wrong LNA index\n");*/ + break; + + } + return rx_pwr_all; +} +#endif + +#if (RTL8195A_SUPPORT == 1) +s8 +odm_CCKRSSI_8195A( + struct PHY_DM_STRUCT *p_dm_odm, + u16 LNA_idx, + u8 VGA_idx +) +{ + s8 rx_pwr_all = 0; + s8 lna_gain = 0; + s8 lna_gain_table_0[8] = {0, -8, -15, -22, -29, -36, -45, -54}; + s8 lna_gain_table_1[8] = {0, -8, -15, -22, -29, -36, -45, -54};/*use 8195A to calibrate this table. 2016.06.24, Dino*/ + + if (p_dm_odm->cck_agc_report_type == 0) + lna_gain = lna_gain_table_0[LNA_idx]; + else + lna_gain = lna_gain_table_1[LNA_idx]; + + rx_pwr_all = lna_gain - (2 * VGA_idx); + + return rx_pwr_all; +} +#endif + +#if (RTL8192E_SUPPORT == 1) +s8 +odm_CCKRSSI_8192E( + struct PHY_DM_STRUCT *p_dm_odm, + u16 LNA_idx, + u8 VGA_idx +) +{ + s8 rx_pwr_all = 0; + s8 lna_gain = 0; + s8 lna_gain_table_0[8] = {15, 9, -10, -21, -23, -27, -43, -44}; + s8 lna_gain_table_1[8] = {24, 18, 13, -4, -11, -18, -31, -36};/*use 8192EU to calibrate this table. 2015.12.15, Dino*/ + + if (p_dm_odm->cck_agc_report_type == 0) + lna_gain = lna_gain_table_0[LNA_idx]; + else + lna_gain = lna_gain_table_1[LNA_idx]; + + rx_pwr_all = lna_gain - (2 * VGA_idx); + + return rx_pwr_all; +} +#endif + +#if (RTL8188E_SUPPORT == 1) +static s8 +odm_CCKRSSI_8188E( + struct PHY_DM_STRUCT *p_dm_odm, + u16 LNA_idx, + u8 VGA_idx +) +{ + s8 rx_pwr_all = 0; + s8 lna_gain = 0; + s8 lna_gain_table_0[8] = {17, -1, -13, -29, -32, -35, -38, -41};/*only use lna0/1/2/3/7*/ + s8 lna_gain_table_1[8] = {29, 20, 12, 3, -6, -15, -24, -33}; /*only use lna3 /7*/ + + if (p_dm_odm->cut_version >= ODM_CUT_I) /*SMIC*/ + lna_gain = lna_gain_table_0[LNA_idx]; + else /*TSMC*/ + lna_gain = lna_gain_table_1[LNA_idx]; + + rx_pwr_all = lna_gain - (2 * VGA_idx); + + return rx_pwr_all; +} +#endif + +static void +odm_rx_phy_status92c_series_parsing( + struct PHY_DM_STRUCT *p_dm_odm, + struct _odm_phy_status_info_ *p_phy_info, + u8 *p_phy_status, + struct _odm_per_pkt_info_ *p_pktinfo +) +{ + struct _sw_antenna_switch_ *p_dm_swat_table = &p_dm_odm->dm_swat_table; + u8 i, max_spatial_stream; + s8 rx_pwr[4], rx_pwr_all = 0; + u8 EVM, PWDB_ALL = 0, PWDB_ALL_BT; + u8 RSSI, total_rssi = 0; + bool is_cck_rate = false; + u8 rf_rx_num = 0; + u8 cck_highpwr = 0; + u8 LNA_idx = 0; + u8 VGA_idx = 0; + u8 cck_agc_rpt; + u8 num_ss; + struct _phy_status_rpt_8192cd *p_phy_sta_rpt = (struct _phy_status_rpt_8192cd *)p_phy_status; + + is_cck_rate = (p_pktinfo->data_rate <= ODM_RATE11M) ? true : false; + + if (p_pktinfo->is_to_self) + p_dm_odm->curr_station_id = p_pktinfo->station_id; + + p_phy_info->rx_mimo_signal_quality[ODM_RF_PATH_A] = -1; + p_phy_info->rx_mimo_signal_quality[ODM_RF_PATH_B] = -1; + + if (is_cck_rate) { + p_dm_odm->phy_dbg_info.num_qry_phy_status_cck++; + cck_agc_rpt = p_phy_sta_rpt->cck_agc_rpt_ofdm_cfosho_a ; + + if (p_dm_odm->support_ic_type & (ODM_RTL8703B)) { + +#if (RTL8703B_SUPPORT == 1) + if (p_dm_odm->cck_agc_report_type == 1) { /*4 bit LNA*/ + + u8 cck_agc_rpt_b = (p_phy_sta_rpt->cck_rpt_b_ofdm_cfosho_b & BIT(7)) ? 1 : 0; + + LNA_idx = (cck_agc_rpt_b << 3) | ((cck_agc_rpt & 0xE0) >> 5); + VGA_idx = (cck_agc_rpt & 0x1F); + + rx_pwr_all = odm_CCKRSSI_8703B(LNA_idx, VGA_idx); + } +#endif + } else { /*3 bit LNA*/ + + LNA_idx = ((cck_agc_rpt & 0xE0) >> 5); + VGA_idx = (cck_agc_rpt & 0x1F); + + if (p_dm_odm->support_ic_type & (ODM_RTL8188E)) { + +#if (RTL8188E_SUPPORT == 1) + rx_pwr_all = odm_CCKRSSI_8188E(p_dm_odm, LNA_idx, VGA_idx); + /**/ +#endif + } +#if (RTL8192E_SUPPORT == 1) + else if (p_dm_odm->support_ic_type & (ODM_RTL8192E)) { + + rx_pwr_all = odm_CCKRSSI_8192E(p_dm_odm, LNA_idx, VGA_idx); + /**/ + } +#endif +#if (RTL8723B_SUPPORT == 1) + else if (p_dm_odm->support_ic_type & (ODM_RTL8723B)) { + + rx_pwr_all = odm_CCKRSSI_8723B(LNA_idx, VGA_idx); + /**/ + } +#endif +#if (RTL8188F_SUPPORT == 1) + else if (p_dm_odm->support_ic_type & (ODM_RTL8188F)) { + + rx_pwr_all = odm_CCKRSSI_8188E(p_dm_odm, LNA_idx, VGA_idx); + /**/ + } +#endif +#if (RTL8195A_SUPPORT == 1) + else if (p_dm_odm->support_ic_type & (ODM_RTL8195A)) { + + rx_pwr_all = odm_CCKRSSI_8195A(LNA_idx, VGA_idx); + /**/ + } +#endif + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RSSI_MONITOR, ODM_DBG_LOUD, ("ext_lna_gain (( %d )), LNA_idx: (( 0x%x )), VGA_idx: (( 0x%x )), rx_pwr_all: (( %d ))\n", + p_dm_odm->ext_lna_gain, LNA_idx, VGA_idx, rx_pwr_all)); + + if (p_dm_odm->board_type & ODM_BOARD_EXT_LNA) + rx_pwr_all -= p_dm_odm->ext_lna_gain; + + PWDB_ALL = odm_query_rx_pwr_percentage(rx_pwr_all); + + if (p_pktinfo->is_to_self) { + p_dm_odm->cck_lna_idx = LNA_idx; + p_dm_odm->cck_vga_idx = VGA_idx; + } + p_phy_info->rx_pwdb_all = PWDB_ALL; + + p_phy_info->bt_rx_rssi_percentage = PWDB_ALL; + p_phy_info->recv_signal_power = rx_pwr_all; + /* */ + /* (3) Get Signal Quality (EVM) */ + /* */ + /* if(p_pktinfo->is_packet_match_bssid) */ + { + u8 SQ, SQ_rpt; + + if (p_phy_info->rx_pwdb_all > 40 && !p_dm_odm->is_in_hct_test) + SQ = 100; + else { + SQ_rpt = p_phy_sta_rpt->cck_sig_qual_ofdm_pwdb_all; + + if (SQ_rpt > 64) + SQ = 0; + else if (SQ_rpt < 20) + SQ = 100; + else + SQ = ((64 - SQ_rpt) * 100) / 44; + + } + + /* dbg_print("cck SQ = %d\n", SQ); */ + p_phy_info->signal_quality = SQ; + p_phy_info->rx_mimo_signal_quality[ODM_RF_PATH_A] = SQ; + p_phy_info->rx_mimo_signal_quality[ODM_RF_PATH_B] = -1; + } + + for (i = ODM_RF_PATH_A; i < ODM_RF_PATH_MAX; i++) { + if (i == 0) + p_phy_info->rx_mimo_signal_strength[0] = PWDB_ALL; + else + p_phy_info->rx_mimo_signal_strength[1] = 0; + } + } else { /* 2 is OFDM rate */ + p_dm_odm->phy_dbg_info.num_qry_phy_status_ofdm++; + + /* */ + /* (1)Get RSSI for HT rate */ + /* */ + + for (i = ODM_RF_PATH_A; i < ODM_RF_PATH_MAX; i++) { + /* 2008/01/30 MH we will judge RF RX path now. */ + if (p_dm_odm->rf_path_rx_enable & BIT(i)) + rf_rx_num++; + /* else */ + /* continue; */ + + rx_pwr[i] = ((p_phy_sta_rpt->path_agc[i].gain & 0x3F) * 2) - 110; + + if (p_pktinfo->is_to_self) { + p_dm_odm->ofdm_agc_idx[i] = (p_phy_sta_rpt->path_agc[i].gain & 0x3F); + /**/ + } + + p_phy_info->rx_pwr[i] = rx_pwr[i]; + + /* Translate DBM to percentage. */ + RSSI = odm_query_rx_pwr_percentage(rx_pwr[i]); + total_rssi += RSSI; + /* RT_DISP(FRX, RX_PHY_SS, ("RF-%d RXPWR=%x RSSI=%d\n", i, rx_pwr[i], RSSI)); */ + + p_phy_info->rx_mimo_signal_strength[i] = (u8) RSSI; + + /* Get Rx snr value in DB */ + p_phy_info->rx_snr[i] = p_dm_odm->phy_dbg_info.rx_snr_db[i] = (s32)(p_phy_sta_rpt->path_rxsnr[i] / 2); + + } + + /* */ + /* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */ + /* */ + rx_pwr_all = (((p_phy_sta_rpt->cck_sig_qual_ofdm_pwdb_all) >> 1) & 0x7f) - 110; + + PWDB_ALL_BT = PWDB_ALL = odm_query_rx_pwr_percentage(rx_pwr_all); + + p_phy_info->rx_pwdb_all = PWDB_ALL; + /* ODM_RT_TRACE(p_dm_odm,ODM_COMP_RSSI_MONITOR, ODM_DBG_LOUD, ("ODM OFDM RSSI=%d\n",p_phy_info->rx_pwdb_all)); */ + p_phy_info->bt_rx_rssi_percentage = PWDB_ALL_BT; + p_phy_info->rx_power = rx_pwr_all; + p_phy_info->recv_signal_power = rx_pwr_all; + + if ((p_dm_odm->support_platform == ODM_WIN) && (p_dm_odm->patch_id == 19)) { + /* do nothing */ + } else if ((p_dm_odm->support_platform == ODM_WIN) && (p_dm_odm->patch_id == 25)) { + /* do nothing */ + } else { /* p_mgnt_info->customer_id != RT_CID_819X_LENOVO */ + /* */ + /* (3)EVM of HT rate */ + /* */ + if (p_pktinfo->data_rate >= ODM_RATEMCS8 && p_pktinfo->data_rate <= ODM_RATEMCS15) + max_spatial_stream = 2; /* both spatial stream make sense */ + else + max_spatial_stream = 1; /* only spatial stream 1 makes sense */ + + for (i = 0; i < max_spatial_stream; i++) { + /* Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment */ + /* fill most significant bit to "zero" when doing shifting operation which may change a negative */ + /* value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore. */ + EVM = odm_evm_db_to_percentage((p_phy_sta_rpt->stream_rxevm[i])); /* dbm */ + + /* GET_RX_STATUS_DESC_RX_MCS(p_desc), p_drv_info->rxevm[i], "%", EVM)); */ + + /* if(p_pktinfo->is_packet_match_bssid) */ + { + if (i == ODM_RF_PATH_A) /* Fill value in RFD, Get the first spatial stream only */ + p_phy_info->signal_quality = (u8)(EVM & 0xff); + p_phy_info->rx_mimo_signal_quality[i] = (u8)(EVM & 0xff); + } + } + } + + num_ss = phydm_rate_to_num_ss(p_dm_odm, p_pktinfo->data_rate); + odm_parsing_cfo(p_dm_odm, p_pktinfo, p_phy_sta_rpt->path_cfotail, num_ss); + + } + /* UI BSS List signal strength(in percentage), make it good looking, from 0~100. */ + /* It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp(). */ + if (is_cck_rate) { + p_phy_info->signal_strength = (u8)(odm_signal_scale_mapping(p_dm_odm, PWDB_ALL));/*PWDB_ALL;*/ + } else { + if (rf_rx_num != 0) + p_phy_info->signal_strength = (u8)(odm_signal_scale_mapping(p_dm_odm, total_rssi /= rf_rx_num)); + } + + /* For 92C/92D HW (Hybrid) Antenna Diversity */ +#if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY)) + /* For 88E HW Antenna Diversity */ + p_dm_odm->dm_fat_table.antsel_rx_keep_0 = p_phy_sta_rpt->ant_sel; + p_dm_odm->dm_fat_table.antsel_rx_keep_1 = p_phy_sta_rpt->ant_sel_b; + p_dm_odm->dm_fat_table.antsel_rx_keep_2 = p_phy_sta_rpt->antsel_rx_keep_2; +#endif +} +#endif + +#if ODM_IC_11AC_SERIES_SUPPORT + +void +odm_rx_phy_bw_jaguar_series_parsing( + struct _odm_phy_status_info_ *p_phy_info, + struct _odm_per_pkt_info_ *p_pktinfo, + struct _phy_status_rpt_8812 *p_phy_sta_rpt +) +{ + + if (p_pktinfo->data_rate <= ODM_RATE54M) { + switch (p_phy_sta_rpt->r_RFMOD) { + case 1: + if (p_phy_sta_rpt->sub_chnl == 0) + p_phy_info->band_width = 1; + else + p_phy_info->band_width = 0; + break; + + case 2: + if (p_phy_sta_rpt->sub_chnl == 0) + p_phy_info->band_width = 2; + else if (p_phy_sta_rpt->sub_chnl == 9 || p_phy_sta_rpt->sub_chnl == 10) + p_phy_info->band_width = 1; + else + p_phy_info->band_width = 0; + break; + + default: + case 0: + p_phy_info->band_width = 0; + break; + } + } + +} + +void +odm_rx_phy_status_jaguar_series_parsing( + struct PHY_DM_STRUCT *p_dm_odm, + struct _odm_phy_status_info_ *p_phy_info, + u8 *p_phy_status, + struct _odm_per_pkt_info_ *p_pktinfo +) +{ + u8 i, max_spatial_stream; + s8 rx_pwr[4], rx_pwr_all = 0; + u8 EVM, evm_dbm, PWDB_ALL = 0, PWDB_ALL_BT; + u8 RSSI, avg_rssi = 0, best_rssi = 0, second_rssi = 0; + u8 is_cck_rate = 0; + u8 rf_rx_num = 0; + u8 cck_highpwr = 0; + u8 LNA_idx, VGA_idx; + struct _phy_status_rpt_8812 *p_phy_sta_rpt = (struct _phy_status_rpt_8812 *)p_phy_status; + struct _FAST_ANTENNA_TRAINNING_ *p_dm_fat_table = &p_dm_odm->dm_fat_table; + u8 num_ss; + + odm_rx_phy_bw_jaguar_series_parsing(p_phy_info, p_pktinfo, p_phy_sta_rpt); + + if (p_pktinfo->data_rate <= ODM_RATE11M) + is_cck_rate = true; + else + is_cck_rate = false; + + if (p_pktinfo->is_to_self) + p_dm_odm->curr_station_id = p_pktinfo->station_id; + else + p_dm_odm->curr_station_id = 0xff; + + p_phy_info->rx_mimo_signal_quality[ODM_RF_PATH_A] = -1; + p_phy_info->rx_mimo_signal_quality[ODM_RF_PATH_B] = -1; + p_phy_info->rx_mimo_signal_quality[ODM_RF_PATH_C] = -1; + p_phy_info->rx_mimo_signal_quality[ODM_RF_PATH_D] = -1; + + if (is_cck_rate) { + u8 cck_agc_rpt; + p_dm_odm->phy_dbg_info.num_qry_phy_status_cck++; + + /*(1)Hardware does not provide RSSI for CCK*/ + /*(2)PWDB, Average PWDB calculated by hardware (for rate adaptive)*/ + + /*if(p_hal_data->e_rf_power_state == e_rf_on)*/ + cck_highpwr = p_dm_odm->is_cck_high_power; + /*else*/ + /*cck_highpwr = false;*/ + + cck_agc_rpt = p_phy_sta_rpt->cfosho[0] ; + LNA_idx = ((cck_agc_rpt & 0xE0) >> 5); + VGA_idx = (cck_agc_rpt & 0x1F); + + if (p_dm_odm->support_ic_type == ODM_RTL8812) { + switch (LNA_idx) { + case 7: + if (VGA_idx <= 27) + rx_pwr_all = -100 + 2 * (27 - VGA_idx); /*VGA_idx = 27~2*/ + else + rx_pwr_all = -100; + break; + case 6: + rx_pwr_all = -48 + 2 * (2 - VGA_idx); /*VGA_idx = 2~0*/ + break; + case 5: + rx_pwr_all = -42 + 2 * (7 - VGA_idx); /*VGA_idx = 7~5*/ + break; + case 4: + rx_pwr_all = -36 + 2 * (7 - VGA_idx); /*VGA_idx = 7~4*/ + break; + case 3: + /*rx_pwr_all = -28 + 2*(7-VGA_idx); VGA_idx = 7~0*/ + rx_pwr_all = -24 + 2 * (7 - VGA_idx); /*VGA_idx = 7~0*/ + break; + case 2: + if (cck_highpwr) + rx_pwr_all = -12 + 2 * (5 - VGA_idx); /*VGA_idx = 5~0*/ + else + rx_pwr_all = -6 + 2 * (5 - VGA_idx); + break; + case 1: + rx_pwr_all = 8 - 2 * VGA_idx; + break; + case 0: + rx_pwr_all = 14 - 2 * VGA_idx; + break; + default: + /*dbg_print("CCK Exception default\n");*/ + break; + } + rx_pwr_all += 6; + PWDB_ALL = odm_query_rx_pwr_percentage(rx_pwr_all); + + if (cck_highpwr == false) { + if (PWDB_ALL >= 80) + PWDB_ALL = ((PWDB_ALL - 80) << 1) + ((PWDB_ALL - 80) >> 1) + 80; + else if ((PWDB_ALL <= 78) && (PWDB_ALL >= 20)) + PWDB_ALL += 3; + if (PWDB_ALL > 100) + PWDB_ALL = 100; + } + } else if (p_dm_odm->support_ic_type & (ODM_RTL8821 | ODM_RTL8881A)) { + s8 pout = -6; + + switch (LNA_idx) { + case 5: + rx_pwr_all = pout - 32 - (2 * VGA_idx); + break; + case 4: + rx_pwr_all = pout - 24 - (2 * VGA_idx); + break; + case 2: + rx_pwr_all = pout - 11 - (2 * VGA_idx); + break; + case 1: + rx_pwr_all = pout + 5 - (2 * VGA_idx); + break; + case 0: + rx_pwr_all = pout + 21 - (2 * VGA_idx); + break; + } + PWDB_ALL = odm_query_rx_pwr_percentage(rx_pwr_all); + } else if (p_dm_odm->support_ic_type == ODM_RTL8814A || p_dm_odm->support_ic_type == ODM_RTL8822B) { + s8 pout = -6; + + switch (LNA_idx) { + /*CCK only use LNA: 2, 3, 5, 7*/ + case 7: + rx_pwr_all = pout - 32 - (2 * VGA_idx); + break; + case 5: + rx_pwr_all = pout - 22 - (2 * VGA_idx); + break; + case 3: + rx_pwr_all = pout - 2 - (2 * VGA_idx); + break; + case 2: + rx_pwr_all = pout + 5 - (2 * VGA_idx); + break; + /*case 6:*/ + /*rx_pwr_all = pout -26 - (2*VGA_idx);*/ + /*break;*/ + /*case 4:*/ + /*rx_pwr_all = pout - 8 - (2*VGA_idx);*/ + /*break;*/ + /*case 1:*/ + /*rx_pwr_all = pout + 21 - (2*VGA_idx);*/ + /*break;*/ + /*case 0:*/ + /*rx_pwr_all = pout + 10 - (2*VGA_idx);*/ + /* break; */ + default: + /* dbg_print("CCK Exception default\n"); */ + break; + } + PWDB_ALL = odm_query_rx_pwr_percentage(rx_pwr_all); + } + + p_dm_odm->cck_lna_idx = LNA_idx; + p_dm_odm->cck_vga_idx = VGA_idx; + p_phy_info->rx_pwdb_all = PWDB_ALL; + /* if(p_pktinfo->station_id == 0) */ + /* { */ + /* dbg_print("CCK: LNA_idx = %d, VGA_idx = %d, p_phy_info->rx_pwdb_all = %d\n", */ + /* LNA_idx, VGA_idx, p_phy_info->rx_pwdb_all); */ + /* } */ + p_phy_info->bt_rx_rssi_percentage = PWDB_ALL; + p_phy_info->recv_signal_power = rx_pwr_all; + /*(3) Get Signal Quality (EVM)*/ + /*if (p_pktinfo->is_packet_match_bssid)*/ + { + u8 SQ, SQ_rpt; + + if ((p_dm_odm->support_platform == ODM_WIN) && + (p_dm_odm->patch_id == RT_CID_819X_LENOVO)) + SQ = odm_sq_process_patch_rt_cid_819x_lenovo(p_dm_odm, is_cck_rate, PWDB_ALL, 0, 0); + else if (p_phy_info->rx_pwdb_all > 40 && !p_dm_odm->is_in_hct_test) + SQ = 100; + else { + SQ_rpt = p_phy_sta_rpt->pwdb_all; + + if (SQ_rpt > 64) + SQ = 0; + else if (SQ_rpt < 20) + SQ = 100; + else + SQ = ((64 - SQ_rpt) * 100) / 44; + } + + /* dbg_print("cck SQ = %d\n", SQ); */ + p_phy_info->signal_quality = SQ; + p_phy_info->rx_mimo_signal_quality[ODM_RF_PATH_A] = SQ; + } + + for (i = ODM_RF_PATH_A; i < ODM_RF_PATH_MAX_JAGUAR; i++) { + if (i == 0) + p_phy_info->rx_mimo_signal_strength[0] = PWDB_ALL; + else + p_phy_info->rx_mimo_signal_strength[i] = 0; + } + } else { + /*is OFDM rate*/ + p_dm_fat_table->hw_antsw_occur = p_phy_sta_rpt->hw_antsw_occur; + + p_dm_odm->phy_dbg_info.num_qry_phy_status_ofdm++; + + /*(1)Get RSSI for OFDM rate*/ + + for (i = ODM_RF_PATH_A; i < ODM_RF_PATH_MAX_JAGUAR; i++) { + /*2008/01/30 MH we will judge RF RX path now.*/ + /* dbg_print("p_dm_odm->rf_path_rx_enable = %x\n", p_dm_odm->rf_path_rx_enable); */ + if (p_dm_odm->rf_path_rx_enable & BIT(i)) + rf_rx_num++; + /* else */ + /* continue; */ + /*2012.05.25 LukeLee: Testchip AGC report is wrong, it should be restored back to old formula in MP chip*/ + /* if((p_dm_odm->support_ic_type & (ODM_RTL8812|ODM_RTL8821)) && (!p_dm_odm->is_mp_chip)) */ + if (i < ODM_RF_PATH_C) + rx_pwr[i] = (p_phy_sta_rpt->gain_trsw[i] & 0x7F) - 110; + else + rx_pwr[i] = (p_phy_sta_rpt->gain_trsw_cd[i - 2] & 0x7F) - 110; + /* else */ + /*rx_pwr[i] = ((p_phy_sta_rpt->gain_trsw[i]& 0x3F)*2) - 110; OLD FORMULA*/ + + p_phy_info->rx_pwr[i] = rx_pwr[i]; + + /* Translate DBM to percentage. */ + RSSI = odm_query_rx_pwr_percentage(rx_pwr[i]); + + /*total_rssi += RSSI;*/ + /*Get the best two RSSI*/ + if (RSSI > best_rssi && RSSI > second_rssi) { + second_rssi = best_rssi; + best_rssi = RSSI; + } else if (RSSI > second_rssi && RSSI <= best_rssi) + second_rssi = RSSI; + + /*RT_DISP(FRX, RX_PHY_SS, ("RF-%d RXPWR=%x RSSI=%d\n", i, rx_pwr[i], RSSI));*/ + + p_phy_info->rx_mimo_signal_strength[i] = (u8) RSSI; + + /*Get Rx snr value in DB*/ + if (i < ODM_RF_PATH_C) + p_phy_info->rx_snr[i] = p_dm_odm->phy_dbg_info.rx_snr_db[i] = p_phy_sta_rpt->rxsnr[i] / 2; + else if (p_dm_odm->support_ic_type & (ODM_RTL8814A | ODM_RTL8822B)) + p_phy_info->rx_snr[i] = p_dm_odm->phy_dbg_info.rx_snr_db[i] = p_phy_sta_rpt->csi_current[i - 2] / 2; + + /*(2) CFO_short & CFO_tail*/ + if (i < ODM_RF_PATH_C) { + p_phy_info->cfo_short[i] = odm_cfo((p_phy_sta_rpt->cfosho[i])); + p_phy_info->cfo_tail[i] = odm_cfo((p_phy_sta_rpt->cfotail[i])); + } + } + + /*(3)PWDB, Average PWDB calculated by hardware (for rate adaptive)*/ + + /*2012.05.25 LukeLee: Testchip AGC report is wrong, it should be restored back to old formula in MP chip*/ + if ((p_dm_odm->support_ic_type & (ODM_RTL8812 | ODM_RTL8821 | ODM_RTL8881A)) && (!p_dm_odm->is_mp_chip)) + rx_pwr_all = (p_phy_sta_rpt->pwdb_all & 0x7f) - 110; + else + rx_pwr_all = (((p_phy_sta_rpt->pwdb_all) >> 1) & 0x7f) - 110; /*OLD FORMULA*/ + + PWDB_ALL_BT = PWDB_ALL = odm_query_rx_pwr_percentage(rx_pwr_all); + + p_phy_info->rx_pwdb_all = PWDB_ALL; + /*ODM_RT_TRACE(p_dm_odm,ODM_COMP_RSSI_MONITOR, ODM_DBG_LOUD, ("ODM OFDM RSSI=%d\n",p_phy_info->rx_pwdb_all));*/ + p_phy_info->bt_rx_rssi_percentage = PWDB_ALL_BT; + p_phy_info->rx_power = rx_pwr_all; + p_phy_info->recv_signal_power = rx_pwr_all; + + if ((p_dm_odm->support_platform == ODM_WIN) && (p_dm_odm->patch_id == 19)) { + /*do nothing*/ + } else { + /*p_mgnt_info->customer_id != RT_CID_819X_LENOVO*/ + + /*(4)EVM of OFDM rate*/ + + if ((p_pktinfo->data_rate >= ODM_RATEMCS8) && + (p_pktinfo->data_rate <= ODM_RATEMCS15)) + max_spatial_stream = 2; + else if ((p_pktinfo->data_rate >= ODM_RATEVHTSS2MCS0) && + (p_pktinfo->data_rate <= ODM_RATEVHTSS2MCS9)) + max_spatial_stream = 2; + else if ((p_pktinfo->data_rate >= ODM_RATEMCS16) && + (p_pktinfo->data_rate <= ODM_RATEMCS23)) + max_spatial_stream = 3; + else if ((p_pktinfo->data_rate >= ODM_RATEVHTSS3MCS0) && + (p_pktinfo->data_rate <= ODM_RATEVHTSS3MCS9)) + max_spatial_stream = 3; + else + max_spatial_stream = 1; + + /*if (p_pktinfo->is_packet_match_bssid) */ + { + /*dbg_print("p_pktinfo->data_rate = %d\n", p_pktinfo->data_rate);*/ + + for (i = 0; i < max_spatial_stream; i++) { + /*Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment*/ + /*fill most significant bit to "zero" when doing shifting operation which may change a negative*/ + /*value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.*/ + + if (p_pktinfo->data_rate >= ODM_RATE6M && p_pktinfo->data_rate <= ODM_RATE54M) { + if (i == ODM_RF_PATH_A) { + EVM = odm_evm_db_to_percentage((p_phy_sta_rpt->sigevm)); /*dbm*/ + EVM += 20; + if (EVM > 100) + EVM = 100; + } + } else { + if (i < ODM_RF_PATH_C) { + if (p_phy_sta_rpt->rxevm[i] == -128) + p_phy_sta_rpt->rxevm[i] = -25; + EVM = odm_evm_db_to_percentage((p_phy_sta_rpt->rxevm[i])); /*dbm*/ + } else { + if (p_phy_sta_rpt->rxevm_cd[i - 2] == -128) + p_phy_sta_rpt->rxevm_cd[i - 2] = -25; + EVM = odm_evm_db_to_percentage((p_phy_sta_rpt->rxevm_cd[i - 2])); /*dbm*/ + } + } + + if (i < ODM_RF_PATH_C) + evm_dbm = odm_evm_dbm_jaguar_series(p_phy_sta_rpt->rxevm[i]); + else + evm_dbm = odm_evm_dbm_jaguar_series(p_phy_sta_rpt->rxevm_cd[i - 2]); + /*RT_DISP(FRX, RX_PHY_SQ, ("RXRATE=%x RXEVM=%x EVM=%s%d\n",*/ + /*p_pktinfo->data_rate, p_phy_sta_rpt->rxevm[i], "%", EVM));*/ + + { + if (i == ODM_RF_PATH_A) { + /*Fill value in RFD, Get the first spatial stream only*/ + p_phy_info->signal_quality = EVM; + } + p_phy_info->rx_mimo_signal_quality[i] = EVM; + p_phy_info->rx_mimo_evm_dbm[i] = evm_dbm; + } + } + } + } + + num_ss = phydm_rate_to_num_ss(p_dm_odm, p_pktinfo->data_rate); + odm_parsing_cfo(p_dm_odm, p_pktinfo, p_phy_sta_rpt->cfotail, num_ss); + + } + /* dbg_print("is_cck_rate= %d, p_phy_info->signal_strength=%d % PWDB_AL=%d rf_rx_num=%d\n", is_cck_rate, p_phy_info->signal_strength, PWDB_ALL, rf_rx_num); */ + + /*UI BSS List signal strength(in percentage), make it good looking, from 0~100.*/ + /*It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().*/ + if (is_cck_rate) { + p_phy_info->signal_strength = (u8)(odm_signal_scale_mapping(p_dm_odm, PWDB_ALL));/*PWDB_ALL;*/ + } else { + if (rf_rx_num != 0) { + /* 2015/01 Sean, use the best two RSSI only, suggested by Ynlin and ChenYu.*/ + if (rf_rx_num == 1) + avg_rssi = best_rssi; + else + avg_rssi = (best_rssi + second_rssi) / 2; + p_phy_info->signal_strength = (u8)(odm_signal_scale_mapping(p_dm_odm, avg_rssi)); + } + } + p_dm_odm->rx_pwdb_ave = p_dm_odm->rx_pwdb_ave + p_phy_info->rx_pwdb_all; + + p_dm_odm->dm_fat_table.antsel_rx_keep_0 = p_phy_sta_rpt->antidx_anta; + p_dm_odm->dm_fat_table.antsel_rx_keep_1 = p_phy_sta_rpt->antidx_antb; + p_dm_odm->dm_fat_table.antsel_rx_keep_2 = p_phy_sta_rpt->antidx_antc; + p_dm_odm->dm_fat_table.antsel_rx_keep_3 = p_phy_sta_rpt->antidx_antd; + /*ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("StaID[%d]: antidx_anta = ((%d)), MatchBSSID = ((%d))\n", p_pktinfo->station_id, p_phy_sta_rpt->antidx_anta, p_pktinfo->is_packet_match_bssid));*/ + + /* dbg_print("p_phy_sta_rpt->antidx_anta = %d, p_phy_sta_rpt->antidx_antb = %d\n",*/ + /* p_phy_sta_rpt->antidx_anta, p_phy_sta_rpt->antidx_antb);*/ + /* dbg_print("----------------------------\n");*/ + /* dbg_print("p_pktinfo->station_id=%d, p_pktinfo->data_rate=0x%x\n",p_pktinfo->station_id, p_pktinfo->data_rate);*/ + /* dbg_print("p_phy_sta_rpt->r_RFMOD = %d\n", p_phy_sta_rpt->r_RFMOD);*/ + /* dbg_print("p_phy_sta_rpt->gain_trsw[0]=0x%x, p_phy_sta_rpt->gain_trsw[1]=0x%x\n",*/ + /* p_phy_sta_rpt->gain_trsw[0],p_phy_sta_rpt->gain_trsw[1]);*/ + /* dbg_print("p_phy_sta_rpt->gain_trsw[2]=0x%x, p_phy_sta_rpt->gain_trsw[3]=0x%x\n",*/ + /* p_phy_sta_rpt->gain_trsw_cd[0],p_phy_sta_rpt->gain_trsw_cd[1]);*/ + /* dbg_print("p_phy_sta_rpt->pwdb_all = 0x%x, p_phy_info->rx_pwdb_all = %d\n", p_phy_sta_rpt->pwdb_all, p_phy_info->rx_pwdb_all);*/ + /* dbg_print("p_phy_sta_rpt->cfotail[i] = 0x%x, p_phy_sta_rpt->CFO_tail[i] = 0x%x\n", p_phy_sta_rpt->cfotail[0], p_phy_sta_rpt->cfotail[1]);*/ + /* dbg_print("p_phy_sta_rpt->rxevm[0] = %d, p_phy_sta_rpt->rxevm[1] = %d\n", p_phy_sta_rpt->rxevm[0], p_phy_sta_rpt->rxevm[1]);*/ + /* dbg_print("p_phy_sta_rpt->rxevm[2] = %d, p_phy_sta_rpt->rxevm[3] = %d\n", p_phy_sta_rpt->rxevm_cd[0], p_phy_sta_rpt->rxevm_cd[1]);*/ + /* dbg_print("p_phy_info->rx_mimo_signal_strength[0]=%d, p_phy_info->rx_mimo_signal_strength[1]=%d, rx_pwdb_all=%d\n",*/ + /* p_phy_info->rx_mimo_signal_strength[0], p_phy_info->rx_mimo_signal_strength[1], p_phy_info->rx_pwdb_all);*/ + /* dbg_print("p_phy_info->rx_mimo_signal_strength[2]=%d, p_phy_info->rx_mimo_signal_strength[3]=%d\n",*/ + /* p_phy_info->rx_mimo_signal_strength[2], p_phy_info->rx_mimo_signal_strength[3]);*/ + /* dbg_print("ppPhyInfo->rx_mimo_signal_quality[0]=%d, p_phy_info->rx_mimo_signal_quality[1]=%d\n",*/ + /* p_phy_info->rx_mimo_signal_quality[0], p_phy_info->rx_mimo_signal_quality[1]);*/ + /* dbg_print("ppPhyInfo->rx_mimo_signal_quality[2]=%d, p_phy_info->rx_mimo_signal_quality[3]=%d\n",*/ + /* p_phy_info->rx_mimo_signal_quality[2], p_phy_info->rx_mimo_signal_quality[3]);*/ + +} + +#endif + +void +phydm_reset_rssi_for_dm( + struct PHY_DM_STRUCT *p_dm_odm, + u8 station_id +) +{ + struct sta_info *p_entry; + + p_entry = p_dm_odm->p_odm_sta_info[station_id]; + + if (!IS_STA_VALID(p_entry)) { + /**/ + return; + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RSSI_MONITOR, ODM_DBG_LOUD, ("Reset RSSI for macid = (( %d ))\n", station_id)); + + p_entry->rssi_stat.undecorated_smoothed_cck = -1; + p_entry->rssi_stat.undecorated_smoothed_ofdm = -1; + p_entry->rssi_stat.undecorated_smoothed_pwdb = -1; + p_entry->rssi_stat.ofdm_pkt = 0; + p_entry->rssi_stat.cck_pkt = 0; + p_entry->rssi_stat.cck_sum_power = 0; + p_entry->rssi_stat.is_send_rssi = RA_RSSI_STATE_INIT; + p_entry->rssi_stat.packet_map = 0; + p_entry->rssi_stat.valid_bit = 0; +} + +void +odm_init_rssi_for_dm( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + +} + +static void +odm_process_rssi_for_dm( + struct PHY_DM_STRUCT *p_dm_odm, + struct _odm_phy_status_info_ *p_phy_info, + struct _odm_per_pkt_info_ *p_pktinfo +) +{ + + s32 undecorated_smoothed_pwdb, undecorated_smoothed_cck, undecorated_smoothed_ofdm, rssi_ave, cck_pkt; + u8 i, is_cck_rate = 0; + u8 RSSI_max, RSSI_min; + u32 weighting = 0; + u8 send_rssi_2_fw = 0; + struct sta_info *p_entry; + + if (p_pktinfo->station_id >= ODM_ASSOCIATE_ENTRY_NUM) + return; + +#ifdef CONFIG_S0S1_SW_ANTENNA_DIVERSITY + odm_s0s1_sw_ant_div_by_ctrl_frame_process_rssi(p_dm_odm, p_phy_info, p_pktinfo); +#endif + + /* */ + /* 2012/05/30 MH/Luke.Lee Add some description */ + /* In windows driver: AP/IBSS mode STA */ + /* */ + /* if (p_dm_odm->support_platform == ODM_WIN) */ + /* { */ + /* p_entry = p_dm_odm->p_odm_sta_info[p_dm_odm->pAidMap[p_pktinfo->station_id-1]]; */ + /* } */ + /* else */ + p_entry = p_dm_odm->p_odm_sta_info[p_pktinfo->station_id]; + + if (!IS_STA_VALID(p_entry)) { + return; + /**/ + } + + if ((!p_pktinfo->is_packet_match_bssid))/*data frame only*/ + return; + + if (p_pktinfo->is_packet_beacon) + p_dm_odm->phy_dbg_info.num_qry_beacon_pkt++; + + is_cck_rate = (p_pktinfo->data_rate <= ODM_RATE11M) ? true : false; + p_dm_odm->rx_rate = p_pktinfo->data_rate; + + /* --------------Statistic for antenna/path diversity------------------ */ + if (p_dm_odm->support_ability & ODM_BB_ANT_DIV) { +#if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY)) + odm_process_rssi_for_ant_div(p_dm_odm, p_phy_info, p_pktinfo); +#endif + } +#if (defined(CONFIG_PATH_DIVERSITY)) + else if (p_dm_odm->support_ability & ODM_BB_PATH_DIV) + phydm_process_rssi_for_path_div(p_dm_odm, p_phy_info, p_pktinfo); +#endif + /* -----------------Smart Antenna Debug Message------------------ */ + + undecorated_smoothed_cck = p_entry->rssi_stat.undecorated_smoothed_cck; + undecorated_smoothed_ofdm = p_entry->rssi_stat.undecorated_smoothed_ofdm; + undecorated_smoothed_pwdb = p_entry->rssi_stat.undecorated_smoothed_pwdb; + + if (p_pktinfo->is_packet_to_self || p_pktinfo->is_packet_beacon) { + + if (!is_cck_rate) { /* ofdm rate */ + { + if (p_phy_info->rx_mimo_signal_strength[ODM_RF_PATH_B] == 0) { + rssi_ave = p_phy_info->rx_mimo_signal_strength[ODM_RF_PATH_A]; + p_dm_odm->RSSI_A = p_phy_info->rx_mimo_signal_strength[ODM_RF_PATH_A]; + p_dm_odm->RSSI_B = 0; + } else { + /*dbg_print("p_rfd->status.rx_mimo_signal_strength[0] = %d, p_rfd->status.rx_mimo_signal_strength[1] = %d\n",*/ + /*p_rfd->status.rx_mimo_signal_strength[0], p_rfd->status.rx_mimo_signal_strength[1]);*/ + p_dm_odm->RSSI_A = p_phy_info->rx_mimo_signal_strength[ODM_RF_PATH_A]; + p_dm_odm->RSSI_B = p_phy_info->rx_mimo_signal_strength[ODM_RF_PATH_B]; + + if (p_phy_info->rx_mimo_signal_strength[ODM_RF_PATH_A] > p_phy_info->rx_mimo_signal_strength[ODM_RF_PATH_B]) { + RSSI_max = p_phy_info->rx_mimo_signal_strength[ODM_RF_PATH_A]; + RSSI_min = p_phy_info->rx_mimo_signal_strength[ODM_RF_PATH_B]; + } else { + RSSI_max = p_phy_info->rx_mimo_signal_strength[ODM_RF_PATH_B]; + RSSI_min = p_phy_info->rx_mimo_signal_strength[ODM_RF_PATH_A]; + } + if ((RSSI_max - RSSI_min) < 3) + rssi_ave = RSSI_max; + else if ((RSSI_max - RSSI_min) < 6) + rssi_ave = RSSI_max - 1; + else if ((RSSI_max - RSSI_min) < 10) + rssi_ave = RSSI_max - 2; + else + rssi_ave = RSSI_max - 3; + } + } + + /* 1 Process OFDM RSSI */ + if (undecorated_smoothed_ofdm <= 0) { /* initialize */ + undecorated_smoothed_ofdm = p_phy_info->rx_pwdb_all; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RSSI_MONITOR, ODM_DBG_LOUD, ("OFDM_INIT: (( %d ))\n", undecorated_smoothed_ofdm)); + } else { + if (p_phy_info->rx_pwdb_all > (u32)undecorated_smoothed_ofdm) { + undecorated_smoothed_ofdm = + (((undecorated_smoothed_ofdm)*(RX_SMOOTH_FACTOR - 1)) + + (rssi_ave)) / (RX_SMOOTH_FACTOR); + undecorated_smoothed_ofdm = undecorated_smoothed_ofdm + 1; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RSSI_MONITOR, ODM_DBG_LOUD, ("OFDM_1: (( %d ))\n", undecorated_smoothed_ofdm)); + } else { + undecorated_smoothed_ofdm = + (((undecorated_smoothed_ofdm)*(RX_SMOOTH_FACTOR - 1)) + + (rssi_ave)) / (RX_SMOOTH_FACTOR); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RSSI_MONITOR, ODM_DBG_LOUD, ("OFDM_2: (( %d ))\n", undecorated_smoothed_ofdm)); + } + } + if (p_entry->rssi_stat.ofdm_pkt != 64) { + i = 63; + p_entry->rssi_stat.ofdm_pkt -= (u8)(((p_entry->rssi_stat.packet_map >> i) & BIT(0)) - 1); + } + p_entry->rssi_stat.packet_map = (p_entry->rssi_stat.packet_map << 1) | BIT(0); + + } else { + rssi_ave = p_phy_info->rx_pwdb_all; + p_dm_odm->RSSI_A = (u8) p_phy_info->rx_pwdb_all; + p_dm_odm->RSSI_B = 0xFF; + p_dm_odm->RSSI_C = 0xFF; + p_dm_odm->RSSI_D = 0xFF; + + if (p_entry->rssi_stat.cck_pkt <= 63) + p_entry->rssi_stat.cck_pkt++; + + /* 1 Process CCK RSSI */ + if (undecorated_smoothed_cck <= 0) { /* initialize */ + undecorated_smoothed_cck = p_phy_info->rx_pwdb_all; + p_entry->rssi_stat.cck_sum_power = (u16)p_phy_info->rx_pwdb_all ; /*reset*/ + p_entry->rssi_stat.cck_pkt = 1; /*reset*/ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RSSI_MONITOR, ODM_DBG_LOUD, ("CCK_INIT: (( %d ))\n", undecorated_smoothed_cck)); + } else if (p_entry->rssi_stat.cck_pkt <= CCK_RSSI_INIT_COUNT) { + + p_entry->rssi_stat.cck_sum_power = p_entry->rssi_stat.cck_sum_power + (u16)p_phy_info->rx_pwdb_all; + undecorated_smoothed_cck = p_entry->rssi_stat.cck_sum_power / p_entry->rssi_stat.cck_pkt; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RSSI_MONITOR, ODM_DBG_LOUD, ("CCK_0: (( %d )), SumPow = (( %d )), cck_pkt = (( %d ))\n", + undecorated_smoothed_cck, p_entry->rssi_stat.cck_sum_power, p_entry->rssi_stat.cck_pkt)); + } else { + if (p_phy_info->rx_pwdb_all > (u32)undecorated_smoothed_cck) { + undecorated_smoothed_cck = + (((undecorated_smoothed_cck)*(RX_SMOOTH_FACTOR - 1)) + + (p_phy_info->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); + undecorated_smoothed_cck = undecorated_smoothed_cck + 1; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RSSI_MONITOR, ODM_DBG_LOUD, ("CCK_1: (( %d ))\n", undecorated_smoothed_cck)); + } else { + undecorated_smoothed_cck = + (((undecorated_smoothed_cck)*(RX_SMOOTH_FACTOR - 1)) + + (p_phy_info->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RSSI_MONITOR, ODM_DBG_LOUD, ("CCK_2: (( %d ))\n", undecorated_smoothed_cck)); + } + } + i = 63; + p_entry->rssi_stat.ofdm_pkt -= (u8)((p_entry->rssi_stat.packet_map >> i) & BIT(0)); + p_entry->rssi_stat.packet_map = p_entry->rssi_stat.packet_map << 1; + } + + /* if(p_entry) */ + { + /* 2011.07.28 LukeLee: modified to prevent unstable CCK RSSI */ + if (p_entry->rssi_stat.ofdm_pkt == 64) { /* speed up when all packets are OFDM*/ + undecorated_smoothed_pwdb = undecorated_smoothed_ofdm; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RSSI_MONITOR, ODM_DBG_LOUD, ("PWDB_0[%d] = (( %d ))\n", p_pktinfo->station_id, undecorated_smoothed_cck)); + } else { + if (p_entry->rssi_stat.valid_bit < 64) + p_entry->rssi_stat.valid_bit++; + + if (p_entry->rssi_stat.valid_bit == 64) { + weighting = ((p_entry->rssi_stat.ofdm_pkt) > 4) ? 64 : (p_entry->rssi_stat.ofdm_pkt << 4); + undecorated_smoothed_pwdb = (weighting * undecorated_smoothed_ofdm + (64 - weighting) * undecorated_smoothed_cck) >> 6; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RSSI_MONITOR, ODM_DBG_LOUD, ("PWDB_1[%d] = (( %d )), W = (( %d ))\n", p_pktinfo->station_id, undecorated_smoothed_cck, weighting)); + } else { + if (p_entry->rssi_stat.valid_bit != 0) + undecorated_smoothed_pwdb = (p_entry->rssi_stat.ofdm_pkt * undecorated_smoothed_ofdm + (p_entry->rssi_stat.valid_bit - p_entry->rssi_stat.ofdm_pkt) * undecorated_smoothed_cck) / p_entry->rssi_stat.valid_bit; + else + undecorated_smoothed_pwdb = 0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RSSI_MONITOR, ODM_DBG_LOUD, ("PWDB_2[%d] = (( %d )), ofdm_pkt = (( %d )), Valid_Bit = (( %d ))\n", p_pktinfo->station_id, undecorated_smoothed_cck, p_entry->rssi_stat.ofdm_pkt, p_entry->rssi_stat.valid_bit)); + } + } + + if ((p_entry->rssi_stat.ofdm_pkt >= 1 || p_entry->rssi_stat.cck_pkt >= 5) && (p_entry->rssi_stat.is_send_rssi == RA_RSSI_STATE_INIT)) { + + send_rssi_2_fw = 1; + p_entry->rssi_stat.is_send_rssi = RA_RSSI_STATE_SEND; + } + + p_entry->rssi_stat.undecorated_smoothed_cck = undecorated_smoothed_cck; + p_entry->rssi_stat.undecorated_smoothed_ofdm = undecorated_smoothed_ofdm; + p_entry->rssi_stat.undecorated_smoothed_pwdb = undecorated_smoothed_pwdb; + + if (send_rssi_2_fw) { /* Trigger init rate by RSSI */ + + if (p_entry->rssi_stat.ofdm_pkt != 0) + p_entry->rssi_stat.undecorated_smoothed_pwdb = undecorated_smoothed_ofdm; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RSSI_MONITOR, ODM_DBG_LOUD, ("[Send to FW] PWDB = (( %d )), ofdm_pkt = (( %d )), cck_pkt = (( %d ))\n", + undecorated_smoothed_pwdb, p_entry->rssi_stat.ofdm_pkt, p_entry->rssi_stat.cck_pkt)); + + phydm_ra_rssi_rpt_wk(p_dm_odm); + } + } + + } +} + +#if (ODM_IC_11N_SERIES_SUPPORT == 1) +/* + * Endianness before calling this API + * */ +static void +odm_phy_status_query_92c_series( + struct PHY_DM_STRUCT *p_dm_odm, + struct _odm_phy_status_info_ *p_phy_info, + u8 *p_phy_status, + struct _odm_per_pkt_info_ *p_pktinfo +) +{ + odm_rx_phy_status92c_series_parsing(p_dm_odm, p_phy_info, p_phy_status, p_pktinfo); + odm_process_rssi_for_dm(p_dm_odm, p_phy_info, p_pktinfo); +} +#endif + +/* + * Endianness before calling this API + * */ +#if ODM_IC_11AC_SERIES_SUPPORT + +void +odm_phy_status_query_jaguar_series( + struct PHY_DM_STRUCT *p_dm_odm, + struct _odm_phy_status_info_ *p_phy_info, + u8 *p_phy_status, + struct _odm_per_pkt_info_ *p_pktinfo +) +{ + odm_rx_phy_status_jaguar_series_parsing(p_dm_odm, p_phy_info, p_phy_status, p_pktinfo); + odm_process_rssi_for_dm(p_dm_odm, p_phy_info, p_pktinfo); + +} +#endif + +void +odm_phy_status_query( + struct PHY_DM_STRUCT *p_dm_odm, + struct _odm_phy_status_info_ *p_phy_info, + u8 *p_phy_status, + struct _odm_per_pkt_info_ *p_pktinfo +) +{ +#if (ODM_PHY_STATUS_NEW_TYPE_SUPPORT == 1) + if (p_dm_odm->support_ic_type & ODM_IC_PHY_STATUE_NEW_TYPE) { + phydm_rx_phy_status_new_type(p_dm_odm, p_phy_status, p_pktinfo, p_phy_info); + return; + } +#endif + +#if ODM_IC_11AC_SERIES_SUPPORT + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) + odm_phy_status_query_jaguar_series(p_dm_odm, p_phy_info, p_phy_status, p_pktinfo); +#endif + +#if ODM_IC_11N_SERIES_SUPPORT + if (p_dm_odm->support_ic_type & ODM_IC_11N_SERIES) + odm_phy_status_query_92c_series(p_dm_odm, p_phy_info, p_phy_status, p_pktinfo); +#endif +} + +/* For future use. */ +void +odm_mac_status_query( + struct PHY_DM_STRUCT *p_dm_odm, + u8 *p_mac_status, + u8 mac_id, + bool is_packet_match_bssid, + bool is_packet_to_self, + bool is_packet_beacon +) +{ + /* 2011/10/19 Driver team will handle in the future. */ + +} + +/* + * If you want to add a new IC, Please follow below template and generate a new one. + * + * */ + +enum hal_status +odm_config_rf_with_header_file( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_rf_config_type config_type, + enum odm_rf_radio_path_e e_rf_path +) +{ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, + ("===>odm_config_rf_with_header_file (%s)\n", (p_dm_odm->is_mp_chip) ? "MPChip" : "TestChip")); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, + ("p_dm_odm->support_platform: 0x%X, p_dm_odm->support_interface: 0x%X, p_dm_odm->board_type: 0x%X\n", + p_dm_odm->support_platform, p_dm_odm->support_interface, p_dm_odm->board_type)); + + /* 1 AP doesn't use PHYDM power tracking table in these ICs */ + + /* 1 All platforms support */ + if (p_dm_odm->support_ic_type == ODM_RTL8188E) { + if (config_type == CONFIG_RF_RADIO) { + if (e_rf_path == ODM_RF_PATH_A) + READ_AND_CONFIG_MP(8188e, _radioa); + } else if (config_type == CONFIG_RF_TXPWR_LMT) + READ_AND_CONFIG_MP(8188e, _txpwr_lmt); + } + return HAL_STATUS_SUCCESS; +} + +enum hal_status +odm_config_rf_with_tx_pwr_track_header_file( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, + ("===>odm_config_rf_with_tx_pwr_track_header_file (%s)\n", (p_dm_odm->is_mp_chip) ? "MPChip" : "TestChip")); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, + ("p_dm_odm->support_platform: 0x%X, p_dm_odm->support_interface: 0x%X, p_dm_odm->board_type: 0x%X\n", + p_dm_odm->support_platform, p_dm_odm->support_interface, p_dm_odm->board_type)); + + /* 1 AP doesn't use PHYDM power tracking table in these ICs */ + if (p_dm_odm->support_ic_type == ODM_RTL8188E) { + if (odm_get_mac_reg(p_dm_odm, 0xF0, 0xF000) >= 8) { /*if 0xF0[15:12] >= 8, SMIC*/ + if (p_dm_odm->support_interface == ODM_ITRF_PCIE) + READ_AND_CONFIG_MP(8188e, _txpowertrack_pcie_icut); + else if (p_dm_odm->support_interface == ODM_ITRF_USB) + READ_AND_CONFIG_MP(8188e, _txpowertrack_usb_icut); + else if (p_dm_odm->support_interface == ODM_ITRF_SDIO) + READ_AND_CONFIG_MP(8188e, _txpowertrack_sdio_icut); + } else { /*else 0xF0[15:12] < 8, TSMC*/ + if (p_dm_odm->support_interface == ODM_ITRF_PCIE) + READ_AND_CONFIG_MP(8188e, _txpowertrack_pcie); + else if (p_dm_odm->support_interface == ODM_ITRF_USB) + READ_AND_CONFIG_MP(8188e, _txpowertrack_usb); + else if (p_dm_odm->support_interface == ODM_ITRF_SDIO) + READ_AND_CONFIG_MP(8188e, _txpowertrack_sdio); + } + + } + + /* 1 All platforms support */ + return HAL_STATUS_SUCCESS; +} + +enum hal_status +odm_config_bb_with_header_file( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_bb_config_type config_type +) +{ + /* 1 All platforms support */ + if (p_dm_odm->support_ic_type == ODM_RTL8188E) { + if (config_type == CONFIG_BB_PHY_REG) + READ_AND_CONFIG_MP(8188e, _phy_reg); + else if (config_type == CONFIG_BB_AGC_TAB) + READ_AND_CONFIG_MP(8188e, _agc_tab); + else if (config_type == CONFIG_BB_PHY_REG_PG) + READ_AND_CONFIG_MP(8188e, _phy_reg_pg); + } + return HAL_STATUS_SUCCESS; +} + +enum hal_status +odm_config_mac_with_header_file( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, + ("===>odm_config_mac_with_header_file (%s)\n", (p_dm_odm->is_mp_chip) ? "MPChip" : "TestChip")); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, + ("p_dm_odm->support_platform: 0x%X, p_dm_odm->support_interface: 0x%X, p_dm_odm->board_type: 0x%X\n", + p_dm_odm->support_platform, p_dm_odm->support_interface, p_dm_odm->board_type)); + + /* 1 All platforms support */ + if (p_dm_odm->support_ic_type == ODM_RTL8188E) + READ_AND_CONFIG_MP(8188e, _mac_reg); + return HAL_STATUS_SUCCESS; +} + +enum hal_status +odm_config_fw_with_header_file( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_fw_config_type config_type, + u8 *p_firmware, + u32 *p_size +) +{ + return HAL_STATUS_SUCCESS; +} + +u32 +odm_get_hw_img_version( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u32 version = 0; + + /*1 All platforms support*/ + if (p_dm_odm->support_ic_type == ODM_RTL8188E) + version = GET_VERSION_MP(8188e, _mac_reg); + return version; +} + +#if (ODM_PHY_STATUS_NEW_TYPE_SUPPORT == 1) +/* For 8822B only!! need to move to FW finally */ +/*==============================================*/ + +bool +phydm_query_is_mu_api( + struct PHY_DM_STRUCT *p_phydm, + u8 ppdu_idx, + u8 *p_data_rate, + u8 *p_gid +) +{ + u8 data_rate = 0, gid = 0; + bool is_mu = FALSE; + + data_rate = p_phydm->phy_dbg_info.num_of_ppdu[ppdu_idx]; + gid = p_phydm->phy_dbg_info.gid_num[ppdu_idx]; + + if (data_rate & BIT(7)) { + is_mu = TRUE; + data_rate = data_rate & ~(BIT(7)); + } else + is_mu = FALSE; + + *p_data_rate = data_rate; + *p_gid = gid; + + return is_mu; + +} + +void +phydm_rx_statistic_cal( + struct PHY_DM_STRUCT *p_phydm, + u8 *p_phy_status, + struct _odm_per_pkt_info_ *p_pktinfo +) +{ + struct _phy_status_rpt_jaguar2_type1 *p_phy_sta_rpt = (struct _phy_status_rpt_jaguar2_type1 *)p_phy_status; + u8 date_rate = p_pktinfo->data_rate & ~(BIT(7)); + + if ((p_phy_sta_rpt->gid != 0) && (p_phy_sta_rpt->gid != 63)) { + if (date_rate >= ODM_RATEVHTSS1MCS0) { + p_phydm->phy_dbg_info.num_qry_mu_vht_pkt[date_rate - 0x2C]++; + p_phydm->phy_dbg_info.num_of_ppdu[p_pktinfo->ppdu_cnt] = date_rate | BIT(7); + p_phydm->phy_dbg_info.gid_num[p_pktinfo->ppdu_cnt] = p_phy_sta_rpt->gid; + } + + } else { + if (date_rate >= ODM_RATEVHTSS1MCS0) { + p_phydm->phy_dbg_info.num_qry_vht_pkt[date_rate - 0x2C]++; + p_phydm->phy_dbg_info.num_of_ppdu[p_pktinfo->ppdu_cnt] = date_rate; + p_phydm->phy_dbg_info.gid_num[p_pktinfo->ppdu_cnt] = p_phy_sta_rpt->gid; + } + } + +} + +void +phydm_reset_phy_info( + struct PHY_DM_STRUCT *p_phydm, + struct _odm_phy_status_info_ *p_phy_info +) +{ + p_phy_info->rx_pwdb_all = 0; + p_phy_info->signal_quality = 0; + p_phy_info->band_width = 0; + p_phy_info->rx_count = 0; + odm_memory_set(p_phydm, p_phy_info->rx_mimo_signal_quality, 0, 4); + odm_memory_set(p_phydm, p_phy_info->rx_mimo_signal_strength, 0, 4); + odm_memory_set(p_phydm, p_phy_info->rx_snr, 0, 4); + + p_phy_info->rx_power = -110; + p_phy_info->recv_signal_power = -110; + p_phy_info->bt_rx_rssi_percentage = 0; + p_phy_info->signal_strength = 0; + p_phy_info->bt_coex_pwr_adjust = 0; + p_phy_info->channel = 0; + p_phy_info->is_mu_packet = 0; + p_phy_info->is_beamformed = 0; + p_phy_info->rxsc = 0; + odm_memory_set(p_phydm, p_phy_info->rx_pwr, -110, 4); + odm_memory_set(p_phydm, p_phy_info->rx_mimo_evm_dbm, 0, 4); + odm_memory_set(p_phydm, p_phy_info->cfo_short, 0, 8); + odm_memory_set(p_phydm, p_phy_info->cfo_tail, 0, 8); +} + +void +phydm_set_per_path_phy_info( + u8 rx_path, + s8 rx_pwr, + s8 rx_evm, + s8 cfo_tail, + s8 rx_snr, + struct _odm_phy_status_info_ *p_phy_info +) +{ + u8 evm_dbm = 0; + u8 evm_percentage = 0; + + /* SNR is S(8,1), EVM is S(8,1), CFO is S(8,7) */ + + if (rx_evm < 0) { + /* Calculate EVM in dBm */ + evm_dbm = ((u8)(0 - rx_evm) >> 1); + + /* Calculate EVM in percentage */ + if (evm_dbm >= 33) + evm_percentage = 100; + else + evm_percentage = (evm_dbm << 1) + (evm_dbm); + } + + p_phy_info->rx_pwr[rx_path] = rx_pwr; + p_phy_info->rx_mimo_evm_dbm[rx_path] = evm_dbm; + + /* CFO = CFO_tail * 312.5 / 2^7 ~= CFO tail * 39/512 (kHz)*/ + p_phy_info->cfo_tail[rx_path] = cfo_tail; + p_phy_info->cfo_tail[rx_path] = ((p_phy_info->cfo_tail[rx_path] << 5) + (p_phy_info->cfo_tail[rx_path] << 2) + + (p_phy_info->cfo_tail[rx_path] << 1) + (p_phy_info->cfo_tail[rx_path])) >> 9; + + p_phy_info->rx_mimo_signal_strength[rx_path] = odm_query_rx_pwr_percentage(rx_pwr); + p_phy_info->rx_mimo_signal_quality[rx_path] = evm_percentage; + p_phy_info->rx_snr[rx_path] = rx_snr >> 1; +} + +void +phydm_set_common_phy_info( + s8 rx_power, + u8 channel, + bool is_beamformed, + bool is_mu_packet, + u8 bandwidth, + u8 signal_quality, + u8 rxsc, + struct _odm_phy_status_info_ *p_phy_info +) +{ + p_phy_info->rx_power = rx_power; /* RSSI in dB */ + p_phy_info->recv_signal_power = rx_power; /* RSSI in dB */ + p_phy_info->channel = channel; /* channel number */ + p_phy_info->is_beamformed = is_beamformed; /* apply BF */ + p_phy_info->is_mu_packet = is_mu_packet; /* MU packet */ + p_phy_info->rxsc = rxsc; + p_phy_info->rx_pwdb_all = odm_query_rx_pwr_percentage(rx_power); /* RSSI in percentage */ + p_phy_info->signal_quality = signal_quality; /* signal quality */ + p_phy_info->band_width = bandwidth; /* bandwidth */ +} + +void +phydm_get_rx_phy_status_type0( + struct PHY_DM_STRUCT *p_dm_odm, + u8 *p_phy_status, + struct _odm_per_pkt_info_ *p_pktinfo, + struct _odm_phy_status_info_ *p_phy_info +) +{ + /* type 0 is used for cck packet */ + + struct _phy_status_rpt_jaguar2_type0 *p_phy_sta_rpt = (struct _phy_status_rpt_jaguar2_type0 *)p_phy_status; + u8 i, SQ = 0; + s8 rx_power = p_phy_sta_rpt->pwdb - 110; + +#if (RTL8723D_SUPPORT == 1) + if (p_dm_odm->support_ic_type & ODM_RTL8723D) + rx_power = p_phy_sta_rpt->pwdb - 97; +#endif +#if (RTL8197F_SUPPORT == 1) + if (p_dm_odm->support_ic_type & ODM_RTL8197F) + rx_power = p_phy_sta_rpt->pwdb - 97; +#endif + + /* Calculate Signal Quality*/ + if (p_pktinfo->is_packet_match_bssid) { + if (p_phy_sta_rpt->signal_quality >= 64) + SQ = 0; + else if (p_phy_sta_rpt->signal_quality <= 20) + SQ = 100; + else { + /* mapping to 2~99% */ + SQ = 64 - p_phy_sta_rpt->signal_quality; + SQ = ((SQ << 3) + SQ) >> 2; + } + } + + /* Modify CCK PWDB if old AGC */ + if (p_dm_odm->cck_new_agc == false) { + u8 lna_idx, vga_idx; + + lna_idx = ((p_phy_sta_rpt->lna_h << 3) | p_phy_sta_rpt->lna_l); + vga_idx = p_phy_sta_rpt->vga; + } + + /* Update CCK packet counter */ + p_dm_odm->phy_dbg_info.num_qry_phy_status_cck++; + + /*CCK no STBC and LDPC*/ + p_dm_odm->phy_dbg_info.is_ldpc_pkt = false; + p_dm_odm->phy_dbg_info.is_stbc_pkt = false; + + /* Update Common information */ + phydm_set_common_phy_info(rx_power, p_phy_sta_rpt->channel, false, + false, ODM_BW20M, SQ, p_phy_sta_rpt->rxsc, p_phy_info); + + /* Update CCK pwdb */ + phydm_set_per_path_phy_info(ODM_RF_PATH_A, rx_power, 0, 0, 0, p_phy_info); /* Update per-path information */ + + p_dm_odm->dm_fat_table.antsel_rx_keep_0 = p_phy_sta_rpt->antidx_a; + p_dm_odm->dm_fat_table.antsel_rx_keep_1 = p_phy_sta_rpt->antidx_b; + p_dm_odm->dm_fat_table.antsel_rx_keep_2 = p_phy_sta_rpt->antidx_c; + p_dm_odm->dm_fat_table.antsel_rx_keep_3 = p_phy_sta_rpt->antidx_d; +} + +void +phydm_get_rx_phy_status_type1( + struct PHY_DM_STRUCT *p_dm_odm, + u8 *p_phy_status, + struct _odm_per_pkt_info_ *p_pktinfo, + struct _odm_phy_status_info_ *p_phy_info +) +{ + /* type 1 is used for ofdm packet */ + + struct _phy_status_rpt_jaguar2_type1 *p_phy_sta_rpt = (struct _phy_status_rpt_jaguar2_type1 *)p_phy_status; + s8 rx_pwr_db = -120; + u8 i, rxsc, bw = ODM_BW20M, rx_count = 0; + bool is_mu; + u8 num_ss; + + /* Update OFDM packet counter */ + p_dm_odm->phy_dbg_info.num_qry_phy_status_ofdm++; + + /* Update per-path information */ + for (i = ODM_RF_PATH_A; i < ODM_RF_PATH_MAX_JAGUAR; i++) { + if (p_dm_odm->rx_ant_status & BIT(i)) { + s8 rx_path_pwr_db; + + /* RX path counter */ + rx_count++; + + /* Update per-path information (RSSI_dB RSSI_percentage EVM SNR CFO SQ) */ + /* EVM report is reported by stream, not path */ + rx_path_pwr_db = p_phy_sta_rpt->pwdb[i] - 110; /* per-path pwdb in dB domain */ + phydm_set_per_path_phy_info(i, rx_path_pwr_db, p_phy_sta_rpt->rxevm[rx_count - 1], + p_phy_sta_rpt->cfo_tail[i], p_phy_sta_rpt->rxsnr[i], p_phy_info); + + /* search maximum pwdb */ + if (rx_path_pwr_db > rx_pwr_db) + rx_pwr_db = rx_path_pwr_db; + } + } + + /* mapping RX counter from 1~4 to 0~3 */ + if (rx_count > 0) + p_phy_info->rx_count = rx_count - 1; + + /* Check if MU packet or not */ + if ((p_phy_sta_rpt->gid != 0) && (p_phy_sta_rpt->gid != 63)) { + is_mu = true; + p_dm_odm->phy_dbg_info.num_qry_mu_pkt++; + } else + is_mu = false; + + /* count BF packet */ + p_dm_odm->phy_dbg_info.num_qry_bf_pkt = p_dm_odm->phy_dbg_info.num_qry_bf_pkt + p_phy_sta_rpt->beamformed; + + /*STBC or LDPC pkt*/ + p_dm_odm->phy_dbg_info.is_ldpc_pkt = p_phy_sta_rpt->ldpc; + p_dm_odm->phy_dbg_info.is_stbc_pkt = p_phy_sta_rpt->stbc; + + /* Check sub-channel */ + if ((p_pktinfo->data_rate > ODM_RATE11M) && (p_pktinfo->data_rate < ODM_RATEMCS0)) + rxsc = p_phy_sta_rpt->l_rxsc; + else + rxsc = p_phy_sta_rpt->ht_rxsc; + + /* Check RX bandwidth */ + if (p_dm_odm->support_ic_type & ODM_RTL8822B) { + if ((rxsc >= 1) && (rxsc <= 8)) + bw = ODM_BW20M; + else if ((rxsc >= 9) && (rxsc <= 12)) + bw = ODM_BW40M; + else if (rxsc >= 13) + bw = ODM_BW80M; + else + bw = p_phy_sta_rpt->rf_mode; + } else if (p_dm_odm->support_ic_type & (ODM_RTL8197F | ODM_RTL8723D)) { + if (p_phy_sta_rpt->rf_mode == 0) + bw = ODM_BW20M; + else if ((rxsc == 1) || (rxsc == 2)) + bw = ODM_BW20M; + else + bw = ODM_BW40M; + } + + /* Update packet information */ + phydm_set_common_phy_info(rx_pwr_db, p_phy_sta_rpt->channel, (bool)p_phy_sta_rpt->beamformed, + is_mu, bw, odm_evm_db_to_percentage(p_phy_sta_rpt->rxevm[0]), rxsc, p_phy_info); + + num_ss = phydm_rate_to_num_ss(p_dm_odm, p_pktinfo->data_rate); + + odm_parsing_cfo(p_dm_odm, p_pktinfo, p_phy_sta_rpt->cfo_tail, num_ss); + p_dm_odm->dm_fat_table.antsel_rx_keep_0 = p_phy_sta_rpt->antidx_a; + p_dm_odm->dm_fat_table.antsel_rx_keep_1 = p_phy_sta_rpt->antidx_b; + p_dm_odm->dm_fat_table.antsel_rx_keep_2 = p_phy_sta_rpt->antidx_c; + p_dm_odm->dm_fat_table.antsel_rx_keep_3 = p_phy_sta_rpt->antidx_d; + + if (p_pktinfo->is_packet_match_bssid) { + /* + dbg_print("channel = %d, band = %d, l_rxsc = %d, ht_rxsc = %d, rf_mode = %d\n", p_phy_sta_rpt->channel, p_phy_sta_rpt->band, p_phy_sta_rpt->l_rxsc, p_phy_sta_rpt->ht_rxsc, p_phy_sta_rpt->rf_mode); + dbg_print("Antidx A = %d, B = %d, C = %d, D = %d\n", p_phy_sta_rpt->antidx_a, p_phy_sta_rpt->antidx_b, p_phy_sta_rpt->antidx_c, p_phy_sta_rpt->antidx_d); + dbg_print("pwdb A: 0x%x, B: 0x%x, C: 0x%x, D: 0x%x\n", p_phy_sta_rpt->pwdb[0], p_phy_sta_rpt->pwdb[1], p_phy_sta_rpt->pwdb[2], p_phy_sta_rpt->pwdb[3]); + dbg_print("EVM A: %d, B: %d, C: %d, D: %d\n", p_phy_sta_rpt->rxevm[0], p_phy_sta_rpt->rxevm[1], p_phy_sta_rpt->rxevm[2], p_phy_sta_rpt->rxevm[3]); + dbg_print("SNR A: %d, B: %d, C: %d, D: %d\n", p_phy_sta_rpt->rxsnr[0], p_phy_sta_rpt->rxsnr[1], p_phy_sta_rpt->rxsnr[2], p_phy_sta_rpt->rxsnr[3]); + dbg_print("CFO A: %d, B: %d, C: %d, D: %d\n", p_phy_sta_rpt->cfo_tail[0], p_phy_sta_rpt->cfo_tail[1], p_phy_sta_rpt->cfo_tail[2], p_phy_sta_rpt->cfo_tail[3]); + dbg_print("paid = %d, gid = %d, length = %d\n", (p_phy_sta_rpt->paid + (p_phy_sta_rpt->paid_msb<<8)), p_phy_sta_rpt->gid, p_phy_sta_rpt->lsig_length); + dbg_print("ldpc: %d, stbc: %d, bf: %d, gnt_bt: %d, antsw: %d\n", p_phy_sta_rpt->ldpc, p_phy_sta_rpt->stbc, p_phy_sta_rpt->beamformed, p_phy_sta_rpt->gnt_bt, p_phy_sta_rpt->hw_antsw_occu); + dbg_print("NBI: %d, pos: %d\n", p_phy_sta_rpt->nb_intf_flag, (p_phy_sta_rpt->intf_pos + (p_phy_sta_rpt->intf_pos_msb<<8))); + dbg_print("rsvd_0 = %d, rsvd_1 = %d, rsvd_2 = %d, rsvd_3 = %d, rsvd_4 = %d, rsvd_5 = %d\n", p_phy_sta_rpt->rsvd_0, p_phy_sta_rpt->rsvd_1, p_phy_sta_rpt->rsvd_2, p_phy_sta_rpt->rsvd_3, p_phy_sta_rpt->rsvd_4, p_phy_sta_rpt->rsvd_5); + */ + phydm_rx_statistic_cal(p_dm_odm, p_phy_status, p_pktinfo); + } + /* + dbg_print("phydm_get_rx_phy_status_type1 p_pktinfo->is_packet_match_bssid = %d\n", p_pktinfo->is_packet_match_bssid); + dbg_print("p_pktinfo->data_rate = 0x%x\n", p_pktinfo->data_rate); + */ +} + +void +phydm_get_rx_phy_status_type2( + struct PHY_DM_STRUCT *p_dm_odm, + u8 *p_phy_status, + struct _odm_per_pkt_info_ *p_pktinfo, + struct _odm_phy_status_info_ *p_phy_info +) +{ + struct _phy_status_rpt_jaguar2_type2 *p_phy_sta_rpt = (struct _phy_status_rpt_jaguar2_type2 *)p_phy_status; + s8 rx_pwr_db = -120; + u8 i, rxsc, bw = ODM_BW20M, rx_count = 0; + + /* Update OFDM packet counter */ + p_dm_odm->phy_dbg_info.num_qry_phy_status_ofdm++; + + /* Update per-path information */ + for (i = ODM_RF_PATH_A; i < ODM_RF_PATH_MAX_JAGUAR; i++) { + if (p_dm_odm->rx_ant_status & BIT(i)) { + s8 rx_path_pwr_db; + + /* RX path counter */ + rx_count++; + + /* Update per-path information (RSSI_dB RSSI_percentage EVM SNR CFO SQ) */ +#if (RTL8197F_SUPPORT == 1) + if ((p_dm_odm->support_ic_type & ODM_RTL8197F) && (p_phy_sta_rpt->pwdb[i] == 0x7f)) { /*for 97f workaround*/ + + if (i == ODM_RF_PATH_A) { + rx_path_pwr_db = (p_phy_sta_rpt->gain_a) << 1; + rx_path_pwr_db = rx_path_pwr_db - 110; + } else if (i == ODM_RF_PATH_B) { + rx_path_pwr_db = (p_phy_sta_rpt->gain_b) << 1; + rx_path_pwr_db = rx_path_pwr_db - 110; + } else + rx_path_pwr_db = 0; + } else +#endif + rx_path_pwr_db = p_phy_sta_rpt->pwdb[i] - 110; /* per-path pwdb in dB domain */ + + phydm_set_per_path_phy_info(i, rx_path_pwr_db, 0, 0, 0, p_phy_info); + + /* search maximum pwdb */ + if (rx_path_pwr_db > rx_pwr_db) + rx_pwr_db = rx_path_pwr_db; + } + } + + /* mapping RX counter from 1~4 to 0~3 */ + if (rx_count > 0) + p_phy_info->rx_count = rx_count - 1; + + /* Check RX sub-channel */ + if ((p_pktinfo->data_rate > ODM_RATE11M) && (p_pktinfo->data_rate < ODM_RATEMCS0)) + rxsc = p_phy_sta_rpt->l_rxsc; + else + rxsc = p_phy_sta_rpt->ht_rxsc; + + /*STBC or LDPC pkt*/ + p_dm_odm->phy_dbg_info.is_ldpc_pkt = p_phy_sta_rpt->ldpc; + p_dm_odm->phy_dbg_info.is_stbc_pkt = p_phy_sta_rpt->stbc; + + /* Check RX bandwidth */ + /* the BW information of sc=0 is useless, because there is no information of RF mode*/ + + if (p_dm_odm->support_ic_type & ODM_RTL8822B) { + if ((rxsc >= 1) && (rxsc <= 8)) + bw = ODM_BW20M; + else if ((rxsc >= 9) && (rxsc <= 12)) + bw = ODM_BW40M; + else if (rxsc >= 13) + bw = ODM_BW80M; + else + bw = ODM_BW20M; + } else if (p_dm_odm->support_ic_type & (ODM_RTL8197F | ODM_RTL8723D)) { + if (rxsc == 3) + bw = ODM_BW40M; + else if ((rxsc == 1) || (rxsc == 2)) + bw = ODM_BW20M; + else + bw = ODM_BW20M; + } + + /* Update packet information */ + phydm_set_common_phy_info(rx_pwr_db, p_phy_sta_rpt->channel, (bool)p_phy_sta_rpt->beamformed, + false, bw, 0, rxsc, p_phy_info); + +} + +void +phydm_get_rx_phy_status_type5( + u8 *p_phy_status +) +{ +} + +void +phydm_process_rssi_for_dm_new_type( + struct PHY_DM_STRUCT *p_dm_odm, + struct _odm_phy_status_info_ *p_phy_info, + struct _odm_per_pkt_info_ *p_pktinfo +) +{ + s32 undecorated_smoothed_pwdb, accumulate_pwdb; + u32 rssi_ave; + u8 i; + struct sta_info *p_entry; + u8 scaling_factor = 4; + + if (p_pktinfo->station_id >= ODM_ASSOCIATE_ENTRY_NUM) + return; + + p_entry = p_dm_odm->p_odm_sta_info[p_pktinfo->station_id]; + + if (!IS_STA_VALID(p_entry)) + return; + + if ((!p_pktinfo->is_packet_match_bssid))/*data frame only*/ + return; + + if (p_pktinfo->is_packet_beacon) + p_dm_odm->phy_dbg_info.num_qry_beacon_pkt++; + +#if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY)) + if (p_dm_odm->support_ability & ODM_BB_ANT_DIV) + odm_process_rssi_for_ant_div(p_dm_odm, p_phy_info, p_pktinfo); +#endif + +#if (CONFIG_DYNAMIC_RX_PATH == 1) + phydm_process_phy_status_for_dynamic_rx_path(p_dm_odm, p_phy_info, p_pktinfo); + dbg_print("====>\n"); +#endif + + if (p_pktinfo->is_packet_to_self || p_pktinfo->is_packet_beacon) { + u32 RSSI_linear = 0; + + p_dm_odm->rx_rate = p_pktinfo->data_rate; + undecorated_smoothed_pwdb = p_entry->rssi_stat.undecorated_smoothed_pwdb; + accumulate_pwdb = p_dm_odm->accumulate_pwdb[p_pktinfo->station_id]; + p_dm_odm->RSSI_A = p_phy_info->rx_mimo_signal_strength[ODM_RF_PATH_A]; + p_dm_odm->RSSI_B = p_phy_info->rx_mimo_signal_strength[ODM_RF_PATH_B]; + p_dm_odm->RSSI_C = p_phy_info->rx_mimo_signal_strength[ODM_RF_PATH_C]; + p_dm_odm->RSSI_D = p_phy_info->rx_mimo_signal_strength[ODM_RF_PATH_D]; + + for (i = ODM_RF_PATH_A; i < ODM_RF_PATH_MAX_JAGUAR; i++) { + if (p_phy_info->rx_mimo_signal_strength[i] != 0) + RSSI_linear += odm_convert_to_linear(p_phy_info->rx_mimo_signal_strength[i]); + } + + switch (p_phy_info->rx_count + 1) { + case 2: + RSSI_linear = (RSSI_linear >> 1); + break; + case 3: + RSSI_linear = ((RSSI_linear) + (RSSI_linear << 1) + (RSSI_linear << 3)) >> 5; /* RSSI_linear/3 ~ RSSI_linear*11/32 */ + break; + case 4: + RSSI_linear = (RSSI_linear >> 2); + break; + } + rssi_ave = odm_convert_to_db(RSSI_linear); + + if (undecorated_smoothed_pwdb <= 0) { + accumulate_pwdb = (p_phy_info->rx_pwdb_all << scaling_factor); + undecorated_smoothed_pwdb = p_phy_info->rx_pwdb_all; + } else { + accumulate_pwdb = accumulate_pwdb - (accumulate_pwdb >> scaling_factor) + rssi_ave; + undecorated_smoothed_pwdb = (accumulate_pwdb + (1 << (scaling_factor - 1))) >> scaling_factor; + } + + if (p_entry->rssi_stat.undecorated_smoothed_pwdb == -1) + phydm_ra_rssi_rpt_wk(p_dm_odm); + p_entry->rssi_stat.undecorated_smoothed_pwdb = undecorated_smoothed_pwdb; + p_dm_odm->accumulate_pwdb[p_pktinfo->station_id] = accumulate_pwdb; + } +} + +void +phydm_rx_phy_status_new_type( + struct PHY_DM_STRUCT *p_phydm, + u8 *p_phy_status, + struct _odm_per_pkt_info_ *p_pktinfo, + struct _odm_phy_status_info_ *p_phy_info +) +{ + u8 phy_status_type = (*p_phy_status & 0xf); + + /* Memory reset */ + phydm_reset_phy_info(p_phydm, p_phy_info); + + /* Phy status parsing */ + switch (phy_status_type) { + case 0: + phydm_get_rx_phy_status_type0(p_phydm, p_phy_status, p_pktinfo, p_phy_info); + break; + case 1: + phydm_get_rx_phy_status_type1(p_phydm, p_phy_status, p_pktinfo, p_phy_info); + break; + case 2: + phydm_get_rx_phy_status_type2(p_phydm, p_phy_status, p_pktinfo, p_phy_info); + break; + default: + return; + } + + /* Update signal strength to UI, and p_phy_info->rx_pwdb_all is the maximum RSSI of all path */ + p_phy_info->signal_strength = (u8)(odm_signal_scale_mapping(p_phydm, p_phy_info->rx_pwdb_all)); + + /* Calculate average RSSI and smoothed RSSI */ + phydm_process_rssi_for_dm_new_type(p_phydm, p_phy_info, p_pktinfo); + +} +/*==============================================*/ +#endif + +u32 +query_phydm_trx_capability( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u32 value32 = 0xFFFFFFFF; + +#if (RTL8821C_SUPPORT == 1) + if (p_dm_odm->support_ic_type == ODM_RTL8821C) + value32 = query_phydm_trx_capability_8821c(p_dm_odm); +#endif + + return value32; +} + +u32 +query_phydm_stbc_capability( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u32 value32 = 0xFFFFFFFF; + +#if (RTL8821C_SUPPORT == 1) + if (p_dm_odm->support_ic_type == ODM_RTL8821C) + value32 = query_phydm_stbc_capability_8821c(p_dm_odm); +#endif + + return value32; +} + +u32 +query_phydm_ldpc_capability( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u32 value32 = 0xFFFFFFFF; + +#if (RTL8821C_SUPPORT == 1) + if (p_dm_odm->support_ic_type == ODM_RTL8821C) + value32 = query_phydm_ldpc_capability_8821c(p_dm_odm); +#endif + + return value32; +} + +u32 +query_phydm_txbf_parameters( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u32 value32 = 0xFFFFFFFF; + +#if (RTL8821C_SUPPORT == 1) + if (p_dm_odm->support_ic_type == ODM_RTL8821C) + value32 = query_phydm_txbf_parameters_8821c(p_dm_odm); +#endif + + return value32; +} + +u32 +query_phydm_txbf_capability( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + u32 value32 = 0xFFFFFFFF; + +#if (RTL8821C_SUPPORT == 1) + if (p_dm_odm->support_ic_type == ODM_RTL8821C) + value32 = query_phydm_txbf_capability_8821c(p_dm_odm); +#endif + + return value32; +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_hwconfig.h b/drivers/staging/rtl8188eu/hal/phydm_hwconfig.h new file mode 100644 index 000000000000..b1964a125e16 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_hwconfig.h @@ -0,0 +1,547 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + + +#ifndef __HALHWOUTSRC_H__ +#define __HALHWOUTSRC_H__ + + +/*--------------------------Define -------------------------------------------*/ +#define CCK_RSSI_INIT_COUNT 5 + +#define RA_RSSI_STATE_INIT 0 +#define RA_RSSI_STATE_SEND 1 +#define RA_RSSI_STATE_HOLD 2 + +#define CFO_HW_RPT_2_MHZ(val) ((val<<1) + (val>>1)) +/* ((X* 3125) / 10)>>7 = (X*10)>>2 = X*2.5 = X<<1 + X>>1 */ + +#define AGC_DIFF_CONFIG_MP(ic, band) (odm_read_and_config_mp_##ic##_agc_tab_diff(p_dm_odm, array_mp_##ic##_agc_tab_diff_##band, \ + sizeof(array_mp_##ic##_agc_tab_diff_##band)/sizeof(u32))) +#define AGC_DIFF_CONFIG_TC(ic, band) (odm_read_and_config_tc_##ic##_agc_tab_diff(p_dm_odm, array_tc_##ic##_agc_tab_diff_##band, \ + sizeof(array_tc_##ic##_agc_tab_diff_##band)/sizeof(u32))) + +#define AGC_DIFF_CONFIG(ic, band) do {\ + if (p_dm_odm->is_mp_chip)\ + AGC_DIFF_CONFIG_MP(ic, band);\ + else\ + AGC_DIFF_CONFIG_TC(ic, band);\ + } while (0) + + +/* ************************************************************ + * structure and define + * ************************************************************ */ + +__PACK struct _phy_rx_agc_info { +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 gain: 7, trsw: 1; +#else + u8 trsw: 1, gain: 7; +#endif +}; + +__PACK struct _phy_status_rpt_8192cd { + struct _phy_rx_agc_info path_agc[2]; + u8 ch_corr[2]; + u8 cck_sig_qual_ofdm_pwdb_all; + u8 cck_agc_rpt_ofdm_cfosho_a; + u8 cck_rpt_b_ofdm_cfosho_b; + u8 rsvd_1;/*ch_corr_msb;*/ + u8 noise_power_db_msb; + s8 path_cfotail[2]; + u8 pcts_mask[2]; + s8 stream_rxevm[2]; + u8 path_rxsnr[2]; + u8 noise_power_db_lsb; + u8 rsvd_2[3]; + u8 stream_csi[2]; + u8 stream_target_csi[2]; + s8 sig_evm; + u8 rsvd_3; + +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 antsel_rx_keep_2: 1; /*ex_intf_flg:1;*/ + u8 sgi_en: 1; + u8 rxsc: 2; + u8 idle_long: 1; + u8 r_ant_train_en: 1; + u8 ant_sel_b: 1; + u8 ant_sel: 1; +#else /*_BIG_ENDIAN_ */ + u8 ant_sel: 1; + u8 ant_sel_b: 1; + u8 r_ant_train_en: 1; + u8 idle_long: 1; + u8 rxsc: 2; + u8 sgi_en: 1; + u8 antsel_rx_keep_2: 1;/*ex_intf_flg:1;*/ +#endif +}; + + +struct _phy_status_rpt_8812 { + /* DWORD 0*/ + u8 gain_trsw[2]; /*path-A and path-B {TRSW, gain[6:0] }*/ + u8 chl_num_LSB; /*channel number[7:0]*/ +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 chl_num_MSB: 2; /*channel number[9:8]*/ + u8 sub_chnl: 4; /*sub-channel location[3:0]*/ + u8 r_RFMOD: 2; /*RF mode[1:0]*/ +#else /*_BIG_ENDIAN_ */ + u8 r_RFMOD: 2; + u8 sub_chnl: 4; + u8 chl_num_MSB: 2; +#endif + + /* DWORD 1*/ + u8 pwdb_all; /*CCK signal quality / OFDM pwdb all*/ + s8 cfosho[2]; /*DW1 byte 1 DW1 byte2 CCK AGC report and CCK_BB_Power / OFDM path-A and path-B short CFO*/ +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + /*this should be checked again because the definition of 8812 and 8814 is different*/ + /* u8 r_cck_rx_enable_pathc:2; cck rx enable pathc[1:0]*/ + /* u8 cck_rx_path:4; cck rx path[3:0]*/ + u8 resvd_0: 6; + u8 bt_RF_ch_MSB: 2; /*8812A:2'b0 8814A: bt rf channel keep[7:6]*/ +#else /*_BIG_ENDIAN_*/ + u8 bt_RF_ch_MSB: 2; + u8 resvd_0: 6; +#endif + + /* DWORD 2*/ +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 ant_div_sw_a: 1; /*8812A: ant_div_sw_a 8814A: 1'b0*/ + u8 ant_div_sw_b: 1; /*8812A: ant_div_sw_b 8814A: 1'b0*/ + u8 bt_RF_ch_LSB: 6; /*8812A: 6'b0 8814A: bt rf channel keep[5:0]*/ +#else /*_BIG_ENDIAN_ */ + u8 bt_RF_ch_LSB: 6; + u8 ant_div_sw_b: 1; + u8 ant_div_sw_a: 1; +#endif + s8 cfotail[2]; /*DW2 byte 1 DW2 byte 2 path-A and path-B CFO tail*/ + u8 PCTS_MSK_RPT_0; /*PCTS mask report[7:0]*/ + u8 PCTS_MSK_RPT_1; /*PCTS mask report[15:8]*/ + + /* DWORD 3*/ + s8 rxevm[2]; /*DW3 byte 1 DW3 byte 2 stream 1 and stream 2 RX EVM*/ + s8 rxsnr[2]; /*DW3 byte 3 DW4 byte 0 path-A and path-B RX SNR*/ + + /* DWORD 4*/ + u8 PCTS_MSK_RPT_2; /*PCTS mask report[23:16]*/ +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 PCTS_MSK_RPT_3: 6; /*PCTS mask report[29:24]*/ + u8 pcts_rpt_valid: 1; /*pcts_rpt_valid*/ + u8 resvd_1: 1; /*1'b0*/ +#else /*_BIG_ENDIAN_*/ + u8 resvd_1: 1; + u8 pcts_rpt_valid: 1; + u8 PCTS_MSK_RPT_3: 6; +#endif + s8 rxevm_cd[2]; /*DW 4 byte 3 DW5 byte 0 8812A: 16'b0 8814A: stream 3 and stream 4 RX EVM*/ + + /* DWORD 5*/ + u8 csi_current[2]; /*DW5 byte 1 DW5 byte 2 8812A: stream 1 and 2 CSI 8814A: path-C and path-D RX SNR*/ + u8 gain_trsw_cd[2]; /*DW5 byte 3 DW6 byte 0 path-C and path-D {TRSW, gain[6:0] }*/ + + /* DWORD 6*/ + s8 sigevm; /*signal field EVM*/ +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 antidx_antc: 3; /*8812A: 3'b0 8814A: antidx_antc[2:0]*/ + u8 antidx_antd: 3; /*8812A: 3'b0 8814A: antidx_antd[2:0]*/ + u8 dpdt_ctrl_keep: 1; /*8812A: 1'b0 8814A: dpdt_ctrl_keep*/ + u8 GNT_BT_keep: 1; /*8812A: 1'b0 8814A: GNT_BT_keep*/ +#else /*_BIG_ENDIAN_*/ + u8 GNT_BT_keep: 1; + u8 dpdt_ctrl_keep: 1; + u8 antidx_antd: 3; + u8 antidx_antc: 3; +#endif +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 antidx_anta: 3; /*antidx_anta[2:0]*/ + u8 antidx_antb: 3; /*antidx_antb[2:0]*/ + u8 hw_antsw_occur: 2; /*1'b0*/ +#else /*_BIG_ENDIAN_*/ + u8 hw_antsw_occur: 2; + u8 antidx_antb: 3; + u8 antidx_anta: 3; +#endif +}; + +void +phydm_reset_rssi_for_dm( + struct PHY_DM_STRUCT *p_dm_odm, + u8 station_id +); + +void +odm_init_rssi_for_dm( + struct PHY_DM_STRUCT *p_dm_odm +); + +void +odm_phy_status_query( + struct PHY_DM_STRUCT *p_dm_odm, + struct _odm_phy_status_info_ *p_phy_info, + u8 *p_phy_status, + struct _odm_per_pkt_info_ *p_pktinfo +); + +void +odm_mac_status_query( + struct PHY_DM_STRUCT *p_dm_odm, + u8 *p_mac_status, + u8 mac_id, + bool is_packet_match_bssid, + bool is_packet_to_self, + bool is_packet_beacon +); + +enum hal_status +odm_config_rf_with_tx_pwr_track_header_file( + struct PHY_DM_STRUCT *p_dm_odm +); + +enum hal_status +odm_config_rf_with_header_file( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_rf_config_type config_type, + enum odm_rf_radio_path_e e_rf_path +); + +enum hal_status +odm_config_bb_with_header_file( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_bb_config_type config_type +); + +enum hal_status +odm_config_mac_with_header_file( + struct PHY_DM_STRUCT *p_dm_odm +); + +enum hal_status +odm_config_fw_with_header_file( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_fw_config_type config_type, + u8 *p_firmware, + u32 *p_size +); + +u32 +odm_get_hw_img_version( + struct PHY_DM_STRUCT *p_dm_odm +); + +s32 +odm_signal_scale_mapping( + struct PHY_DM_STRUCT *p_dm_odm, + s32 curr_sig +); + +#if (ODM_PHY_STATUS_NEW_TYPE_SUPPORT == 1) +/*For 8822B only!! need to move to FW finally */ +/*==============================================*/ +void +phydm_rx_phy_status_new_type( + struct PHY_DM_STRUCT *p_phydm, + u8 *p_phy_status, + struct _odm_per_pkt_info_ *p_pktinfo, + struct _odm_phy_status_info_ *p_phy_info +); + +bool +phydm_query_is_mu_api( + struct PHY_DM_STRUCT *p_phydm, + u8 ppdu_idx, + u8 *p_data_rate, + u8 *p_gid +); + +struct _phy_status_rpt_jaguar2_type0 { + /* DW0 */ + u8 page_num; + u8 pwdb; +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 gain: 6; + u8 rsvd_0: 1; + u8 trsw: 1; +#else + u8 trsw: 1; + u8 rsvd_0: 1; + u8 gain: 6; +#endif + u8 rsvd_1; + + /* DW1 */ + u8 rsvd_2; +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 rxsc: 4; + u8 agc_table: 4; +#else + u8 agc_table: 4; + u8 rxsc: 4; +#endif + u8 channel; + u8 band; + + /* DW2 */ + u16 length; +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 antidx_a: 3; + u8 antidx_b: 3; + u8 rsvd_3: 2; + u8 antidx_c: 3; + u8 antidx_d: 3; + u8 rsvd_4:2; +#else + u8 rsvd_3: 2; + u8 antidx_b: 3; + u8 antidx_a: 3; + u8 rsvd_4:2; + u8 antidx_d: 3; + u8 antidx_c: 3; +#endif + + /* DW3 */ + u8 signal_quality; +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 vga:5; + u8 lna_l:3; + u8 bb_power:6; + u8 rsvd_9:1; + u8 lna_h:1; +#else + u8 lna_l:3; + u8 vga:5; + u8 lna_h:1; + u8 rsvd_9:1; + u8 bb_power:6; +#endif + u8 rsvd_5; + + /* DW4 */ + u32 rsvd_6; + + /* DW5 */ + u32 rsvd_7; + + /* DW6 */ + u32 rsvd_8; +}; + +struct _phy_status_rpt_jaguar2_type1 { + /* DW0 and DW1 */ + u8 page_num; + u8 pwdb[4]; +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 l_rxsc: 4; + u8 ht_rxsc: 4; +#else + u8 ht_rxsc: 4; + u8 l_rxsc: 4; +#endif + u8 channel; +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 band: 2; + u8 rsvd_0: 1; + u8 hw_antsw_occu: 1; + u8 gnt_bt: 1; + u8 ldpc: 1; + u8 stbc: 1; + u8 beamformed: 1; +#else + u8 beamformed: 1; + u8 stbc: 1; + u8 ldpc: 1; + u8 gnt_bt: 1; + u8 hw_antsw_occu: 1; + u8 rsvd_0: 1; + u8 band: 2; +#endif + + /* DW2 */ + u16 lsig_length; +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 antidx_a: 3; + u8 antidx_b: 3; + u8 rsvd_1: 2; + u8 antidx_c: 3; + u8 antidx_d: 3; + u8 rsvd_2: 2; +#else + u8 rsvd_1: 2; + u8 antidx_b: 3; + u8 antidx_a: 3; + u8 rsvd_2: 2; + u8 antidx_d: 3; + u8 antidx_c: 3; +#endif + + /* DW3 */ + u8 paid; +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 paid_msb: 1; + u8 gid: 6; + u8 rsvd_3: 1; +#else + u8 rsvd_3: 1; + u8 gid: 6; + u8 paid_msb: 1; +#endif + u8 intf_pos; +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 intf_pos_msb: 1; + u8 rsvd_4: 2; + u8 nb_intf_flag: 1; + u8 rf_mode: 2; + u8 rsvd_5: 2; +#else + u8 rsvd_5: 2; + u8 rf_mode: 2; + u8 nb_intf_flag: 1; + u8 rsvd_4: 2; + u8 intf_pos_msb: 1; +#endif + + /* DW4 */ + s8 rxevm[4]; /* s(8,1) */ + + /* DW5 */ + s8 cfo_tail[4]; /* s(8,7) */ + + /* DW6 */ + s8 rxsnr[4]; /* s(8,1) */ +}; + +struct _phy_status_rpt_jaguar2_type2 { + /* DW0 ane DW1 */ + u8 page_num; + u8 pwdb[4]; +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 l_rxsc: 4; + u8 ht_rxsc: 4; +#else + u8 ht_rxsc: 4; + u8 l_rxsc: 4; +#endif + u8 channel; +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 band: 2; + u8 rsvd_0: 1; + u8 hw_antsw_occu: 1; + u8 gnt_bt: 1; + u8 ldpc: 1; + u8 stbc: 1; + u8 beamformed: 1; +#else + u8 beamformed: 1; + u8 stbc: 1; + u8 ldpc: 1; + u8 gnt_bt: 1; + u8 hw_antsw_occu: 1; + u8 rsvd_0: 1; + u8 band: 2; +#endif + + /* DW2 */ +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 shift_l_map: 6; + u8 rsvd_1: 2; +#else + u8 rsvd_1: 2; + u8 shift_l_map: 6; +#endif + u8 cnt_pw2cca; +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 agc_table_a: 4; + u8 agc_table_b: 4; + u8 agc_table_c: 4; + u8 agc_table_d: 4; +#else + u8 agc_table_b: 4; + u8 agc_table_a: 4; + u8 agc_table_d: 4; + u8 agc_table_c: 4; +#endif + + /* DW3 ~ DW6*/ + u8 cnt_cca2agc_rdy; +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 gain_a: 6; + u8 rsvd_2: 1; + u8 trsw_a: 1; + u8 gain_b: 6; + u8 rsvd_3: 1; + u8 trsw_b: 1; + u8 gain_c: 6; + u8 rsvd_4: 1; + u8 trsw_c: 1; + u8 gain_d: 6; + u8 rsvd_5: 1; + u8 trsw_d: 1; + u8 aagc_step_a: 2; + u8 aagc_step_b: 2; + u8 aagc_step_c: 2; + u8 aagc_step_d: 2; +#else + u8 trsw_a: 1; + u8 rsvd_2: 1; + u8 gain_a: 6; + u8 trsw_b: 1; + u8 rsvd_3: 1; + u8 gain_b: 6; + u8 trsw_c: 1; + u8 rsvd_4: 1; + u8 gain_c: 6; + u8 trsw_d: 1; + u8 rsvd_5: 1; + u8 gain_d: 6; + u8 aagc_step_d: 2; + u8 aagc_step_c: 2; + u8 aagc_step_b: 2; + u8 aagc_step_a: 2; +#endif + u8 ht_aagc_gain[4]; + u8 dagc_gain[4]; +#if (ODM_ENDIAN_TYPE == ODM_ENDIAN_LITTLE) + u8 counter: 6; + u8 rsvd_6: 2; + u8 syn_count: 5; + u8 rsvd_7:3; +#else + u8 rsvd_6: 2; + u8 counter: 6; + u8 rsvd_7:3; + u8 syn_count: 5; +#endif +}; +/*==============================================*/ +#endif /*#if (ODM_PHY_STATUS_NEW_TYPE_SUPPORT == 1)*/ + +u32 +query_phydm_trx_capability( + struct PHY_DM_STRUCT *p_dm_odm +); + +u32 +query_phydm_stbc_capability( + struct PHY_DM_STRUCT *p_dm_odm +); + +u32 +query_phydm_ldpc_capability( + struct PHY_DM_STRUCT *p_dm_odm +); + +u32 +query_phydm_txbf_parameters( + struct PHY_DM_STRUCT *p_dm_odm +); + +u32 +query_phydm_txbf_capability( + struct PHY_DM_STRUCT *p_dm_odm +); + +#endif /*#ifndef __HALHWOUTSRC_H__*/ diff --git a/drivers/staging/rtl8188eu/hal/phydm_interface.c b/drivers/staging/rtl8188eu/hal/phydm_interface.c new file mode 100644 index 000000000000..e4a18e55d350 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_interface.c @@ -0,0 +1,451 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* ************************************************************ + * include files + * ************************************************************ */ + +#include "mp_precomp.h" +#include "phydm_precomp.h" + +/* + * ODM IO Relative API. + * */ + +u8 +odm_read_1byte( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr +) +{ + struct _ADAPTER *adapter = p_dm_odm->adapter; + + return rtw_read8(adapter, reg_addr); +} + +u16 +odm_read_2byte( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr +) +{ + struct _ADAPTER *adapter = p_dm_odm->adapter; + + return rtw_read16(adapter, reg_addr); +} + +u32 +odm_read_4byte( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr +) +{ + struct _ADAPTER *adapter = p_dm_odm->adapter; + + return rtw_read32(adapter, reg_addr); +} + +void +odm_write_1byte( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr, + u8 data +) +{ + struct _ADAPTER *adapter = p_dm_odm->adapter; + + rtw_write8(adapter, reg_addr, data); +} + + +void +odm_write_2byte( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr, + u16 data +) +{ + struct _ADAPTER *adapter = p_dm_odm->adapter; + + rtw_write16(adapter, reg_addr, data); +} + +void +odm_write_4byte( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr, + u32 data +) +{ + struct _ADAPTER *adapter = p_dm_odm->adapter; + + rtw_write32(adapter, reg_addr, data); +} + +void +odm_set_mac_reg( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr, + u32 bit_mask, + u32 data +) +{ + phy_set_bb_reg(p_dm_odm->adapter, reg_addr, bit_mask, data); +} + +u32 +odm_get_mac_reg( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr, + u32 bit_mask +) +{ + return phy_query_mac_reg(p_dm_odm->adapter, reg_addr, bit_mask); +} + +void +odm_set_bb_reg( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr, + u32 bit_mask, + u32 data +) +{ + phy_set_bb_reg(p_dm_odm->adapter, reg_addr, bit_mask, data); +} + +u32 +odm_get_bb_reg( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr, + u32 bit_mask +) +{ + return phy_query_bb_reg(p_dm_odm->adapter, reg_addr, bit_mask); +} + +void +odm_set_rf_reg( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_rf_radio_path_e e_rf_path, + u32 reg_addr, + u32 bit_mask, + u32 data +) +{ + phy_set_rf_reg(p_dm_odm->adapter, e_rf_path, reg_addr, bit_mask, data); +} + +u32 +odm_get_rf_reg( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_rf_radio_path_e e_rf_path, + u32 reg_addr, + u32 bit_mask +) +{ + return phy_query_rf_reg(p_dm_odm->adapter, e_rf_path, reg_addr, bit_mask); +} + +/* + * ODM Memory relative API. + * */ +void +odm_allocate_memory( + struct PHY_DM_STRUCT *p_dm_odm, + void **p_ptr, + u32 length +) +{ + *p_ptr = rtw_zvmalloc(length); +} + +/* length could be ignored, used to detect memory leakage. */ +void +odm_free_memory( + struct PHY_DM_STRUCT *p_dm_odm, + void *p_ptr, + u32 length +) +{ + rtw_vmfree(p_ptr, length); +} + +void +odm_move_memory( + struct PHY_DM_STRUCT *p_dm_odm, + void *p_dest, + void *p_src, + u32 length +) +{ + memcpy(p_dest, p_src, length); +} + +void odm_memory_set( + struct PHY_DM_STRUCT *p_dm_odm, + void *pbuf, + s8 value, + u32 length +) +{ + memset(pbuf, value, length); +} + +s32 odm_compare_memory( + struct PHY_DM_STRUCT *p_dm_odm, + void *p_buf1, + void *p_buf2, + u32 length +) +{ + return !memcmp(p_buf1, p_buf2, length); +} + +/* + * ODM MISC relative API. + * */ +void +odm_acquire_spin_lock( + struct PHY_DM_STRUCT *p_dm_odm, + enum rt_spinlock_type type +) +{ + struct _ADAPTER *adapter = p_dm_odm->adapter; + + rtw_odm_acquirespinlock(adapter, type); +} + +void +odm_release_spin_lock( + struct PHY_DM_STRUCT *p_dm_odm, + enum rt_spinlock_type type +) +{ + struct _ADAPTER *adapter = p_dm_odm->adapter; + rtw_odm_releasespinlock(adapter, type); +} + +/* + * ODM Timer relative API. + * */ +void +odm_stall_execution( + u32 us_delay +) +{ + rtw_udelay_os(us_delay); +} + +void +ODM_delay_ms(u32 ms) +{ + rtw_mdelay_os(ms); +} + +void +ODM_delay_us(u32 us) +{ + rtw_udelay_os(us); +} + +void +ODM_sleep_ms(u32 ms) +{ + rtw_msleep_os(ms); +} + +void +ODM_sleep_us(u32 us) +{ + rtw_usleep_os(us); +} + +void +odm_set_timer( + struct PHY_DM_STRUCT *p_dm_odm, + struct timer_list *p_timer, + u32 ms_delay +) +{ + _set_timer(p_timer, ms_delay); /* ms */ +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) +void +odm_initialize_timer( + struct PHY_DM_STRUCT *p_dm_odm, + struct timer_list *p_timer, + void *call_back_func, + void *p_context, + const char *sz_id +) +{ + struct _ADAPTER *adapter = p_dm_odm->adapter; + _init_timer(p_timer, adapter->pnetdev, call_back_func, p_dm_odm); +} +#endif + +void +odm_cancel_timer( + struct PHY_DM_STRUCT *p_dm_odm, + struct timer_list *p_timer +) +{ + _cancel_timer_ex(p_timer); +} + +void +odm_release_timer( + struct PHY_DM_STRUCT *p_dm_odm, + struct timer_list *p_timer +) +{ +} + +static u8 +phydm_trans_h2c_id( + struct PHY_DM_STRUCT *p_dm_odm, + u8 phydm_h2c_id +) +{ + u8 platform_h2c_id = phydm_h2c_id; + + switch (phydm_h2c_id) { + /* 1 [0] */ + case ODM_H2C_RSSI_REPORT: + platform_h2c_id = H2C_RSSI_SETTING; + break; + /* 1 [3] */ + case ODM_H2C_WIFI_CALIBRATION: + break; + /* 1 [4] */ + case ODM_H2C_IQ_CALIBRATION: + break; + /* 1 [5] */ + case ODM_H2C_RA_PARA_ADJUST: + break; + /* 1 [6] */ + case PHYDM_H2C_DYNAMIC_TX_PATH: + break; + /* [7]*/ + case PHYDM_H2C_FW_TRACE_EN: + platform_h2c_id = 0x49; + break; + case PHYDM_H2C_TXBF: + break; + case PHYDM_H2C_MU: + break; + default: + platform_h2c_id = phydm_h2c_id; + break; + } + return platform_h2c_id; +} + +/*ODM FW relative API.*/ + +void +odm_fill_h2c_cmd( + struct PHY_DM_STRUCT *p_dm_odm, + u8 phydm_h2c_id, + u32 cmd_len, + u8 *p_cmd_buffer +) +{ + struct _ADAPTER *adapter = p_dm_odm->adapter; + u8 platform_h2c_id; + + platform_h2c_id = phydm_trans_h2c_id(p_dm_odm, phydm_h2c_id); + + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, ("[H2C] platform_h2c_id = ((0x%x))\n", platform_h2c_id)); + + rtw_hal_fill_h2c_cmd(adapter, platform_h2c_id, cmd_len, p_cmd_buffer); +} + +u8 +phydm_c2H_content_parsing( + void *p_dm_void, + u8 c2h_cmd_id, + u8 c2h_cmd_len, + u8 *tmp_buf +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 extend_c2h_sub_id = 0; + u8 find_c2h_cmd = true; + + switch (c2h_cmd_id) { + case PHYDM_C2H_DBG: + phydm_fw_trace_handler(p_dm_odm, tmp_buf, c2h_cmd_len); + break; + case PHYDM_C2H_RA_RPT: + phydm_c2h_ra_report_handler(p_dm_odm, tmp_buf, c2h_cmd_len); + break; + case PHYDM_C2H_RA_PARA_RPT: + odm_c2h_ra_para_report_handler(p_dm_odm, tmp_buf, c2h_cmd_len); + break; + case PHYDM_C2H_DYNAMIC_TX_PATH_RPT: + if (p_dm_odm->support_ic_type & (ODM_RTL8814A)) + phydm_c2h_dtp_handler(p_dm_odm, tmp_buf, c2h_cmd_len); + break; + case PHYDM_C2H_IQK_FINISH: + break; + case PHYDM_C2H_DBG_CODE: + phydm_fw_trace_handler_code(p_dm_odm, tmp_buf, c2h_cmd_len); + break; + + case PHYDM_C2H_EXTEND: + extend_c2h_sub_id = tmp_buf[0]; + if (extend_c2h_sub_id == PHYDM_EXTEND_C2H_DBG_PRINT) + phydm_fw_trace_handler_8051(p_dm_odm, tmp_buf, c2h_cmd_len); + + break; + default: + find_c2h_cmd = false; + break; + } + return find_c2h_cmd; +} + +u64 +odm_get_current_time( + struct PHY_DM_STRUCT *p_dm_odm +) +{ + return (u64)jiffies; +} + +u64 +odm_get_progressing_time( + struct PHY_DM_STRUCT *p_dm_odm, + u64 start_time +) +{ + return rtw_get_passing_time_ms((u32)start_time); +} + +void +phydm_set_hw_reg_handler_interface ( + struct PHY_DM_STRUCT *p_dm_odm, + u8 RegName, + u8 *val + ) +{ + struct _ADAPTER *adapter = p_dm_odm->adapter; + + adapter->hal_func.set_hw_reg_handler(adapter, RegName, val); +} + +void +phydm_get_hal_def_var_handler_interface ( + struct PHY_DM_STRUCT *p_dm_odm, + enum _HAL_DEF_VARIABLE e_variable, + void *p_value + ) +{ + struct _ADAPTER *adapter = p_dm_odm->adapter; + + adapter->hal_func.get_hal_def_var_handler(adapter, e_variable, p_value); +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_interface.h b/drivers/staging/rtl8188eu/hal/phydm_interface.h new file mode 100644 index 000000000000..232da6f9d606 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_interface.h @@ -0,0 +1,351 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + + +#ifndef __ODM_INTERFACE_H__ +#define __ODM_INTERFACE_H__ + +#define INTERFACE_VERSION "1.1" /*2015.07.29 YuChen*/ + +/* + * =========== Constant/Structure/Enum/... Define + * */ + + + +/* + * =========== Macro Define + * */ + +#define _reg_all(_name) ODM_##_name +#define _reg_ic(_name, _ic) ODM_##_name##_ic +#define _bit_all(_name) BIT_##_name +#define _bit_ic(_name, _ic) BIT_##_name##_ic + +/* _cat: implemented by Token-Passing Operator. */ + +/*=================================== + +#define ODM_REG_DIG_11N 0xC50 +#define ODM_REG_DIG_11AC 0xDDD + +ODM_REG(DIG, _pdm_odm) +=====================================*/ + +#define _reg_11N(_name) ODM_REG_##_name##_11N +#define _reg_11AC(_name) ODM_REG_##_name##_11AC +#define _bit_11N(_name) ODM_BIT_##_name##_11N +#define _bit_11AC(_name) ODM_BIT_##_name##_11AC + +#ifdef __ECOS +#define _rtk_cat(_name, _ic_type, _func) \ + (\ + ((_ic_type) & ODM_IC_11N_SERIES) ? _func##_11N(_name) : \ + _func##_11AC(_name) \ + ) +#else + +#define _cat(_name, _ic_type, _func) \ + (\ + ((_ic_type) & ODM_IC_11N_SERIES) ? _func##_11N(_name) : \ + _func##_11AC(_name) \ + ) +#endif +/* + * only sample code + *#define _cat(_name, _ic_type, _func) \ + * ( \ + * ((_ic_type) & ODM_RTL8188E) ? _func##_ic(_name, _8188E) : \ + * _func##_ic(_name, _8195) \ + * ) + */ + +/* _name: name of register or bit. + * Example: "ODM_REG(R_A_AGC_CORE1, p_dm_odm)" + * gets "ODM_R_A_AGC_CORE1" or "ODM_R_A_AGC_CORE1_8192C", depends on support_ic_type. */ +#ifdef __ECOS + #define ODM_REG(_name, _pdm_odm) _rtk_cat(_name, _pdm_odm->support_ic_type, _reg) + #define ODM_BIT(_name, _pdm_odm) _rtk_cat(_name, _pdm_odm->support_ic_type, _bit) +#else + #define ODM_REG(_name, _pdm_odm) _cat(_name, _pdm_odm->support_ic_type, _reg) + #define ODM_BIT(_name, _pdm_odm) _cat(_name, _pdm_odm->support_ic_type, _bit) +#endif +enum phydm_h2c_cmd { + PHYDM_H2C_TXBF = 0x41, + ODM_H2C_RSSI_REPORT = 0x42, + ODM_H2C_IQ_CALIBRATION = 0x45, + ODM_H2C_RA_PARA_ADJUST = 0x47, + PHYDM_H2C_DYNAMIC_TX_PATH = 0x48, + PHYDM_H2C_FW_TRACE_EN = 0x49, + ODM_H2C_WIFI_CALIBRATION = 0x6d, + PHYDM_H2C_MU = 0x4a, + ODM_MAX_H2CCMD +}; + +enum phydm_c2h_evt { + PHYDM_C2H_DBG = 0, + PHYDM_C2H_LB = 1, + PHYDM_C2H_XBF = 2, + PHYDM_C2H_TX_REPORT = 3, + PHYDM_C2H_INFO = 9, + PHYDM_C2H_BT_MP = 11, + PHYDM_C2H_RA_RPT = 12, + PHYDM_C2H_RA_PARA_RPT = 14, + PHYDM_C2H_DYNAMIC_TX_PATH_RPT = 15, + PHYDM_C2H_IQK_FINISH = 17, /*0x11*/ + PHYDM_C2H_DBG_CODE = 0xFE, + PHYDM_C2H_EXTEND = 0xFF, +}; + +enum phydm_extend_c2h_evt { + PHYDM_EXTEND_C2H_DBG_PRINT = 0 + +}; + + +/* + * =========== Extern Variable ??? It should be forbidden. + * */ + + +/* + * =========== EXtern Function Prototype + * */ + + +u8 +odm_read_1byte( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr +); + +u16 +odm_read_2byte( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr +); + +u32 +odm_read_4byte( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr +); + +void +odm_write_1byte( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr, + u8 data +); + +void +odm_write_2byte( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr, + u16 data +); + +void +odm_write_4byte( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr, + u32 data +); + +void +odm_set_mac_reg( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr, + u32 bit_mask, + u32 data +); + +u32 +odm_get_mac_reg( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr, + u32 bit_mask +); + +void +odm_set_bb_reg( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr, + u32 bit_mask, + u32 data +); + +u32 +odm_get_bb_reg( + struct PHY_DM_STRUCT *p_dm_odm, + u32 reg_addr, + u32 bit_mask +); + +void +odm_set_rf_reg( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_rf_radio_path_e e_rf_path, + u32 reg_addr, + u32 bit_mask, + u32 data +); + +u32 +odm_get_rf_reg( + struct PHY_DM_STRUCT *p_dm_odm, + enum odm_rf_radio_path_e e_rf_path, + u32 reg_addr, + u32 bit_mask +); + + +/* + * Memory Relative Function. + * */ +void +odm_allocate_memory( + struct PHY_DM_STRUCT *p_dm_odm, + void **p_ptr, + u32 length +); +void +odm_free_memory( + struct PHY_DM_STRUCT *p_dm_odm, + void *p_ptr, + u32 length +); + +void +odm_move_memory( + struct PHY_DM_STRUCT *p_dm_odm, + void *p_dest, + void *p_src, + u32 length +); + +s32 odm_compare_memory( + struct PHY_DM_STRUCT *p_dm_odm, + void *p_buf1, + void *p_buf2, + u32 length +); + +void odm_memory_set +(struct PHY_DM_STRUCT *p_dm_odm, + void *pbuf, + s8 value, + u32 length); + +/* + * ODM MISC-spin lock relative API. + * */ +void +odm_acquire_spin_lock( + struct PHY_DM_STRUCT *p_dm_odm, + enum rt_spinlock_type type +); + +void +odm_release_spin_lock( + struct PHY_DM_STRUCT *p_dm_odm, + enum rt_spinlock_type type +); + +/* + * ODM Timer relative API. + * */ +void +odm_stall_execution( + u32 us_delay +); + +void +ODM_delay_ms(u32 ms); + + + +void +ODM_delay_us(u32 us); + +void +ODM_sleep_ms(u32 ms); + +void +ODM_sleep_us(u32 us); + +void +odm_set_timer( + struct PHY_DM_STRUCT *p_dm_odm, + struct timer_list *p_timer, + u32 ms_delay +); + +void +odm_initialize_timer( + struct PHY_DM_STRUCT *p_dm_odm, + struct timer_list *p_timer, + void *call_back_func, + void *p_context, + const char *sz_id +); + +void +odm_cancel_timer( + struct PHY_DM_STRUCT *p_dm_odm, + struct timer_list *p_timer +); + +void +odm_release_timer( + struct PHY_DM_STRUCT *p_dm_odm, + struct timer_list *p_timer +); + +/* + * ODM FW relative API. + * */ +void +odm_fill_h2c_cmd( + struct PHY_DM_STRUCT *p_dm_odm, + u8 element_id, + u32 cmd_len, + u8 *p_cmd_buffer +); + +u8 +phydm_c2H_content_parsing( + void *p_dm_void, + u8 c2h_cmd_id, + u8 c2h_cmd_len, + u8 *tmp_buf +); + +u64 +odm_get_current_time( + struct PHY_DM_STRUCT *p_dm_odm +); + +u64 +odm_get_progressing_time( + struct PHY_DM_STRUCT *p_dm_odm, + u64 start_time +); + +void +phydm_set_hw_reg_handler_interface ( + struct PHY_DM_STRUCT *p_dm_odm, + u8 reg_Name, + u8 *val + ); + +void +phydm_get_hal_def_var_handler_interface ( + struct PHY_DM_STRUCT *p_dm_odm, + enum _HAL_DEF_VARIABLE e_variable, + void *p_value +); + +#endif /* __ODM_INTERFACE_H__ */ + diff --git a/drivers/staging/rtl8188eu/hal/phydm_iqk.h b/drivers/staging/rtl8188eu/hal/phydm_iqk.h new file mode 100644 index 000000000000..2c6338124746 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_iqk.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDMIQK_H__ +#define __PHYDMIQK_H__ + +/*--------------------------Define Parameters-------------------------------*/ +#define LOK_delay 1 +#define WBIQK_delay 10 +#define TX_IQK 0 +#define RX_IQK 1 +#define TXIQK 0 +#define RXIQK1 1 +#define RXIQK2 2 +#define kcount_limit_80m 2 +#define kcount_limit_others 4 +#define rxiqk_gs_limit 4 + +#define NUM 4 +/*---------------------------End Define Parameters-------------------------------*/ + +struct _IQK_INFORMATION { + bool LOK_fail[NUM]; + bool IQK_fail[2][NUM]; + u32 iqc_matrix[2][NUM]; + u8 iqk_times; + u32 rf_reg18; + u32 lna_idx; + u8 rxiqk_step; + u8 tmp1bcc; + u8 kcount; + + u32 iqk_channel[2]; + bool IQK_fail_report[2][4][2]; /*channel/path/TRX(TX:0, RX:1) */ + u32 IQK_CFIR_real[2][4][2][8]; /*channel / path / TRX(TX:0, RX:1) / CFIR_real*/ + u32 IQK_CFIR_imag[2][4][2][8]; /*channel / path / TRX(TX:0, RX:1) / CFIR_imag*/ + u8 retry_count[2][4][3]; /* channel / path / (TXK:0, RXK1:1, RXK2:2) */ + u8 gs_retry_count[2][4][2]; /* channel / path / (GSRXK1:0, GSRXK2:1) */ + u8 RXIQK_fail_code[2][4]; /* channel / path 0:SRXK1 fail, 1:RXK1 fail 2:RXK2 fail */ + u32 LOK_IDAC[2][4]; /*channel / path*/ + u16 RXIQK_AGC[2][4]; /*channel / path*/ + u32 bypass_iqk[2][4]; /*channel / 0xc94/0xe94*/ + u32 tmp_GNTWL; + bool is_BTG; + bool isbnd; +}; + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_kfree.c b/drivers/staging/rtl8188eu/hal/phydm_kfree.c new file mode 100644 index 000000000000..31d33110e785 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_kfree.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/*============================================================*/ +/*include files*/ +/*============================================================*/ +#include "mp_precomp.h" +#include "phydm_precomp.h" + + +/* Add for KFree Feature Requested by RF David.*/ +/*This is a phydm API*/ + +static void phydm_set_kfree_to_rf_8814a(void *p_dm_void, u8 e_rf_path, u8 data) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct odm_rf_calibration_structure *p_rf_calibrate_info = &(p_dm_odm->rf_calibrate_info); + bool is_odd; + + if ((data % 2) != 0) { /*odd->positive*/ + data = data - 1; + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(19), 1); + is_odd = true; + } else { /*even->negative*/ + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(19), 0); + is_odd = false; + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_MP, ODM_DBG_LOUD, ("phy_ConfigKFree8814A(): RF_0x55[19]= %d\n", is_odd)); + switch (data) { + case 0: + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14), 0); + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(17) | BIT(16) | BIT(15), 0); + p_rf_calibrate_info->kfree_offset[e_rf_path] = 0; + break; + case 2: + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14), 1); + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(17) | BIT(16) | BIT(15), 0); + p_rf_calibrate_info->kfree_offset[e_rf_path] = 0; + break; + case 4: + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14), 0); + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(17) | BIT(16) | BIT(15), 1); + p_rf_calibrate_info->kfree_offset[e_rf_path] = 1; + break; + case 6: + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14), 1); + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(17) | BIT(16) | BIT(15), 1); + p_rf_calibrate_info->kfree_offset[e_rf_path] = 1; + break; + case 8: + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14), 0); + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(17) | BIT(16) | BIT(15), 2); + p_rf_calibrate_info->kfree_offset[e_rf_path] = 2; + break; + case 10: + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14), 1); + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(17) | BIT(16) | BIT(15), 2); + p_rf_calibrate_info->kfree_offset[e_rf_path] = 2; + break; + case 12: + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14), 0); + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(17) | BIT(16) | BIT(15), 3); + p_rf_calibrate_info->kfree_offset[e_rf_path] = 3; + break; + case 14: + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14), 1); + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(17) | BIT(16) | BIT(15), 3); + p_rf_calibrate_info->kfree_offset[e_rf_path] = 3; + break; + case 16: + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14), 0); + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(17) | BIT(16) | BIT(15), 4); + p_rf_calibrate_info->kfree_offset[e_rf_path] = 4; + break; + case 18: + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14), 1); + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(17) | BIT(16) | BIT(15), 4); + p_rf_calibrate_info->kfree_offset[e_rf_path] = 4; + break; + case 20: + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14), 0); + odm_set_rf_reg(p_dm_odm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(17) | BIT(16) | BIT(15), 5); + p_rf_calibrate_info->kfree_offset[e_rf_path] = 5; + break; + + default: + break; + } + + if (is_odd == false) { + /*that means Kfree offset is negative, we need to record it.*/ + p_rf_calibrate_info->kfree_offset[e_rf_path] = (-1) * p_rf_calibrate_info->kfree_offset[e_rf_path]; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_MP, ODM_DBG_LOUD, ("phy_ConfigKFree8814A(): kfree_offset = %d\n", p_rf_calibrate_info->kfree_offset[e_rf_path])); + } else + ODM_RT_TRACE(p_dm_odm, ODM_COMP_MP, ODM_DBG_LOUD, ("phy_ConfigKFree8814A(): kfree_offset = %d\n", p_rf_calibrate_info->kfree_offset[e_rf_path])); + +} + + +static void phydm_set_kfree_to_rf(void *p_dm_void, u8 e_rf_path, u8 data) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (p_dm_odm->support_ic_type & ODM_RTL8814A) + phydm_set_kfree_to_rf_8814a(p_dm_odm, e_rf_path, data); +} + +void +phydm_config_kfree( + void *p_dm_void, + u8 channel_to_sw, + u8 *kfree_table +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct odm_rf_calibration_structure *p_rf_calibrate_info = &(p_dm_odm->rf_calibrate_info); + u8 rfpath = 0, max_rf_path = 0; + u8 channel_idx = 0; + + if (p_dm_odm->support_ic_type & ODM_RTL8814A) + max_rf_path = 4; /*0~3*/ + else if (p_dm_odm->support_ic_type & (ODM_RTL8812 | ODM_RTL8192E | ODM_RTL8822B)) + max_rf_path = 2; /*0~1*/ + else + max_rf_path = 1; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_MP, ODM_DBG_LOUD, ("===>phy_ConfigKFree8814A()\n")); + + if (p_rf_calibrate_info->reg_rf_kfree_enable == 2) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_MP, ODM_DBG_LOUD, ("phy_ConfigKFree8814A(): reg_rf_kfree_enable == 2, Disable\n")); + return; + } else if (p_rf_calibrate_info->reg_rf_kfree_enable == 1 || p_rf_calibrate_info->reg_rf_kfree_enable == 0) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_MP, ODM_DBG_LOUD, ("phy_ConfigKFree8814A(): reg_rf_kfree_enable == true\n")); + /*Make sure the targetval is defined*/ + if (((p_rf_calibrate_info->reg_rf_kfree_enable == 1) && (kfree_table[0] != 0xFF)) || (p_rf_calibrate_info->rf_kfree_enable == true)) { + /*if kfree_table[0] == 0xff, means no Kfree*/ + if (*p_dm_odm->p_band_type == ODM_BAND_2_4G) { + if (channel_to_sw <= 14 && channel_to_sw >= 1) + channel_idx = PHYDM_2G; + } else if (*p_dm_odm->p_band_type == ODM_BAND_5G) { + if (channel_to_sw >= 36 && channel_to_sw <= 48) + channel_idx = PHYDM_5GLB1; + if (channel_to_sw >= 52 && channel_to_sw <= 64) + channel_idx = PHYDM_5GLB2; + if (channel_to_sw >= 100 && channel_to_sw <= 120) + channel_idx = PHYDM_5GMB1; + if (channel_to_sw >= 124 && channel_to_sw <= 144) + channel_idx = PHYDM_5GMB2; + if (channel_to_sw >= 149 && channel_to_sw <= 177) + channel_idx = PHYDM_5GHB; + } + + for (rfpath = ODM_RF_PATH_A; rfpath < max_rf_path; rfpath++) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_MP, ODM_DBG_LOUD, ("phydm_kfree(): PATH_%d: %#x\n", rfpath, kfree_table[channel_idx * max_rf_path + rfpath])); + phydm_set_kfree_to_rf(p_dm_odm, rfpath, kfree_table[channel_idx * max_rf_path + rfpath]); + } + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_MP, ODM_DBG_LOUD, ("phy_ConfigKFree8814A(): targetval not defined, Don't execute KFree Process.\n")); + return; + } + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_MP, ODM_DBG_LOUD, ("<===phy_ConfigKFree8814A()\n")); +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_kfree.h b/drivers/staging/rtl8188eu/hal/phydm_kfree.h new file mode 100644 index 000000000000..6de330dabdb9 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_kfree.h @@ -0,0 +1,29 @@ + +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDMKFREE_H__ +#define __PHYDKFREE_H__ + +#define KFREE_VERSION "1.0" + +enum phydm_kfree_channeltosw { + PHYDM_2G = 0, + PHYDM_5GLB1 = 1, + PHYDM_5GLB2 = 2, + PHYDM_5GMB1 = 3, + PHYDM_5GMB2 = 4, + PHYDM_5GHB = 5, +}; + + +void +phydm_config_kfree( + void *p_dm_void, + u8 channel_to_sw, + u8 *kfree_table +); + + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_noisemonitor.c b/drivers/staging/rtl8188eu/hal/phydm_noisemonitor.c new file mode 100644 index 000000000000..f9cd06f2cba7 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_noisemonitor.c @@ -0,0 +1,270 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* ************************************************************ + * include files + * ************************************************************ */ +#include "mp_precomp.h" +#include "phydm_precomp.h" +#include "phydm_noisemonitor.h" + +/* ************************************************* + * This function is for inband noise test utility only + * To obtain the inband noise level(dbm), do the following. + * 1. disable DIG and Power Saving + * 2. Set initial gain = 0x1a + * 3. Stop updating idle time pwer report (for driver read) + * - 0x80c[25] + * + * ************************************************* */ + +#define VALID_MIN -35 +#define VALID_MAX 10 +#define VALID_CNT 5 + +static s16 odm_inband_noise_monitor_n_series(struct PHY_DM_STRUCT *p_dm_odm, u8 is_pause_dig, u8 igi_value, u32 max_time) +{ + u32 tmp4b; + u8 max_rf_path = 0, rf_path; + u8 reg_c50, reg_c58, valid_done = 0; + struct noise_level noise_data; + u64 start = 0, func_start = 0, func_end = 0; + + func_start = odm_get_current_time(p_dm_odm); + p_dm_odm->noise_level.noise_all = 0; + + if ((p_dm_odm->rf_type == ODM_1T2R) || (p_dm_odm->rf_type == ODM_2T2R)) + max_rf_path = 2; + else + max_rf_path = 1; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_DebugControlInbandNoise_Nseries() ==>\n")); + + odm_memory_set(p_dm_odm, &noise_data, 0, sizeof(struct noise_level)); + + /* */ + /* step 1. Disable DIG && Set initial gain. */ + /* */ + + if (is_pause_dig) + odm_pause_dig(p_dm_odm, PHYDM_PAUSE, PHYDM_PAUSE_LEVEL_1, igi_value); + /* */ + /* step 2. Disable all power save for read registers */ + /* */ + /* dcmd_DebugControlPowerSave(p_adapter, PSDisable); */ + + /* */ + /* step 3. Get noise power level */ + /* */ + start = odm_get_current_time(p_dm_odm); + while (1) { + + /* Stop updating idle time pwer report (for driver read) */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_TX_GAIN_STAGE, BIT(25), 1); + + /* Read Noise Floor Report */ + tmp4b = odm_get_bb_reg(p_dm_odm, 0x8f8, MASKDWORD); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("Noise Floor Report (0x8f8) = 0x%08x\n", tmp4b)); + + /* odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XA_AGC_CORE1, MASKBYTE0, TestInitialGain); */ + /* if(max_rf_path == 2) */ + /* odm_set_bb_reg(p_dm_odm, REG_OFDM_0_XB_AGC_CORE1, MASKBYTE0, TestInitialGain); */ + + /* update idle time pwer report per 5us */ + odm_set_bb_reg(p_dm_odm, REG_FPGA0_TX_GAIN_STAGE, BIT(25), 0); + + noise_data.value[ODM_RF_PATH_A] = (u8)(tmp4b & 0xff); + noise_data.value[ODM_RF_PATH_B] = (u8)((tmp4b & 0xff00) >> 8); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("value_a = 0x%x(%d), value_b = 0x%x(%d)\n", + noise_data.value[ODM_RF_PATH_A], noise_data.value[ODM_RF_PATH_A], noise_data.value[ODM_RF_PATH_B], noise_data.value[ODM_RF_PATH_B])); + + for (rf_path = ODM_RF_PATH_A; rf_path < max_rf_path; rf_path++) { + noise_data.sval[rf_path] = (s8)noise_data.value[rf_path]; + noise_data.sval[rf_path] /= 2; + } + + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("sval_a = %d, sval_b = %d\n", + noise_data.sval[ODM_RF_PATH_A], noise_data.sval[ODM_RF_PATH_B])); + /* ODM_delay_ms(10); */ + /* ODM_sleep_ms(10); */ + + for (rf_path = ODM_RF_PATH_A; rf_path < max_rf_path; rf_path++) { + if ((noise_data.valid_cnt[rf_path] < VALID_CNT) && (noise_data.sval[rf_path] < VALID_MAX && noise_data.sval[rf_path] >= VALID_MIN)) { + noise_data.valid_cnt[rf_path]++; + noise_data.sum[rf_path] += noise_data.sval[rf_path]; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("rf_path:%d Valid sval = %d\n", rf_path, noise_data.sval[rf_path])); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("Sum of sval = %d,\n", noise_data.sum[rf_path])); + if (noise_data.valid_cnt[rf_path] == VALID_CNT) { + valid_done++; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("After divided, rf_path:%d,sum = %d\n", rf_path, noise_data.sum[rf_path])); + } + + } + + } + + /* printk("####### valid_done:%d #############\n",valid_done); */ + if ((valid_done == max_rf_path) || (odm_get_progressing_time(p_dm_odm, start) > max_time)) { + for (rf_path = ODM_RF_PATH_A; rf_path < max_rf_path; rf_path++) { + /* printk("%s PATH_%d - sum = %d, VALID_CNT = %d\n",__func__,rf_path,noise_data.sum[rf_path], noise_data.valid_cnt[rf_path]); */ + if (noise_data.valid_cnt[rf_path]) + noise_data.sum[rf_path] /= noise_data.valid_cnt[rf_path]; + else + noise_data.sum[rf_path] = 0; + } + break; + } + } + reg_c50 = (u8)odm_get_bb_reg(p_dm_odm, REG_OFDM_0_XA_AGC_CORE1, MASKBYTE0); + reg_c50 &= ~BIT(7); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("0x%x = 0x%02x(%d)\n", REG_OFDM_0_XA_AGC_CORE1, reg_c50, reg_c50)); + p_dm_odm->noise_level.noise[ODM_RF_PATH_A] = (u8)(-110 + reg_c50 + noise_data.sum[ODM_RF_PATH_A]); + p_dm_odm->noise_level.noise_all += p_dm_odm->noise_level.noise[ODM_RF_PATH_A]; + + if (max_rf_path == 2) { + reg_c58 = (u8)odm_get_bb_reg(p_dm_odm, REG_OFDM_0_XB_AGC_CORE1, MASKBYTE0); + reg_c58 &= ~BIT(7); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("0x%x = 0x%02x(%d)\n", REG_OFDM_0_XB_AGC_CORE1, reg_c58, reg_c58)); + p_dm_odm->noise_level.noise[ODM_RF_PATH_B] = (u8)(-110 + reg_c58 + noise_data.sum[ODM_RF_PATH_B]); + p_dm_odm->noise_level.noise_all += p_dm_odm->noise_level.noise[ODM_RF_PATH_B]; + } + p_dm_odm->noise_level.noise_all /= max_rf_path; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("noise_a = %d, noise_b = %d\n", + p_dm_odm->noise_level.noise[ODM_RF_PATH_A], + p_dm_odm->noise_level.noise[ODM_RF_PATH_B])); + + /* */ + /* step 4. Recover the Dig */ + /* */ + if (is_pause_dig) + odm_pause_dig(p_dm_odm, PHYDM_RESUME, PHYDM_PAUSE_LEVEL_1, igi_value); + func_end = odm_get_progressing_time(p_dm_odm, func_start) ; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_DebugControlInbandNoise_Nseries() <==\n")); + return p_dm_odm->noise_level.noise_all; + +} + +static s16 +odm_inband_noise_monitor_ac_series(struct PHY_DM_STRUCT *p_dm_odm, u8 is_pause_dig, u8 igi_value, u32 max_time + ) +{ + s32 rxi_buf_anta, rxq_buf_anta; /*rxi_buf_antb, rxq_buf_antb;*/ + s32 value32, pwdb_A = 0, sval, noise, sum; + bool pd_flag; + u8 i, valid_cnt; + u64 start = 0, func_start = 0, func_end = 0; + + + if (!(p_dm_odm->support_ic_type & (ODM_RTL8812 | ODM_RTL8821 | ODM_RTL8814A))) + return 0; + + func_start = odm_get_current_time(p_dm_odm); + p_dm_odm->noise_level.noise_all = 0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_inband_noise_monitor_ac_series() ==>\n")); + + /* step 1. Disable DIG && Set initial gain. */ + if (is_pause_dig) + odm_pause_dig(p_dm_odm, PHYDM_PAUSE, PHYDM_PAUSE_LEVEL_1, igi_value); + + /* step 2. Disable all power save for read registers */ + /*dcmd_DebugControlPowerSave(p_adapter, PSDisable); */ + + /* step 3. Get noise power level */ + start = odm_get_current_time(p_dm_odm); + + /* reset counters */ + sum = 0; + valid_cnt = 0; + + /* step 3. Get noise power level */ + while (1) { + /*Set IGI=0x1C */ + odm_write_dig(p_dm_odm, 0x1C); + /*stop CK320&CK88 */ + odm_set_bb_reg(p_dm_odm, 0x8B4, BIT(6), 1); + /*Read path-A */ + odm_set_bb_reg(p_dm_odm, 0x8FC, MASKDWORD, 0x200); /*set debug port*/ + value32 = odm_get_bb_reg(p_dm_odm, 0xFA0, MASKDWORD); /*read debug port*/ + + rxi_buf_anta = (value32 & 0xFFC00) >> 10; /*rxi_buf_anta=RegFA0[19:10]*/ + rxq_buf_anta = value32 & 0x3FF; /*rxq_buf_anta=RegFA0[19:10]*/ + + pd_flag = (bool)((value32 & BIT(31)) >> 31); + + /*Not in packet detection period or Tx state */ + if ((!pd_flag) || (rxi_buf_anta != 0x200)) { + /*sign conversion*/ + rxi_buf_anta = odm_sign_conversion(rxi_buf_anta, 10); + rxq_buf_anta = odm_sign_conversion(rxq_buf_anta, 10); + + pwdb_A = odm_pwdb_conversion(rxi_buf_anta * rxi_buf_anta + rxq_buf_anta * rxq_buf_anta, 20, 18); /*S(10,9)*S(10,9)=S(20,18)*/ + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pwdb_A= %d dB, rxi_buf_anta= 0x%x, rxq_buf_anta= 0x%x\n", pwdb_A, rxi_buf_anta & 0x3FF, rxq_buf_anta & 0x3FF)); + } + /*Start CK320&CK88*/ + odm_set_bb_reg(p_dm_odm, 0x8B4, BIT(6), 0); + /*BB Reset*/ + odm_write_1byte(p_dm_odm, 0x02, odm_read_1byte(p_dm_odm, 0x02) & (~BIT(0))); + odm_write_1byte(p_dm_odm, 0x02, odm_read_1byte(p_dm_odm, 0x02) | BIT(0)); + /*PMAC Reset*/ + odm_write_1byte(p_dm_odm, 0xB03, odm_read_1byte(p_dm_odm, 0xB03) & (~BIT(0))); + odm_write_1byte(p_dm_odm, 0xB03, odm_read_1byte(p_dm_odm, 0xB03) | BIT(0)); + /*CCK Reset*/ + if (odm_read_1byte(p_dm_odm, 0x80B) & BIT(4)) { + odm_write_1byte(p_dm_odm, 0x80B, odm_read_1byte(p_dm_odm, 0x80B) & (~BIT(4))); + odm_write_1byte(p_dm_odm, 0x80B, odm_read_1byte(p_dm_odm, 0x80B) | BIT(4)); + } + + sval = pwdb_A; + + if (sval < 0 && sval >= -27) { + if (valid_cnt < VALID_CNT) { + valid_cnt++; + sum += sval; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("Valid sval = %d\n", sval)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("Sum of sval = %d,\n", sum)); + if ((valid_cnt >= VALID_CNT) || (odm_get_progressing_time(p_dm_odm, start) > max_time)) { + sum /= VALID_CNT; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("After divided, sum = %d\n", sum)); + break; + } + } + } + } + + /*ADC backoff is 12dB,*/ + /*Ptarget=0x1C-110=-82dBm*/ + noise = sum + 12 + 0x1C - 110; + + /*Offset*/ + noise = noise - 3; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("noise = %d\n", noise)); + p_dm_odm->noise_level.noise_all = (s16)noise; + + /* step 4. Recover the Dig*/ + if (is_pause_dig) + odm_pause_dig(p_dm_odm, PHYDM_RESUME, PHYDM_PAUSE_LEVEL_1, igi_value); + + func_end = odm_get_progressing_time(p_dm_odm, func_start); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_inband_noise_monitor_ac_series() <==\n")); + + return p_dm_odm->noise_level.noise_all; +} + +s16 +odm_inband_noise_monitor(void *p_dm_void, u8 is_pause_dig, u8 igi_value, u32 max_time) +{ + + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES) + return odm_inband_noise_monitor_ac_series(p_dm_odm, is_pause_dig, igi_value, max_time); + else + return odm_inband_noise_monitor_n_series(p_dm_odm, is_pause_dig, igi_value, max_time); +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_noisemonitor.h b/drivers/staging/rtl8188eu/hal/phydm_noisemonitor.h new file mode 100644 index 000000000000..bab7cae20177 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_noisemonitor.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#ifndef __ODMNOISEMONITOR_H__ +#define __ODMNOISEMONITOR_H__ + +#define ODM_MAX_CHANNEL_NUM 38/* 14+24 */ +struct noise_level { + /* u8 value_a, value_b; */ + u8 value[MAX_RF_PATH]; + /* s8 sval_a, sval_b; */ + s8 sval[MAX_RF_PATH]; + + /* s32 noise_a=0, noise_b=0,sum_a=0, sum_b=0; */ + /* s32 noise[ODM_RF_PATH_MAX]; */ + s32 sum[MAX_RF_PATH]; + /* u8 valid_cnt_a=0, valid_cnt_b=0, */ + u8 valid[MAX_RF_PATH]; + u8 valid_cnt[MAX_RF_PATH]; + +}; + + +struct _ODM_NOISE_MONITOR_ { + s8 noise[MAX_RF_PATH]; + s16 noise_all; +}; + +s16 odm_inband_noise_monitor(void *p_dm_void, u8 is_pause_dig, u8 igi_value, u32 max_time); + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_pathdiv.c b/drivers/staging/rtl8188eu/hal/phydm_pathdiv.c new file mode 100644 index 000000000000..81a4901e878d --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_pathdiv.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* ************************************************************ + * include files + * ************************************************************ */ +#include "mp_precomp.h" +#include "phydm_precomp.h" + +#if (defined(CONFIG_PATH_DIVERSITY)) +void odm_pathdiv_debug(void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ODM_PATH_DIVERSITY_ *p_dm_path_div = &(p_dm_odm->dm_path_div); + u32 used = *_used; + u32 out_len = *_out_len; + + p_dm_odm->path_select = (dm_value[0] & 0xf); + PHYDM_SNPRINTF((output + used, out_len - used, "Path_select = (( 0x%x ))\n", p_dm_odm->path_select)); + + /* 2 [Fix path] */ + if (p_dm_odm->path_select != PHYDM_AUTO_PATH) { + PHYDM_SNPRINTF((output + used, out_len - used, "Trun on path [%s%s%s%s]\n", + ((p_dm_odm->path_select) & 0x1) ? "A" : "", + ((p_dm_odm->path_select) & 0x2) ? "B" : "", + ((p_dm_odm->path_select) & 0x4) ? "C" : "", + ((p_dm_odm->path_select) & 0x8) ? "D" : "")); + + phydm_dtp_fix_tx_path(p_dm_odm, p_dm_odm->path_select); + } else + PHYDM_SNPRINTF((output + used, out_len - used, "%s\n", "Auto path")); +} + +#endif /* #if(defined(CONFIG_PATH_DIVERSITY)) */ + +void +phydm_c2h_dtp_handler( + void *p_dm_void, + u8 *cmd_buf, + u8 cmd_len +) +{ +#if (defined(CONFIG_PATH_DIVERSITY)) + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ODM_PATH_DIVERSITY_ *p_dm_path_div = &(p_dm_odm->dm_path_div); + + u8 macid = cmd_buf[0]; + u8 target = cmd_buf[1]; + u8 nsc_1 = cmd_buf[2]; + u8 nsc_2 = cmd_buf[3]; + u8 nsc_3 = cmd_buf[4]; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, ("Target_candidate = (( %d ))\n", target)); +#endif +} + +void +odm_path_diversity( + void *p_dm_void +) +{ +#if (defined(CONFIG_PATH_DIVERSITY)) + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + if (!(p_dm_odm->support_ability & ODM_BB_PATH_DIV)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, ("Return: Not Support PathDiv\n")); + return; + } +#endif +} + +void +odm_path_diversity_init( + void *p_dm_void +) +{ +#if (defined(CONFIG_PATH_DIVERSITY)) + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + /*p_dm_odm->support_ability |= ODM_BB_PATH_DIV;*/ + + if (p_dm_odm->mp_mode == true) + return; + + if (!(p_dm_odm->support_ability & ODM_BB_PATH_DIV)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_PATH_DIV, ODM_DBG_LOUD, ("Return: Not Support PathDiv\n")); + return; + } +#endif +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_pathdiv.h b/drivers/staging/rtl8188eu/hal/phydm_pathdiv.h new file mode 100644 index 000000000000..97a160d46be6 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_pathdiv.h @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDMPATHDIV_H__ +#define __PHYDMPATHDIV_H__ +/*#define PATHDIV_VERSION "2.0" //2014.11.04*/ +#define PATHDIV_VERSION "3.1" /*2015.07.29 by YuChen*/ + +#if (defined(CONFIG_PATH_DIVERSITY)) +#define USE_PATH_A_AS_DEFAULT_ANT /* for 8814 dynamic TX path selection */ + +#define NUM_RESET_DTP_PERIOD 5 +#define ANT_DECT_RSSI_TH 3 + +#define PATH_A 1 +#define PATH_B 2 +#define PATH_C 3 +#define PATH_D 4 + +#define PHYDM_AUTO_PATH 0 +#define PHYDM_FIX_PATH 1 + +#define NUM_CHOOSE2_FROM4 6 +#define NUM_CHOOSE3_FROM4 4 + + +#define PHYDM_A BIT(0) +#define PHYDM_B BIT(1) +#define PHYDM_C BIT(2) +#define PHYDM_D BIT(3) +#define PHYDM_AB (BIT(0) | BIT1) /* 0 */ +#define PHYDM_AC (BIT(0) | BIT2) /* 1 */ +#define PHYDM_AD (BIT(0) | BIT3) /* 2 */ +#define PHYDM_BC (BIT(1) | BIT2) /* 3 */ +#define PHYDM_BD (BIT(1) | BIT3) /* 4 */ +#define PHYDM_CD (BIT(2) | BIT3) /* 5 */ + +#define PHYDM_ABC (BIT(0) | BIT1 | BIT2) /* 0*/ +#define PHYDM_ABD (BIT(0) | BIT1 | BIT3) /* 1*/ +#define PHYDM_ACD (BIT(0) | BIT2 | BIT3) /* 2*/ +#define PHYDM_BCD (BIT(1) | BIT2 | BIT3) /* 3*/ + +#define PHYDM_ABCD (BIT(0) | BIT(1) | BIT(2) | BIT(3)) + + +enum phydm_dtp_state { + PHYDM_DTP_INIT = 1, + PHYDM_DTP_RUNNING_1 + +}; + +enum phydm_path_div_type { + PHYDM_2R_PATH_DIV = 1, + PHYDM_4R_PATH_DIV = 2 +}; + +void +phydm_process_rssi_for_path_div( + void *p_dm_void, + void *p_phy_info_void, + void *p_pkt_info_void +); + +struct _ODM_PATH_DIVERSITY_ { + u8 resp_tx_path; + u8 path_sel[ODM_ASSOCIATE_ENTRY_NUM]; + u32 path_a_sum[ODM_ASSOCIATE_ENTRY_NUM]; + u32 path_b_sum[ODM_ASSOCIATE_ENTRY_NUM]; + u16 path_a_cnt[ODM_ASSOCIATE_ENTRY_NUM]; + u16 path_b_cnt[ODM_ASSOCIATE_ENTRY_NUM]; + u8 phydm_path_div_type; +#if RTL8814A_SUPPORT + + u32 path_a_sum_all; + u32 path_b_sum_all; + u32 path_c_sum_all; + u32 path_d_sum_all; + + u32 path_a_cnt_all; + u32 path_b_cnt_all; + u32 path_c_cnt_all; + u32 path_d_cnt_all; + + u8 dtp_period; + bool is_become_linked; + bool is_u3_mode; + u8 num_tx_path; + u8 default_path; + u8 num_candidate; + u8 ant_candidate_1; + u8 ant_candidate_2; + u8 ant_candidate_3; + u8 phydm_dtp_state; + u8 dtp_check_patha_counter; + bool fix_path_bfer; + u8 search_space_2[NUM_CHOOSE2_FROM4]; + u8 search_space_3[NUM_CHOOSE3_FROM4]; + + u8 pre_tx_path; + u8 use_path_a_as_default_ant; + bool is_path_a_exist; + +#endif +}; + + +#endif /* #if(defined(CONFIG_PATH_DIVERSITY)) */ + +void +phydm_c2h_dtp_handler( + void *p_dm_void, + u8 *cmd_buf, + u8 cmd_len +); + +void +odm_path_diversity_init( + void *p_dm_void +); + +void +odm_path_diversity( + void *p_dm_void +); + +void +odm_pathdiv_debug( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +); + +#endif /* #ifndef __ODMPATHDIV_H__ */ diff --git a/drivers/staging/rtl8188eu/hal/phydm_powertracking_ce.c b/drivers/staging/rtl8188eu/hal/phydm_powertracking_ce.c new file mode 100644 index 000000000000..3f0ae1142526 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_powertracking_ce.c @@ -0,0 +1,646 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/*============================================================ */ +/* include files */ +/*============================================================ */ +#include "mp_precomp.h" +#include "phydm_precomp.h" + +/* ************************************************************ + * Global var + * ************************************************************ */ + +u32 ofdm_swing_table[OFDM_TABLE_SIZE] = { + 0x7f8001fe, /* 0, +6.0dB */ + 0x788001e2, /* 1, +5.5dB */ + 0x71c001c7, /* 2, +5.0dB*/ + 0x6b8001ae, /* 3, +4.5dB*/ + 0x65400195, /* 4, +4.0dB*/ + 0x5fc0017f, /* 5, +3.5dB*/ + 0x5a400169, /* 6, +3.0dB*/ + 0x55400155, /* 7, +2.5dB*/ + 0x50800142, /* 8, +2.0dB*/ + 0x4c000130, /* 9, +1.5dB*/ + 0x47c0011f, /* 10, +1.0dB*/ + 0x43c0010f, /* 11, +0.5dB*/ + 0x40000100, /* 12, +0dB*/ + 0x3c8000f2, /* 13, -0.5dB*/ + 0x390000e4, /* 14, -1.0dB*/ + 0x35c000d7, /* 15, -1.5dB*/ + 0x32c000cb, /* 16, -2.0dB*/ + 0x300000c0, /* 17, -2.5dB*/ + 0x2d4000b5, /* 18, -3.0dB*/ + 0x2ac000ab, /* 19, -3.5dB*/ + 0x288000a2, /* 20, -4.0dB*/ + 0x26000098, /* 21, -4.5dB*/ + 0x24000090, /* 22, -5.0dB*/ + 0x22000088, /* 23, -5.5dB*/ + 0x20000080, /* 24, -6.0dB*/ + 0x1e400079, /* 25, -6.5dB*/ + 0x1c800072, /* 26, -7.0dB*/ + 0x1b00006c, /* 27. -7.5dB*/ + 0x19800066, /* 28, -8.0dB*/ + 0x18000060, /* 29, -8.5dB*/ + 0x16c0005b, /* 30, -9.0dB*/ + 0x15800056, /* 31, -9.5dB*/ + 0x14400051, /* 32, -10.0dB*/ + 0x1300004c, /* 33, -10.5dB*/ + 0x12000048, /* 34, -11.0dB*/ + 0x11000044, /* 35, -11.5dB*/ + 0x10000040, /* 36, -12.0dB*/ +}; + +u8 cck_swing_table_ch1_ch13[CCK_TABLE_SIZE][8] = { + {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */ + {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */ + {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB*/ + {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB*/ + {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */ + {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB*/ + {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB*/ + {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB*/ + {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */ + {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB*/ + {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */ + {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB*/ + {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB <== default */ + {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB*/ + {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */ + {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB*/ + {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ + {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB*/ + {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */ + {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB*/ + {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB*/ + {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB*/ + {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB*/ + {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB*/ + {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB*/ + {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB*/ + {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB*/ + {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB*/ + {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB*/ + {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB*/ + {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB*/ + {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB*/ + {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB*/ +}; + + +u8 cck_swing_table_ch14[CCK_TABLE_SIZE][8] = { + {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */ + {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */ + {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */ + {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB*/ + {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */ + {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB*/ + {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */ + {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */ + {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */ + {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB*/ + {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */ + {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB*/ + {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB <== default*/ + {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */ + {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */ + {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB*/ + {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ + {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB*/ + {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */ + {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB*/ + {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB*/ + {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB*/ + {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB*/ + {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB*/ + {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB*/ + {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB*/ + {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB*/ + {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB*/ + {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB*/ + {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB*/ + {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB*/ + {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB*/ + {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB*/ +}; + + +u32 ofdm_swing_table_new[OFDM_TABLE_SIZE] = { + 0x0b40002d, /* 0, -15.0dB */ + 0x0c000030, /* 1, -14.5dB*/ + 0x0cc00033, /* 2, -14.0dB*/ + 0x0d800036, /* 3, -13.5dB*/ + 0x0e400039, /* 4, -13.0dB */ + 0x0f00003c, /* 5, -12.5dB*/ + 0x10000040, /* 6, -12.0dB*/ + 0x11000044, /* 7, -11.5dB*/ + 0x12000048, /* 8, -11.0dB*/ + 0x1300004c, /* 9, -10.5dB*/ + 0x14400051, /* 10, -10.0dB*/ + 0x15800056, /* 11, -9.5dB*/ + 0x16c0005b, /* 12, -9.0dB*/ + 0x18000060, /* 13, -8.5dB*/ + 0x19800066, /* 14, -8.0dB*/ + 0x1b00006c, /* 15, -7.5dB*/ + 0x1c800072, /* 16, -7.0dB*/ + 0x1e400079, /* 17, -6.5dB*/ + 0x20000080, /* 18, -6.0dB*/ + 0x22000088, /* 19, -5.5dB*/ + 0x24000090, /* 20, -5.0dB*/ + 0x26000098, /* 21, -4.5dB*/ + 0x288000a2, /* 22, -4.0dB*/ + 0x2ac000ab, /* 23, -3.5dB*/ + 0x2d4000b5, /* 24, -3.0dB*/ + 0x300000c0, /* 25, -2.5dB*/ + 0x32c000cb, /* 26, -2.0dB*/ + 0x35c000d7, /* 27, -1.5dB*/ + 0x390000e4, /* 28, -1.0dB*/ + 0x3c8000f2, /* 29, -0.5dB*/ + 0x40000100, /* 30, +0dB*/ + 0x43c0010f, /* 31, +0.5dB*/ + 0x47c0011f, /* 32, +1.0dB*/ + 0x4c000130, /* 33, +1.5dB*/ + 0x50800142, /* 34, +2.0dB*/ + 0x55400155, /* 35, +2.5dB*/ + 0x5a400169, /* 36, +3.0dB*/ + 0x5fc0017f, /* 37, +3.5dB*/ + 0x65400195, /* 38, +4.0dB*/ + 0x6b8001ae, /* 39, +4.5dB*/ + 0x71c001c7, /* 40, +5.0dB*/ + 0x788001e2, /* 41, +5.5dB*/ + 0x7f8001fe /* 42, +6.0dB*/ +}; + + +u8 cck_swing_table_ch1_ch14_88f[CCK_TABLE_SIZE_88F][16] = { + {0x44, 0x42, 0x3C, 0x33, 0x28, 0x1C, 0x13, 0x0B, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-16dB*/ + {0x48, 0x46, 0x3F, 0x36, 0x2A, 0x1E, 0x14, 0x0B, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-15.5dB*/ + {0x4D, 0x4A, 0x43, 0x39, 0x2C, 0x20, 0x15, 0x0C, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-15dB*/ + {0x51, 0x4F, 0x47, 0x3C, 0x2F, 0x22, 0x16, 0x0D, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-14.5dB*/ + {0x56, 0x53, 0x4B, 0x40, 0x32, 0x24, 0x17, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-14dB*/ + {0x5B, 0x58, 0x50, 0x43, 0x35, 0x26, 0x19, 0x0E, 0x07, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-13.5dB*/ + {0x60, 0x5D, 0x54, 0x47, 0x38, 0x28, 0x1A, 0x0F, 0x07, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-13dB*/ + {0x66, 0x63, 0x59, 0x4C, 0x3B, 0x2B, 0x1C, 0x10, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-12.5dB*/ + {0x6C, 0x69, 0x5F, 0x50, 0x3F, 0x2D, 0x1E, 0x11, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-12dB*/ + {0x73, 0x6F, 0x64, 0x55, 0x42, 0x30, 0x1F, 0x12, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-11.5dB*/ + {0x79, 0x76, 0x6A, 0x5A, 0x46, 0x33, 0x21, 0x13, 0x09, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-11dB*/ + {0x81, 0x7C, 0x71, 0x5F, 0x4A, 0x36, 0x23, 0x14, 0x0A, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-10.5dB*/ + {0x88, 0x84, 0x77, 0x65, 0x4F, 0x39, 0x25, 0x15, 0x0A, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-10dB*/ + {0x90, 0x8C, 0x7E, 0x6B, 0x54, 0x3C, 0x27, 0x17, 0x0B, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-9.5dB*/ + {0x99, 0x94, 0x86, 0x71, 0x58, 0x40, 0x2A, 0x18, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-9dB*/ + {0xA2, 0x9D, 0x8E, 0x78, 0x5E, 0x43, 0x2C, 0x19, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-8.5dB*/ + {0xAC, 0xA6, 0x96, 0x7F, 0x63, 0x47, 0x2F, 0x1B, 0x0D, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-8dB*/ + {0xB6, 0xB0, 0x9F, 0x87, 0x69, 0x4C, 0x32, 0x1D, 0x0D, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-7.5dB*/ + {0xC1, 0xBA, 0xA8, 0x8F, 0x6F, 0x50, 0x35, 0x1E, 0x0E, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-7dB*/ + {0xCC, 0xC5, 0xB2, 0x97, 0x76, 0x55, 0x38, 0x20, 0x0F, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-6.5dB*/ + {0xD8, 0xD1, 0xBD, 0xA0, 0x7D, 0x5A, 0x3B, 0x22, 0x10, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /*-6dB*/ +}; + + +u8 cck_swing_table_ch1_ch13_88f[CCK_TABLE_SIZE_88F][16] = { + {0x44, 0x42, 0x3C, 0x33, 0x28, 0x1C, 0x13, 0x0B, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-16dB*/ + {0x48, 0x46, 0x3F, 0x36, 0x2A, 0x1E, 0x14, 0x0B, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-15.5dB*/ + {0x4D, 0x4A, 0x43, 0x39, 0x2C, 0x20, 0x15, 0x0C, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-15dB*/ + {0x51, 0x4F, 0x47, 0x3C, 0x2F, 0x22, 0x16, 0x0D, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-14.5dB*/ + {0x56, 0x53, 0x4B, 0x40, 0x32, 0x24, 0x17, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-14dB*/ + {0x5B, 0x58, 0x50, 0x43, 0x35, 0x26, 0x19, 0x0E, 0x07, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-13.5dB*/ + {0x60, 0x5D, 0x54, 0x47, 0x38, 0x28, 0x1A, 0x0F, 0x07, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-13dB*/ + {0x66, 0x63, 0x59, 0x4C, 0x3B, 0x2B, 0x1C, 0x10, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-12.5dB*/ + {0x6C, 0x69, 0x5F, 0x50, 0x3F, 0x2D, 0x1E, 0x11, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-12dB*/ + {0x73, 0x6F, 0x64, 0x55, 0x42, 0x30, 0x1F, 0x12, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-11.5dB*/ + {0x79, 0x76, 0x6A, 0x5A, 0x46, 0x33, 0x21, 0x13, 0x09, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-11dB*/ + {0x81, 0x7C, 0x71, 0x5F, 0x4A, 0x36, 0x23, 0x14, 0x0A, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-10.5dB*/ + {0x88, 0x84, 0x77, 0x65, 0x4F, 0x39, 0x25, 0x15, 0x0A, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-10dB*/ + {0x90, 0x8C, 0x7E, 0x6B, 0x54, 0x3C, 0x27, 0x17, 0x0B, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-9.5dB*/ + {0x99, 0x94, 0x86, 0x71, 0x58, 0x40, 0x2A, 0x18, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-9dB*/ + {0xA2, 0x9D, 0x8E, 0x78, 0x5E, 0x43, 0x2C, 0x19, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-8.5dB*/ + {0xAC, 0xA6, 0x96, 0x7F, 0x63, 0x47, 0x2F, 0x1B, 0x0D, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-8dB*/ + {0xB6, 0xB0, 0x9F, 0x87, 0x69, 0x4C, 0x32, 0x1D, 0x0D, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-7.5dB*/ + {0xC1, 0xBA, 0xA8, 0x8F, 0x6F, 0x50, 0x35, 0x1E, 0x0E, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-7dB*/ + {0xCC, 0xC5, 0xB2, 0x97, 0x76, 0x55, 0x38, 0x20, 0x0F, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-6.5dB*/ + {0xD8, 0xD1, 0xBD, 0xA0, 0x7D, 0x5A, 0x3B, 0x22, 0x10, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /*-6dB*/ +}; + + +u8 cck_swing_table_ch14_88f[CCK_TABLE_SIZE_88F][16] = { + {0x44, 0x42, 0x3C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-16dB*/ + {0x48, 0x46, 0x3F, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-15.5dB*/ + {0x4D, 0x4A, 0x43, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-15dB*/ + {0x51, 0x4F, 0x47, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-14.5dB*/ + {0x56, 0x53, 0x4B, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-14dB*/ + {0x5B, 0x58, 0x50, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-13.5dB*/ + {0x60, 0x5D, 0x54, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-13dB*/ + {0x66, 0x63, 0x59, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-12.5dB*/ + {0x6C, 0x69, 0x5F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-12dB*/ + {0x73, 0x6F, 0x64, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-11.5dB*/ + {0x79, 0x76, 0x6A, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-11dB*/ + {0x81, 0x7C, 0x71, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-10.5dB*/ + {0x88, 0x84, 0x77, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-10dB*/ + {0x90, 0x8C, 0x7E, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-9.5dB*/ + {0x99, 0x94, 0x86, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-9dB*/ + {0xA2, 0x9D, 0x8E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-8.5dB*/ + {0xAC, 0xA6, 0x96, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-8dB*/ + {0xB6, 0xB0, 0x9F, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-7.5dB*/ + {0xC1, 0xBA, 0xA8, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-7dB*/ + {0xCC, 0xC5, 0xB2, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*-6.5dB*/ + {0xD8, 0xD1, 0xBD, 0x7D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /*-6dB*/ +}; + + +u8 cck_swing_table_ch1_ch13_new[CCK_TABLE_SIZE][8] = { + {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}, /* 0, -16.0dB*/ + {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 1, -15.5dB*/ + {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 2, -15.0dB*/ + {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 3, -14.5dB*/ + {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 4, -14.0dB*/ + {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 5, -13.5dB*/ + {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 6, -13.0dB*/ + {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 7, -12.5dB*/ + {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 8, -12.0dB*/ + {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 9, -11.5dB*/ + {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 10, -11.0dB*/ + {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11, -10.5dB*/ + {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 12, -10.0dB*/ + {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 13, -9.5dB*/ + {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 14, -9.0dB */ + {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 15, -8.5dB*/ + {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ + {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 17, -7.5dB*/ + {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 18, -7.0dB */ + {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 19, -6.5dB*/ + {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /*20, -6.0dB */ + {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 21, -5.5dB*/ + {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 22, -5.0dB */ + {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 23, -4.5dB*/ + {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 24, -4.0dB */ + {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 25, -3.5dB*/ + {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 26, -3.0dB*/ + {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 27, -2.5dB*/ + {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 28, -2.0dB */ + {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 29, -1.5dB*/ + {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 30, -1.0dB*/ + {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 31, -0.5dB*/ + {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04} /* 32, +0dB*/ +}; + + +u8 cck_swing_table_ch14_new[CCK_TABLE_SIZE][8] = { + {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}, /* 0, -16.0dB*/ + {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 1, -15.5dB*/ + {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 2, -15.0dB*/ + {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 3, -14.5dB*/ + {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 4, -14.0dB*/ + {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /*5, -13.5dB*/ + {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 6, -13.0dB*/ + {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 7, -12.5dB*/ + {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 8, -12.0dB*/ + {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 9, -11.5dB*/ + {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 10, -11.0dB*/ + {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /*11, -10.5dB*/ + {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 12, -10.0dB*/ + {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 13, -9.5dB*/ + {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /*14, -9.0dB */ + {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 15, -8.5dB*/ + {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ + {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 17, -7.5dB*/ + {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 18, -7.0dB */ + {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 19, -6.5dB */ + {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 20, -6.0dB */ + {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 21, -5.5dB*/ + {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 22, -5.0dB */ + {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /*23, -4.5dB*/ + {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 24, -4.0dB */ + {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 25, -3.5dB */ + {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 26, -3.0dB */ + {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /*27, -2.5dB*/ + {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 28, -2.0dB */ + {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /*29, -1.5dB*/ + {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 30, -1.0dB */ + {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 31, -0.5dB */ + {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00} /* 32, +0dB */ +}; +u32 cck_swing_table_ch1_ch14_8723d[CCK_TABLE_SIZE_8723D] = { + 0x0CD, /*0 , -20dB*/ + 0x0D9, + 0x0E6, + 0x0F3, + 0x102, + 0x111, + 0x121, + 0x132, + 0x144, + 0x158, + 0x16C, + 0x182, + 0x198, + 0x1B1, + 0x1CA, + 0x1E5, + 0x202, + 0x221, + 0x241, + 0x263, + 0x287, + 0x2AE, + 0x2D6, + 0x301, + 0x32F, + 0x35F, + 0x392, + 0x3C9, + 0x402, + 0x43F, + 0x47F, + 0x4C3, + 0x50C, + 0x558, + 0x5A9, + 0x5FF, + 0x65A, + 0x6BA, + 0x720, + 0x78C, + 0x7FF, +}; + + +u32 tx_scaling_table_jaguar[TXSCALE_TABLE_SIZE] = { + 0x081, /* 0, -12.0dB*/ + 0x088, /* 1, -11.5dB*/ + 0x090, /* 2, -11.0dB*/ + 0x099, /* 3, -10.5dB*/ + 0x0A2, /* 4, -10.0dB*/ + 0x0AC, /* 5, -9.5dB*/ + 0x0B6, /* 6, -9.0dB*/ + 0x0C0, /*7, -8.5dB*/ + 0x0CC, /* 8, -8.0dB*/ + 0x0D8, /* 9, -7.5dB*/ + 0x0E5, /* 10, -7.0dB*/ + 0x0F2, /* 11, -6.5dB*/ + 0x101, /* 12, -6.0dB*/ + 0x110, /* 13, -5.5dB*/ + 0x120, /* 14, -5.0dB*/ + 0x131, /* 15, -4.5dB*/ + 0x143, /* 16, -4.0dB*/ + 0x156, /* 17, -3.5dB*/ + 0x16A, /* 18, -3.0dB*/ + 0x180, /* 19, -2.5dB*/ + 0x197, /* 20, -2.0dB*/ + 0x1AF, /* 21, -1.5dB*/ + 0x1C8, /* 22, -1.0dB*/ + 0x1E3, /* 23, -0.5dB*/ + 0x200, /* 24, +0 dB*/ + 0x21E, /* 25, +0.5dB*/ + 0x23E, /* 26, +1.0dB*/ + 0x261, /* 27, +1.5dB*/ + 0x285,/* 28, +2.0dB*/ + 0x2AB, /* 29, +2.5dB*/ + 0x2D3, /*30, +3.0dB*/ + 0x2FE, /* 31, +3.5dB*/ + 0x32B, /* 32, +4.0dB*/ + 0x35C, /* 33, +4.5dB*/ + 0x38E, /* 34, +5.0dB*/ + 0x3C4, /* 35, +5.5dB*/ + 0x3FE /* 36, +6.0dB */ +}; + +#ifdef AP_BUILD_WORKAROUND + +unsigned int tx_pwr_trk_ofdm_swing_tbl[tx_pwr_trk_ofdm_swing_tbl_len] = { + /* +6.0dB */ 0x7f8001fe, + /* +5.5dB */ 0x788001e2, + /* +5.0dB */ 0x71c001c7, + /* +4.5dB */ 0x6b8001ae, + /* +4.0dB */ 0x65400195, + /* +3.5dB */ 0x5fc0017f, + /* +3.0dB */ 0x5a400169, + /* +2.5dB */ 0x55400155, + /* +2.0dB */ 0x50800142, + /* +1.5dB */ 0x4c000130, + /* +1.0dB */ 0x47c0011f, + /* +0.5dB */ 0x43c0010f, + /* 0.0dB */ 0x40000100, + /* -0.5dB */ 0x3c8000f2, + /* -1.0dB */ 0x390000e4, + /* -1.5dB */ 0x35c000d7, + /* -2.0dB */ 0x32c000cb, + /* -2.5dB */ 0x300000c0, + /* -3.0dB */ 0x2d4000b5, + /* -3.5dB */ 0x2ac000ab, + /* -4.0dB */ 0x288000a2, + /* -4.5dB */ 0x26000098, + /* -5.0dB */ 0x24000090, + /* -5.5dB */ 0x22000088, + /* -6.0dB */ 0x20000080, + /* -6.5dB */ 0x1a00006c, + /* -7.0dB */ 0x1c800072, + /* -7.5dB */ 0x18000060, + /* -8.0dB */ 0x19800066, + /* -8.5dB */ 0x15800056, + /* -9.0dB */ 0x26c0005b, + /* -9.5dB */ 0x14400051, + /* -10.0dB */ 0x24400051, + /* -10.5dB */ 0x1300004c, + /* -11.0dB */ 0x12000048, + /* -11.5dB */ 0x11000044, + /* -12.0dB */ 0x10000040 +}; +#endif + + + +void +odm_txpowertracking_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + odm_txpowertracking_thermal_meter_init(p_dm_odm); +} + +static u8 +get_swing_index( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTER *adapter = p_dm_odm->adapter; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(adapter); + u8 i = 0; + u32 bb_swing; + u32 swing_table_size; + u32 *p_swing_table; + + if (p_dm_odm->support_ic_type == ODM_RTL8188E || p_dm_odm->support_ic_type == ODM_RTL8723B + || p_dm_odm->support_ic_type == ODM_RTL8192E || p_dm_odm->support_ic_type == ODM_RTL8188F || p_dm_odm->support_ic_type == ODM_RTL8703B + ) { + bb_swing = odm_get_bb_reg(p_dm_odm, REG_OFDM_0_XA_TX_IQ_IMBALANCE, 0xFFC00000); + + p_swing_table = ofdm_swing_table_new; + swing_table_size = OFDM_TABLE_SIZE; + } else { +#if ((RTL8812A_SUPPORT == 1) || (RTL8821A_SUPPORT == 1)) + if (p_dm_odm->support_ic_type == ODM_RTL8812 || p_dm_odm->support_ic_type == ODM_RTL8821) { + bb_swing = phy_get_tx_bb_swing_8812a(adapter, p_hal_data->current_band_type, ODM_RF_PATH_A); + p_swing_table = tx_scaling_table_jaguar; + swing_table_size = TXSCALE_TABLE_SIZE; + } else +#endif + { + bb_swing = 0; + p_swing_table = ofdm_swing_table; + swing_table_size = OFDM_TABLE_SIZE; + } + } + + for (i = 0; i < swing_table_size; ++i) { + u32 table_value = p_swing_table[i]; + + if (table_value >= 0x100000) + table_value >>= 22; + if (bb_swing == table_value) + break; + } + return i; +} + +void +odm_txpowertracking_thermal_meter_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 default_swing_index = get_swing_index(p_dm_odm); + u8 p = 0; + struct odm_rf_calibration_structure *p_rf_calibrate_info = &(p_dm_odm->rf_calibrate_info); + struct _ADAPTER *adapter = p_dm_odm->adapter; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(adapter); + + p_rf_calibrate_info->is_txpowertracking = true; + p_rf_calibrate_info->tx_powercount = 0; + p_rf_calibrate_info->is_txpowertracking_init = false; + + if (p_dm_odm->mp_mode == false) + p_rf_calibrate_info->txpowertrack_control = true; + else + p_rf_calibrate_info->txpowertrack_control = false; + + if (p_dm_odm->mp_mode == false) + p_rf_calibrate_info->txpowertrack_control = true; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("p_dm_odm txpowertrack_control = %d\n", p_rf_calibrate_info->txpowertrack_control)); + + /* p_dm_odm->rf_calibrate_info.txpowertrack_control = true; */ + p_rf_calibrate_info->thermal_value = p_hal_data->eeprom_thermal_meter; + p_rf_calibrate_info->thermal_value_iqk = p_hal_data->eeprom_thermal_meter; + p_rf_calibrate_info->thermal_value_lck = p_hal_data->eeprom_thermal_meter; + + if (p_rf_calibrate_info->default_bb_swing_index_flag != true) { + /*The index of "0 dB" in SwingTable.*/ + if (p_dm_odm->support_ic_type == ODM_RTL8188E || p_dm_odm->support_ic_type == ODM_RTL8723B || + p_dm_odm->support_ic_type == ODM_RTL8192E || p_dm_odm->support_ic_type == ODM_RTL8703B) { + p_rf_calibrate_info->default_ofdm_index = (default_swing_index >= OFDM_TABLE_SIZE) ? 30 : default_swing_index; + p_rf_calibrate_info->default_cck_index = 20; + } else if (p_dm_odm->support_ic_type == ODM_RTL8188F) { /*add by Mingzhi.Guo 2015-03-23*/ + p_rf_calibrate_info->default_ofdm_index = 28; /*OFDM: -1dB*/ + p_rf_calibrate_info->default_cck_index = 20; /*CCK:-6dB*/ + } else if (p_dm_odm->support_ic_type == ODM_RTL8723D) { /*add by zhaohe 2015-10-27*/ + p_rf_calibrate_info->default_ofdm_index = 28; /*OFDM: -1dB*/ + p_rf_calibrate_info->default_cck_index = 28; /*CCK: -6dB*/ + } else { + p_rf_calibrate_info->default_ofdm_index = (default_swing_index >= TXSCALE_TABLE_SIZE) ? 24 : default_swing_index; + p_rf_calibrate_info->default_cck_index = 24; + } + p_rf_calibrate_info->default_bb_swing_index_flag = true; + } + + p_rf_calibrate_info->bb_swing_idx_cck_base = p_rf_calibrate_info->default_cck_index; + p_rf_calibrate_info->CCK_index = p_rf_calibrate_info->default_cck_index; + + for (p = ODM_RF_PATH_A; p < MAX_RF_PATH; ++p) { + p_rf_calibrate_info->bb_swing_idx_ofdm_base[p] = p_rf_calibrate_info->default_ofdm_index; + p_rf_calibrate_info->OFDM_index[p] = p_rf_calibrate_info->default_ofdm_index; + p_rf_calibrate_info->delta_power_index[p] = 0; + p_rf_calibrate_info->delta_power_index_last[p] = 0; + p_rf_calibrate_info->power_index_offset[p] = 0; + } + p_rf_calibrate_info->modify_tx_agc_value_ofdm = 0; + p_rf_calibrate_info->modify_tx_agc_value_cck = 0; + +} + + +void +odm_txpowertracking_check( + void *p_dm_void +) +{ + /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate + at the same time. In the stage2/3, we need to prive universal interface and merge all + HW dynamic mechanism. */ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + switch (p_dm_odm->support_platform) { + case ODM_WIN: + odm_txpowertracking_check_mp(p_dm_odm); + break; + + case ODM_CE: + odm_txpowertracking_check_ce(p_dm_odm); + break; + + case ODM_AP: + odm_txpowertracking_check_ap(p_dm_odm); + break; + + default: + break; + } + +} + +void +odm_txpowertracking_check_ce( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTER *adapter = p_dm_odm->adapter; + + if (!(p_dm_odm->support_ability & ODM_RF_TX_PWR_TRACK)) + return; + + if (!p_dm_odm->rf_calibrate_info.tm_trigger) { + + if (IS_HARDWARE_TYPE_8188E(adapter)) + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_T_METER_NEW, (BIT(17) | BIT(16)), 0x03); + else + odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_T_METER_OLD, RFREGOFFSETMASK, 0x60); + + + + p_dm_odm->rf_calibrate_info.tm_trigger = 1; + return; + } else { + + odm_txpowertracking_callback_thermal_meter(adapter); + p_dm_odm->rf_calibrate_info.tm_trigger = 0; + } +} + +void +odm_txpowertracking_check_mp( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; +} + +void +odm_txpowertracking_check_ap( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_powertracking_ce.h b/drivers/staging/rtl8188eu/hal/phydm_powertracking_ce.h new file mode 100644 index 000000000000..ca45b6b8712f --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_powertracking_ce.h @@ -0,0 +1,285 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDMPOWERTRACKING_H__ +#define __PHYDMPOWERTRACKING_H__ + +#define POWRTRACKING_VERSION "1.1" + +#define DPK_DELTA_MAPPING_NUM 13 +#define index_mapping_HP_NUM 15 +#define OFDM_TABLE_SIZE 43 +#define CCK_TABLE_SIZE 33 +#define CCK_TABLE_SIZE_88F 21 +#define TXSCALE_TABLE_SIZE 37 +#define CCK_TABLE_SIZE_8723D 41 + +#define TXPWR_TRACK_TABLE_SIZE 30 +#define DELTA_SWINGIDX_SIZE 30 +#define DELTA_SWINTSSI_SIZE 61 +#define BAND_NUM 4 + +#define AVG_THERMAL_NUM 8 +#define HP_THERMAL_NUM 8 +#define IQK_MAC_REG_NUM 4 +#define IQK_ADDA_REG_NUM 16 +#define IQK_BB_REG_NUM_MAX 10 + +#define IQK_BB_REG_NUM 9 + + + +#define iqk_matrix_reg_num 8 +#define IQK_MATRIX_SETTINGS_NUM (14+24+21) /* Channels_2_4G_NUM + Channels_5G_20M_NUM + Channels_5G */ + +extern u32 ofdm_swing_table[OFDM_TABLE_SIZE]; +extern u8 cck_swing_table_ch1_ch13[CCK_TABLE_SIZE][8]; +extern u8 cck_swing_table_ch14[CCK_TABLE_SIZE][8]; + +extern u32 ofdm_swing_table_new[OFDM_TABLE_SIZE]; +extern u8 cck_swing_table_ch1_ch13_new[CCK_TABLE_SIZE][8]; +extern u8 cck_swing_table_ch14_new[CCK_TABLE_SIZE][8]; +extern u8 cck_swing_table_ch1_ch14_88f[CCK_TABLE_SIZE_88F][16]; +extern u8 cck_swing_table_ch1_ch13_88f[CCK_TABLE_SIZE_88F][16]; +extern u8 cck_swing_table_ch14_88f[CCK_TABLE_SIZE_88F][16]; +extern u32 cck_swing_table_ch1_ch14_8723d[CCK_TABLE_SIZE_8723D]; + +extern u32 tx_scaling_table_jaguar[TXSCALE_TABLE_SIZE]; + +/* <20121018, Kordan> In case fail to read TxPowerTrack.txt, we use the table of 88E as the default table. */ +static u8 delta_swing_table_idx_2ga_p_8188e[] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9}; +static u8 delta_swing_table_idx_2ga_n_8188e[] = {0, 0, 0, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11}; + +#define dm_check_txpowertracking odm_txpowertracking_check + +struct _IQK_MATRIX_REGS_SETTING { + bool is_iqk_done; + s32 value[3][iqk_matrix_reg_num]; + bool is_bw_iqk_result_saved[3]; +}; + +struct odm_rf_calibration_structure { + /* for tx power tracking */ + + u32 rega24; /* for TempCCK */ + s32 rege94; + s32 rege9c; + s32 regeb4; + s32 regebc; + + u8 tx_powercount; + bool is_txpowertracking_init; + bool is_txpowertracking; + u8 txpowertrack_control; /* for mp mode, turn off txpwrtracking as default */ + u8 tm_trigger; + u8 internal_pa_5g[2]; /* pathA / pathB */ + + u8 thermal_meter[2]; /* thermal_meter, index 0 for RFIC0, and 1 for RFIC1 */ + u8 thermal_value; + u8 thermal_value_lck; + u8 thermal_value_iqk; + s8 thermal_value_delta; /* delta of thermal_value and efuse thermal */ + u8 thermal_value_dpk; + u8 thermal_value_avg[AVG_THERMAL_NUM]; + u8 thermal_value_avg_index; + u8 thermal_value_rx_gain; + u8 thermal_value_crystal; + u8 thermal_value_dpk_store; + u8 thermal_value_dpk_track; + bool txpowertracking_in_progress; + + bool is_reloadtxpowerindex; + u8 is_rf_pi_enable; + u32 txpowertracking_callback_cnt; /* cosa add for debug */ + + + /* ------------------------- Tx power Tracking ------------------------- */ + u8 is_cck_in_ch14; + u8 CCK_index; + u8 OFDM_index[MAX_RF_PATH]; + s8 power_index_offset[MAX_RF_PATH]; + s8 delta_power_index[MAX_RF_PATH]; + s8 delta_power_index_last[MAX_RF_PATH]; + bool is_tx_power_changed; + s8 xtal_offset; + s8 xtal_offset_last; + + u8 thermal_value_hp[HP_THERMAL_NUM]; + u8 thermal_value_hp_index; + struct _IQK_MATRIX_REGS_SETTING iqk_matrix_reg_setting[IQK_MATRIX_SETTINGS_NUM]; + u8 delta_lck; + s8 bb_swing_diff_2g, bb_swing_diff_5g; /* Unit: dB */ + u8 delta_swing_table_idx_2g_cck_a_p[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2g_cck_a_n[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2g_cck_b_p[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2g_cck_b_n[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2g_cck_c_p[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2g_cck_c_n[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2g_cck_d_p[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2g_cck_d_n[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2ga_p[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2ga_n[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2gb_p[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2gb_n[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2gc_p[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2gc_n[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2gd_p[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2gd_n[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_5ga_p[BAND_NUM][DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_5ga_n[BAND_NUM][DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_5gb_p[BAND_NUM][DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_5gb_n[BAND_NUM][DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_5gc_p[BAND_NUM][DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_5gc_n[BAND_NUM][DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_5gd_p[BAND_NUM][DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_5gd_n[BAND_NUM][DELTA_SWINGIDX_SIZE]; + u8 delta_swing_tssi_table_2g_cck_a[DELTA_SWINTSSI_SIZE]; + u8 delta_swing_tssi_table_2g_cck_b[DELTA_SWINTSSI_SIZE]; + u8 delta_swing_tssi_table_2g_cck_c[DELTA_SWINTSSI_SIZE]; + u8 delta_swing_tssi_table_2g_cck_d[DELTA_SWINTSSI_SIZE]; + u8 delta_swing_tssi_table_2ga[DELTA_SWINTSSI_SIZE]; + u8 delta_swing_tssi_table_2gb[DELTA_SWINTSSI_SIZE]; + u8 delta_swing_tssi_table_2gc[DELTA_SWINTSSI_SIZE]; + u8 delta_swing_tssi_table_2gd[DELTA_SWINTSSI_SIZE]; + u8 delta_swing_tssi_table_5ga[BAND_NUM][DELTA_SWINTSSI_SIZE]; + u8 delta_swing_tssi_table_5gb[BAND_NUM][DELTA_SWINTSSI_SIZE]; + u8 delta_swing_tssi_table_5gc[BAND_NUM][DELTA_SWINTSSI_SIZE]; + u8 delta_swing_tssi_table_5gd[BAND_NUM][DELTA_SWINTSSI_SIZE]; + s8 delta_swing_table_xtal_p[DELTA_SWINGIDX_SIZE]; + s8 delta_swing_table_xtal_n[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2ga_p_8188e[DELTA_SWINGIDX_SIZE]; + u8 delta_swing_table_idx_2ga_n_8188e[DELTA_SWINGIDX_SIZE]; + + u8 bb_swing_idx_ofdm[MAX_RF_PATH]; + u8 bb_swing_idx_ofdm_current; + u8 bb_swing_idx_ofdm_base[MAX_RF_PATH]; + bool default_bb_swing_index_flag; + bool bb_swing_flag_ofdm; + u8 bb_swing_idx_cck; + u8 bb_swing_idx_cck_current; + u8 bb_swing_idx_cck_base; + u8 default_ofdm_index; + u8 default_cck_index; + bool bb_swing_flag_cck; + + s8 absolute_ofdm_swing_idx[MAX_RF_PATH]; + s8 remnant_ofdm_swing_idx[MAX_RF_PATH]; + s8 absolute_cck_swing_idx[MAX_RF_PATH]; + s8 remnant_cck_swing_idx; + s8 modify_tx_agc_value; /*Remnat compensate value at tx_agc */ + bool modify_tx_agc_flag_path_a; + bool modify_tx_agc_flag_path_b; + bool modify_tx_agc_flag_path_c; + bool modify_tx_agc_flag_path_d; + bool modify_tx_agc_flag_path_a_cck; + + s8 kfree_offset[MAX_RF_PATH]; + + /* -------------------------------------------------------------------- */ + + /* for IQK */ + u32 regc04; + u32 reg874; + u32 regc08; + u32 regb68; + u32 regb6c; + u32 reg870; + u32 reg860; + u32 reg864; + + bool is_iqk_initialized; + bool is_lck_in_progress; + bool is_antenna_detected; + bool is_need_iqk; + bool is_iqk_in_progress; + bool is_iqk_pa_off; + u8 delta_iqk; + u32 ADDA_backup[IQK_ADDA_REG_NUM]; + u32 IQK_MAC_backup[IQK_MAC_REG_NUM]; + u32 IQK_BB_backup_recover[9]; + u32 IQK_BB_backup[IQK_BB_REG_NUM]; + u32 tx_iqc_8723b[2][3][2]; /* { {S1: 0xc94, 0xc80, 0xc4c} , {S0: 0xc9c, 0xc88, 0xc4c}} */ + u32 rx_iqc_8723b[2][2][2]; /* { {S1: 0xc14, 0xca0} , {S0: 0xc14, 0xca0}} */ + u32 tx_iqc_8703b[3][2]; /* { {S1: 0xc94, 0xc80, 0xc4c} , {S0: 0xc9c, 0xc88, 0xc4c}}*/ + u32 rx_iqc_8703b[2][2]; /* { {S1: 0xc14, 0xca0} , {S0: 0xc14, 0xca0}}*/ + u32 tx_iqc_8723d[2][3][2]; /* { {S1: 0xc94, 0xc80, 0xc4c} , {S0: 0xc9c, 0xc88, 0xc4c}}*/ + u32 rx_iqc_8723d[2][2][2]; /* { {S1: 0xc14, 0xca0} , {S0: 0xc14, 0xca0}}*/ + + u8 iqk_step; + u8 kcount; + u8 retry_count[4][2]; /* [4]: path ABCD, [2] TXK, RXK */ + bool is_mp_mode; + + + + /* IQK time measurement */ + u64 iqk_start_time; + u64 iqk_progressing_time; + u64 iqk_total_progressing_time; + + u32 lok_result; + + /* for APK */ + u32 ap_koutput[2][2]; /* path A/B; output1_1a/output1_2a */ + u8 is_ap_kdone; + u8 is_apk_thermal_meter_ignore; + + /* DPK */ + bool is_dpk_fail; + u8 is_dp_done; + u8 is_dp_path_aok; + u8 is_dp_path_bok; + + u32 tx_lok[2]; + u32 dpk_tx_agc; + s32 dpk_gain; + u32 dpk_thermal[4]; + s8 modify_tx_agc_value_ofdm; + s8 modify_tx_agc_value_cck; + + /*Add by Yuchen for Kfree Phydm*/ + u8 reg_rf_kfree_enable; /*for registry*/ + u8 rf_kfree_enable; /*for efuse enable check*/ + +}; + + +void +odm_txpowertracking_check( + void *p_dm_void +); + + +void +odm_txpowertracking_init( + void *p_dm_void +); + +void +odm_txpowertracking_check_ap( + void *p_dm_void +); + +void +odm_txpowertracking_thermal_meter_init( + void *p_dm_void +); + +void +odm_txpowertracking_init( + void *p_dm_void +); + +void +odm_txpowertracking_check_mp( + void *p_dm_void +); + + +void +odm_txpowertracking_check_ce( + void *p_dm_void +); + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_pre_define.h b/drivers/staging/rtl8188eu/hal/phydm_pre_define.h new file mode 100644 index 000000000000..de83ea4a3d5c --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_pre_define.h @@ -0,0 +1,578 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + + +#ifndef __PHYDMPREDEFINE_H__ +#define __PHYDMPREDEFINE_H__ + +/* 1 ============================================================ + * 1 Definition + * 1 ============================================================ */ + +#define PHYDM_CODE_BASE "PHYDM_012" +#define PHYDM_RELEASE_DATE "20160900" + +/* Max path of IC */ +#define MAX_PATH_NUM_8188E 1 +#define MAX_PATH_NUM_8192E 2 +#define MAX_PATH_NUM_8723B 1 +#define MAX_PATH_NUM_8812A 2 +#define MAX_PATH_NUM_8821A 1 +#define MAX_PATH_NUM_8814A 4 +#define MAX_PATH_NUM_8822B 2 +#define MAX_PATH_NUM_8821B 2 +#define MAX_PATH_NUM_8703B 1 +#define MAX_PATH_NUM_8188F 1 +#define MAX_PATH_NUM_8723D 1 +#define MAX_PATH_NUM_8197F 2 +#define MAX_PATH_NUM_8821C 1 + +/* Max RF path */ +#define ODM_RF_PATH_MAX 2 +#define ODM_RF_PATH_MAX_JAGUAR 4 + +/*Bit define path*/ +#define PHYDM_A BIT(0) +#define PHYDM_B BIT(1) +#define PHYDM_C BIT(2) +#define PHYDM_D BIT(3) +#define PHYDM_AB (BIT(0) | BIT(1)) +#define PHYDM_AC (BIT(0) | BIT(2)) +#define PHYDM_AD (BIT(0) | BIT(3)) +#define PHYDM_BC (BIT(1) | BIT(2)) +#define PHYDM_BD (BIT(1) | BIT(3)) +#define PHYDM_CD (BIT(2) | BIT(3)) +#define PHYDM_ABC (BIT(0) | BIT(1) | BIT(2)) +#define PHYDM_ABD (BIT(0) | BIT(1) | BIT(3)) +#define PHYDM_ACD (BIT(0) | BIT(2) | BIT(3)) +#define PHYDM_BCD (BIT(1) | BIT(2) | BIT(3)) +#define PHYDM_ABCD (BIT(0) | BIT(1) | BIT(2) | BIT(3)) + +/* number of entry */ +#define ASSOCIATE_ENTRY_NUM MACID_NUM_SW_LIMIT /* Max size of asoc_entry[].*/ +#define ODM_ASSOCIATE_ENTRY_NUM ASSOCIATE_ENTRY_NUM + +/* -----MGN rate--------------------------------- */ + +enum ODM_MGN_RATE { + ODM_MGN_1M = 0x02, + ODM_MGN_2M = 0x04, + ODM_MGN_5_5M = 0x0B, + ODM_MGN_6M = 0x0C, + ODM_MGN_9M = 0x12, + ODM_MGN_11M = 0x16, + ODM_MGN_12M = 0x18, + ODM_MGN_18M = 0x24, + ODM_MGN_24M = 0x30, + ODM_MGN_36M = 0x48, + ODM_MGN_48M = 0x60, + ODM_MGN_54M = 0x6C, + ODM_MGN_MCS32 = 0x7F, + ODM_MGN_MCS0, + ODM_MGN_MCS1, + ODM_MGN_MCS2, + ODM_MGN_MCS3, + ODM_MGN_MCS4, + ODM_MGN_MCS5, + ODM_MGN_MCS6, + ODM_MGN_MCS7, + ODM_MGN_MCS8, + ODM_MGN_MCS9, + ODM_MGN_MCS10, + ODM_MGN_MCS11, + ODM_MGN_MCS12, + ODM_MGN_MCS13, + ODM_MGN_MCS14, + ODM_MGN_MCS15, + ODM_MGN_MCS16, + ODM_MGN_MCS17, + ODM_MGN_MCS18, + ODM_MGN_MCS19, + ODM_MGN_MCS20, + ODM_MGN_MCS21, + ODM_MGN_MCS22, + ODM_MGN_MCS23, + ODM_MGN_MCS24, + ODM_MGN_MCS25, + ODM_MGN_MCS26, + ODM_MGN_MCS27, + ODM_MGN_MCS28, + ODM_MGN_MCS29, + ODM_MGN_MCS30, + ODM_MGN_MCS31, + ODM_MGN_VHT1SS_MCS0, + ODM_MGN_VHT1SS_MCS1, + ODM_MGN_VHT1SS_MCS2, + ODM_MGN_VHT1SS_MCS3, + ODM_MGN_VHT1SS_MCS4, + ODM_MGN_VHT1SS_MCS5, + ODM_MGN_VHT1SS_MCS6, + ODM_MGN_VHT1SS_MCS7, + ODM_MGN_VHT1SS_MCS8, + ODM_MGN_VHT1SS_MCS9, + ODM_MGN_VHT2SS_MCS0, + ODM_MGN_VHT2SS_MCS1, + ODM_MGN_VHT2SS_MCS2, + ODM_MGN_VHT2SS_MCS3, + ODM_MGN_VHT2SS_MCS4, + ODM_MGN_VHT2SS_MCS5, + ODM_MGN_VHT2SS_MCS6, + ODM_MGN_VHT2SS_MCS7, + ODM_MGN_VHT2SS_MCS8, + ODM_MGN_VHT2SS_MCS9, + ODM_MGN_VHT3SS_MCS0, + ODM_MGN_VHT3SS_MCS1, + ODM_MGN_VHT3SS_MCS2, + ODM_MGN_VHT3SS_MCS3, + ODM_MGN_VHT3SS_MCS4, + ODM_MGN_VHT3SS_MCS5, + ODM_MGN_VHT3SS_MCS6, + ODM_MGN_VHT3SS_MCS7, + ODM_MGN_VHT3SS_MCS8, + ODM_MGN_VHT3SS_MCS9, + ODM_MGN_VHT4SS_MCS0, + ODM_MGN_VHT4SS_MCS1, + ODM_MGN_VHT4SS_MCS2, + ODM_MGN_VHT4SS_MCS3, + ODM_MGN_VHT4SS_MCS4, + ODM_MGN_VHT4SS_MCS5, + ODM_MGN_VHT4SS_MCS6, + ODM_MGN_VHT4SS_MCS7, + ODM_MGN_VHT4SS_MCS8, + ODM_MGN_VHT4SS_MCS9, + ODM_MGN_UNKNOWN +}; + +#define ODM_MGN_MCS0_SG 0xc0 +#define ODM_MGN_MCS1_SG 0xc1 +#define ODM_MGN_MCS2_SG 0xc2 +#define ODM_MGN_MCS3_SG 0xc3 +#define ODM_MGN_MCS4_SG 0xc4 +#define ODM_MGN_MCS5_SG 0xc5 +#define ODM_MGN_MCS6_SG 0xc6 +#define ODM_MGN_MCS7_SG 0xc7 +#define ODM_MGN_MCS8_SG 0xc8 +#define ODM_MGN_MCS9_SG 0xc9 +#define ODM_MGN_MCS10_SG 0xca +#define ODM_MGN_MCS11_SG 0xcb +#define ODM_MGN_MCS12_SG 0xcc +#define ODM_MGN_MCS13_SG 0xcd +#define ODM_MGN_MCS14_SG 0xce +#define ODM_MGN_MCS15_SG 0xcf + +/* -----DESC rate--------------------------------- */ + +#define ODM_RATEMCS15_SG 0x1c +#define ODM_RATEMCS32 0x20 + + +/* CCK Rates, TxHT = 0 */ +#define ODM_RATE1M 0x00 +#define ODM_RATE2M 0x01 +#define ODM_RATE5_5M 0x02 +#define ODM_RATE11M 0x03 +/* OFDM Rates, TxHT = 0 */ +#define ODM_RATE6M 0x04 +#define ODM_RATE9M 0x05 +#define ODM_RATE12M 0x06 +#define ODM_RATE18M 0x07 +#define ODM_RATE24M 0x08 +#define ODM_RATE36M 0x09 +#define ODM_RATE48M 0x0A +#define ODM_RATE54M 0x0B +/* MCS Rates, TxHT = 1 */ +#define ODM_RATEMCS0 0x0C +#define ODM_RATEMCS1 0x0D +#define ODM_RATEMCS2 0x0E +#define ODM_RATEMCS3 0x0F +#define ODM_RATEMCS4 0x10 +#define ODM_RATEMCS5 0x11 +#define ODM_RATEMCS6 0x12 +#define ODM_RATEMCS7 0x13 +#define ODM_RATEMCS8 0x14 +#define ODM_RATEMCS9 0x15 +#define ODM_RATEMCS10 0x16 +#define ODM_RATEMCS11 0x17 +#define ODM_RATEMCS12 0x18 +#define ODM_RATEMCS13 0x19 +#define ODM_RATEMCS14 0x1A +#define ODM_RATEMCS15 0x1B +#define ODM_RATEMCS16 0x1C +#define ODM_RATEMCS17 0x1D +#define ODM_RATEMCS18 0x1E +#define ODM_RATEMCS19 0x1F +#define ODM_RATEMCS20 0x20 +#define ODM_RATEMCS21 0x21 +#define ODM_RATEMCS22 0x22 +#define ODM_RATEMCS23 0x23 +#define ODM_RATEMCS24 0x24 +#define ODM_RATEMCS25 0x25 +#define ODM_RATEMCS26 0x26 +#define ODM_RATEMCS27 0x27 +#define ODM_RATEMCS28 0x28 +#define ODM_RATEMCS29 0x29 +#define ODM_RATEMCS30 0x2A +#define ODM_RATEMCS31 0x2B +#define ODM_RATEVHTSS1MCS0 0x2C +#define ODM_RATEVHTSS1MCS1 0x2D +#define ODM_RATEVHTSS1MCS2 0x2E +#define ODM_RATEVHTSS1MCS3 0x2F +#define ODM_RATEVHTSS1MCS4 0x30 +#define ODM_RATEVHTSS1MCS5 0x31 +#define ODM_RATEVHTSS1MCS6 0x32 +#define ODM_RATEVHTSS1MCS7 0x33 +#define ODM_RATEVHTSS1MCS8 0x34 +#define ODM_RATEVHTSS1MCS9 0x35 +#define ODM_RATEVHTSS2MCS0 0x36 +#define ODM_RATEVHTSS2MCS1 0x37 +#define ODM_RATEVHTSS2MCS2 0x38 +#define ODM_RATEVHTSS2MCS3 0x39 +#define ODM_RATEVHTSS2MCS4 0x3A +#define ODM_RATEVHTSS2MCS5 0x3B +#define ODM_RATEVHTSS2MCS6 0x3C +#define ODM_RATEVHTSS2MCS7 0x3D +#define ODM_RATEVHTSS2MCS8 0x3E +#define ODM_RATEVHTSS2MCS9 0x3F +#define ODM_RATEVHTSS3MCS0 0x40 +#define ODM_RATEVHTSS3MCS1 0x41 +#define ODM_RATEVHTSS3MCS2 0x42 +#define ODM_RATEVHTSS3MCS3 0x43 +#define ODM_RATEVHTSS3MCS4 0x44 +#define ODM_RATEVHTSS3MCS5 0x45 +#define ODM_RATEVHTSS3MCS6 0x46 +#define ODM_RATEVHTSS3MCS7 0x47 +#define ODM_RATEVHTSS3MCS8 0x48 +#define ODM_RATEVHTSS3MCS9 0x49 +#define ODM_RATEVHTSS4MCS0 0x4A +#define ODM_RATEVHTSS4MCS1 0x4B +#define ODM_RATEVHTSS4MCS2 0x4C +#define ODM_RATEVHTSS4MCS3 0x4D +#define ODM_RATEVHTSS4MCS4 0x4E +#define ODM_RATEVHTSS4MCS5 0x4F +#define ODM_RATEVHTSS4MCS6 0x50 +#define ODM_RATEVHTSS4MCS7 0x51 +#define ODM_RATEVHTSS4MCS8 0x52 +#define ODM_RATEVHTSS4MCS9 0x53 + +#define ODM_NUM_RATE_IDX (ODM_RATEVHTSS4MCS9+1) + +/* 1 ============================================================ + * 1 enumeration + * 1 ============================================================ */ + + +/* ODM_CMNINFO_INTERFACE */ +enum odm_interface_e { + ODM_ITRF_PCIE = 0x1, + ODM_ITRF_USB = 0x2, + ODM_ITRF_SDIO = 0x4, + ODM_ITRF_ALL = 0x7, +}; + +/* ODM_CMNINFO_IC_TYPE */ +enum odm_ic_type_e { + ODM_RTL8188E = BIT(0), + ODM_RTL8812 = BIT(1), + ODM_RTL8821 = BIT(2), + ODM_RTL8192E = BIT(3), + ODM_RTL8723B = BIT(4), + ODM_RTL8814A = BIT(5), + ODM_RTL8881A = BIT(6), + ODM_RTL8822B = BIT(7), + ODM_RTL8703B = BIT(8), + ODM_RTL8195A = BIT(9), + ODM_RTL8188F = BIT(10), + ODM_RTL8723D = BIT(11), + ODM_RTL8197F = BIT(12), + ODM_RTL8821C = BIT(13), + ODM_RTL8814B = BIT(14), + ODM_RTL8198F = BIT(15) +}; + + +#define ODM_IC_1SS (ODM_RTL8188E | ODM_RTL8188F | ODM_RTL8723B | ODM_RTL8703B | ODM_RTL8723D | ODM_RTL8881A | ODM_RTL8821 | ODM_RTL8821C | ODM_RTL8195A) +#define ODM_IC_2SS (ODM_RTL8192E | ODM_RTL8197F | ODM_RTL8812 | ODM_RTL8822B) +#define ODM_IC_3SS (ODM_RTL8814A) +#define ODM_IC_4SS (ODM_RTL8814B | ODM_RTL8198F) + + +#define ODM_IC_11N_SERIES (ODM_RTL8188E | ODM_RTL8192E | ODM_RTL8723B | ODM_RTL8703B | ODM_RTL8188F | ODM_RTL8723D | ODM_RTL8197F) +#define ODM_IC_11AC_SERIES (ODM_RTL8812 | ODM_RTL8821 | ODM_RTL8814A | ODM_RTL8881A | ODM_RTL8822B | ODM_RTL8821C) +#define ODM_IC_11AC_1_SERIES (ODM_RTL8812 | ODM_RTL8821 | ODM_RTL8881A) +#define ODM_IC_11AC_2_SERIES (ODM_RTL8814A | ODM_RTL8822B | ODM_RTL8821C) +#define ODM_IC_TXBF_SUPPORT (ODM_RTL8192E | ODM_RTL8812 | ODM_RTL8821 | ODM_RTL8814A | ODM_RTL8881A | ODM_RTL8822B | ODM_RTL8197F | ODM_RTL8821C) +#define ODM_IC_11N_GAIN_IDX_EDCCA (ODM_RTL8195A | ODM_RTL8703B | ODM_RTL8188F | ODM_RTL8723D | ODM_RTL8197F) +#define ODM_IC_11AC_GAIN_IDX_EDCCA (ODM_RTL8814A | ODM_RTL8822B | ODM_RTL8821C) +#define ODM_IC_PHY_STATUE_NEW_TYPE (ODM_RTL8197F | ODM_RTL8822B | ODM_RTL8723D | ODM_RTL8821C) + +#define PHYDM_IC_8051_SERIES (ODM_RTL8881A | ODM_RTL8812 | ODM_RTL8821 | ODM_RTL8188E | ODM_RTL8192E | ODM_RTL8723B | ODM_RTL8703B | ODM_RTL8188F) +#define PHYDM_IC_3081_SERIES (ODM_RTL8814A | ODM_RTL8822B | ODM_RTL8197F | ODM_RTL8821C) + +#define PHYDM_IC_SUPPORT_LA_MODE (ODM_RTL8814A | ODM_RTL8822B | ODM_RTL8197F | ODM_RTL8821C) + +#define ODM_IC_11N_SERIES_SUPPORT 1 +#define ODM_IC_11AC_SERIES_SUPPORT 0 + +#ifdef CONFIG_BT_COEXIST + #define ODM_CONFIG_BT_COEXIST 1 +#else + #define ODM_CONFIG_BT_COEXIST 0 +#endif + +#define ODM_PHY_STATUS_NEW_TYPE_SUPPORT 0 + +/* ODM_CMNINFO_CUT_VER */ +enum odm_cut_version_e { + ODM_CUT_A = 0, + ODM_CUT_B = 1, + ODM_CUT_C = 2, + ODM_CUT_D = 3, + ODM_CUT_E = 4, + ODM_CUT_F = 5, + + ODM_CUT_I = 8, + ODM_CUT_J = 9, + ODM_CUT_K = 10, + ODM_CUT_TEST = 15, +}; + +/* ODM_CMNINFO_FAB_VER */ +enum odm_fab_e { + ODM_TSMC = 0, + ODM_UMC = 1, +}; + +/* ODM_CMNINFO_RF_TYPE + * + * For example 1T2R (A+AB = BIT(0)|BIT(4)|BIT(5)) + * */ +enum odm_rf_path_e { + ODM_RF_A = BIT(0), + ODM_RF_B = BIT(1), + ODM_RF_C = BIT(2), + ODM_RF_D = BIT(3), +}; + +enum odm_rf_tx_num_e { + ODM_1T = 1, + ODM_2T = 2, + ODM_3T = 3, + ODM_4T = 4, +}; + +enum odm_rf_type_e { + ODM_1T1R, + ODM_1T2R, + ODM_2T2R, + ODM_2T2R_GREEN, + ODM_2T3R, + ODM_2T4R, + ODM_3T3R, + ODM_3T4R, + ODM_4T4R, + ODM_XTXR +}; + + +enum odm_mac_phy_mode_e { + ODM_SMSP = 0, + ODM_DMSP = 1, + ODM_DMDP = 2, +}; + + +enum odm_bt_coexist_e { + ODM_BT_BUSY = 1, + ODM_BT_ON = 2, + ODM_BT_OFF = 3, + ODM_BT_NONE = 4, +}; + +/* ODM_CMNINFO_OP_MODE */ +enum odm_operation_mode_e { + ODM_NO_LINK = BIT(0), + ODM_LINK = BIT(1), + ODM_SCAN = BIT(2), + ODM_POWERSAVE = BIT(3), + ODM_AP_MODE = BIT(4), + ODM_CLIENT_MODE = BIT(5), + ODM_AD_HOC = BIT(6), + ODM_WIFI_DIRECT = BIT(7), + ODM_WIFI_DISPLAY = BIT(8), +}; + +/* ODM_CMNINFO_WM_MODE */ +enum odm_wireless_mode_e { + ODM_WM_UNKNOW = 0x0, + ODM_WM_B = BIT(0), + ODM_WM_G = BIT(1), + ODM_WM_A = BIT(2), + ODM_WM_N24G = BIT(3), + ODM_WM_N5G = BIT(4), + ODM_WM_AUTO = BIT(5), + ODM_WM_AC = BIT(6), +}; + +/* ODM_CMNINFO_BAND */ +enum odm_band_type_e { + ODM_BAND_2_4G = 0, + ODM_BAND_5G, + ODM_BAND_ON_BOTH, + ODM_BANDMAX +}; + +/* ODM_CMNINFO_SEC_CHNL_OFFSET */ +enum phydm_sec_chnl_offset_e { + + PHYDM_DONT_CARE = 0, + PHYDM_BELOW = 1, + PHYDM_ABOVE = 2 +}; + +/* ODM_CMNINFO_SEC_MODE */ +enum odm_security_e { + ODM_SEC_OPEN = 0, + ODM_SEC_WEP40 = 1, + ODM_SEC_TKIP = 2, + ODM_SEC_RESERVE = 3, + ODM_SEC_AESCCMP = 4, + ODM_SEC_WEP104 = 5, + ODM_WEP_WPA_MIXED = 6, /* WEP + WPA */ + ODM_SEC_SMS4 = 7, +}; + +/* ODM_CMNINFO_BW */ +enum odm_bw_e { + ODM_BW20M = 0, + ODM_BW40M = 1, + ODM_BW80M = 2, + ODM_BW160M = 3, + ODM_BW5M = 4, + ODM_BW10M = 5, + ODM_BW_MAX = 6 +}; + +/* ODM_CMNINFO_CHNL */ + +/* ODM_CMNINFO_BOARD_TYPE */ +enum odm_board_type_e { + ODM_BOARD_DEFAULT = 0, /* The DEFAULT case. */ + ODM_BOARD_MINICARD = BIT(0), /* 0 = non-mini card, 1= mini card. */ + ODM_BOARD_SLIM = BIT(1), /* 0 = non-slim card, 1 = slim card */ + ODM_BOARD_BT = BIT(2), /* 0 = without BT card, 1 = with BT */ + ODM_BOARD_EXT_PA = BIT(3), /* 0 = no 2G ext-PA, 1 = existing 2G ext-PA */ + ODM_BOARD_EXT_LNA = BIT(4), /* 0 = no 2G ext-LNA, 1 = existing 2G ext-LNA */ + ODM_BOARD_EXT_TRSW = BIT(5), /* 0 = no ext-TRSW, 1 = existing ext-TRSW */ + ODM_BOARD_EXT_PA_5G = BIT(6), /* 0 = no 5G ext-PA, 1 = existing 5G ext-PA */ + ODM_BOARD_EXT_LNA_5G = BIT(7), /* 0 = no 5G ext-LNA, 1 = existing 5G ext-LNA */ +}; + +enum odm_package_type_e { + ODM_PACKAGE_DEFAULT = 0, + ODM_PACKAGE_QFN68 = BIT(0), + ODM_PACKAGE_TFBGA90 = BIT(1), + ODM_PACKAGE_TFBGA79 = BIT(2), +}; + +enum odm_type_gpa_e { + TYPE_GPA0 = 0x0000, + TYPE_GPA1 = 0x0055, + TYPE_GPA2 = 0x00AA, + TYPE_GPA3 = 0x00FF, + TYPE_GPA4 = 0x5500, + TYPE_GPA5 = 0x5555, + TYPE_GPA6 = 0x55AA, + TYPE_GPA7 = 0x55FF, + TYPE_GPA8 = 0xAA00, + TYPE_GPA9 = 0xAA55, + TYPE_GPA10 = 0xAAAA, + TYPE_GPA11 = 0xAAFF, + TYPE_GPA12 = 0xFF00, + TYPE_GPA13 = 0xFF55, + TYPE_GPA14 = 0xFFAA, + TYPE_GPA15 = 0xFFFF, +}; + +enum odm_type_apa_e { + TYPE_APA0 = 0x0000, + TYPE_APA1 = 0x0055, + TYPE_APA2 = 0x00AA, + TYPE_APA3 = 0x00FF, + TYPE_APA4 = 0x5500, + TYPE_APA5 = 0x5555, + TYPE_APA6 = 0x55AA, + TYPE_APA7 = 0x55FF, + TYPE_APA8 = 0xAA00, + TYPE_APA9 = 0xAA55, + TYPE_APA10 = 0xAAAA, + TYPE_APA11 = 0xAAFF, + TYPE_APA12 = 0xFF00, + TYPE_APA13 = 0xFF55, + TYPE_APA14 = 0xFFAA, + TYPE_APA15 = 0xFFFF, +}; + +enum odm_type_glna_e { + TYPE_GLNA0 = 0x0000, + TYPE_GLNA1 = 0x0055, + TYPE_GLNA2 = 0x00AA, + TYPE_GLNA3 = 0x00FF, + TYPE_GLNA4 = 0x5500, + TYPE_GLNA5 = 0x5555, + TYPE_GLNA6 = 0x55AA, + TYPE_GLNA7 = 0x55FF, + TYPE_GLNA8 = 0xAA00, + TYPE_GLNA9 = 0xAA55, + TYPE_GLNA10 = 0xAAAA, + TYPE_GLNA11 = 0xAAFF, + TYPE_GLNA12 = 0xFF00, + TYPE_GLNA13 = 0xFF55, + TYPE_GLNA14 = 0xFFAA, + TYPE_GLNA15 = 0xFFFF, +}; + +enum odm_type_alna_e { + TYPE_ALNA0 = 0x0000, + TYPE_ALNA1 = 0x0055, + TYPE_ALNA2 = 0x00AA, + TYPE_ALNA3 = 0x00FF, + TYPE_ALNA4 = 0x5500, + TYPE_ALNA5 = 0x5555, + TYPE_ALNA6 = 0x55AA, + TYPE_ALNA7 = 0x55FF, + TYPE_ALNA8 = 0xAA00, + TYPE_ALNA9 = 0xAA55, + TYPE_ALNA10 = 0xAAAA, + TYPE_ALNA11 = 0xAAFF, + TYPE_ALNA12 = 0xFF00, + TYPE_ALNA13 = 0xFF55, + TYPE_ALNA14 = 0xFFAA, + TYPE_ALNA15 = 0xFFFF, +}; + + +enum odm_rf_radio_path_e { + ODM_RF_PATH_A = 0, /* Radio path A */ + ODM_RF_PATH_B = 1, /* Radio path B */ + ODM_RF_PATH_C = 2, /* Radio path C */ + ODM_RF_PATH_D = 3, /* Radio path D */ + ODM_RF_PATH_AB, + ODM_RF_PATH_AC, + ODM_RF_PATH_AD, + ODM_RF_PATH_BC, + ODM_RF_PATH_BD, + ODM_RF_PATH_CD, + ODM_RF_PATH_ABC, + ODM_RF_PATH_ACD, + ODM_RF_PATH_BCD, + ODM_RF_PATH_ABCD, + /* ODM_RF_PATH_MAX, */ /* Max RF number 90 support */ +}; + +enum odm_parameter_init_e { + ODM_PRE_SETTING = 0, + ODM_POST_SETTING = 1, +}; + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_precomp.h b/drivers/staging/rtl8188eu/hal/phydm_precomp.h new file mode 100644 index 000000000000..7bd1d4b52e25 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_precomp.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __ODM_PRECOMP_H__ +#define __ODM_PRECOMP_H__ + +#include "phydm_types.h" + +#define TEST_FALG___ 1 + +/* 2 Config Flags and Structs - defined by each ODM type */ + +#define __PACK +#define __WLAN_ATTRIB_PACK__ + +/* 2 OutSrc Header Files */ + +#include "phydm.h" +#include "phydm_hwconfig.h" +#include "phydm_debug.h" +#include "phydm_regdefine11ac.h" +#include "phydm_regdefine11n.h" +#include "phydm_interface.h" +#include "phydm_reg.h" + +#include "phydm_adc_sampling.h" + + +void +phy_set_tx_power_limit( + struct PHY_DM_STRUCT *p_dm_odm, + u8 *regulation, + u8 *band, + u8 *bandwidth, + u8 *rate_section, + u8 *rf_path, + u8 *channel, + u8 *power_limit +); + +#define RTL8188E_T_SUPPORT 1 +#ifdef CONFIG_SFW_SUPPORTED + #define RTL8188E_S_SUPPORT 1 +#else + #define RTL8188E_S_SUPPORT 0 +#endif + +#include "hal8188erateadaptive.h" /* for RA,Power training */ +#include "halhwimg8188e_mac.h" +#include "halhwimg8188e_rf.h" +#include "halhwimg8188e_bb.h" +#include "phydm_regconfig8188e.h" +#include "phydm_rtl8188e.h" +#include "hal8188ereg.h" +#include "version_rtl8188e.h" +#include "rtl8188e_hal.h" +#include "halphyrf_8188e_ce.h" + +#endif /* __ODM_PRECOMP_H__ */ diff --git a/drivers/staging/rtl8188eu/hal/phydm_rainfo.c b/drivers/staging/rtl8188eu/hal/phydm_rainfo.c new file mode 100644 index 000000000000..dcfe419329da --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_rainfo.c @@ -0,0 +1,2198 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/* ************************************************************ + * include files + * ************************************************************ */ +#include "mp_precomp.h" +#include "phydm_precomp.h" + +void +phydm_h2C_debug( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 h2c_parameter[H2C_MAX_LENGTH] = {0}; + u8 phydm_h2c_id = (u8)dm_value[0]; + u8 i; + u32 used = *_used; + u32 out_len = *_out_len; + + PHYDM_SNPRINTF((output + used, out_len - used, "Phydm Send H2C_ID (( 0x%x))\n", phydm_h2c_id)); + for (i = 0; i < H2C_MAX_LENGTH; i++) { + + h2c_parameter[i] = (u8)dm_value[i + 1]; + PHYDM_SNPRINTF((output + used, out_len - used, "H2C: Byte[%d] = ((0x%x))\n", i, h2c_parameter[i])); + } + + odm_fill_h2c_cmd(p_dm_odm, phydm_h2c_id, H2C_MAX_LENGTH, h2c_parameter); + +} + +#if (defined(CONFIG_RA_DBG_CMD)) +void +odm_ra_para_adjust_send_h2c( + void *p_dm_void +) +{ + + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + u8 h2c_parameter[6] = {0}; + + h2c_parameter[0] = RA_FIRST_MACID; + + if (p_ra_table->ra_para_feedback_req) { /*h2c_parameter[5]=1 ; ask FW for all RA parameters*/ + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, ("[H2C] Ask FW for RA parameter\n")); + h2c_parameter[5] |= BIT(1); /*ask FW to report RA parameters*/ + h2c_parameter[1] = p_ra_table->para_idx; /*p_ra_table->para_idx;*/ + p_ra_table->ra_para_feedback_req = 0; + } else { + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, ("[H2C] Send H2C to FW for modifying RA parameter\n")); + + h2c_parameter[1] = p_ra_table->para_idx; + h2c_parameter[2] = p_ra_table->rate_idx; + /* [8 bit]*/ + if (p_ra_table->para_idx == RADBG_RTY_PENALTY || p_ra_table->para_idx == RADBG_RATE_UP_RTY_RATIO || p_ra_table->para_idx == RADBG_RATE_DOWN_RTY_RATIO) { + h2c_parameter[3] = p_ra_table->value; + h2c_parameter[4] = 0; + } + /* [16 bit]*/ + else { + h2c_parameter[3] = (u8)(((p_ra_table->value_16) & 0xf0) >> 4); /*byte1*/ + h2c_parameter[4] = (u8)((p_ra_table->value_16) & 0x0f); /*byte0*/ + } + } + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" h2c_parameter[1] = 0x%x\n", h2c_parameter[1])); + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" h2c_parameter[2] = 0x%x\n", h2c_parameter[2])); + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" h2c_parameter[3] = 0x%x\n", h2c_parameter[3])); + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" h2c_parameter[4] = 0x%x\n", h2c_parameter[4])); + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" h2c_parameter[5] = 0x%x\n", h2c_parameter[5])); + + odm_fill_h2c_cmd(p_dm_odm, ODM_H2C_RA_PARA_ADJUST, 6, h2c_parameter); + +} + + +void +odm_ra_para_adjust( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + u8 rate_idx = p_ra_table->rate_idx; + u8 value = p_ra_table->value; + u8 pre_value = 0xff; + + if (p_ra_table->para_idx == RADBG_RTY_PENALTY) { + pre_value = p_ra_table->RTY_P[rate_idx]; + p_ra_table->RTY_P[rate_idx] = value; + p_ra_table->RTY_P_modify_note[rate_idx] = 1; + } else if (p_ra_table->para_idx == RADBG_N_HIGH) { + + } else if (p_ra_table->para_idx == RADBG_N_LOW) { + + } else if (p_ra_table->para_idx == RADBG_RATE_UP_RTY_RATIO) { + pre_value = p_ra_table->RATE_UP_RTY_RATIO[rate_idx]; + p_ra_table->RATE_UP_RTY_RATIO[rate_idx] = value; + p_ra_table->RATE_UP_RTY_RATIO_modify_note[rate_idx] = 1; + } else if (p_ra_table->para_idx == RADBG_RATE_DOWN_RTY_RATIO) { + pre_value = p_ra_table->RATE_DOWN_RTY_RATIO[rate_idx]; + p_ra_table->RATE_DOWN_RTY_RATIO[rate_idx] = value; + p_ra_table->RATE_DOWN_RTY_RATIO_modify_note[rate_idx] = 1; + } + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, ("Change RA Papa[%d], rate[ %d ], ((%d)) -> ((%d))\n", p_ra_table->para_idx, rate_idx, pre_value, value)); + odm_ra_para_adjust_send_h2c(p_dm_odm); +} + +void +phydm_ra_print_msg( + void *p_dm_void, + u8 *value, + u8 *value_default, + u8 *modify_note +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + u32 i; + + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" |rate index| |Current-value| |Default-value| |Modify?|\n")); + for (i = 0 ; i <= (p_ra_table->rate_length); i++) { + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" [ %d ] %10d %14d %14s\n", i, value[i], value_default[i], ((modify_note[i] == 1) ? "V" : " . "))); + } + +} + +void +odm_RA_debug( + void *p_dm_void, + u32 *const dm_value +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + + p_ra_table->is_ra_dbg_init = false; + + if (dm_value[0] == 100) { /*1 Print RA Parameters*/ + u8 default_pointer_value; + u8 *pvalue; + u8 *pvalue_default; + u8 *pmodify_note; + + pvalue = pvalue_default = pmodify_note = &default_pointer_value; + + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, ("\n------------------------------------------------------------------------------------\n")); + + if (dm_value[1] == RADBG_RTY_PENALTY) { /* [1]*/ + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" [1] RTY_PENALTY\n")); + pvalue = &(p_ra_table->RTY_P[0]); + pvalue_default = &(p_ra_table->RTY_P_default[0]); + pmodify_note = (u8 *)&(p_ra_table->RTY_P_modify_note[0]); + } else if (dm_value[1] == RADBG_N_HIGH) /* [2]*/ + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" [2] N_HIGH\n")); + + else if (dm_value[1] == RADBG_N_LOW) /*[3]*/ + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" [3] N_LOW\n")); + + else if (dm_value[1] == RADBG_RATE_UP_RTY_RATIO) { /* [8]*/ + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" [8] RATE_UP_RTY_RATIO\n")); + pvalue = &(p_ra_table->RATE_UP_RTY_RATIO[0]); + pvalue_default = &(p_ra_table->RATE_UP_RTY_RATIO_default[0]); + pmodify_note = (u8 *)&(p_ra_table->RATE_UP_RTY_RATIO_modify_note[0]); + } else if (dm_value[1] == RADBG_RATE_DOWN_RTY_RATIO) { /* [9]*/ + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" [9] RATE_DOWN_RTY_RATIO\n")); + pvalue = &(p_ra_table->RATE_DOWN_RTY_RATIO[0]); + pvalue_default = &(p_ra_table->RATE_DOWN_RTY_RATIO_default[0]); + pmodify_note = (u8 *)&(p_ra_table->RATE_DOWN_RTY_RATIO_modify_note[0]); + } + + phydm_ra_print_msg(p_dm_odm, pvalue, pvalue_default, pmodify_note); + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, ("\n------------------------------------------------------------------------------------\n\n")); + + } else if (dm_value[0] == 101) { + p_ra_table->para_idx = (u8)dm_value[1]; + + p_ra_table->ra_para_feedback_req = 1; + odm_ra_para_adjust_send_h2c(p_dm_odm); + } else { + p_ra_table->para_idx = (u8)dm_value[0]; + p_ra_table->rate_idx = (u8)dm_value[1]; + p_ra_table->value = (u8)dm_value[2]; + + odm_ra_para_adjust(p_dm_odm); + } +} + +void +odm_ra_para_adjust_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + u8 i; + u8 ra_para_pool_u8[3] = { RADBG_RTY_PENALTY, RADBG_RATE_UP_RTY_RATIO, RADBG_RATE_DOWN_RTY_RATIO}; + u8 rate_size_ht_1ss = 20, rate_size_ht_2ss = 28, rate_size_ht_3ss = 36; /*4+8+8+8+8 =36*/ + u8 rate_size_vht_1ss = 10, rate_size_vht_2ss = 20, rate_size_vht_3ss = 30; /*10 + 10 +10 =30*/ + + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, ("odm_ra_para_adjust_init\n")); + + if (p_dm_odm->support_ic_type & (ODM_RTL8188F | ODM_RTL8195A | ODM_RTL8703B | ODM_RTL8723B | ODM_RTL8188E | ODM_RTL8723D)) + p_ra_table->rate_length = rate_size_ht_1ss; + else if (p_dm_odm->support_ic_type & (ODM_RTL8192E | ODM_RTL8197F)) + p_ra_table->rate_length = rate_size_ht_2ss; + else if (p_dm_odm->support_ic_type & (ODM_RTL8821 | ODM_RTL8881A | ODM_RTL8821C)) + p_ra_table->rate_length = rate_size_ht_1ss + rate_size_vht_1ss; + else if (p_dm_odm->support_ic_type & (ODM_RTL8812 | ODM_RTL8822B)) + p_ra_table->rate_length = rate_size_ht_2ss + rate_size_vht_2ss; + else if (p_dm_odm->support_ic_type == ODM_RTL8814A) + p_ra_table->rate_length = rate_size_ht_3ss + rate_size_vht_3ss; + else + p_ra_table->rate_length = rate_size_ht_1ss; + + p_ra_table->is_ra_dbg_init = true; + for (i = 0; i < 3; i++) { + p_ra_table->ra_para_feedback_req = 1; + p_ra_table->para_idx = ra_para_pool_u8[i]; + odm_ra_para_adjust_send_h2c(p_dm_odm); + } +} + +#else + +void +phydm_RA_debug_PCR( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + u32 used = *_used; + u32 out_len = *_out_len; + + if (dm_value[0] == 100) { + PHYDM_SNPRINTF((output + used, out_len - used, "[Get] PCR RA_threshold_offset = (( %s%d ))\n", ((p_ra_table->RA_threshold_offset == 0) ? " " : ((p_ra_table->RA_offset_direction) ? "+" : "-")), p_ra_table->RA_threshold_offset)); + /**/ + } else if (dm_value[0] == 0) { + p_ra_table->RA_offset_direction = 0; + p_ra_table->RA_threshold_offset = (u8)dm_value[1]; + PHYDM_SNPRINTF((output + used, out_len - used, "[Set] PCR RA_threshold_offset = (( -%d ))\n", p_ra_table->RA_threshold_offset)); + } else if (dm_value[0] == 1) { + p_ra_table->RA_offset_direction = 1; + p_ra_table->RA_threshold_offset = (u8)dm_value[1]; + PHYDM_SNPRINTF((output + used, out_len - used, "[Set] PCR RA_threshold_offset = (( +%d ))\n", p_ra_table->RA_threshold_offset)); + } else { + PHYDM_SNPRINTF((output + used, out_len - used, "[Set] Error\n")); + /**/ + } + +} + +#endif /*#if (defined(CONFIG_RA_DBG_CMD))*/ + +void +odm_c2h_ra_para_report_handler( + void *p_dm_void, + u8 *cmd_buf, + u8 cmd_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + + u8 para_idx = cmd_buf[0]; /*Retry Penalty, NH, NL*/ + u8 rate_type_start = cmd_buf[1]; + u8 rate_type_length = cmd_len - 2; + u8 i; + + + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, ("[ From FW C2H RA Para ] cmd_buf[0]= (( %d ))\n", cmd_buf[0])); + +#if (defined(CONFIG_RA_DBG_CMD)) + if (para_idx == RADBG_RTY_PENALTY) { + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" |rate index| |RTY Penality index|\n")); + + for (i = 0 ; i < (rate_type_length) ; i++) { + if (p_ra_table->is_ra_dbg_init) + p_ra_table->RTY_P_default[rate_type_start + i] = cmd_buf[2 + i]; + + p_ra_table->RTY_P[rate_type_start + i] = cmd_buf[2 + i]; + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, ("%8d %15d\n", (rate_type_start + i), p_ra_table->RTY_P[rate_type_start + i])); + } + + } else if (para_idx == RADBG_N_HIGH) { + /**/ + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" |rate index| |N-High|\n")); + + + } else if (para_idx == RADBG_N_LOW) { + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" |rate index| |N-Low|\n")); + /**/ + } else if (para_idx == RADBG_RATE_UP_RTY_RATIO) { + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" |rate index| |rate Up RTY Ratio|\n")); + + for (i = 0; i < (rate_type_length); i++) { + if (p_ra_table->is_ra_dbg_init) + p_ra_table->RATE_UP_RTY_RATIO_default[rate_type_start + i] = cmd_buf[2 + i]; + + p_ra_table->RATE_UP_RTY_RATIO[rate_type_start + i] = cmd_buf[2 + i]; + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, ("%8d %15d\n", (rate_type_start + i), p_ra_table->RATE_UP_RTY_RATIO[rate_type_start + i])); + } + } else if (para_idx == RADBG_RATE_DOWN_RTY_RATIO) { + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" |rate index| |rate Down RTY Ratio|\n")); + + for (i = 0; i < (rate_type_length); i++) { + if (p_ra_table->is_ra_dbg_init) + p_ra_table->RATE_DOWN_RTY_RATIO_default[rate_type_start + i] = cmd_buf[2 + i]; + + p_ra_table->RATE_DOWN_RTY_RATIO[rate_type_start + i] = cmd_buf[2 + i]; + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, ("%8d %15d\n", (rate_type_start + i), p_ra_table->RATE_DOWN_RTY_RATIO[rate_type_start + i])); + } + } else +#endif + if (para_idx == RADBG_DEBUG_MONITOR1) { + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("-------------------------------\n")); + if (p_dm_odm->support_ic_type & PHYDM_IC_3081_SERIES) { + + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %d\n", "RSSI =", cmd_buf[1])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s 0x%x\n", "rate =", cmd_buf[2] & 0x7f)); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %d\n", "SGI =", (cmd_buf[2] & 0x80) >> 7)); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %d\n", "BW =", cmd_buf[3])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %d\n", "BW_max =", cmd_buf[4])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s 0x%x\n", "multi_rate0 =", cmd_buf[5])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s 0x%x\n", "multi_rate1 =", cmd_buf[6])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %d\n", "DISRA =", cmd_buf[7])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %d\n", "VHT_EN =", cmd_buf[8])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %d\n", "SGI_support =", cmd_buf[9])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %d\n", "try_ness =", cmd_buf[10])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s 0x%x\n", "pre_rate =", cmd_buf[11])); + } else { + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %d\n", "RSSI =", cmd_buf[1])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %x\n", "BW =", cmd_buf[2])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %d\n", "DISRA =", cmd_buf[3])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %d\n", "VHT_EN =", cmd_buf[4])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %d\n", "Hightest rate =", cmd_buf[5])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s 0x%x\n", "Lowest rate =", cmd_buf[6])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s 0x%x\n", "SGI_support =", cmd_buf[7])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %d\n", "Rate_ID =", cmd_buf[8]));; + } + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("-------------------------------\n")); + } else if (para_idx == RADBG_DEBUG_MONITOR2) { + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("-------------------------------\n")); + if (p_dm_odm->support_ic_type & PHYDM_IC_3081_SERIES) { + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %d\n", "rate_id =", cmd_buf[1])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s 0x%x\n", "highest_rate =", cmd_buf[2])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s 0x%x\n", "lowest_rate =", cmd_buf[3])); + + for (i = 4; i <= 11; i++) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("RAMASK = 0x%x\n", cmd_buf[i])); + } else { + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %x%x %x%x %x%x %x%x\n", "RA Mask:", + cmd_buf[8], cmd_buf[7], cmd_buf[6], cmd_buf[5], cmd_buf[4], cmd_buf[3], cmd_buf[2], cmd_buf[1])); + } + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("-------------------------------\n")); + } else if (para_idx == RADBG_DEBUG_MONITOR3) { + + for (i = 0; i < (cmd_len - 1); i++) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("content[%d] = %d\n", i, cmd_buf[1 + i])); + } else if (para_idx == RADBG_DEBUG_MONITOR4) + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s {%d.%d}\n", "RA version =", cmd_buf[1], cmd_buf[2])); + else if (para_idx == RADBG_DEBUG_MONITOR5) { + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s 0x%x\n", "Current rate =", cmd_buf[1])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %d\n", "Retry ratio =", cmd_buf[2])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s %d\n", "rate down ratio =", cmd_buf[3])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s 0x%x\n", "highest rate =", cmd_buf[4])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s {0x%x 0x%x}\n", "Muti-try =", cmd_buf[5], cmd_buf[6])); + ODM_RT_TRACE(p_dm_odm, ODM_FW_DEBUG_TRACE, ODM_DBG_LOUD, ("%5s 0x%x%x%x%x%x\n", "RA mask =", cmd_buf[11], cmd_buf[10], cmd_buf[9], cmd_buf[8], cmd_buf[7])); + } +} + +void +phydm_ra_dynamic_retry_count( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + struct sta_info *p_entry; + u8 i, retry_offset; + u32 ma_rx_tp; + + if (!(p_dm_odm->support_ability & ODM_BB_DYNAMIC_ARFR)) + return; + + /*ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("p_dm_odm->pre_b_noisy = %d\n", p_dm_odm->pre_b_noisy ));*/ + if (p_dm_odm->pre_b_noisy != p_dm_odm->noisy_decision) { + + if (p_dm_odm->noisy_decision) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("->Noisy Env. RA fallback value\n")); + odm_set_mac_reg(p_dm_odm, 0x430, MASKDWORD, 0x0); + odm_set_mac_reg(p_dm_odm, 0x434, MASKDWORD, 0x04030201); + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("->Clean Env. RA fallback value\n")); + odm_set_mac_reg(p_dm_odm, 0x430, MASKDWORD, 0x01000000); + odm_set_mac_reg(p_dm_odm, 0x434, MASKDWORD, 0x06050402); + } + p_dm_odm->pre_b_noisy = p_dm_odm->noisy_decision; + } +} + +#if (defined(CONFIG_RA_DYNAMIC_RTY_LIMIT)) + +void +phydm_retry_limit_table_bound( + void *p_dm_void, + u8 *retry_limit, + u8 offset +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + + if (*retry_limit > offset) { + + *retry_limit -= offset; + + if (*retry_limit < p_ra_table->retrylimit_low) + *retry_limit = p_ra_table->retrylimit_low; + else if (*retry_limit > p_ra_table->retrylimit_high) + *retry_limit = p_ra_table->retrylimit_high; + } else + *retry_limit = p_ra_table->retrylimit_low; +} + +void +phydm_reset_retry_limit_table( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + u8 i; + +#if ((RTL8192E_SUPPORT == 1) || (RTL8723B_SUPPORT == 1) || (RTL8188E_SUPPORT == 1)) + u8 per_rate_retrylimit_table_20M[ODM_RATEMCS15 + 1] = { + 1, 1, 2, 4, /*CCK*/ + 2, 2, 4, 6, 8, 12, 16, 18, /*OFDM*/ + 2, 4, 6, 8, 12, 18, 20, 22, /*20M HT-1SS*/ + 2, 4, 6, 8, 12, 18, 20, 22 /*20M HT-2SS*/ + }; + u8 per_rate_retrylimit_table_40M[ODM_RATEMCS15 + 1] = { + 1, 1, 2, 4, /*CCK*/ + 2, 2, 4, 6, 8, 12, 16, 18, /*OFDM*/ + 4, 8, 12, 16, 24, 32, 32, 32, /*40M HT-1SS*/ + 4, 8, 12, 16, 24, 32, 32, 32 /*40M HT-2SS*/ + }; + +#elif (RTL8821A_SUPPORT == 1) || (RTL8881A_SUPPORT == 1) + +#elif (RTL8812A_SUPPORT == 1) + +#elif (RTL8814A_SUPPORT == 1) + +#else + +#endif + + memcpy(&(p_ra_table->per_rate_retrylimit_20M[0]), &(per_rate_retrylimit_table_20M[0]), ODM_NUM_RATE_IDX); + memcpy(&(p_ra_table->per_rate_retrylimit_40M[0]), &(per_rate_retrylimit_table_40M[0]), ODM_NUM_RATE_IDX); + + for (i = 0; i < ODM_NUM_RATE_IDX; i++) { + phydm_retry_limit_table_bound(p_dm_odm, &(p_ra_table->per_rate_retrylimit_20M[i]), 0); + phydm_retry_limit_table_bound(p_dm_odm, &(p_ra_table->per_rate_retrylimit_40M[i]), 0); + } +} + +void +phydm_ra_dynamic_retry_limit_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + + p_ra_table->retry_descend_num = RA_RETRY_DESCEND_NUM; + p_ra_table->retrylimit_low = RA_RETRY_LIMIT_LOW; + p_ra_table->retrylimit_high = RA_RETRY_LIMIT_HIGH; + + phydm_reset_retry_limit_table(p_dm_odm); + +} + +#endif + +void +phydm_ra_dynamic_retry_limit( + void *p_dm_void +) +{ +#if (defined(CONFIG_RA_DYNAMIC_RTY_LIMIT)) + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + struct sta_info *p_entry; + u8 i, retry_offset; + u32 ma_rx_tp; + + + if (p_dm_odm->pre_number_active_client == p_dm_odm->number_active_client) { + + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, (" pre_number_active_client == number_active_client\n")); + return; + + } else { + if (p_dm_odm->number_active_client == 1) { + phydm_reset_retry_limit_table(p_dm_odm); + ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_RA_DBG, ODM_DBG_LOUD, ("one client only->reset to default value\n")); + } else { + + retry_offset = p_dm_odm->number_active_client * p_ra_table->retry_descend_num; + + for (i = 0; i < ODM_NUM_RATE_IDX; i++) { + + phydm_retry_limit_table_bound(p_dm_odm, &(p_ra_table->per_rate_retrylimit_20M[i]), retry_offset); + phydm_retry_limit_table_bound(p_dm_odm, &(p_ra_table->per_rate_retrylimit_40M[i]), retry_offset); + } + } + } +#endif +} + +#if (defined(CONFIG_RA_DYNAMIC_RATE_ID)) +void +phydm_ra_dynamic_rate_id_on_assoc( + void *p_dm_void, + u8 wireless_mode, + u8 init_rate_id +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("[ON ASSOC] rf_mode = ((0x%x)), wireless_mode = ((0x%x)), init_rate_id = ((0x%x))\n", p_dm_odm->rf_type, wireless_mode, init_rate_id)); + + if ((p_dm_odm->rf_type == ODM_2T2R) | (p_dm_odm->rf_type == ODM_2T2R_GREEN) | (p_dm_odm->rf_type == ODM_2T3R) | (p_dm_odm->rf_type == ODM_2T4R)) { + + if ((p_dm_odm->support_ic_type & (ODM_RTL8812 | ODM_RTL8192E)) && + (wireless_mode & (ODM_WM_N24G | ODM_WM_N5G)) + ) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("[ON ASSOC] set N-2SS ARFR5 table\n")); + odm_set_mac_reg(p_dm_odm, 0x4a4, MASKDWORD, 0xfc1ffff); /*N-2SS, ARFR5, rate_id = 0xe*/ + odm_set_mac_reg(p_dm_odm, 0x4a8, MASKDWORD, 0x0); /*N-2SS, ARFR5, rate_id = 0xe*/ + } else if ((p_dm_odm->support_ic_type & (ODM_RTL8812)) && + (wireless_mode & (ODM_WM_AC_5G | ODM_WM_AC_24G | ODM_WM_AC_ONLY)) + ) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("[ON ASSOC] set AC-2SS ARFR0 table\n")); + odm_set_mac_reg(p_dm_odm, 0x444, MASKDWORD, 0x0fff); /*AC-2SS, ARFR0, rate_id = 0x9*/ + odm_set_mac_reg(p_dm_odm, 0x448, MASKDWORD, 0xff01f000); /*AC-2SS, ARFR0, rate_id = 0x9*/ + } + } + +} + +void +phydm_ra_dynamic_rate_id_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (p_dm_odm->support_ic_type & (ODM_RTL8812 | ODM_RTL8192E)) { + + odm_set_mac_reg(p_dm_odm, 0x4a4, MASKDWORD, 0xfc1ffff); /*N-2SS, ARFR5, rate_id = 0xe*/ + odm_set_mac_reg(p_dm_odm, 0x4a8, MASKDWORD, 0x0); /*N-2SS, ARFR5, rate_id = 0xe*/ + + odm_set_mac_reg(p_dm_odm, 0x444, MASKDWORD, 0x0fff); /*AC-2SS, ARFR0, rate_id = 0x9*/ + odm_set_mac_reg(p_dm_odm, 0x448, MASKDWORD, 0xff01f000); /*AC-2SS, ARFR0, rate_id = 0x9*/ + } +} + +void +phydm_update_rate_id( + void *p_dm_void, + u8 rate, + u8 platform_macid +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + u8 current_tx_ss; + u8 rate_idx = rate & 0x7f; /*remove bit7 SGI*/ + u8 wireless_mode; + u8 phydm_macid; + struct sta_info *p_entry; + + +#if 0 + if (rate_idx >= ODM_RATEVHTSS2MCS0) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("rate[%d]: (( VHT2SS-MCS%d ))\n", platform_macid, (rate_idx - ODM_RATEVHTSS2MCS0))); + /*dummy for SD4 check patch*/ + } else if (rate_idx >= ODM_RATEVHTSS1MCS0) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("rate[%d]: (( VHT1SS-MCS%d ))\n", platform_macid, (rate_idx - ODM_RATEVHTSS1MCS0))); + /*dummy for SD4 check patch*/ + } else if (rate_idx >= ODM_RATEMCS0) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("rate[%d]: (( HT-MCS%d ))\n", platform_macid, (rate_idx - ODM_RATEMCS0))); + /*dummy for SD4 check patch*/ + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("rate[%d]: (( HT-MCS%d ))\n", platform_macid, rate_idx)); + /*dummy for SD4 check patch*/ + } +#endif + + phydm_macid = p_dm_odm->platform2phydm_macid_table[platform_macid]; + p_entry = p_dm_odm->p_odm_sta_info[phydm_macid]; + + if (IS_STA_VALID(p_entry)) { + wireless_mode = p_entry->wireless_mode; + + if ((p_dm_odm->rf_type == ODM_2T2R) | (p_dm_odm->rf_type == ODM_2T2R_GREEN) | (p_dm_odm->rf_type == ODM_2T3R) | (p_dm_odm->rf_type == ODM_2T4R)) { + + p_entry->ratr_idx = p_entry->ratr_idx_init; + if (wireless_mode & (ODM_WM_N24G | ODM_WM_N5G)) { /*N mode*/ + if (rate_idx >= ODM_RATEMCS8 && rate_idx <= ODM_RATEMCS15) { /*2SS mode*/ + + p_entry->ratr_idx = ARFR_5_RATE_ID; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("ARFR_5\n")); + } + } else if (wireless_mode & (ODM_WM_AC_5G | ODM_WM_AC_24G | ODM_WM_AC_ONLY)) {/*AC mode*/ + if (rate_idx >= ODM_RATEVHTSS2MCS0 && rate_idx <= ODM_RATEVHTSS2MCS9) {/*2SS mode*/ + + p_entry->ratr_idx = ARFR_0_RATE_ID; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("ARFR_0\n")); + } + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("UPdate_RateID[%d]: (( 0x%x ))\n", platform_macid, p_entry->ratr_idx)); + } + } + +} +#endif + +void +phydm_print_rate( + void *p_dm_void, + u8 rate, + u32 dbg_component +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 legacy_table[12] = {1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54}; + u8 rate_idx = rate & 0x7f; /*remove bit7 SGI*/ + u8 vht_en = (rate_idx >= ODM_RATEVHTSS1MCS0) ? 1 : 0; + u8 b_sgi = (rate & 0x80) >> 7; + + ODM_RT_TRACE_F(p_dm_odm, dbg_component, ODM_DBG_LOUD, ("( %s%s%s%s%d%s%s)\n", + ((rate_idx >= ODM_RATEVHTSS1MCS0) && (rate_idx <= ODM_RATEVHTSS1MCS9)) ? "VHT 1ss " : "", + ((rate_idx >= ODM_RATEVHTSS2MCS0) && (rate_idx <= ODM_RATEVHTSS2MCS9)) ? "VHT 2ss " : "", + ((rate_idx >= ODM_RATEVHTSS3MCS0) && (rate_idx <= ODM_RATEVHTSS3MCS9)) ? "VHT 3ss " : "", + (rate_idx >= ODM_RATEMCS0) ? "MCS " : "", + (vht_en) ? ((rate_idx - ODM_RATEVHTSS1MCS0) % 10) : ((rate_idx >= ODM_RATEMCS0) ? (rate_idx - ODM_RATEMCS0) : ((rate_idx <= ODM_RATE54M) ? legacy_table[rate_idx] : 0)), + (b_sgi) ? "-S" : " ", + (rate_idx >= ODM_RATEMCS0) ? "" : "M")); +} + +void +phydm_c2h_ra_report_handler( + void *p_dm_void, + u8 *cmd_buf, + u8 cmd_len +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + u8 legacy_table[12] = {1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54}; + u8 macid = cmd_buf[1]; + u8 rate = cmd_buf[0]; + u8 rate_idx = rate & 0x7f; /*remove bit7 SGI*/ + u8 pre_rate = p_ra_table->link_tx_rate[macid]; + u8 rate_order; + + if (cmd_len >= 4) { + if (cmd_buf[3] == 0) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("TX Init-rate Update[%d]:", macid)); + /**/ + } else if (cmd_buf[3] == 0xff) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("FW Level: Fix rate[%d]:", macid)); + /**/ + } else if (cmd_buf[3] == 1) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("Try Success[%d]:", macid)); + /**/ + } else if (cmd_buf[3] == 2) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("Try Fail & Try Again[%d]:", macid)); + /**/ + } else if (cmd_buf[3] == 3) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("rate Back[%d]:", macid)); + /**/ + } else if (cmd_buf[3] == 4) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("start rate by RSSI[%d]:", macid)); + /**/ + } else if (cmd_buf[3] == 5) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("Try rate[%d]:", macid)); + /**/ + } + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("Tx rate Update[%d]:", macid)); + /**/ + } + + /*phydm_print_rate(p_dm_odm, pre_rate_idx, ODM_COMP_RATE_ADAPTIVE);*/ + /*ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, (">\n",macid );*/ + phydm_print_rate(p_dm_odm, rate, ODM_COMP_RATE_ADAPTIVE); + + p_ra_table->link_tx_rate[macid] = rate; + + /*trigger power training*/ + + rate_order = phydm_rate_order_compute(p_dm_odm, rate_idx); + + if ((p_dm_odm->is_one_entry_only) || + ((rate_order > p_ra_table->highest_client_tx_order) && (p_ra_table->power_tracking_flag == 1)) + ) { + phydm_update_pwr_track(p_dm_odm, rate_idx); + p_ra_table->power_tracking_flag = 0; + } + + /*trigger dynamic rate ID*/ +#if (defined(CONFIG_RA_DYNAMIC_RATE_ID)) + if (p_dm_odm->support_ic_type & (ODM_RTL8812 | ODM_RTL8192E)) + phydm_update_rate_id(p_dm_odm, rate, macid); +#endif + +} + +void +odm_rssi_monitor_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + + p_ra_table->firstconnect = false; +} + +void +odm_ra_post_action_on_assoc( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + /* + p_dm_odm->h2c_rarpt_connect = 1; + odm_rssi_monitor_check(p_dm_odm); + p_dm_odm->h2c_rarpt_connect = 0; + */ +} + +void +phydm_init_ra_info( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; +} + +void +phydm_modify_RA_PCR_threshold( + void *p_dm_void, + u8 RA_offset_direction, + u8 RA_threshold_offset + +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + + p_ra_table->RA_offset_direction = RA_offset_direction; + p_ra_table->RA_threshold_offset = RA_threshold_offset; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("Set RA_threshold_offset = (( %s%d ))\n", ((RA_threshold_offset == 0) ? " " : ((RA_offset_direction) ? "+" : "-")), RA_threshold_offset)); +} + +static void +odm_rssi_monitor_check_mp( + void *p_dm_void +) +{ +} + +/*H2C_RSSI_REPORT*/ +static s8 phydm_rssi_report(struct PHY_DM_STRUCT *p_dm_odm, u8 mac_id) +{ + struct _ADAPTER *adapter = p_dm_odm->adapter; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter); + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(adapter); + u8 h2c_parameter[H2C_0X42_LENGTH] = {0}; + u8 UL_DL_STATE = 0, STBC_TX = 0, tx_bf_en = 0; + u8 cmdlen = H2C_0X42_LENGTH, first_connect = false; + u64 cur_tx_ok_cnt = 0, cur_rx_ok_cnt = 0; + struct sta_info *p_entry = p_dm_odm->p_odm_sta_info[mac_id]; + + if (!IS_STA_VALID(p_entry)) + return _FAIL; + + if (mac_id != p_entry->mac_id) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("%s mac_id:%u:%u invalid\n", __func__, mac_id, p_entry->mac_id)); + rtw_warn_on(1); + return _FAIL; + } + + if (IS_MCAST(p_entry->hwaddr)) /*if(psta->mac_id ==1)*/ + return _FAIL; + + if (p_entry->rssi_stat.undecorated_smoothed_pwdb == (-1)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("%s mac_id:%u, mac:"MAC_FMT", rssi == -1\n", __func__, p_entry->mac_id, MAC_ARG(p_entry->hwaddr))); + return _FAIL; + } + + cur_tx_ok_cnt = pdvobjpriv->traffic_stat.cur_tx_bytes; + cur_rx_ok_cnt = pdvobjpriv->traffic_stat.cur_rx_bytes; + if (cur_rx_ok_cnt > (cur_tx_ok_cnt * 6)) + UL_DL_STATE = 1; + else + UL_DL_STATE = 0; + +#ifdef CONFIG_BEAMFORMING + { +#if (BEAMFORMING_SUPPORT == 1) + enum beamforming_cap beamform_cap = phydm_beamforming_get_entry_beam_cap_by_mac_id(p_dm_odm, p_entry->mac_id); +#else/*for drv beamforming*/ + enum beamforming_cap beamform_cap = beamforming_get_entry_beam_cap_by_mac_id(&adapter->mlmepriv, p_entry->mac_id); +#endif + + if (beamform_cap & (BEAMFORMER_CAP_HT_EXPLICIT | BEAMFORMER_CAP_VHT_SU)) + tx_bf_en = 1; + else + tx_bf_en = 0; + } +#endif /*#ifdef CONFIG_BEAMFORMING*/ + + if (tx_bf_en) + STBC_TX = 0; + else + STBC_TX = TEST_FLAG(p_entry->htpriv.stbc_cap, STBC_HT_ENABLE_TX); + + h2c_parameter[0] = (u8)(p_entry->mac_id & 0xFF); + h2c_parameter[2] = p_entry->rssi_stat.undecorated_smoothed_pwdb & 0x7F; + + if (UL_DL_STATE) + h2c_parameter[3] |= RAINFO_BE_RX_STATE; + + if (tx_bf_en) + h2c_parameter[3] |= RAINFO_BF_STATE; + if (STBC_TX) + h2c_parameter[3] |= RAINFO_STBC_STATE; + if (p_dm_odm->noisy_decision) + h2c_parameter[3] |= RAINFO_NOISY_STATE; + + if ((p_entry->ra_rpt_linked == false) && (p_entry->rssi_stat.is_send_rssi == RA_RSSI_STATE_SEND)) { + h2c_parameter[3] |= RAINFO_INIT_RSSI_RATE_STATE; + p_entry->ra_rpt_linked = true; + p_entry->rssi_stat.is_send_rssi = RA_RSSI_STATE_HOLD; + first_connect = true; + } + + h2c_parameter[4] = (p_ra_table->RA_threshold_offset & 0x7f) | (p_ra_table->RA_offset_direction << 7); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("RA_threshold_offset = (( %s%d ))\n", ((p_ra_table->RA_threshold_offset == 0) ? " " : ((p_ra_table->RA_offset_direction) ? "+" : "-")), p_ra_table->RA_threshold_offset)); + + if (first_connect) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("%s mac_id:%u, mac:"MAC_FMT", rssi:%d\n", __func__, + p_entry->mac_id, MAC_ARG(p_entry->hwaddr), p_entry->rssi_stat.undecorated_smoothed_pwdb)); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("%s RAINFO - TP:%s, TxBF:%s, STBC:%s, Noisy:%s, Firstcont:%s\n", __func__, + (UL_DL_STATE) ? "DL" : "UL", (tx_bf_en) ? "EN" : "DIS", (STBC_TX) ? "EN" : "DIS", + (p_dm_odm->noisy_decision) ? "True" : "False", (first_connect) ? "True" : "False")); + } + + if (p_hal_data->fw_ractrl == true) { + if (p_dm_odm->support_ic_type == ODM_RTL8188E) + cmdlen = 3; + odm_fill_h2c_cmd(p_dm_odm, ODM_H2C_RSSI_REPORT, cmdlen, h2c_parameter); + } else { +#if ((RATE_ADAPTIVE_SUPPORT == 1)) + if (p_dm_odm->support_ic_type == ODM_RTL8188E) + odm_ra_set_rssi_8188e(p_dm_odm, (u8)(p_entry->mac_id & 0xFF), p_entry->rssi_stat.undecorated_smoothed_pwdb & 0x7F); +#endif + } + return _SUCCESS; +} + +static void phydm_ra_rssi_rpt_wk_hdl(void *p_context) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_context; + int i; + u8 mac_id = 0xFF; + struct sta_info *p_entry = NULL; + + for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { + p_entry = p_dm_odm->p_odm_sta_info[i]; + if (IS_STA_VALID(p_entry)) { + if (IS_MCAST(p_entry->hwaddr)) /*if(psta->mac_id ==1)*/ + continue; + if (p_entry->ra_rpt_linked == false) { + mac_id = i; + break; + } + } + } + if (mac_id != 0xFF) + phydm_rssi_report(p_dm_odm, mac_id); +} +void phydm_ra_rssi_rpt_wk(void *p_context) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_context; + + rtw_run_in_thread_cmd(p_dm_odm->adapter, phydm_ra_rssi_rpt_wk_hdl, p_dm_odm); +} + +static void +odm_rssi_monitor_check_ce( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ADAPTER *adapter = p_dm_odm->adapter; + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(adapter); + struct sta_info *p_entry; + int i; + int tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff; + u8 sta_cnt = 0; + + if (p_dm_odm->is_linked != true) + return; + + for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { + p_entry = p_dm_odm->p_odm_sta_info[i]; + if (IS_STA_VALID(p_entry)) { + if (IS_MCAST(p_entry->hwaddr)) /*if(psta->mac_id ==1)*/ + continue; + + if (p_entry->rssi_stat.undecorated_smoothed_pwdb == (-1)) + continue; + + if (p_entry->rssi_stat.undecorated_smoothed_pwdb < tmp_entry_min_pwdb) + tmp_entry_min_pwdb = p_entry->rssi_stat.undecorated_smoothed_pwdb; + + if (p_entry->rssi_stat.undecorated_smoothed_pwdb > tmp_entry_max_pwdb) + tmp_entry_max_pwdb = p_entry->rssi_stat.undecorated_smoothed_pwdb; + + if (phydm_rssi_report(p_dm_odm, i)) + sta_cnt++; + } + } + + if (tmp_entry_max_pwdb != 0) /* If associated entry is found */ + p_hal_data->entry_max_undecorated_smoothed_pwdb = tmp_entry_max_pwdb; + else + p_hal_data->entry_max_undecorated_smoothed_pwdb = 0; + + if (tmp_entry_min_pwdb != 0xff) /* If associated entry is found */ + p_hal_data->entry_min_undecorated_smoothed_pwdb = tmp_entry_min_pwdb; + else + p_hal_data->entry_min_undecorated_smoothed_pwdb = 0; + + find_minimum_rssi(adapter);/* get pdmpriv->min_undecorated_pwdb_for_dm */ + + p_dm_odm->rssi_min = p_hal_data->min_undecorated_pwdb_for_dm; + /* odm_cmn_info_update(&p_hal_data->odmpriv,ODM_CMNINFO_RSSI_MIN, pdmpriv->min_undecorated_pwdb_for_dm); */ +} + +static void +odm_rssi_monitor_check_ap( + void *p_dm_void +) +{ +} + +void +odm_rssi_monitor_check( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (!(p_dm_odm->support_ability & ODM_BB_RSSI_MONITOR)) + return; + + switch (p_dm_odm->support_platform) { + case ODM_WIN: + odm_rssi_monitor_check_mp(p_dm_odm); + break; + + case ODM_CE: + odm_rssi_monitor_check_ce(p_dm_odm); + break; + + case ODM_AP: + odm_rssi_monitor_check_ap(p_dm_odm); + break; + + default: + break; + } + +} + +void +odm_rate_adaptive_mask_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ODM_RATE_ADAPTIVE *p_odm_ra = &p_dm_odm->rate_adaptive; + + p_odm_ra->type = dm_type_by_driver; + if (p_odm_ra->type == dm_type_by_driver) + p_dm_odm->is_use_ra_mask = true; + else + p_dm_odm->is_use_ra_mask = false; + + p_odm_ra->ratr_state = DM_RATR_STA_INIT; + + p_odm_ra->ldpc_thres = 35; + p_odm_ra->is_use_ldpc = false; + + p_odm_ra->high_rssi_thresh = 50; + p_odm_ra->low_rssi_thresh = 20; +} +/*----------------------------------------------------------------------------- + * Function: odm_refresh_rate_adaptive_mask() + * + * Overview: Update rate table mask according to rssi + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/27/2009 hpfan Create version 0. + * + *---------------------------------------------------------------------------*/ +void +odm_refresh_rate_adaptive_mask( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + + if (!p_dm_odm->is_linked) + return; + + if (!(p_dm_odm->support_ability & ODM_BB_RA_MASK)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_TRACE, ("odm_refresh_rate_adaptive_mask(): Return cos not supported\n")); + return; + } + + p_ra_table->force_update_ra_mask_count++; + /* */ + /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */ + /* at the same time. In the stage2/3, we need to prive universal interface and merge all */ + /* HW dynamic mechanism. */ + /* */ + switch (p_dm_odm->support_platform) { + case ODM_WIN: + odm_refresh_rate_adaptive_mask_mp(p_dm_odm); + break; + + case ODM_CE: + odm_refresh_rate_adaptive_mask_ce(p_dm_odm); + break; + + case ODM_AP: + odm_refresh_rate_adaptive_mask_apadsl(p_dm_odm); + break; + } + +} + +static u8 +phydm_trans_platform_bw( + void *p_dm_void, + u8 BW +) +{ + if (BW == CHANNEL_WIDTH_20) + BW = PHYDM_BW_20; + + else if (BW == CHANNEL_WIDTH_40) + BW = PHYDM_BW_40; + + else if (BW == CHANNEL_WIDTH_80) + BW = PHYDM_BW_80; + + else if (BW == CHANNEL_WIDTH_160) + BW = PHYDM_BW_160; + + else if (BW == CHANNEL_WIDTH_80_80) + BW = PHYDM_BW_80_80; + + return BW; +} + +static u8 +phydm_trans_platform_rf_type( + void *p_dm_void, + u8 rf_type +) +{ + if (rf_type == RF_1T2R) + rf_type = PHYDM_RF_1T2R; + + else if (rf_type == RF_2T4R) + rf_type = PHYDM_RF_2T4R; + + else if (rf_type == RF_2T2R) + rf_type = PHYDM_RF_2T2R; + + else if (rf_type == RF_1T1R) + rf_type = PHYDM_RF_1T1R; + + else if (rf_type == RF_2T2R_GREEN) + rf_type = PHYDM_RF_2T2R_GREEN; + + else if (rf_type == RF_3T3R) + rf_type = PHYDM_RF_3T3R; + + else if (rf_type == RF_4T4R) + rf_type = PHYDM_RF_4T4R; + + else if (rf_type == RF_2T3R) + rf_type = PHYDM_RF_1T2R; + + else if (rf_type == RF_3T4R) + rf_type = PHYDM_RF_3T4R; + + return rf_type; +} + +static u32 +phydm_trans_platform_wireless_mode( + void *p_dm_void, + u32 wireless_mode +) +{ + if (wireless_mode == WIRELESS_11A) + wireless_mode = PHYDM_WIRELESS_MODE_A; + + else if (wireless_mode == WIRELESS_11B) + wireless_mode = PHYDM_WIRELESS_MODE_B; + + else if ((wireless_mode == WIRELESS_11G) || (wireless_mode == WIRELESS_11BG)) + wireless_mode = PHYDM_WIRELESS_MODE_G; + + else if (wireless_mode == WIRELESS_AUTO) + wireless_mode = PHYDM_WIRELESS_MODE_AUTO; + + else if ((wireless_mode == WIRELESS_11_24N) || + (wireless_mode == WIRELESS_11G_24N) || + (wireless_mode == WIRELESS_11B_24N) || + (wireless_mode == WIRELESS_11BG_24N) || + (wireless_mode == WIRELESS_MODE_24G) || + (wireless_mode == WIRELESS_11ABGN) || + (wireless_mode == WIRELESS_11AGN)) + wireless_mode = PHYDM_WIRELESS_MODE_N_24G; + + else if ((wireless_mode == WIRELESS_11_5N) || (wireless_mode == WIRELESS_11A_5N)) + wireless_mode = PHYDM_WIRELESS_MODE_N_5G; + + else if ((wireless_mode == WIRELESS_11AC) || (wireless_mode == WIRELESS_11_5AC) || (wireless_mode == WIRELESS_MODE_5G)) + wireless_mode = PHYDM_WIRELESS_MODE_AC_5G; + + else if (wireless_mode == WIRELESS_11_24AC) + wireless_mode = PHYDM_WIRELESS_MODE_AC_24G; + + else if (wireless_mode == WIRELESS_11AC) + wireless_mode = PHYDM_WIRELESS_MODE_AC_ONLY; + + else if (wireless_mode == WIRELESS_MODE_MAX) + wireless_mode = PHYDM_WIRELESS_MODE_MAX; + else + wireless_mode = PHYDM_WIRELESS_MODE_UNKNOWN; + + return wireless_mode; +} + +u8 +phydm_vht_en_mapping( + void *p_dm_void, + u32 wireless_mode +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 vht_en_out = 0; + + if ((wireless_mode == PHYDM_WIRELESS_MODE_AC_5G) || + (wireless_mode == PHYDM_WIRELESS_MODE_AC_24G) || + (wireless_mode == PHYDM_WIRELESS_MODE_AC_ONLY) + ) { + vht_en_out = 1; + /**/ + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("wireless_mode= (( 0x%x )), VHT_EN= (( %d ))\n", wireless_mode, vht_en_out)); + return vht_en_out; +} + +u8 +phydm_rate_id_mapping( + void *p_dm_void, + u32 wireless_mode, + u8 rf_type, + u8 bw +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 rate_id_idx = 0; + u8 phydm_BW; + u8 phydm_rf_type; + + phydm_BW = phydm_trans_platform_bw(p_dm_odm, bw); + phydm_rf_type = phydm_trans_platform_rf_type(p_dm_odm, rf_type); + wireless_mode = phydm_trans_platform_wireless_mode(p_dm_odm, wireless_mode); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("wireless_mode= (( 0x%x )), rf_type = (( 0x%x )), BW = (( 0x%x ))\n", + wireless_mode, phydm_rf_type, phydm_BW)); + + + switch (wireless_mode) { + + case PHYDM_WIRELESS_MODE_N_24G: + { + + if (phydm_BW == PHYDM_BW_40) { + + if (phydm_rf_type == PHYDM_RF_1T1R) + rate_id_idx = PHYDM_BGN_40M_1SS; + else if (phydm_rf_type == PHYDM_RF_2T2R) + rate_id_idx = PHYDM_BGN_40M_2SS; + else + rate_id_idx = PHYDM_ARFR5_N_3SS; + + } else { + + if (phydm_rf_type == PHYDM_RF_1T1R) + rate_id_idx = PHYDM_BGN_20M_1SS; + else if (phydm_rf_type == PHYDM_RF_2T2R) + rate_id_idx = PHYDM_BGN_20M_2SS; + else + rate_id_idx = PHYDM_ARFR5_N_3SS; + } + } + break; + + case PHYDM_WIRELESS_MODE_N_5G: + { + if (phydm_rf_type == PHYDM_RF_1T1R) + rate_id_idx = PHYDM_GN_N1SS; + else if (phydm_rf_type == PHYDM_RF_2T2R) + rate_id_idx = PHYDM_GN_N2SS; + else + rate_id_idx = PHYDM_ARFR5_N_3SS; + } + + break; + + case PHYDM_WIRELESS_MODE_G: + rate_id_idx = PHYDM_BG; + break; + + case PHYDM_WIRELESS_MODE_A: + rate_id_idx = PHYDM_G; + break; + + case PHYDM_WIRELESS_MODE_B: + rate_id_idx = PHYDM_B_20M; + break; + + + case PHYDM_WIRELESS_MODE_AC_5G: + case PHYDM_WIRELESS_MODE_AC_ONLY: + { + if (phydm_rf_type == PHYDM_RF_1T1R) + rate_id_idx = PHYDM_ARFR1_AC_1SS; + else if (phydm_rf_type == PHYDM_RF_2T2R) + rate_id_idx = PHYDM_ARFR0_AC_2SS; + else + rate_id_idx = PHYDM_ARFR4_AC_3SS; + } + break; + + case PHYDM_WIRELESS_MODE_AC_24G: + { + /*Becareful to set "Lowest rate" while using PHYDM_ARFR4_AC_3SS in 2.4G/5G*/ + if (phydm_BW >= PHYDM_BW_80) { + if (phydm_rf_type == PHYDM_RF_1T1R) + rate_id_idx = PHYDM_ARFR1_AC_1SS; + else if (phydm_rf_type == PHYDM_RF_2T2R) + rate_id_idx = PHYDM_ARFR0_AC_2SS; + else + rate_id_idx = PHYDM_ARFR4_AC_3SS; + } else { + + if (phydm_rf_type == PHYDM_RF_1T1R) + rate_id_idx = PHYDM_ARFR2_AC_2G_1SS; + else if (phydm_rf_type == PHYDM_RF_2T2R) + rate_id_idx = PHYDM_ARFR3_AC_2G_2SS; + else + rate_id_idx = PHYDM_ARFR4_AC_3SS; + } + } + break; + + default: + rate_id_idx = 0; + break; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("RA rate ID = (( 0x%x ))\n", rate_id_idx)); + + return rate_id_idx; +} + +void +phydm_update_hal_ra_mask( + void *p_dm_void, + u32 wireless_mode, + u8 rf_type, + u8 BW, + u8 mimo_ps_enable, + u8 disable_cck_rate, + u32 *ratr_bitmap_msb_in, + u32 *ratr_bitmap_lsb_in, + u8 tx_rate_level +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u32 mask_rate_threshold; + u8 phydm_rf_type; + u8 phydm_BW; + u32 ratr_bitmap = *ratr_bitmap_lsb_in, ratr_bitmap_msb = *ratr_bitmap_msb_in; + + wireless_mode = phydm_trans_platform_wireless_mode(p_dm_odm, wireless_mode); + + phydm_rf_type = phydm_trans_platform_rf_type(p_dm_odm, rf_type); + phydm_BW = phydm_trans_platform_bw(p_dm_odm, BW); + + /*ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("phydm_rf_type = (( %x )), rf_type = (( %x ))\n", phydm_rf_type, rf_type));*/ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("Platfoem original RA Mask = (( 0x %x | %x ))\n", ratr_bitmap_msb, ratr_bitmap)); + + switch (wireless_mode) { + + case PHYDM_WIRELESS_MODE_B: + { + ratr_bitmap &= 0x0000000f; + } + break; + + case PHYDM_WIRELESS_MODE_G: + { + ratr_bitmap &= 0x00000ff5; + } + break; + + case PHYDM_WIRELESS_MODE_A: + { + ratr_bitmap &= 0x00000ff0; + } + break; + + case PHYDM_WIRELESS_MODE_N_24G: + case PHYDM_WIRELESS_MODE_N_5G: + { + if (mimo_ps_enable) + phydm_rf_type = PHYDM_RF_1T1R; + + if (phydm_rf_type == PHYDM_RF_1T1R) { + + if (phydm_BW == PHYDM_BW_40) + ratr_bitmap &= 0x000ff015; + else + ratr_bitmap &= 0x000ff005; + } else if (phydm_rf_type == PHYDM_RF_2T2R || phydm_rf_type == PHYDM_RF_2T4R || phydm_rf_type == PHYDM_RF_2T3R) { + + if (phydm_BW == PHYDM_BW_40) + ratr_bitmap &= 0x0ffff015; + else + ratr_bitmap &= 0x0ffff005; + } else { /*3T*/ + + ratr_bitmap &= 0xfffff015; + ratr_bitmap_msb &= 0xf; + } + } + break; + + case PHYDM_WIRELESS_MODE_AC_24G: + { + if (phydm_rf_type == PHYDM_RF_1T1R) + ratr_bitmap &= 0x003ff015; + else if (phydm_rf_type == PHYDM_RF_2T2R || phydm_rf_type == PHYDM_RF_2T4R || phydm_rf_type == PHYDM_RF_2T3R) + ratr_bitmap &= 0xfffff015; + else {/*3T*/ + + ratr_bitmap &= 0xfffff010; + ratr_bitmap_msb &= 0x3ff; + } + + if (phydm_BW == PHYDM_BW_20) {/* AC 20MHz doesn't support MCS9 */ + ratr_bitmap &= 0x7fdfffff; + ratr_bitmap_msb &= 0x1ff; + } + } + break; + + case PHYDM_WIRELESS_MODE_AC_5G: + { + if (phydm_rf_type == PHYDM_RF_1T1R) + ratr_bitmap &= 0x003ff010; + else if (phydm_rf_type == PHYDM_RF_2T2R || phydm_rf_type == PHYDM_RF_2T4R || phydm_rf_type == PHYDM_RF_2T3R) + ratr_bitmap &= 0xfffff010; + else {/*3T*/ + + ratr_bitmap &= 0xfffff010; + ratr_bitmap_msb &= 0x3ff; + } + + if (phydm_BW == PHYDM_BW_20) {/* AC 20MHz doesn't support MCS9 */ + ratr_bitmap &= 0x7fdfffff; + ratr_bitmap_msb &= 0x1ff; + } + } + break; + + default: + break; + } + + if (wireless_mode != PHYDM_WIRELESS_MODE_B) { + + if (tx_rate_level == 0) + ratr_bitmap &= 0xffffffff; + else if (tx_rate_level == 1) + ratr_bitmap &= 0xfffffff0; + else if (tx_rate_level == 2) + ratr_bitmap &= 0xffffefe0; + else if (tx_rate_level == 3) + ratr_bitmap &= 0xffffcfc0; + else if (tx_rate_level == 4) + ratr_bitmap &= 0xffff8f80; + else if (tx_rate_level >= 5) + ratr_bitmap &= 0xffff0f00; + + } + + if (disable_cck_rate) + ratr_bitmap &= 0xfffffff0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("wireless_mode= (( 0x%x )), rf_type = (( 0x%x )), BW = (( 0x%x )), MimoPs_en = (( %d )), tx_rate_level= (( 0x%x ))\n", + wireless_mode, phydm_rf_type, phydm_BW, mimo_ps_enable, tx_rate_level)); + + /*ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("111 Phydm modified RA Mask = (( 0x %x | %x ))\n", ratr_bitmap_msb, ratr_bitmap));*/ + + *ratr_bitmap_lsb_in = ratr_bitmap; + *ratr_bitmap_msb_in = ratr_bitmap_msb; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("Phydm modified RA Mask = (( 0x %x | %x ))\n", *ratr_bitmap_msb_in, *ratr_bitmap_lsb_in)); + +} + +u8 +phydm_RA_level_decision( + void *p_dm_void, + u32 rssi, + u8 ratr_state +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 ra_lowest_rate; + u8 ra_rate_floor_table[RA_FLOOR_TABLE_SIZE] = {20, 34, 38, 42, 46, 50, 100}; /*MCS0 ~ MCS4 , VHT1SS MCS0 ~ MCS4 , G 6M~24M*/ + u8 new_ratr_state = 0; + u8 i; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("curr RA level = ((%d)), Rate_floor_table ori [ %d , %d, %d , %d, %d, %d]\n", ratr_state, + ra_rate_floor_table[0], ra_rate_floor_table[1], ra_rate_floor_table[2], ra_rate_floor_table[3], ra_rate_floor_table[4], ra_rate_floor_table[5])); + + for (i = 0; i < RA_FLOOR_TABLE_SIZE; i++) { + + if (i >= (ratr_state)) + ra_rate_floor_table[i] += RA_FLOOR_UP_GAP; + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("RSSI = ((%d)), Rate_floor_table_mod [ %d , %d, %d , %d, %d, %d]\n", + rssi, ra_rate_floor_table[0], ra_rate_floor_table[1], ra_rate_floor_table[2], ra_rate_floor_table[3], ra_rate_floor_table[4], ra_rate_floor_table[5])); + + for (i = 0; i < RA_FLOOR_TABLE_SIZE; i++) { + + if (rssi < ra_rate_floor_table[i]) { + new_ratr_state = i; + break; + } + } + + + + return new_ratr_state; + +} + +void +odm_refresh_rate_adaptive_mask_mp( + void *p_dm_void +) +{ +} + +void +odm_refresh_rate_adaptive_mask_ce( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + struct _ADAPTER *p_adapter = p_dm_odm->adapter; + struct _ODM_RATE_ADAPTIVE *p_ra = &p_dm_odm->rate_adaptive; + u32 i; + struct sta_info *p_entry; + u8 ratr_state_new; + + if (RTW_CANNOT_RUN(p_adapter)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_TRACE, ("<---- odm_refresh_rate_adaptive_mask(): driver is going to unload\n")); + return; + } + + if (!p_dm_odm->is_use_ra_mask) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("<---- odm_refresh_rate_adaptive_mask(): driver does not control rate adaptive mask\n")); + return; + } + + for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { + + p_entry = p_dm_odm->p_odm_sta_info[i]; + + if (IS_STA_VALID(p_entry)) { + + if (IS_MCAST(p_entry->hwaddr)) + continue; + +#if ((RTL8812A_SUPPORT == 1) || (RTL8821A_SUPPORT == 1)) + if ((p_dm_odm->support_ic_type == ODM_RTL8812) || (p_dm_odm->support_ic_type == ODM_RTL8821)) { + if (p_entry->rssi_stat.undecorated_smoothed_pwdb < p_ra->ldpc_thres) { + p_ra->is_use_ldpc = true; + p_ra->is_lower_rts_rate = true; + if ((p_dm_odm->support_ic_type == ODM_RTL8821) && (p_dm_odm->cut_version == ODM_CUT_A)) + set_ra_ldpc_8812(p_entry, true); + /* dbg_print("RSSI=%d, is_use_ldpc = true\n", p_hal_data->undecorated_smoothed_pwdb); */ + } else if (p_entry->rssi_stat.undecorated_smoothed_pwdb > (p_ra->ldpc_thres - 5)) { + p_ra->is_use_ldpc = false; + p_ra->is_lower_rts_rate = false; + if ((p_dm_odm->support_ic_type == ODM_RTL8821) && (p_dm_odm->cut_version == ODM_CUT_A)) + set_ra_ldpc_8812(p_entry, false); + /* dbg_print("RSSI=%d, is_use_ldpc = false\n", p_hal_data->undecorated_smoothed_pwdb); */ + } + } +#endif + +#if RA_MASK_PHYDMLIZE_CE + ratr_state_new = phydm_RA_level_decision(p_dm_odm, p_entry->rssi_stat.undecorated_smoothed_pwdb, p_entry->rssi_level); + + if ((p_entry->rssi_level != ratr_state_new) || (p_ra_table->force_update_ra_mask_count >= FORCED_UPDATE_RAMASK_PERIOD)) { + + p_ra_table->force_update_ra_mask_count = 0; + /*ODM_PRINT_ADDR(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("Target AP addr :"), pstat->hwaddr);*/ + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("Update Tx RA Level: ((%x)) -> ((%x)), RSSI = ((%d))\n", + p_entry->rssi_level, ratr_state_new, p_entry->rssi_stat.undecorated_smoothed_pwdb)); + + p_entry->rssi_level = ratr_state_new; + rtw_hal_update_ra_mask(p_entry, p_entry->rssi_level, false); + } else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("Stay in RA level = (( %d ))\n\n", ratr_state_new)); + /**/ + } +#else + if (odm_ra_state_check(p_dm_odm, p_entry->rssi_stat.undecorated_smoothed_pwdb, false, &p_entry->rssi_level)) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("RSSI:%d, RSSI_LEVEL:%d\n", p_entry->rssi_stat.undecorated_smoothed_pwdb, p_entry->rssi_level)); + /* printk("RSSI:%d, RSSI_LEVEL:%d\n", pstat->rssi_stat.undecorated_smoothed_pwdb, pstat->rssi_level); */ + rtw_hal_update_ra_mask(p_entry, p_entry->rssi_level, false); + } else if (p_dm_odm->is_change_state) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("Change Power Training state, is_disable_power_training = %d\n", p_dm_odm->is_disable_power_training)); + rtw_hal_update_ra_mask(p_entry, p_entry->rssi_level, false); + } +#endif + + } + } +} + +void +odm_refresh_rate_adaptive_mask_apadsl( + void *p_dm_void +) +{ +} + +void +odm_refresh_basic_rate_mask( + void *p_dm_void +) +{ +} + +u8 +phydm_rate_order_compute( + void *p_dm_void, + u8 rate_idx +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 rate_order = 0; + + if (rate_idx >= ODM_RATEVHTSS4MCS0) { + + rate_idx -= ODM_RATEVHTSS4MCS0; + /**/ + } else if (rate_idx >= ODM_RATEVHTSS3MCS0) { + + rate_idx -= ODM_RATEVHTSS3MCS0; + /**/ + } else if (rate_idx >= ODM_RATEVHTSS2MCS0) { + + rate_idx -= ODM_RATEVHTSS2MCS0; + /**/ + } else if (rate_idx >= ODM_RATEVHTSS1MCS0) { + + rate_idx -= ODM_RATEVHTSS1MCS0; + /**/ + } else if (rate_idx >= ODM_RATEMCS24) { + + rate_idx -= ODM_RATEMCS24; + /**/ + } else if (rate_idx >= ODM_RATEMCS16) { + + rate_idx -= ODM_RATEMCS16; + /**/ + } else if (rate_idx >= ODM_RATEMCS8) { + + rate_idx -= ODM_RATEMCS8; + /**/ + } + rate_order = rate_idx; + + return rate_order; + +} + +static void +phydm_ra_common_info_update( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + u16 macid; + u8 rate_order_tmp; + u8 cnt = 0; + + p_ra_table->highest_client_tx_order = 0; + p_ra_table->power_tracking_flag = 1; + + if (p_dm_odm->number_linked_client != 0) { + for (macid = 0; macid < ODM_ASSOCIATE_ENTRY_NUM; macid++) { + + rate_order_tmp = phydm_rate_order_compute(p_dm_odm, ((p_ra_table->link_tx_rate[macid]) & 0x7f)); + + if (rate_order_tmp >= (p_ra_table->highest_client_tx_order)) { + p_ra_table->highest_client_tx_order = rate_order_tmp; + p_ra_table->highest_client_tx_rate_order = macid; + } + + cnt++; + + if (cnt == p_dm_odm->number_linked_client) + break; + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("MACID[%d], Highest Tx order Update for power traking: %d\n", (p_ra_table->highest_client_tx_rate_order), (p_ra_table->highest_client_tx_order))); + } +} + +void +phydm_ra_info_watchdog( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + phydm_ra_common_info_update(p_dm_odm); + phydm_ra_dynamic_retry_limit(p_dm_odm); + phydm_ra_dynamic_retry_count(p_dm_odm); + odm_refresh_rate_adaptive_mask(p_dm_odm); + odm_refresh_basic_rate_mask(p_dm_odm); +} + +void +phydm_ra_info_init( + void *p_dm_void +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _rate_adaptive_table_ *p_ra_table = &p_dm_odm->dm_ra_table; + + p_ra_table->highest_client_tx_rate_order = 0; + p_ra_table->highest_client_tx_order = 0; + p_ra_table->RA_threshold_offset = 0; + p_ra_table->RA_offset_direction = 0; + +#if (defined(CONFIG_RA_DYNAMIC_RTY_LIMIT)) + phydm_ra_dynamic_retry_limit_init(p_dm_odm); +#endif + +#if (defined(CONFIG_RA_DYNAMIC_RATE_ID)) + phydm_ra_dynamic_rate_id_init(p_dm_odm); +#endif +#if (defined(CONFIG_RA_DBG_CMD)) + odm_ra_para_adjust_init(p_dm_odm); +#endif + +} + +u8 +odm_find_rts_rate( + void *p_dm_void, + u8 tx_rate, + bool is_erp_protect +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 rts_ini_rate = ODM_RATE6M; + + if (is_erp_protect) /* use CCK rate as RTS*/ + rts_ini_rate = ODM_RATE1M; + else { + switch (tx_rate) { + case ODM_RATEVHTSS3MCS9: + case ODM_RATEVHTSS3MCS8: + case ODM_RATEVHTSS3MCS7: + case ODM_RATEVHTSS3MCS6: + case ODM_RATEVHTSS3MCS5: + case ODM_RATEVHTSS3MCS4: + case ODM_RATEVHTSS3MCS3: + case ODM_RATEVHTSS2MCS9: + case ODM_RATEVHTSS2MCS8: + case ODM_RATEVHTSS2MCS7: + case ODM_RATEVHTSS2MCS6: + case ODM_RATEVHTSS2MCS5: + case ODM_RATEVHTSS2MCS4: + case ODM_RATEVHTSS2MCS3: + case ODM_RATEVHTSS1MCS9: + case ODM_RATEVHTSS1MCS8: + case ODM_RATEVHTSS1MCS7: + case ODM_RATEVHTSS1MCS6: + case ODM_RATEVHTSS1MCS5: + case ODM_RATEVHTSS1MCS4: + case ODM_RATEVHTSS1MCS3: + case ODM_RATEMCS15: + case ODM_RATEMCS14: + case ODM_RATEMCS13: + case ODM_RATEMCS12: + case ODM_RATEMCS11: + case ODM_RATEMCS7: + case ODM_RATEMCS6: + case ODM_RATEMCS5: + case ODM_RATEMCS4: + case ODM_RATEMCS3: + case ODM_RATE54M: + case ODM_RATE48M: + case ODM_RATE36M: + case ODM_RATE24M: + rts_ini_rate = ODM_RATE24M; + break; + case ODM_RATEVHTSS3MCS2: + case ODM_RATEVHTSS3MCS1: + case ODM_RATEVHTSS2MCS2: + case ODM_RATEVHTSS2MCS1: + case ODM_RATEVHTSS1MCS2: + case ODM_RATEVHTSS1MCS1: + case ODM_RATEMCS10: + case ODM_RATEMCS9: + case ODM_RATEMCS2: + case ODM_RATEMCS1: + case ODM_RATE18M: + case ODM_RATE12M: + rts_ini_rate = ODM_RATE12M; + break; + case ODM_RATEVHTSS3MCS0: + case ODM_RATEVHTSS2MCS0: + case ODM_RATEVHTSS1MCS0: + case ODM_RATEMCS8: + case ODM_RATEMCS0: + case ODM_RATE9M: + case ODM_RATE6M: + rts_ini_rate = ODM_RATE6M; + break; + case ODM_RATE11M: + case ODM_RATE5_5M: + case ODM_RATE2M: + case ODM_RATE1M: + rts_ini_rate = ODM_RATE1M; + break; + default: + rts_ini_rate = ODM_RATE6M; + break; + } + } + + if (*p_dm_odm->p_band_type == 1) { + if (rts_ini_rate < ODM_RATE6M) + rts_ini_rate = ODM_RATE6M; + } + return rts_ini_rate; + +} + +static void +odm_set_ra_dm_arfb_by_noisy( + struct PHY_DM_STRUCT *p_dm_odm +) +{ +} + +void +odm_update_noisy_state( + void *p_dm_void, + bool is_noisy_state_from_c2h +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + + if (p_dm_odm->support_ic_type == ODM_RTL8821 || p_dm_odm->support_ic_type == ODM_RTL8812 || + p_dm_odm->support_ic_type == ODM_RTL8723B || p_dm_odm->support_ic_type == ODM_RTL8192E || p_dm_odm->support_ic_type == ODM_RTL8188E || p_dm_odm->support_ic_type == ODM_RTL8723D) + p_dm_odm->is_noisy_state = is_noisy_state_from_c2h; + odm_set_ra_dm_arfb_by_noisy(p_dm_odm); +}; + +void +phydm_update_pwr_track( + void *p_dm_void, + u8 rate +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + u8 path_idx = 0; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("Pwr Track Get rate=0x%x\n", rate)); + + p_dm_odm->tx_rate = rate; +} + + +static void +find_minimum_rssi( + struct _ADAPTER *p_adapter +) +{ + HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter); + struct PHY_DM_STRUCT *p_dm_odm = &(p_hal_data->odmpriv); + + /*Determine the minimum RSSI*/ + + if ((p_dm_odm->is_linked != true) && + (p_hal_data->entry_min_undecorated_smoothed_pwdb == 0)) { + p_hal_data->min_undecorated_pwdb_for_dm = 0; + /*ODM_RT_TRACE(p_dm_odm,COMP_BB_POWERSAVING, DBG_LOUD, ("Not connected to any\n"));*/ + } else + p_hal_data->min_undecorated_pwdb_for_dm = p_hal_data->entry_min_undecorated_smoothed_pwdb; + + /*DBG_8192C("%s=>min_undecorated_pwdb_for_dm(%d)\n",__func__,pdmpriv->min_undecorated_pwdb_for_dm);*/ + /*ODM_RT_TRACE(p_dm_odm,COMP_DIG, DBG_LOUD, ("min_undecorated_pwdb_for_dm =%d\n",p_hal_data->min_undecorated_pwdb_for_dm));*/ +} + +u64 +phydm_get_rate_bitmap_ex( + void *p_dm_void, + u32 macid, + u64 ra_mask, + u8 rssi_level, + u64 *dm_ra_mask, + u8 *dm_rte_id +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct sta_info *p_entry; + u64 rate_bitmap = 0; + u8 wireless_mode; + + p_entry = p_dm_odm->p_odm_sta_info[macid]; + if (!IS_STA_VALID(p_entry)) + return ra_mask; + wireless_mode = p_entry->wireless_mode; + switch (wireless_mode) { + case ODM_WM_B: + if (ra_mask & 0x000000000000000c) /* 11M or 5.5M enable */ + rate_bitmap = 0x000000000000000d; + else + rate_bitmap = 0x000000000000000f; + break; + + case (ODM_WM_G): + case (ODM_WM_A): + if (rssi_level == DM_RATR_STA_HIGH) + rate_bitmap = 0x0000000000000f00; + else + rate_bitmap = 0x0000000000000ff0; + break; + + case (ODM_WM_B|ODM_WM_G): + if (rssi_level == DM_RATR_STA_HIGH) + rate_bitmap = 0x0000000000000f00; + else if (rssi_level == DM_RATR_STA_MIDDLE) + rate_bitmap = 0x0000000000000ff0; + else + rate_bitmap = 0x0000000000000ff5; + break; + + case (ODM_WM_B|ODM_WM_G|ODM_WM_N24G): + case (ODM_WM_B|ODM_WM_N24G): + case (ODM_WM_G|ODM_WM_N24G): + case (ODM_WM_A|ODM_WM_N5G): + { + if (p_dm_odm->rf_type == ODM_1T2R || p_dm_odm->rf_type == ODM_1T1R) { + if (rssi_level == DM_RATR_STA_HIGH) + rate_bitmap = 0x00000000000f0000; + else if (rssi_level == DM_RATR_STA_MIDDLE) + rate_bitmap = 0x00000000000ff000; + else { + if (*(p_dm_odm->p_band_width) == ODM_BW40M) + rate_bitmap = 0x00000000000ff015; + else + rate_bitmap = 0x00000000000ff005; + } + } else if (p_dm_odm->rf_type == ODM_2T2R || p_dm_odm->rf_type == ODM_2T3R || p_dm_odm->rf_type == ODM_2T4R) { + if (rssi_level == DM_RATR_STA_HIGH) + rate_bitmap = 0x000000000f8f0000; + else if (rssi_level == DM_RATR_STA_MIDDLE) + rate_bitmap = 0x000000000f8ff000; + else { + if (*(p_dm_odm->p_band_width) == ODM_BW40M) + rate_bitmap = 0x000000000f8ff015; + else + rate_bitmap = 0x000000000f8ff005; + } + } else { + if (rssi_level == DM_RATR_STA_HIGH) + rate_bitmap = 0x0000000f0f0f0000L; + else if (rssi_level == DM_RATR_STA_MIDDLE) + rate_bitmap = 0x0000000fcfcfe000L; + else { + if (*(p_dm_odm->p_band_width) == ODM_BW40M) + rate_bitmap = 0x0000000ffffff015L; + else + rate_bitmap = 0x0000000ffffff005L; + } + } + } + break; + + case (ODM_WM_AC|ODM_WM_G): + if (rssi_level == 1) + rate_bitmap = 0x00000000fc3f0000L; + else if (rssi_level == 2) + rate_bitmap = 0x00000000fffff000L; + else + rate_bitmap = 0x00000000ffffffffL; + break; + + case (ODM_WM_AC|ODM_WM_A): + + if (p_dm_odm->rf_type == ODM_1T2R || p_dm_odm->rf_type == ODM_1T1R) { + if (rssi_level == 1) /* add by Gary for ac-series */ + rate_bitmap = 0x00000000003f8000L; + else if (rssi_level == 2) + rate_bitmap = 0x00000000003fe000L; + else + rate_bitmap = 0x00000000003ff010L; + } else if (p_dm_odm->rf_type == ODM_2T2R || p_dm_odm->rf_type == ODM_2T3R || p_dm_odm->rf_type == ODM_2T4R) { + if (rssi_level == 1) /* add by Gary for ac-series */ + rate_bitmap = 0x00000000fe3f8000L; /* VHT 2SS MCS3~9 */ + else if (rssi_level == 2) + rate_bitmap = 0x00000000fffff000L; /* VHT 2SS MCS0~9 */ + else + rate_bitmap = 0x00000000fffff010L; /* All */ + } else { + if (rssi_level == 1) /* add by Gary for ac-series */ + rate_bitmap = 0x000003f8fe3f8000ULL; /* VHT 3SS MCS3~9 */ + else if (rssi_level == 2) + rate_bitmap = 0x000003fffffff000ULL; /* VHT3SS MCS0~9 */ + else + rate_bitmap = 0x000003fffffff010ULL; /* All */ + } + break; + + default: + if (p_dm_odm->rf_type == ODM_1T2R || p_dm_odm->rf_type == ODM_1T1R) + rate_bitmap = 0x00000000000fffff; + else if (p_dm_odm->rf_type == ODM_2T2R || p_dm_odm->rf_type == ODM_2T3R || p_dm_odm->rf_type == ODM_2T4R) + rate_bitmap = 0x000000000fffffff; + else + rate_bitmap = 0x0000003fffffffffULL; + break; + + } + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, (" ==> rssi_level:0x%02x, wireless_mode:0x%02x, rate_bitmap:0x%016llx\n", rssi_level, wireless_mode, rate_bitmap)); + + return ra_mask & rate_bitmap; +} + + +u32 +odm_get_rate_bitmap( + void *p_dm_void, + u32 macid, + u32 ra_mask, + u8 rssi_level +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct sta_info *p_entry; + u32 rate_bitmap = 0; + u8 wireless_mode; + /* u8 wireless_mode =*(p_dm_odm->p_wireless_mode); */ + + + p_entry = p_dm_odm->p_odm_sta_info[macid]; + if (!IS_STA_VALID(p_entry)) + return ra_mask; + + wireless_mode = p_entry->wireless_mode; + + switch (wireless_mode) { + case ODM_WM_B: + if (ra_mask & 0x0000000c) /* 11M or 5.5M enable */ + rate_bitmap = 0x0000000d; + else + rate_bitmap = 0x0000000f; + break; + + case (ODM_WM_G): + case (ODM_WM_A): + if (rssi_level == DM_RATR_STA_HIGH) + rate_bitmap = 0x00000f00; + else + rate_bitmap = 0x00000ff0; + break; + + case (ODM_WM_B|ODM_WM_G): + if (rssi_level == DM_RATR_STA_HIGH) + rate_bitmap = 0x00000f00; + else if (rssi_level == DM_RATR_STA_MIDDLE) + rate_bitmap = 0x00000ff0; + else + rate_bitmap = 0x00000ff5; + break; + + case (ODM_WM_B|ODM_WM_G|ODM_WM_N24G): + case (ODM_WM_B|ODM_WM_N24G): + case (ODM_WM_G|ODM_WM_N24G): + case (ODM_WM_A|ODM_WM_N5G): + { + if (p_dm_odm->rf_type == ODM_1T2R || p_dm_odm->rf_type == ODM_1T1R) { + if (rssi_level == DM_RATR_STA_HIGH) + rate_bitmap = 0x000f0000; + else if (rssi_level == DM_RATR_STA_MIDDLE) + rate_bitmap = 0x000ff000; + else { + if (*(p_dm_odm->p_band_width) == ODM_BW40M) + rate_bitmap = 0x000ff015; + else + rate_bitmap = 0x000ff005; + } + } else { + if (rssi_level == DM_RATR_STA_HIGH) + rate_bitmap = 0x0f8f0000; + else if (rssi_level == DM_RATR_STA_MIDDLE) + rate_bitmap = 0x0f8ff000; + else { + if (*(p_dm_odm->p_band_width) == ODM_BW40M) + rate_bitmap = 0x0f8ff015; + else + rate_bitmap = 0x0f8ff005; + } + } + } + break; + + case (ODM_WM_AC|ODM_WM_G): + if (rssi_level == 1) + rate_bitmap = 0xfc3f0000; + else if (rssi_level == 2) + rate_bitmap = 0xfffff000; + else + rate_bitmap = 0xffffffff; + break; + + case (ODM_WM_AC|ODM_WM_A): + + if (p_dm_odm->rf_type == RF_1T1R) { + if (rssi_level == 1) /* add by Gary for ac-series */ + rate_bitmap = 0x003f8000; + else if (rssi_level == 2) + rate_bitmap = 0x003ff000; + else + rate_bitmap = 0x003ff010; + } else { + if (rssi_level == 1) /* add by Gary for ac-series */ + rate_bitmap = 0xfe3f8000; /* VHT 2SS MCS3~9 */ + else if (rssi_level == 2) + rate_bitmap = 0xfffff000; /* VHT 2SS MCS0~9 */ + else + rate_bitmap = 0xfffff010; /* All */ + } + break; + + default: + if (p_dm_odm->rf_type == RF_1T2R) + rate_bitmap = 0x000fffff; + else + rate_bitmap = 0x0fffffff; + break; + + } + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("%s ==> rssi_level:0x%02x, wireless_mode:0x%02x, rate_bitmap:0x%08x\n", __func__, rssi_level, wireless_mode, rate_bitmap)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, (" ==> rssi_level:0x%02x, wireless_mode:0x%02x, rate_bitmap:0x%08x\n", rssi_level, wireless_mode, rate_bitmap)); + + return ra_mask & rate_bitmap; + +} + +/* RA_MASK_PHYDMLIZE, will delete it later*/ + +#if (RA_MASK_PHYDMLIZE_CE || RA_MASK_PHYDMLIZE_AP || RA_MASK_PHYDMLIZE_WIN) + +bool +odm_ra_state_check( + void *p_dm_void, + s32 RSSI, + bool is_force_update, + u8 *p_ra_tr_state +) +{ + struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void; + struct _ODM_RATE_ADAPTIVE *p_ra = &p_dm_odm->rate_adaptive; + const u8 go_up_gap = 5; + u8 high_rssi_thresh_for_ra = p_ra->high_rssi_thresh; + u8 low_rssi_thresh_for_ra = p_ra->low_rssi_thresh; + u8 ratr_state; + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("RSSI= (( %d )), Current_RSSI_level = (( %d ))\n", RSSI, *p_ra_tr_state)); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("[Ori RA RSSI Thresh] High= (( %d )), Low = (( %d ))\n", high_rssi_thresh_for_ra, low_rssi_thresh_for_ra)); + /* threshold Adjustment:*/ + /* when RSSI state trends to go up one or two levels, make sure RSSI is high enough.*/ + /* Here go_up_gap is added to solve the boundary's level alternation issue.*/ + switch (*p_ra_tr_state) { + case DM_RATR_STA_INIT: + case DM_RATR_STA_HIGH: + break; + case DM_RATR_STA_MIDDLE: + high_rssi_thresh_for_ra += go_up_gap; + break; + case DM_RATR_STA_LOW: + high_rssi_thresh_for_ra += go_up_gap; + low_rssi_thresh_for_ra += go_up_gap; + break; + default: + ODM_RT_ASSERT(p_dm_odm, false, ("wrong rssi level setting %d !", *p_ra_tr_state)); + break; + } + + /* Decide ratr_state by RSSI.*/ + if (RSSI > high_rssi_thresh_for_ra) + ratr_state = DM_RATR_STA_HIGH; + else if (RSSI > low_rssi_thresh_for_ra) + ratr_state = DM_RATR_STA_MIDDLE; + + else + ratr_state = DM_RATR_STA_LOW; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("[Mod RA RSSI Thresh] High= (( %d )), Low = (( %d ))\n", high_rssi_thresh_for_ra, low_rssi_thresh_for_ra)); + if (*p_ra_tr_state != ratr_state || is_force_update) { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("[RSSI Level Update] %d->%d\n", *p_ra_tr_state, ratr_state)); + *p_ra_tr_state = ratr_state; + return true; + } + + return false; +} + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_rainfo.h b/drivers/staging/rtl8188eu/hal/phydm_rainfo.h new file mode 100644 index 000000000000..9eda17d184a1 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_rainfo.h @@ -0,0 +1,484 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __PHYDMRAINFO_H__ +#define __PHYDMRAINFO_H__ + +/*#define RAINFO_VERSION "2.0" //2014.11.04*/ +/*#define RAINFO_VERSION "3.0" //2015.01.13 Dino*/ +/*#define RAINFO_VERSION "3.1" //2015.01.14 Dino*/ +/*#define RAINFO_VERSION "3.3" 2015.07.29 YuChen*/ +/*#define RAINFO_VERSION "3.4"*/ /*2015.12.15 Stanley*/ +/*#define RAINFO_VERSION "4.0"*/ /*2016.03.24 Dino, Add more RA mask state and Phydm-lize partial ra mask function */ +/*#define RAINFO_VERSION "4.1"*/ /*2016.04.20 Dino, Add new function to adjust PCR RA threshold */ +/*#define RAINFO_VERSION "4.2"*/ /*2016.05.17 Dino, Add H2C debug cmd */ +#define RAINFO_VERSION "4.3" /*2016.07.11 Dino, Fix RA hang in CCK 1M problem */ + +#define FORCED_UPDATE_RAMASK_PERIOD 5 + +#define H2C_0X42_LENGTH 5 +#define H2C_MAX_LENGTH 7 + +#define RA_FLOOR_UP_GAP 3 +#define RA_FLOOR_TABLE_SIZE 7 + +#define ACTIVE_TP_THRESHOLD 150 +#define RA_RETRY_DESCEND_NUM 2 +#define RA_RETRY_LIMIT_LOW 4 +#define RA_RETRY_LIMIT_HIGH 32 + +#define RAINFO_BE_RX_STATE BIT(0) /* 1:RX */ /* ULDL */ +#define RAINFO_STBC_STATE BIT(1) +/* #define RAINFO_LDPC_STATE BIT2 */ +#define RAINFO_NOISY_STATE BIT(2) /* set by Noisy_Detection */ +#define RAINFO_SHURTCUT_STATE BIT(3) +#define RAINFO_SHURTCUT_FLAG BIT(4) +#define RAINFO_INIT_RSSI_RATE_STATE BIT(5) +#define RAINFO_BF_STATE BIT(6) +#define RAINFO_BE_TX_STATE BIT(7) /* 1:TX */ + +#define RA_MASK_CCK 0xf +#define RA_MASK_OFDM 0xff0 +#define RA_MASK_HT1SS 0xff000 +#define RA_MASK_HT2SS 0xff00000 +/*#define RA_MASK_MCS3SS */ +#define RA_MASK_HT4SS 0xff0 +#define RA_MASK_VHT1SS 0x3ff000 +#define RA_MASK_VHT2SS 0xffc00000 + + #define RA_FIRST_MACID 0 + +#define ap_init_rate_adaptive_state odm_rate_adaptive_state_ap_init + +#if (RA_MASK_PHYDMLIZE_CE || RA_MASK_PHYDMLIZE_AP || RA_MASK_PHYDMLIZE_WIN) + #define DM_RATR_STA_INIT 0 + #define DM_RATR_STA_HIGH 1 + #define DM_RATR_STA_MIDDLE 2 + #define DM_RATR_STA_LOW 3 + #define DM_RATR_STA_ULTRA_LOW 4 +#endif + +enum phydm_ra_arfr_num_e { + ARFR_0_RATE_ID = 0x9, + ARFR_1_RATE_ID = 0xa, + ARFR_2_RATE_ID = 0xb, + ARFR_3_RATE_ID = 0xc, + ARFR_4_RATE_ID = 0xd, + ARFR_5_RATE_ID = 0xe +}; + +enum phydm_ra_dbg_para_e { + RADBG_PCR_TH_OFFSET = 0, + RADBG_RTY_PENALTY = 1, + RADBG_N_HIGH = 2, + RADBG_N_LOW = 3, + RADBG_TRATE_UP_TABLE = 4, + RADBG_TRATE_DOWN_TABLE = 5, + RADBG_TRYING_NECESSARY = 6, + RADBG_TDROPING_NECESSARY = 7, + RADBG_RATE_UP_RTY_RATIO = 8, + RADBG_RATE_DOWN_RTY_RATIO = 9, /* u8 */ + + RADBG_DEBUG_MONITOR1 = 0xc, + RADBG_DEBUG_MONITOR2 = 0xd, + RADBG_DEBUG_MONITOR3 = 0xe, + RADBG_DEBUG_MONITOR4 = 0xf, + RADBG_DEBUG_MONITOR5 = 0x10, + NUM_RA_PARA +}; + +enum phydm_wireless_mode_e { + + PHYDM_WIRELESS_MODE_UNKNOWN = 0x00, + PHYDM_WIRELESS_MODE_A = 0x01, + PHYDM_WIRELESS_MODE_B = 0x02, + PHYDM_WIRELESS_MODE_G = 0x04, + PHYDM_WIRELESS_MODE_AUTO = 0x08, + PHYDM_WIRELESS_MODE_N_24G = 0x10, + PHYDM_WIRELESS_MODE_N_5G = 0x20, + PHYDM_WIRELESS_MODE_AC_5G = 0x40, + PHYDM_WIRELESS_MODE_AC_24G = 0x80, + PHYDM_WIRELESS_MODE_AC_ONLY = 0x100, + PHYDM_WIRELESS_MODE_MAX = 0x800, + PHYDM_WIRELESS_MODE_ALL = 0xFFFF +}; + +enum phydm_rateid_idx_e { + + PHYDM_BGN_40M_2SS = 0, + PHYDM_BGN_40M_1SS = 1, + PHYDM_BGN_20M_2SS = 2, + PHYDM_BGN_20M_1SS = 3, + PHYDM_GN_N2SS = 4, + PHYDM_GN_N1SS = 5, + PHYDM_BG = 6, + PHYDM_G = 7, + PHYDM_B_20M = 8, + PHYDM_ARFR0_AC_2SS = 9, + PHYDM_ARFR1_AC_1SS = 10, + PHYDM_ARFR2_AC_2G_1SS = 11, + PHYDM_ARFR3_AC_2G_2SS = 12, + PHYDM_ARFR4_AC_3SS = 13, + PHYDM_ARFR5_N_3SS = 14 +}; + +enum phydm_rf_type_def_e { + PHYDM_RF_1T1R = 0, + PHYDM_RF_1T2R, + PHYDM_RF_2T2R, + PHYDM_RF_2T2R_GREEN, + PHYDM_RF_2T3R, + PHYDM_RF_2T4R, + PHYDM_RF_3T3R, + PHYDM_RF_3T4R, + PHYDM_RF_4T4R, + PHYDM_RF_MAX_TYPE +}; + +enum phydm_bw_e { + PHYDM_BW_20 = 0, + PHYDM_BW_40, + PHYDM_BW_80, + PHYDM_BW_80_80, + PHYDM_BW_160, + PHYDM_BW_10, + PHYDM_BW_5 +}; + + +#if (RATE_ADAPTIVE_SUPPORT == 1)/* 88E RA */ +struct _odm_ra_info_ { + u8 rate_id; + u32 rate_mask; + u32 ra_use_rate; + u8 rate_sgi; + u8 rssi_sta_ra; + u8 pre_rssi_sta_ra; + u8 sgi_enable; + u8 decision_rate; + u8 pre_rate; + u8 highest_rate; + u8 lowest_rate; + u32 nsc_up; + u32 nsc_down; + u16 RTY[5]; + u32 TOTAL; + u16 DROP; + u8 active; + u16 rpt_time; + u8 ra_waiting_counter; + u8 ra_pending_counter; + u8 ra_drop_after_down; + u8 pt_active; /* on or off */ + u8 pt_try_state; /* 0 trying state, 1 for decision state */ + u8 pt_stage; /* 0~6 */ + u8 pt_stop_count; /* Stop PT counter */ + u8 pt_pre_rate; /* if rate change do PT */ + u8 pt_pre_rssi; /* if RSSI change 5% do PT */ + u8 pt_mode_ss; /* decide whitch rate should do PT */ + u8 ra_stage; /* StageRA, decide how many times RA will be done between PT */ + u8 pt_smooth_factor; +}; +#endif + + +struct _rate_adaptive_table_ { + u8 firstconnect; +#if (defined(CONFIG_RA_DBG_CMD)) + bool is_ra_dbg_init; + + u8 RTY_P[ODM_NUM_RATE_IDX]; + u8 RTY_P_default[ODM_NUM_RATE_IDX]; + bool RTY_P_modify_note[ODM_NUM_RATE_IDX]; + + u8 RATE_UP_RTY_RATIO[ODM_NUM_RATE_IDX]; + u8 RATE_UP_RTY_RATIO_default[ODM_NUM_RATE_IDX]; + bool RATE_UP_RTY_RATIO_modify_note[ODM_NUM_RATE_IDX]; + + u8 RATE_DOWN_RTY_RATIO[ODM_NUM_RATE_IDX]; + u8 RATE_DOWN_RTY_RATIO_default[ODM_NUM_RATE_IDX]; + bool RATE_DOWN_RTY_RATIO_modify_note[ODM_NUM_RATE_IDX]; + + bool ra_para_feedback_req; + + u8 para_idx; + u8 rate_idx; + u8 value; + u16 value_16; + u8 rate_length; +#endif + u8 link_tx_rate[ODM_ASSOCIATE_ENTRY_NUM]; + u8 highest_client_tx_order; + u16 highest_client_tx_rate_order; + u8 power_tracking_flag; + u8 RA_threshold_offset; + u8 RA_offset_direction; + u8 force_update_ra_mask_count; + +#if (defined(CONFIG_RA_DYNAMIC_RTY_LIMIT)) + u8 per_rate_retrylimit_20M[ODM_NUM_RATE_IDX]; + u8 per_rate_retrylimit_40M[ODM_NUM_RATE_IDX]; + u8 retry_descend_num; + u8 retrylimit_low; + u8 retrylimit_high; +#endif + + +}; + +struct _ODM_RATE_ADAPTIVE { + u8 type; /* dm_type_by_fw/dm_type_by_driver */ + u8 high_rssi_thresh; /* if RSSI > high_rssi_thresh => ratr_state is DM_RATR_STA_HIGH */ + u8 low_rssi_thresh; /* if RSSI <= low_rssi_thresh => ratr_state is DM_RATR_STA_LOW */ + u8 ratr_state; /* Current RSSI level, DM_RATR_STA_HIGH/DM_RATR_STA_MIDDLE/DM_RATR_STA_LOW */ + + u8 ldpc_thres; /* if RSSI > ldpc_thres => switch from LPDC to BCC */ + bool is_lower_rts_rate; + + bool is_use_ldpc; +}; + +void +phydm_h2C_debug( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +); + +#if (defined(CONFIG_RA_DBG_CMD)) + +void +odm_RA_debug( + void *p_dm_void, + u32 *const dm_value +); + +void +odm_ra_para_adjust_init( + void *p_dm_void +); + +#else + +void +phydm_RA_debug_PCR( + void *p_dm_void, + u32 *const dm_value, + u32 *_used, + char *output, + u32 *_out_len +); + +#endif + +void +odm_c2h_ra_para_report_handler( + void *p_dm_void, + u8 *cmd_buf, + u8 cmd_len +); + +void +odm_ra_para_adjust( + void *p_dm_void +); + +void +phydm_ra_dynamic_retry_count( + void *p_dm_void +); + +void +phydm_ra_dynamic_retry_limit( + void *p_dm_void +); + +void +phydm_ra_dynamic_rate_id_on_assoc( + void *p_dm_void, + u8 wireless_mode, + u8 init_rate_id +); + +void +phydm_print_rate( + void *p_dm_void, + u8 rate, + u32 dbg_component +); + +void +phydm_c2h_ra_report_handler( + void *p_dm_void, + u8 *cmd_buf, + u8 cmd_len +); + +u8 +phydm_rate_order_compute( + void *p_dm_void, + u8 rate_idx +); + +void +phydm_ra_info_watchdog( + void *p_dm_void +); + +void +phydm_ra_info_init( + void *p_dm_void +); + +void +odm_rssi_monitor_init( + void *p_dm_void +); + +void +phydm_modify_RA_PCR_threshold( + void *p_dm_void, + u8 RA_offset_direction, + u8 RA_threshold_offset +); + +void +odm_rssi_monitor_check( + void *p_dm_void +); + +void +phydm_init_ra_info( + void *p_dm_void +); + +u8 +phydm_vht_en_mapping( + void *p_dm_void, + u32 wireless_mode +); + +u8 +phydm_rate_id_mapping( + void *p_dm_void, + u32 wireless_mode, + u8 rf_type, + u8 bw +); + +void +phydm_update_hal_ra_mask( + void *p_dm_void, + u32 wireless_mode, + u8 rf_type, + u8 BW, + u8 mimo_ps_enable, + u8 disable_cck_rate, + u32 *ratr_bitmap_msb_in, + u32 *ratr_bitmap_in, + u8 tx_rate_level +); + +void +odm_rate_adaptive_mask_init( + void *p_dm_void +); + +void +odm_refresh_rate_adaptive_mask( + void *p_dm_void +); + +void +odm_refresh_rate_adaptive_mask_mp( + void *p_dm_void +); + +void +odm_refresh_rate_adaptive_mask_ce( + void *p_dm_void +); + +void +odm_refresh_rate_adaptive_mask_apadsl( + void *p_dm_void +); + +u8 +phydm_RA_level_decision( + void *p_dm_void, + u32 rssi, + u8 ratr_state +); + +bool +odm_ra_state_check( + void *p_dm_void, + s32 RSSI, + bool is_force_update, + u8 *p_ra_tr_state +); + +void +odm_refresh_basic_rate_mask( + void *p_dm_void +); +void +odm_ra_post_action_on_assoc( + void *p_dm_odm +); + +u8 +odm_find_rts_rate( + void *p_dm_void, + u8 tx_rate, + bool is_erp_protect +); + +void +odm_update_noisy_state( + void *p_dm_void, + bool is_noisy_state_from_c2h +); + +void +phydm_update_pwr_track( + void *p_dm_void, + u8 rate +); + + +void +odm_rate_adaptive_state_ap_init( + void *PADAPTER_void, + struct sta_info *p_entry +); + +static void +find_minimum_rssi( + struct _ADAPTER *p_adapter +); + +u64 +phydm_get_rate_bitmap_ex( + void *p_dm_void, + u32 macid, + u64 ra_mask, + u8 rssi_level, + u64 *dm_ra_mask, + u8 *dm_rte_id +); +u32 +odm_get_rate_bitmap( + void *p_dm_void, + u32 macid, + u32 ra_mask, + u8 rssi_level +); + +void phydm_ra_rssi_rpt_wk(void *p_context); + +#endif /*#ifndef __ODMRAINFO_H__*/ diff --git a/drivers/staging/rtl8188eu/hal/phydm_reg.h b/drivers/staging/rtl8188eu/hal/phydm_reg.h new file mode 100644 index 000000000000..1e0c230d7112 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_reg.h @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +/* ************************************************************ + * File Name: odm_reg.h + * + * Description: + * + * This file is for general register definition. + * + * + * ************************************************************ */ +#ifndef __HAL_ODM_REG_H__ +#define __HAL_ODM_REG_H__ + +/* + * Register Definition + * */ + +/* MAC REG */ +#define ODM_BB_RESET 0x002 +#define ODM_DUMMY 0x4fe +#define RF_T_METER_OLD 0x24 +#define RF_T_METER_NEW 0x42 + +#define ODM_EDCA_VO_PARAM 0x500 +#define ODM_EDCA_VI_PARAM 0x504 +#define ODM_EDCA_BE_PARAM 0x508 +#define ODM_EDCA_BK_PARAM 0x50C +#define ODM_TXPAUSE 0x522 + +/* LTE_COEX */ +#define REG_LTECOEX_CTRL 0x07C0 +#define REG_LTECOEX_WRITE_DATA 0x07C4 +#define REG_LTECOEX_READ_DATA 0x07C8 +#define REG_LTECOEX_PATH_CONTROL 0x70 + +/* BB REG */ +#define ODM_FPGA_PHY0_PAGE8 0x800 +#define ODM_PSD_SETTING 0x808 +#define ODM_AFE_SETTING 0x818 +#define ODM_TXAGC_B_6_18 0x830 +#define ODM_TXAGC_B_24_54 0x834 +#define ODM_TXAGC_B_MCS32_5 0x838 +#define ODM_TXAGC_B_MCS0_MCS3 0x83c +#define ODM_TXAGC_B_MCS4_MCS7 0x848 +#define ODM_TXAGC_B_MCS8_MCS11 0x84c +#define ODM_ANALOG_REGISTER 0x85c +#define ODM_RF_INTERFACE_OUTPUT 0x860 +#define ODM_TXAGC_B_MCS12_MCS15 0x868 +#define ODM_TXAGC_B_11_A_2_11 0x86c +#define ODM_AD_DA_LSB_MASK 0x874 +#define ODM_ENABLE_3_WIRE 0x88c +#define ODM_PSD_REPORT 0x8b4 +#define ODM_R_ANT_SELECT 0x90c +#define ODM_CCK_ANT_SELECT 0xa07 +#define ODM_CCK_PD_THRESH 0xa0a +#define ODM_CCK_RF_REG1 0xa11 +#define ODM_CCK_MATCH_FILTER 0xa20 +#define ODM_CCK_RAKE_MAC 0xa2e +#define ODM_CCK_CNT_RESET 0xa2d +#define ODM_CCK_TX_DIVERSITY 0xa2f +#define ODM_CCK_FA_CNT_MSB 0xa5b +#define ODM_CCK_FA_CNT_LSB 0xa5c +#define ODM_CCK_NEW_FUNCTION 0xa75 +#define ODM_OFDM_PHY0_PAGE_C 0xc00 +#define ODM_OFDM_RX_ANT 0xc04 +#define ODM_R_A_RXIQI 0xc14 +#define ODM_R_A_AGC_CORE1 0xc50 +#define ODM_R_A_AGC_CORE2 0xc54 +#define ODM_R_B_AGC_CORE1 0xc58 +#define ODM_R_AGC_PAR 0xc70 +#define ODM_R_HTSTF_AGC_PAR 0xc7c +#define ODM_TX_PWR_TRAINING_A 0xc90 +#define ODM_TX_PWR_TRAINING_B 0xc98 +#define ODM_OFDM_FA_CNT1 0xcf0 +#define ODM_OFDM_PHY0_PAGE_D 0xd00 +#define ODM_OFDM_FA_CNT2 0xda0 +#define ODM_OFDM_FA_CNT3 0xda4 +#define ODM_OFDM_FA_CNT4 0xda8 +#define ODM_TXAGC_A_6_18 0xe00 +#define ODM_TXAGC_A_24_54 0xe04 +#define ODM_TXAGC_A_1_MCS32 0xe08 +#define ODM_TXAGC_A_MCS0_MCS3 0xe10 +#define ODM_TXAGC_A_MCS4_MCS7 0xe14 +#define ODM_TXAGC_A_MCS8_MCS11 0xe18 +#define ODM_TXAGC_A_MCS12_MCS15 0xe1c + +/* RF REG */ +#define ODM_GAIN_SETTING 0x00 +#define ODM_CHANNEL 0x18 +#define ODM_RF_T_METER 0x24 +#define ODM_RF_T_METER_92D 0x42 +#define ODM_RF_T_METER_88E 0x42 +#define ODM_RF_T_METER_92E 0x42 +#define ODM_RF_T_METER_8812 0x42 +#define REG_RF_TX_GAIN_OFFSET 0x55 + +/* ant Detect Reg */ +#define ODM_DPDT 0x300 + +/* PSD Init */ +#define ODM_PSDREG 0x808 + +/* 92D path Div */ +#define PATHDIV_REG 0xB30 +#define PATHDIV_TRI 0xBA0 + + +/* + * Bitmap Definition + * */ + +#define BIT_FA_RESET BIT(0) + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_regconfig8188e.c b/drivers/staging/rtl8188eu/hal/phydm_regconfig8188e.c new file mode 100644 index 000000000000..90d6239f942a --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_regconfig8188e.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#include "mp_precomp.h" + +#include "phydm_precomp.h" + +#if (RTL8188E_SUPPORT == 1) + +void +odm_config_rf_reg_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u32 addr, + u32 data, + enum odm_rf_radio_path_e RF_PATH, + u32 reg_addr +) +{ + if (addr == 0xffe) { +#ifdef CONFIG_LONG_DELAY_ISSUE + ODM_sleep_ms(50); +#else + ODM_delay_ms(50); +#endif + } else if (addr == 0xfd) + ODM_delay_ms(5); + else if (addr == 0xfc) + ODM_delay_ms(1); + else if (addr == 0xfb) + ODM_delay_us(50); + else if (addr == 0xfa) + ODM_delay_us(5); + else if (addr == 0xf9) + ODM_delay_us(1); + else { + odm_set_rf_reg(p_dm_odm, RF_PATH, reg_addr, RFREGOFFSETMASK, data); + /* Add 1us delay between BB/RF register setting. */ + ODM_delay_us(1); + } +} + + +void +odm_config_rf_radio_a_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u32 addr, + u32 data +) +{ + u32 content = 0x1000; /* RF_Content: radioa_txt */ + u32 maskfor_phy_set = (u32)(content & 0xE000); + + odm_config_rf_reg_8188e(p_dm_odm, addr, data, ODM_RF_PATH_A, addr | maskfor_phy_set); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, ("===> odm_config_rf_with_header_file: [RadioA] %08X %08X\n", addr, data)); +} + +void +odm_config_rf_radio_b_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u32 addr, + u32 data +) +{ + u32 content = 0x1001; /* RF_Content: radiob_txt */ + u32 maskfor_phy_set = (u32)(content & 0xE000); + + odm_config_rf_reg_8188e(p_dm_odm, addr, data, ODM_RF_PATH_B, addr | maskfor_phy_set); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, ("===> odm_config_rf_with_header_file: [RadioB] %08X %08X\n", addr, data)); + +} + +void +odm_config_mac_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u32 addr, + u8 data +) +{ + odm_write_1byte(p_dm_odm, addr, data); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, ("===> odm_config_mac_with_header_file: [MAC_REG] %08X %08X\n", addr, data)); +} + +void +odm_config_bb_agc_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u32 addr, + u32 bitmask, + u32 data +) +{ + odm_set_bb_reg(p_dm_odm, addr, bitmask, data); + /* Add 1us delay between BB/RF register setting. */ + ODM_delay_us(1); + + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, ("===> odm_config_bb_with_header_file: [AGC_TAB] %08X %08X\n", addr, data)); +} + +void +odm_config_bb_phy_reg_pg_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u32 band, + u32 rf_path, + u32 tx_num, + u32 addr, + u32 bitmask, + u32 data +) +{ + if (addr == 0xfe) { +#ifdef CONFIG_LONG_DELAY_ISSUE + ODM_sleep_ms(50); +#else + ODM_delay_ms(50); +#endif + } else if (addr == 0xfd) + ODM_delay_ms(5); + else if (addr == 0xfc) + ODM_delay_ms(1); + else if (addr == 0xfb) + ODM_delay_us(50); + else if (addr == 0xfa) + ODM_delay_us(5); + else if (addr == 0xf9) + ODM_delay_us(1); + else { + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("===> odm_config_bb_with_header_file: [PHY_REG] %08X %08X %08X\n", addr, bitmask, data)); + phy_store_tx_power_by_rate(p_dm_odm->adapter, band, rf_path, tx_num, addr, bitmask, data); + } +} + +void +odm_config_bb_txpwr_lmt_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u8 *regulation, + u8 *band, + u8 *bandwidth, + u8 *rate_section, + u8 *rf_path, + u8 *channel, + u8 *power_limit +) +{ + phy_set_tx_power_limit(p_dm_odm, regulation, band, + bandwidth, rate_section, rf_path, channel, power_limit); +} + +void +odm_config_bb_phy_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u32 addr, + u32 bitmask, + u32 data +) +{ + if (addr == 0xfe) { +#ifdef CONFIG_LONG_DELAY_ISSUE + ODM_sleep_ms(50); +#else + ODM_delay_ms(50); +#endif + } else if (addr == 0xfd) + ODM_delay_ms(5); + else if (addr == 0xfc) + ODM_delay_ms(1); + else if (addr == 0xfb) + ODM_delay_us(50); + else if (addr == 0xfa) + ODM_delay_us(5); + else if (addr == 0xf9) + ODM_delay_us(1); + else { + if (addr == 0xa24) + p_dm_odm->rf_calibrate_info.rega24 = data; + odm_set_bb_reg(p_dm_odm, addr, bitmask, data); + + /* Add 1us delay between BB/RF register setting. */ + ODM_delay_us(1); + ODM_RT_TRACE(p_dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, ("===> odm_config_bb_with_header_file: [PHY_REG] %08X %08X\n", addr, data)); + } +} +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_regconfig8188e.h b/drivers/staging/rtl8188eu/hal/phydm_regconfig8188e.h new file mode 100644 index 000000000000..a530c3b58072 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_regconfig8188e.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#ifndef __INC_ODM_REGCONFIG_H_8188E +#define __INC_ODM_REGCONFIG_H_8188E + +#if (RTL8188E_SUPPORT == 1) + +void +odm_config_rf_reg_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u32 addr, + u32 data, + enum odm_rf_radio_path_e RF_PATH, + u32 reg_addr +); + +void +odm_config_rf_radio_a_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u32 addr, + u32 data +); + +void +odm_config_rf_radio_b_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u32 addr, + u32 data +); + +void +odm_config_mac_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u32 addr, + u8 data +); + +void +odm_config_bb_agc_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u32 addr, + u32 bitmask, + u32 data +); + +void +odm_config_bb_phy_reg_pg_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u32 band, + u32 rf_path, + u32 tx_num, + u32 addr, + u32 bitmask, + u32 data +); + +void +odm_config_bb_phy_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u32 addr, + u32 bitmask, + u32 data +); + +void +odm_config_bb_txpwr_lmt_8188e( + struct PHY_DM_STRUCT *p_dm_odm, + u8 *regulation, + u8 *band, + u8 *bandwidth, + u8 *rate_section, + u8 *rf_path, + u8 *channel, + u8 *power_limit +); + +#endif +#endif /* end of SUPPORT */ diff --git a/drivers/staging/rtl8188eu/hal/phydm_regdefine11ac.h b/drivers/staging/rtl8188eu/hal/phydm_regdefine11ac.h new file mode 100644 index 000000000000..596b07afc0ca --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_regdefine11ac.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __ODM_REGDEFINE11AC_H__ +#define __ODM_REGDEFINE11AC_H__ + +/* 2 RF REG LIST */ + + + +/* 2 BB REG LIST + * PAGE 8 */ +#define ODM_REG_CCK_RPT_FORMAT_11AC 0x804 +#define ODM_REG_BB_RX_PATH_11AC 0x808 +#define ODM_REG_BB_TX_PATH_11AC 0x80c +#define ODM_REG_BB_ATC_11AC 0x860 +#define ODM_REG_EDCCA_POWER_CAL 0x8dc +#define ODM_REG_DBG_RPT_11AC 0x8fc +/* PAGE 9 */ +#define ODM_REG_EDCCA_DOWN_OPT 0x900 +#define ODM_REG_ACBB_EDCCA_ENHANCE 0x944 +#define odm_adc_trigger_jaguar2 0x95C /*ADC sample mode*/ +#define ODM_REG_OFDM_FA_RST_11AC 0x9A4 +#define ODM_REG_CCX_PERIOD_11AC 0x990 +#define ODM_REG_NHM_TH9_TH10_11AC 0x994 +#define ODM_REG_CLM_11AC 0x994 +#define ODM_REG_NHM_TH3_TO_TH0_11AC 0x998 +#define ODM_REG_NHM_TH7_TO_TH4_11AC 0x99c +#define ODM_REG_NHM_TH8_11AC 0x9a0 +#define ODM_REG_NHM_9E8_11AC 0x9e8 +#define ODM_REG_CSI_CONTENT_VALUE 0x9b4 +/* PAGE A */ +#define ODM_REG_CCK_CCA_11AC 0xA0A +#define ODM_REG_CCK_FA_RST_11AC 0xA2C +#define ODM_REG_CCK_FA_11AC 0xA5C +/* PAGE B */ +#define ODM_REG_RST_RPT_11AC 0xB58 +/* PAGE C */ +#define ODM_REG_TRMUX_11AC 0xC08 +#define ODM_REG_IGI_A_11AC 0xC50 +/* PAGE E */ +#define ODM_REG_IGI_B_11AC 0xE50 +#define ODM_REG_TRMUX_11AC_B 0xE08 +/* PAGE F */ +#define ODM_REG_CCK_CRC32_CNT_11AC 0xF04 +#define ODM_REG_CCK_CCA_CNT_11AC 0xF08 +#define ODM_REG_VHT_CRC32_CNT_11AC 0xF0c +#define ODM_REG_HT_CRC32_CNT_11AC 0xF10 +#define ODM_REG_OFDM_CRC32_CNT_11AC 0xF14 +#define ODM_REG_OFDM_FA_11AC 0xF48 +#define ODM_REG_RPT_11AC 0xfa0 +#define ODM_REG_CLM_RESULT_11AC 0xfa4 +#define ODM_REG_NHM_CNT_11AC 0xfa8 +#define ODM_REG_NHM_DUR_READY_11AC 0xfb4 + +#define ODM_REG_NHM_CNT7_TO_CNT4_11AC 0xfac +#define ODM_REG_NHM_CNT11_TO_CNT8_11AC 0xfb0 +#define ODM_REG_OFDM_FA_TYPE2_11AC 0xFD0 +/* PAGE 18 */ +#define ODM_REG_IGI_C_11AC 0x1850 +/* PAGE 1A */ +#define ODM_REG_IGI_D_11AC 0x1A50 + +/* 2 MAC REG LIST */ +#define ODM_REG_RESP_TX_11AC 0x6D8 + + + +/* DIG Related */ +#define ODM_BIT_IGI_11AC 0xFFFFFFFF +#define ODM_BIT_CCK_RPT_FORMAT_11AC BIT(16) +#define ODM_BIT_BB_RX_PATH_11AC 0xF +#define ODM_BIT_BB_TX_PATH_11AC 0xF +#define ODM_BIT_BB_ATC_11AC BIT(14) + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_regdefine11n.h b/drivers/staging/rtl8188eu/hal/phydm_regdefine11n.h new file mode 100644 index 000000000000..90d753576f02 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_regdefine11n.h @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#ifndef __ODM_REGDEFINE11N_H__ +#define __ODM_REGDEFINE11N_H__ + + +/* 2 RF REG LIST */ +#define ODM_REG_RF_MODE_11N 0x00 +#define ODM_REG_RF_0B_11N 0x0B +#define ODM_REG_CHNBW_11N 0x18 +#define ODM_REG_T_METER_11N 0x24 +#define ODM_REG_RF_25_11N 0x25 +#define ODM_REG_RF_26_11N 0x26 +#define ODM_REG_RF_27_11N 0x27 +#define ODM_REG_RF_2B_11N 0x2B +#define ODM_REG_RF_2C_11N 0x2C +#define ODM_REG_RXRF_A3_11N 0x3C +#define ODM_REG_T_METER_92D_11N 0x42 +#define ODM_REG_T_METER_88E_11N 0x42 + + + +/* 2 BB REG LIST + * PAGE 8 */ +#define ODM_REG_BB_CTRL_11N 0x800 +#define ODM_REG_RF_PIN_11N 0x804 +#define ODM_REG_PSD_CTRL_11N 0x808 +#define ODM_REG_TX_ANT_CTRL_11N 0x80C +#define ODM_REG_BB_PWR_SAV5_11N 0x818 +#define ODM_REG_CCK_RPT_FORMAT_11N 0x824 +#define ODM_REG_CCK_RPT_FORMAT_11N_B 0x82C +#define ODM_REG_RX_DEFUALT_A_11N 0x858 +#define ODM_REG_RX_DEFUALT_B_11N 0x85A +#define ODM_REG_BB_PWR_SAV3_11N 0x85C +#define ODM_REG_ANTSEL_CTRL_11N 0x860 +#define ODM_REG_RX_ANT_CTRL_11N 0x864 +#define ODM_REG_PIN_CTRL_11N 0x870 +#define ODM_REG_BB_PWR_SAV1_11N 0x874 +#define ODM_REG_ANTSEL_PATH_11N 0x878 +#define ODM_REG_BB_3WIRE_11N 0x88C +#define ODM_REG_SC_CNT_11N 0x8C4 +#define ODM_REG_PSD_DATA_11N 0x8B4 +#define ODM_REG_CCX_PERIOD_11N 0x894 +#define ODM_REG_NHM_TH9_TH10_11N 0x890 +#define ODM_REG_CLM_11N 0x890 +#define ODM_REG_NHM_TH3_TO_TH0_11N 0x898 +#define ODM_REG_NHM_TH7_TO_TH4_11N 0x89c +#define ODM_REG_NHM_TH8_11N 0xe28 +#define ODM_REG_CLM_READY_11N 0x8b4 +#define ODM_REG_CLM_RESULT_11N 0x8d0 +#define ODM_REG_NHM_CNT_11N 0x8d8 + +/* For struct _ACS_, Jeffery, 2014-12-26 */ +#define ODM_REG_NHM_CNT7_TO_CNT4_11N 0x8dc +#define ODM_REG_NHM_CNT9_TO_CNT8_11N 0x8d0 +#define ODM_REG_NHM_CNT10_TO_CNT11_11N 0x8d4 + +/* PAGE 9 */ +#define ODM_REG_BB_CTRL_PAGE9_11N 0x900 +#define ODM_REG_DBG_RPT_11N 0x908 +#define ODM_REG_BB_TX_PATH_11N 0x90c +#define ODM_REG_ANT_MAPPING1_11N 0x914 +#define ODM_REG_ANT_MAPPING2_11N 0x918 +#define ODM_REG_EDCCA_DOWN_OPT_11N 0x948 +#define ODM_REG_RX_DFIR_MOD_97F 0x948 + +/* PAGE A */ +#define ODM_REG_CCK_ANTDIV_PARA1_11N 0xA00 +#define ODM_REG_CCK_ANT_SEL_11N 0xA04 +#define ODM_REG_CCK_CCA_11N 0xA0A +#define ODM_REG_CCK_ANTDIV_PARA2_11N 0xA0C +#define ODM_REG_CCK_ANTDIV_PARA3_11N 0xA10 +#define ODM_REG_CCK_ANTDIV_PARA4_11N 0xA14 +#define ODM_REG_CCK_FILTER_PARA1_11N 0xA22 +#define ODM_REG_CCK_FILTER_PARA2_11N 0xA23 +#define ODM_REG_CCK_FILTER_PARA3_11N 0xA24 +#define ODM_REG_CCK_FILTER_PARA4_11N 0xA25 +#define ODM_REG_CCK_FILTER_PARA5_11N 0xA26 +#define ODM_REG_CCK_FILTER_PARA6_11N 0xA27 +#define ODM_REG_CCK_FILTER_PARA7_11N 0xA28 +#define ODM_REG_CCK_FILTER_PARA8_11N 0xA29 +#define ODM_REG_CCK_FA_RST_11N 0xA2C +#define ODM_REG_CCK_FA_MSB_11N 0xA58 +#define ODM_REG_CCK_FA_LSB_11N 0xA5C +#define ODM_REG_CCK_CCA_CNT_11N 0xA60 +#define ODM_REG_BB_PWR_SAV4_11N 0xA74 +/* PAGE B */ +#define ODM_REG_LNA_SWITCH_11N 0xB2C +#define ODM_REG_PATH_SWITCH_11N 0xB30 +#define ODM_REG_RSSI_CTRL_11N 0xB38 +#define ODM_REG_CONFIG_ANTA_11N 0xB68 +#define ODM_REG_RSSI_BT_11N 0xB9C +#define ODM_REG_RXCK_RFMOD 0xBB0 +#define ODM_REG_EDCCA_DCNF_97F 0xBC0 + +/* PAGE C */ +#define ODM_REG_OFDM_FA_HOLDC_11N 0xC00 +#define ODM_REG_BB_RX_PATH_11N 0xC04 +#define ODM_REG_TRMUX_11N 0xC08 +#define ODM_REG_OFDM_FA_RSTC_11N 0xC0C +#define ODM_REG_DOWNSAM_FACTOR_11N 0xC10 +#define ODM_REG_RXIQI_MATRIX_11N 0xC14 +#define ODM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C +#define ODM_REG_IGI_A_11N 0xC50 +#define ODM_REG_ANTDIV_PARA2_11N 0xC54 +#define ODM_REG_IGI_B_11N 0xC58 +#define ODM_REG_ANTDIV_PARA3_11N 0xC5C +#define ODM_REG_L1SBD_PD_CH_11N 0XC6C +#define ODM_REG_BB_PWR_SAV2_11N 0xC70 +#define ODM_REG_BB_AGC_SET_2_11N 0xc74 +#define ODM_REG_RX_OFF_11N 0xC7C +#define ODM_REG_TXIQK_MATRIXA_11N 0xC80 +#define ODM_REG_TXIQK_MATRIXB_11N 0xC88 +#define ODM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94 +#define ODM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C +#define ODM_REG_RXIQK_MATRIX_LSB_11N 0xCA0 +#define ODM_REG_ANTDIV_PARA1_11N 0xCA4 +#define ODM_REG_SMALL_BANDWIDTH_11N 0xCE4 +#define ODM_REG_OFDM_FA_TYPE1_11N 0xCF0 +/* PAGE D */ +#define ODM_REG_OFDM_FA_RSTD_11N 0xD00 +#define ODM_REG_BB_RX_ANT_11N 0xD04 +#define ODM_REG_BB_ATC_11N 0xD2C +#define ODM_REG_OFDM_FA_TYPE2_11N 0xDA0 +#define ODM_REG_OFDM_FA_TYPE3_11N 0xDA4 +#define ODM_REG_OFDM_FA_TYPE4_11N 0xDA8 +#define ODM_REG_RPT_11N 0xDF4 +/* PAGE E */ +#define ODM_REG_TXAGC_A_6_18_11N 0xE00 +#define ODM_REG_TXAGC_A_24_54_11N 0xE04 +#define ODM_REG_TXAGC_A_1_MCS32_11N 0xE08 +#define ODM_REG_TXAGC_A_MCS0_3_11N 0xE10 +#define ODM_REG_TXAGC_A_MCS4_7_11N 0xE14 +#define ODM_REG_TXAGC_A_MCS8_11_11N 0xE18 +#define ODM_REG_TXAGC_A_MCS12_15_11N 0xE1C +#define ODM_REG_EDCCA_DCNF_11N 0xE24 +#define ODM_REG_TAP_UPD_97F 0xE24 +#define ODM_REG_FPGA0_IQK_11N 0xE28 +#define ODM_REG_PAGE_B1_97F 0xE28 +#define ODM_REG_TXIQK_TONE_A_11N 0xE30 +#define ODM_REG_RXIQK_TONE_A_11N 0xE34 +#define ODM_REG_TXIQK_PI_A_11N 0xE38 +#define ODM_REG_RXIQK_PI_A_11N 0xE3C +#define ODM_REG_TXIQK_11N 0xE40 +#define ODM_REG_RXIQK_11N 0xE44 +#define ODM_REG_IQK_AGC_PTS_11N 0xE48 +#define ODM_REG_IQK_AGC_RSP_11N 0xE4C +#define ODM_REG_BLUETOOTH_11N 0xE6C +#define ODM_REG_RX_WAIT_CCA_11N 0xE70 +#define ODM_REG_TX_CCK_RFON_11N 0xE74 +#define ODM_REG_TX_CCK_BBON_11N 0xE78 +#define ODM_REG_OFDM_RFON_11N 0xE7C +#define ODM_REG_OFDM_BBON_11N 0xE80 +#define ODM_REG_TX2RX_11N 0xE84 +#define ODM_REG_TX2TX_11N 0xE88 +#define ODM_REG_RX_CCK_11N 0xE8C +#define ODM_REG_RX_OFDM_11N 0xED0 +#define ODM_REG_RX_WAIT_RIFS_11N 0xED4 +#define ODM_REG_RX2RX_11N 0xED8 +#define ODM_REG_STANDBY_11N 0xEDC +#define ODM_REG_SLEEP_11N 0xEE0 +#define ODM_REG_PMPD_ANAEN_11N 0xEEC +/* PAGE F */ +#define ODM_REG_PAGE_F_RST_11N 0xF14 +#define ODM_REG_IGI_C_11N 0xF84 +#define ODM_REG_IGI_D_11N 0xF88 +#define ODM_REG_CCK_CRC32_ERROR_CNT_11N 0xF84 +#define ODM_REG_CCK_CRC32_OK_CNT_11N 0xF88 +#define ODM_REG_HT_CRC32_CNT_11N 0xF90 +#define ODM_REG_OFDM_CRC32_CNT_11N 0xF94 + +/* 2 MAC REG LIST */ +#define ODM_REG_BB_RST_11N 0x02 +#define ODM_REG_ANTSEL_PIN_11N 0x4C +#define ODM_REG_EARLY_MODE_11N 0x4D0 +#define ODM_REG_RSSI_MONITOR_11N 0x4FE +#define ODM_REG_EDCA_VO_11N 0x500 +#define ODM_REG_EDCA_VI_11N 0x504 +#define ODM_REG_EDCA_BE_11N 0x508 +#define ODM_REG_EDCA_BK_11N 0x50C +#define ODM_REG_TXPAUSE_11N 0x522 +#define ODM_REG_RESP_TX_11N 0x6D8 +#define ODM_REG_ANT_TRAIN_PARA1_11N 0x7b0 +#define ODM_REG_ANT_TRAIN_PARA2_11N 0x7b4 + + +/* DIG Related */ +#define ODM_BIT_IGI_11N 0x0000007F +#define ODM_BIT_CCK_RPT_FORMAT_11N BIT(9) +#define ODM_BIT_BB_RX_PATH_11N 0xF +#define ODM_BIT_BB_TX_PATH_11N 0xF +#define ODM_BIT_BB_ATC_11N BIT(11) + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_rtl8188e.c b/drivers/staging/rtl8188eu/hal/phydm_rtl8188e.c new file mode 100644 index 000000000000..43f5ba125ee0 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_rtl8188e.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#include "mp_precomp.h" + +#include "phydm_precomp.h" + +void odm_dig_lower_bound_88e(struct PHY_DM_STRUCT *p_dm_odm) +{ + struct _dynamic_initial_gain_threshold_ *p_dm_dig_table = + &p_dm_odm->dm_dig_table; + + if (p_dm_odm->ant_div_type == CG_TRX_HW_ANTDIV) { + p_dm_dig_table->rx_gain_range_min = + (u8)p_dm_dig_table->ant_div_rssi_max; + ODM_RT_TRACE(p_dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, + ("odm_dig_lower_bound_88e(): p_dm_dig_table->ant_div_rssi_max=%d\n", + p_dm_dig_table->ant_div_rssi_max)); + } +} + +/*============================================================= +* AntDiv Before Link +===============================================================*/ +void odm_sw_ant_div_reset_before_link(struct PHY_DM_STRUCT *p_dm_odm) +{ + struct _sw_antenna_switch_ *p_dm_swat_table = &p_dm_odm->dm_swat_table; + + p_dm_swat_table->swas_no_link_state = 0; +} + +/* 3============================================================ + * 3 Dynamic Primary CCA + * 3============================================================ */ + +void odm_primary_cca_init(struct PHY_DM_STRUCT *p_dm_odm) +{ + struct _dynamic_primary_cca *primary_cca = &(p_dm_odm->dm_pri_cca); + primary_cca->dup_rts_flag = 0; + primary_cca->intf_flag = 0; + primary_cca->intf_type = 0; + primary_cca->monitor_flag = 0; + primary_cca->pri_cca_flag = 0; +} + +bool odm_dynamic_primary_cca_dup_rts(struct PHY_DM_STRUCT *p_dm_odm) +{ + struct _dynamic_primary_cca *primary_cca = &(p_dm_odm->dm_pri_cca); + + return primary_cca->dup_rts_flag; +} + +void odm_dynamic_primary_cca(struct PHY_DM_STRUCT *p_dm_odm) +{ +} diff --git a/drivers/staging/rtl8188eu/hal/phydm_rtl8188e.h b/drivers/staging/rtl8188eu/hal/phydm_rtl8188e.h new file mode 100644 index 000000000000..c131632ea092 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_rtl8188e.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#ifndef __ODM_RTL8188E_H__ +#define __ODM_RTL8188E_H__ + +#if (RTL8188E_SUPPORT == 1) + + + +#define MAIN_ANT_CG_TRX 1 +#define AUX_ANT_CG_TRX 0 +#define MAIN_ANT_CGCS_RX 0 +#define AUX_ANT_CGCS_RX 1 + +void +odm_dig_lower_bound_88e( + struct PHY_DM_STRUCT *p_dm_odm +); + +#define sw_ant_div_reset_before_link odm_sw_ant_div_reset_before_link + +void odm_sw_ant_div_reset_before_link(struct PHY_DM_STRUCT *p_dm_odm); + +void +odm_set_tx_ant_by_tx_info_88e( + struct PHY_DM_STRUCT *p_dm_odm, + u8 *p_desc, + u8 mac_id +); + +void +odm_primary_cca_init( + struct PHY_DM_STRUCT *p_dm_odm); + +bool +odm_dynamic_primary_cca_dup_rts( + struct PHY_DM_STRUCT *p_dm_odm); + +void +odm_dynamic_primary_cca( + struct PHY_DM_STRUCT *p_dm_odm); + +#else /* (RTL8188E_SUPPORT == 0)*/ + +#define odm_primary_cca_init(_pdm_odm) +#define odm_dynamic_primary_cca(_pdm_odm) + +#endif /* RTL8188E_SUPPORT */ + +#endif diff --git a/drivers/staging/rtl8188eu/hal/phydm_types.h b/drivers/staging/rtl8188eu/hal/phydm_types.h new file mode 100644 index 000000000000..f5fe63953a9f --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/phydm_types.h @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#ifndef __ODM_TYPES_H__ +#define __ODM_TYPES_H__ + + +/*Define Different SW team support*/ +#define ODM_AP 0x01 /*BIT0*/ +#define ODM_CE 0x04 /*BIT2*/ +#define ODM_WIN 0x08 /*BIT3*/ +#define ODM_ADSL 0x10 /*BIT4*/ +#define ODM_IOT 0x20 /*BIT5*/ + +/*Deifne HW endian support*/ +#define ODM_ENDIAN_BIG 0 +#define ODM_ENDIAN_LITTLE 1 + + #define GET_PDM_ODM(__padapter) ((struct PHY_DM_STRUCT*)(&((GET_HAL_DATA(__padapter))->odmpriv))) + + #define RT_PCI_INTERFACE 1 + #define RT_USB_INTERFACE 2 + #define RT_SDIO_INTERFACE 3 + +enum hal_status { + HAL_STATUS_SUCCESS, + HAL_STATUS_FAILURE, + /*RT_STATUS_PENDING, + RT_STATUS_RESOURCE, + RT_STATUS_INVALID_CONTEXT, + RT_STATUS_INVALID_PARAMETER, + RT_STATUS_NOT_SUPPORT, + RT_STATUS_OS_API_FAILED,*/ +}; + + +#define VISTA_USB_RX_REVISE 0 + +/* + * Declare for ODM spin lock defintion temporarily fro compile pass. + * */ +enum rt_spinlock_type { + RT_TX_SPINLOCK = 1, + RT_RX_SPINLOCK = 2, + RT_RM_SPINLOCK = 3, + RT_CAM_SPINLOCK = 4, + RT_SCAN_SPINLOCK = 5, + RT_LOG_SPINLOCK = 7, + RT_BW_SPINLOCK = 8, + RT_CHNLOP_SPINLOCK = 9, + RT_RF_OPERATE_SPINLOCK = 10, + RT_INITIAL_SPINLOCK = 11, + RT_RF_STATE_SPINLOCK = 12, /* For RF state. Added by Bruce, 2007-10-30. */ +#if VISTA_USB_RX_REVISE + RT_USBRX_CONTEXT_SPINLOCK = 13, + RT_USBRX_POSTPROC_SPINLOCK = 14, /* protect data of adapter->IndicateW/ IndicateR */ +#endif + /* Shall we define Ndis 6.2 SpinLock Here ? */ + RT_PORT_SPINLOCK = 16, + RT_VNIC_SPINLOCK = 17, + RT_HVL_SPINLOCK = 18, + RT_H2C_SPINLOCK = 20, /* For H2C cmd. Added by tynli. 2009.11.09. */ + + rt_bt_data_spinlock = 25, + + RT_WAPI_OPTION_SPINLOCK = 26, + RT_WAPI_RX_SPINLOCK = 27, + + /* add for 92D CCK control issue */ + RT_CCK_PAGEA_SPINLOCK = 28, + RT_BUFFER_SPINLOCK = 29, + RT_CHANNEL_AND_BANDWIDTH_SPINLOCK = 30, + RT_GEN_TEMP_BUF_SPINLOCK = 31, + RT_AWB_SPINLOCK = 32, + RT_FW_PS_SPINLOCK = 33, + RT_HW_TIMER_SPIN_LOCK = 34, + RT_MPT_WI_SPINLOCK = 35, + RT_P2P_SPIN_LOCK = 36, /* Protect P2P context */ + RT_DBG_SPIN_LOCK = 37, + RT_IQK_SPINLOCK = 38, + RT_PENDED_OID_SPINLOCK = 39, + RT_CHNLLIST_SPINLOCK = 40, + RT_INDIC_SPINLOCK = 41, /* protect indication */ + RT_RFD_SPINLOCK = 42, + RT_SYNC_IO_CNT_SPINLOCK = 43, + RT_LAST_SPINLOCK, +}; + + #include + #define DEV_BUS_TYPE RT_USB_INTERFACE + + #if defined(__LITTLE_ENDIAN) + #define ODM_ENDIAN_TYPE ODM_ENDIAN_LITTLE + #elif defined (__BIG_ENDIAN) + #define ODM_ENDIAN_TYPE ODM_ENDIAN_BIG + #endif + + #define SET_TX_DESC_ANTSEL_A_88E(__ptx_desc, __value) SET_BITS_TO_LE_4BYTE(__ptx_desc+8, 24, 1, __value) + #define SET_TX_DESC_ANTSEL_B_88E(__ptx_desc, __value) SET_BITS_TO_LE_4BYTE(__ptx_desc+8, 25, 1, __value) + #define SET_TX_DESC_ANTSEL_C_88E(__ptx_desc, __value) SET_BITS_TO_LE_4BYTE(__ptx_desc+28, 29, 1, __value) + + /* define useless flag to avoid compile warning */ + #define USE_WORKITEM 0 + #define FOR_BRAZIL_PRETEST 0 + #define FPGA_TWO_MAC_VERIFICATION 0 + #define RTL8881A_SUPPORT 0 + + #if (defined(TESTCHIP_SUPPORT)) + #define PHYDM_TESTCHIP_SUPPORT 1 + #else + #define PHYDM_TESTCHIP_SUPPORT 0 + #endif + +#define READ_NEXT_PAIR(v1, v2, i) do { if (i+2 >= array_len) break; i += 2; v1 = array[i]; v2 = array[i+1]; } while (0) +#define COND_ELSE 2 +#define COND_ENDIF 3 + +#define MASKBYTE0 0xff +#define MASKBYTE1 0xff00 +#define MASKBYTE2 0xff0000 +#define MASKBYTE3 0xff000000 +#define MASKHWORD 0xffff0000 +#define MASKLWORD 0x0000ffff +#define MASKDWORD 0xffffffff +#define MASK7BITS 0x7f +#define MASK12BITS 0xfff +#define MASKH4BITS 0xf0000000 +#define MASK20BITS 0xfffff +#define MASKOFDM_D 0xffc00000 +#define MASKCCK 0x3f3f3f3f +#define RFREGOFFSETMASK 0xfffff +#define MASKH3BYTES 0xffffff00 +#define MASKL3BYTES 0x00ffffff +#define MASKBYTE2HIGHNIBBLE 0x00f00000 +#define MASKBYTE3LOWNIBBLE 0x0f000000 +#define MASKL3BYTES 0x00ffffff +#define RFREGOFFSETMASK 0xfffff + + +#include "phydm_features.h" + +#endif /* __ODM_TYPES_H__ */ diff --git a/drivers/staging/rtl8188eu/hal/rtchnlplan.c b/drivers/staging/rtl8188eu/hal/rtchnlplan.c new file mode 100644 index 000000000000..20c2a5d4ad18 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/rtchnlplan.c @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +/****************************************************************************** + + History: + data Who Remark (Internal History) + + 05/14/2012 MH Collect RTK inernal infromation and generate channel plan draft. + +******************************************************************************/ + +/* ************************************************************ + * include files + * ************************************************************ */ +#include "mp_precomp.h" +#include "phydm_precomp.h" +#include "rtchnlplan.h" + + + +/* + * channel Plan Domain Code + * */ + +/* + channel Plan Contents + Domain Code EEPROM Countries in Specific Domain + 2G RD 5G RD Bit[6:0] 2G 5G + Case Old Define 00h~1Fh Old Define Old Define + 1 2G_WORLD 5G_NULL 20h Worldwird 13 NA + 2 2G_ETSI1 5G_NULL 21h Europe 2G NA + 3 2G_FCC1 5G_NULL 22h US 2G NA + 4 2G_MKK1 5G_NULL 23h Japan 2G NA + 5 2G_ETSI2 5G_NULL 24h France 2G NA + 6 2G_FCC1 5G_FCC1 25h US 2G US 5G �K�j��{�� + 7 2G_WORLD 5G_ETSI1 26h Worldwird 13 Europe �K�j��{�� + 8 2G_MKK1 5G_MKK1 27h Japan 2G Japan 5G �K�j��{�� + 9 2G_WORLD 5G_KCC1 28h Worldwird 13 Korea �K�j��{�� + 10 2G_WORLD 5G_FCC2 29h Worldwird 13 US o/w DFS Channels + 11 2G_WORLD 5G_FCC3 30h Worldwird 13 India, Mexico + 12 2G_WORLD 5G_FCC4 31h Worldwird 13 Venezuela + 13 2G_WORLD 5G_FCC5 32h Worldwird 13 China + 14 2G_WORLD 5G_FCC6 33h Worldwird 13 Israel + 15 2G_FCC1 5G_FCC7 34h US 2G US/Canada �K�j��{�� + 16 2G_WORLD 5G_ETSI2 35h Worldwird 13 Australia, New Zealand �K�j��{�� + 17 2G_WORLD 5G_ETSI3 36h Worldwird 13 Russia + 18 2G_MKK1 5G_MKK2 37h Japan 2G Japan (W52, W53) + 19 2G_MKK1 5G_MKK3 38h Japan 2G Japan (W56) + 20 2G_FCC1 5G_NCC1 39h US 2G Taiwan �K�j��{�� + + NA 2G_WORLD 5G_FCC1 7F FCC FCC DFS Channels Realtek Define + + + + + + 2.4G Regulatory Domains + Case 2G RD regulation Channels Frequencyes Note Countries in Specific Domain + 1 2G_WORLD ETSI 1~13 2412~2472 Passive scan CH 12, 13 Worldwird 13 + 2 2G_ETSI1 ETSI 1~13 2412~2472 Europe + 3 2G_FCC1 FCC 1~11 2412~2462 US + 4 2G_MKK1 MKK 1~13, 14 2412~2472, 2484 Japan + 5 2G_ETSI2 ETSI 10~13 2457~2472 France + + + + + 5G Regulatory Domains + Case 5G RD regulation Channels Frequencyes Note Countries in Specific Domain + 1 5G_NULL NA NA NA Do not support 5GHz + 2 5G_ETSI1 ETSI "36~48, 52~64, + 100~140" "5180~5240, 5260~5230 + 5500~5700" Band1, Ban2, Band3 Europe + 3 5G_ETSI2 ETSI "36~48, 52~64, + 100~140, 149~165" "5180~5240, 5260~5230 + 5500~5700, 5745~5825" Band1, Ban2, Band3, Band4 Australia, New Zealand + 4 5G_ETSI3 ETSI "36~48, 52~64, + 100~132, 149~165" + "5180~5240, 5260~5230 + 5500~5660, 5745~5825" Band1, Ban2, Band3(except CH 136, 140), Band4" Russia + 5 5G_FCC1 FCC "36~48, 52~64, + 100~140, 149~165" + "5180~5240, 5260~5230 + 5500~5700, 5745~5825" Band1(5150~5250MHz), + Band2(5250~5350MHz), + Band3(5470~5725MHz), + Band4(5725~5850MHz)" US + 6 5G_FCC2 FCC 36~48, 149~165 5180~5240, 5745~5825 Band1, Band4 FCC o/w DFS Channels + 7 5G_FCC3 FCC "36~48, 52~64, + 149~165" "5180~5240, 5260~5230 + 5745~5825" Band1, Ban2, Band4 India, Mexico + 8 5G_FCC4 FCC "36~48, 52~64, + 149~161" "5180~5240, 5260~5230 + 5745~5805" Band1, Ban2, + Band4(except CH 165)" Venezuela + 9 5G_FCC5 FCC 149~165 5745~5825 Band4 China + 10 5G_FCC6 FCC 36~48, 52~64 5180~5240, 5260~5230 Band1, Band2 Israel + 11 5G_FCC7 + 5G_IC1 FCC + IC" "36~48, 52~64, + 100~116, 136, 140, + 149~165" "5180~5240, 5260~5230 + 5500~5580, 5680, 5700, + 5745~5825" "Band1, Band2, + Band3(except 5600~5650MHz), + Band4" "US + Canada" + 12 5G_KCC1 KCC "36~48, 52~64, + 100~124, 149~165" "5180~5240, 5260~5230 + 5500~5620, 5745~5825" "Band1, Ban2, + Band3(5470~5650MHz), + Band4" Korea + 13 5G_MKK1 MKK "36~48, 52~64, + 100~140" "5180~5240, 5260~5230 + 5500~5700" W52, W53, W56 Japan + 14 5G_MKK2 MKK 36~48, 52~64 5180~5240, 5260~5230 W52, W53 Japan (W52, W53) + 15 5G_MKK3 MKK 100~140 5500~5700 W56 Japan (W56) + 16 5G_NCC1 NCC "56~64, + 100~116, 136, 140, + 149~165" "5260~5320 + 5500~5580, 5680, 5700, + 5745~5825" "Band2(except CH 52), + Band3(except 5600~5650MHz), + Band4" Taiwan + + +*/ + +/* + * 2.4G CHannel + * + * + + 2.4G band Regulatory Domains RTL8192D + channel number channel Frequency US Canada Europe Spain France Japan Japan 20M 40M + (MHz) (FCC) (IC) (ETSI) (MPHPT) + 1 2412 v v v v v + 2 2417 v v v v v + 3 2422 v v v v v v + 4 2427 v v v v v v + 5 2432 v v v v v v + 6 2437 v v v v v v + 7 2442 v v v v v v + 8 2447 v v v v v v + 9 2452 v v v v v v + 10 2457 v v v v v v v v + 11 2462 v v v v v v v v + 12 2467 v v v v v + 13 2472 v v v v + 14 2484 v v + + +*/ + + +/* + * 5G Operating channel + * + * + + 5G band RTL8192D RTL8195 (Jaguar) Jaguar 2 Regulatory Domains + channel number channel Frequency Global Global Global "US +(FCC 15.407)" "Canada +(FCC, except 5.6~5.65GHz)" Argentina, Australia, New Zealand, Brazil, S. Africa (FCC/ETSI) "Europe +(CE 301 893)" China India, Mexico, Singapore Israel, Turkey "Japan +(MIC Item 19-3, 19-3-2)" Korea Russia, Ukraine "Taiwan +(NCC)" Venezuela + (MHz) (20MHz) (20MHz) (40MHz) (80MHz) (160MHz) (20MHz) (20MHz) (20MHz) (20MHz) (20MHz) (20MHz) (20MHz) (20MHz) (20MHz) (20MHz) (20MHz) (20MHz) (20MHz) +"band 1 +5.15GHz +~ +5.25GHz" 36 5180 v v v v v Indoor Indoor v Indoor v Indoor Indoor v v v + 40 5200 v v v Indoor Indoor v Indoor v Indoor Indoor v v v + 44 5220 v v v v Indoor Indoor v Indoor v Indoor Indoor v v v + 48 5240 v v v Indoor Indoor v Indoor v Indoor Indoor v v v +"band 2 +5.25GHz +~ +5.35GHz +(DFS)" 52 5260 v v v v v v v v Indoor v Indoor Indoor v v v + 56 5280 v v v v v v Indoor v Indoor Indoor v v Indoor v + 60 5300 v v v v v v v Indoor v Indoor Indoor v v Indoor v + 64 5320 v v v v v v Indoor v Indoor Indoor v v Indoor v + +"band 3 +5.47GHz +~ +5.725GHz +(DFS)" 100 5500 v v v v v v v v v v v v v + 104 5520 v v v v v v v v v v v + 108 5540 v v v v v v v v v v v v + 112 5560 v v v v v v v v v v v + 116 5580 v v v v v v v v v v v v v + 120 5600 v v v Indoor v Indoor v v v + 124 5620 v v v v Indoor v Indoor v v v + 128 5640 v v v Indoor v Indoor v v + 132 5660 v v v E v Indoor v Indoor v v + 136 5680 v v v v v v v v v + 140 5700 v v E v v v v v v v + 144 5720 E E E +"band 4 +5.725GHz +~ +5.85GHz +(~5.9GHz)" 149 5745 v v v v v v v v v v v v v v + 153 5765 v v v v v v v v v v v v + 157 5785 v v v v v v v v v v v v v + 161 5805 v v v v v v v v v v v v + 165 5825 v v P P v v v v v v v v v + 169 5845 P P P + 173 5865 P P P P + 177 5885 P P P +channel count 28 28 14 7 0 28 24 20 24 19 5 13 8 19 20 22 15 12 + E: FCC accepted the ask for CH144 from Accord. PS: 160MHz �� 80MHz+80MHz��{�H Argentina Belgium (��Q��) India Israel Russia + P: Customer's requirement from James. Australia The Netherlands (����) Mexico Turkey Ukraine + New Zealand UK (�^��) Singapore + Brazil Switzerland (��h) + + +*/ + +/*---------------------------Define Local Constant---------------------------*/ + + +/* define Maximum Power v.s each band for each region + * ISRAEL + * Format: + * RT_CHANNEL_DOMAIN_Region ={{{chnl_start, chnl_end, Pwr_dB_Max}, {Chn2_Start, Chn2_end, Pwr_dB_Max}, {Chn3_Start, Chn3_end, Pwr_dB_Max}, {Chn4_Start, Chn4_end, Pwr_dB_Max}, {Chn5_Start, Chn5_end, Pwr_dB_Max}}, Limit_Num} + * RT_CHANNEL_DOMAIN_FCC ={{{01,11,30}, {36,48,17}, {52,64,24}, {100,140,24}, {149,165,30}}, 5} + * "NR" is non-release channle. + * Issue--- Israel--Russia--New Zealand + * DOMAIN_01= (2G_WORLD, 5G_NULL) + * DOMAIN_02= (2G_ETSI1, 5G_NULL) + * DOMAIN_03= (2G_FCC1, 5G_NULL) + * DOMAIN_04= (2G_MKK1, 5G_NULL) + * DOMAIN_05= (2G_ETSI2, 5G_NULL) + * DOMAIN_06= (2G_FCC1, 5G_FCC1) + * DOMAIN_07= (2G_WORLD, 5G_ETSI1) + * DOMAIN_08= (2G_MKK1, 5G_MKK1) + * DOMAIN_09= (2G_WORLD, 5G_KCC1) + * DOMAIN_10= (2G_WORLD, 5G_FCC2) + * DOMAIN_11= (2G_WORLD, 5G_FCC3)----india + * DOMAIN_12= (2G_WORLD, 5G_FCC4)----Venezuela + * DOMAIN_13= (2G_WORLD, 5G_FCC5)----China + * DOMAIN_14= (2G_WORLD, 5G_FCC6)----Israel + * DOMAIN_15= (2G_FCC1, 5G_FCC7)-----Canada + * DOMAIN_16= (2G_WORLD, 5G_ETSI2)---Australia + * DOMAIN_17= (2G_WORLD, 5G_ETSI3)---Russia + * DOMAIN_18= (2G_MKK1, 5G_MKK2)-----Japan + * DOMAIN_19= (2G_MKK1, 5G_MKK3)-----Japan + * DOMAIN_20= (2G_FCC1, 5G_NCC1)-----Taiwan + * DOMAIN_21= (2G_FCC1, 5G_NCC1)-----Taiwan */ + + +static struct _RT_CHANNEL_PLAN_MAXPWR chnl_plan_pwr_max_2g[] = { + + /* 2G_WORLD, */ + {{1, 13, 20}, 1}, + + /* 2G_ETSI1 */ + {{1, 13, 20}, 1}, + + /* RT_CHANNEL_DOMAIN_ETSI */ + {{{1, 11, 17}, {40, 56, 17}, {60, 128, 17}, {0, 0, 0}, {149, 165, 17}}, 4}, + + /* RT_CHANNEL_DOMAIN_MKK */ + {{{1, 11, 17}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, 1}, + + /* Add new channel plan mex power table. */ + /* ...... */ +}; + +/* + * counter & Realtek channel plan transfer table. + * */ +struct _RT_CHANNEL_PLAN_COUNTRY_TRANSFER_TABLE rt_ctry_chnl_tbl[] = { + + { + RT_CTRY_AL, /* "Albania�����ڥ���" */ + "AL", + RT_2G_WORLD, + RT_5G_WORLD, + RT_CHANNEL_DOMAIN_UNDEFINED /* 2G/5G world. */ + }, +}; /* rt_ctry_chnl_tbl */ diff --git a/drivers/staging/rtl8188eu/hal/rtchnlplan.h b/drivers/staging/rtl8188eu/hal/rtchnlplan.h new file mode 100644 index 000000000000..5d9d049cd474 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/rtchnlplan.h @@ -0,0 +1,615 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + + +#ifndef __RT_CHANNELPLAN_H__ +#define __RT_CHANNELPLAN_H__ + +enum rt_channel_domain_new { + + /* ===== Add new channel plan above this line =============== */ + + /* For new architecture we define different 2G/5G CH area for all country. */ + /* 2.4 G only */ + RT_CHANNEL_DOMAIN_2G_WORLD_5G_NULL = 0x20, + RT_CHANNEL_DOMAIN_2G_ETSI1_5G_NULL = 0x21, + RT_CHANNEL_DOMAIN_2G_FCC1_5G_NULL = 0x22, + RT_CHANNEL_DOMAIN_2G_MKK1_5G_NULL = 0x23, + RT_CHANNEL_DOMAIN_2G_ETSI2_5G_NULL = 0x24, + /* 2.4 G + 5G type 1 */ + RT_CHANNEL_DOMAIN_2G_FCC1_5G_FCC1 = 0x25, + RT_CHANNEL_DOMAIN_2G_WORLD_5G_ETSI1 = 0x26, + /* RT_CHANNEL_DOMAIN_2G_WORLD_5G_ETSI1 = 0x27, */ + /* ..... */ + + RT_CHANNEL_DOMAIN_MAX_NEW, + +}; + +/* + * + * + * + +Countries "Country Abbreviation" Domain Code SKU's Ch# of 20MHz + 2G 5G Ch# of 40MHz +"Albania�����ڥ���" AL Local Test + +"Algeria�����ΧQ��" DZ CE TCF + +"Antigua & Barbuda�w���ʮq&�ڥ��F" AG 2G_WORLD FCC TCF + +"Argentina���ڧ�" AR 2G_WORLD Local Test + +"Armenia�Ȭ�����" AM 2G_WORLD ETSI + +"Aruba���|�ڮq" AW 2G_WORLD FCC TCF + +"Australia�D�w" AU 2G_WORLD 5G_ETSI2 + +"Austria���a�Q" AT 2G_WORLD 5G_ETSI1 CE + +"Azerbaijan�������" AZ 2G_WORLD CE TCF + +"Bahamas�ګ���" BS 2G_WORLD + +"Barbados�ڤڦh��" BB 2G_WORLD FCC TCF + +"Belgium��Q��" BE 2G_WORLD 5G_ETSI1 CE + +"Bermuda�ʼ}�F" BM 2G_WORLD FCC TCF + +"Brazil�ڦ�" BR 2G_WORLD Local Test + +"Bulgaria�O�[�Q��" BG 2G_WORLD 5G_ETSI1 CE + +"Canada�[���j" CA 2G_FCC1 5G_FCC7 IC / FCC IC / FCC + +"Cayman Islands�}�Ҹs�q" KY 2G_WORLD 5G_ETSI1 CE + +"Chile���Q" CL 2G_WORLD FCC TCF + +"China����" CN 2G_WORLD 5G_FCC5 �H��?�i2002�j353? + +"Columbia���ۤ��" CO 2G_WORLD Voluntary + +"Costa Rica�����F���[" CR 2G_WORLD FCC TCF + +"Cyprus�������" CY 2G_WORLD 5G_ETSI1 CE + +"Czech ���J" CZ 2G_WORLD 5G_ETSI1 CE + +"Denmark����" DK 2G_WORLD 5G_ETSI1 CE + +"Dominican Republic�h�����[�@�M��" DO 2G_WORLD FCC TCF + +"Egypt�J��" EG 2G_WORLD CE T CF + +"El Salvador�ĺ��˦h" SV 2G_WORLD Voluntary + +"Estonia�R�F����" EE 2G_WORLD 5G_ETSI1 CE + +"Finland����" FI 2G_WORLD 5G_ETSI1 CE + +"France�k��" FR 5G_E TSI1 CE + +"Germany�w��" DE 2G_WORLD 5G_ETSI1 CE + +"Greece ��þ" GR 2G_WORLD 5G_ETSI1 CE + +"Guam���q" GU 2G_WORLD + +"Guatemala�ʦa����" GT 2G_WORLD + +"Haiti���a" HT 2G_WORLD FCC TCF + +"Honduras�����Դ�" HN 2G_WORLD FCC TCF + +"Hungary�I���Q" HU 2G_WORLD 5G_ETSI1 CE + +"Iceland�B�q" IS 2G_WORLD 5G_ETSI1 CE + +"India�L��" 2G_WORLD 5G_FCC3 FCC/CE TCF + +"Ireland�R����" IE 2G_WORLD 5G_ETSI1 CE + +"Israel�H��C" IL 5G_F CC6 CE TCF + +"Italy�q�j�Q" IT 2G_WORLD 5G_ETSI1 CE + +"Japan�饻" JP 2G_MKK1 5G_MKK1 MKK MKK + +"Korea����" KR 2G_WORLD 5G_KCC1 KCC KCC + +"Latvia�Բ����" LV 2G_WORLD 5G_ETSI1 CE + +"Lithuania�߳��{" LT 2G_WORLD 5G_ETSI1 CE + +"Luxembourg�c�˳�" LU 2G_WORLD 5G_ETSI1 CE + +"Malaysia���Ӧ��" MY 2G_WORLD Local Test + +"Malta�����L" MT 2G_WORLD 5G_ETSI1 CE + +"Mexico�����" MX 2G_WORLD 5G_FCC3 Local Test + +"Morocco������" MA CE TCF + +"Netherlands����" NL 2G_WORLD 5G_ETSI1 CE + +"New Zealand���" NZ 2G_WORLD 5G_ETSI2 + +"Norway����" NO 2G_WORLD 5G_ETSI1 CE + +"Panama�ڮ��� " PA 2G_FCC1 Voluntary + +"Philippines��߻�" PH 2G_WORLD FCC TCF + +"Poland�i��" PL 2G_WORLD 5G_ETSI1 CE + +"Portugal�����" PT 2G_WORLD 5G_ETSI1 CE + +"Romaniaù������" RO 2G_WORLD 5G_ETSI1 CE + +"Russia�Xù��" RU 2G_WORLD 5G_ETSI3 CE TCF + +"Saudi Arabia�F�a���ԧB" SA 2G_WORLD CE TCF + +"Singapore�s�[�Y" SG 2G_WORLD + +"Slovakia������J" SK 2G_WORLD 5G_ETSI1 CE + +"Slovenia����������" SI 2G_WORLD 5G_ETSI1 CE + +"South Africa�n�D" ZA 2G_WORLD CE TCF + +"Spain��Z��" ES 5G_ETSI1 CE + +"Sweden���" SE 2G_WORLD 5G_ETSI1 CE + +"Switzerland��h" CH 2G_WORLD 5G_ETSI1 CE + +"Taiwan�O�W" TW 2G_FCC1 5G_NCC1 NCC + +"Thailand����" TH 2G_WORLD FCC/CE TCF + +"Turkey�g�ը�" TR 2G_WORLD + +"Ukraine�Q�J��" UA 2G_WORLD Local Test + +"United Kingdom�^��" GB 2G_WORLD 5G_ETSI1 CE ETSI + +"United States����" US 2G_FCC1 5G_FCC7 FCC FCC + +"Venezuela�e�����" VE 2G_WORLD 5G_FCC4 FCC TCF + +"Vietnam�V�n" VN 2G_WORLD FCC/CE TCF + + + +*/ + +/* counter abbervation. */ +enum rt_country_name { + RT_CTRY_AL, /* "Albania�����ڥ���" */ + RT_CTRY_DZ, /* "Algeria�����ΧQ��" */ + RT_CTRY_AG, /* "Antigua & Barbuda�w���ʮq&�ڥ��F" */ + RT_CTRY_AR, /* "Argentina���ڧ�" */ + RT_CTRY_AM, /* "Armenia�Ȭ�����" */ + RT_CTRY_AW, /* "Aruba���|�ڮq" */ + RT_CTRY_AU, /* "Australia�D�w" */ + RT_CTRY_AT, /* "Austria���a�Q" */ + RT_CTRY_AZ, /* "Azerbaijan�������" */ + RT_CTRY_BS, /* "Bahamas�ګ���" */ + RT_CTRY_BB, /* "Barbados�ڤڦh��" */ + RT_CTRY_BE, /* "Belgium��Q��" */ + RT_CTRY_BM, /* "Bermuda�ʼ}�F" */ + RT_CTRY_BR, /* "Brazil�ڦ�" */ + RT_CTRY_BG, /* "Bulgaria�O�[�Q��" */ + RT_CTRY_CA, /* "Canada�[���j" */ + RT_CTRY_KY, /* "Cayman Islands�}�Ҹs�q" */ + RT_CTRY_CL, /* "Chile���Q" */ + RT_CTRY_CN, /* "China����" */ + RT_CTRY_CO, /* "Columbia���ۤ��" */ + RT_CTRY_CR, /* "Costa Rica�����F���[" */ + RT_CTRY_CY, /* "Cyprus�������" */ + RT_CTRY_CZ, /* "Czech ���J" */ + RT_CTRY_DK, /* "Denmark����" */ + RT_CTRY_DO, /* "Dominican Republic�h�����[�@�M��" */ + RT_CTRY_CE, /* "Egypt�J��" EG 2G_WORLD */ + RT_CTRY_SV, /* "El Salvador�ĺ��˦h" */ + RT_CTRY_EE, /* "Estonia�R�F����" */ + RT_CTRY_FI, /* "Finland����" */ + RT_CTRY_FR, /* "France�k��" */ + RT_CTRY_DE, /* "Germany�w��" */ + RT_CTRY_GR, /* "Greece ��þ" */ + RT_CTRY_GU, /* "Guam���q" */ + RT_CTRY_GT, /* "Guatemala�ʦa����" */ + RT_CTRY_HT, /* "Haiti���a" */ + RT_CTRY_HN, /* "Honduras�����Դ�" */ + RT_CTRY_HU, /* "Hungary�I���Q" */ + RT_CTRY_IS, /* "Iceland�B�q" */ + RT_CTRY_IN, /* "India�L��" */ + RT_CTRY_IE, /* "Ireland�R����" */ + RT_CTRY_IL, /* "Israel�H��C" */ + RT_CTRY_IT, /* "Italy�q�j�Q" */ + RT_CTRY_JP, /* "Japan�饻" */ + RT_CTRY_KR, /* "Korea����" */ + RT_CTRY_LV, /* "Latvia�Բ����" */ + RT_CTRY_LT, /* "Lithuania�߳��{" */ + RT_CTRY_LU, /* "Luxembourg�c�˳�" */ + RT_CTRY_MY, /* "Malaysia���Ӧ��" */ + RT_CTRY_MT, /* "Malta�����L" */ + RT_CTRY_MX, /* "Mexico�����" */ + RT_CTRY_MA, /* "Morocco������" */ + RT_CTRY_NL, /* "Netherlands����" */ + RT_CTRY_NZ, /* "New Zealand���" */ + RT_CTRY_NO, /* "Norway����" */ + RT_CTRY_PA, /* "Panama�ڮ��� " */ + RT_CTRY_PH, /* "Philippines��߻�" */ + RT_CTRY_PL, /* "Poland�i��" */ + RT_CTRY_PT, /* "Portugal�����" */ + RT_CTRY_RO, /* "Romaniaù������" */ + RT_CTRY_RU, /* "Russia�Xù��" */ + RT_CTRY_SA, /* "Saudi Arabia�F�a���ԧB" */ + RT_CTRY_SG, /* "Singapore�s�[�Y" */ + RT_CTRY_SK, /* "Slovakia������J" */ + RT_CTRY_SI, /* "Slovenia����������" */ + RT_CTRY_ZA, /* "South Africa�n�D" */ + RT_CTRY_ES, /* "Spain��Z��" */ + RT_CTRY_SE, /* "Sweden���" */ + RT_CTRY_CH, /* "Switzerland��h" */ + RT_CTRY_TW, /* "Taiwan�O�W" */ + RT_CTRY_TH, /* "Thailand����" */ + RT_CTRY_TR, /* "Turkey�g�ը�" */ + RT_CTRY_UA, /* "Ukraine�Q�J��" */ + RT_CTRY_GB, /* "United Kingdom�^��" */ + RT_CTRY_US, /* "United States����" */ + RT_CTRY_VE, /* "Venezuela�e�����" */ + RT_CTRY_VN, /* "Vietnam�V�n" */ + RT_CTRY_MAX, + +}; + +/* Scan type including active and passive scan. */ +enum rt_scan_type_new { + SCAN_NULL, + SCAN_ACT, + SCAN_PAS, + SCAN_BOTH, +}; + + +/* Power table sample. */ + +struct _RT_CHNL_PLAN_LIMIT { + u16 chnl_start; + u16 chnl_end; + + u16 freq_start; + u16 freq_end; +}; + + +/* + * 2.4G Regulatory Domains + * */ +enum rt_regulation_2g { + RT_2G_NULL, + RT_2G_WORLD, + RT_2G_ETSI1, + RT_2G_FCC1, + RT_2G_MKK1, + RT_2G_ETSI2 + +}; + + +/* typedef struct _RT_CHANNEL_BEHAVIOR + * { + * u8 chnl; + * enum rt_scan_type_new + * + * }RT_CHANNEL_BEHAVIOR, *PRT_CHANNEL_BEHAVIOR; */ + +/* typedef struct _RT_CHANNEL_PLAN_TYPE + * { + * RT_CHANNEL_BEHAVIOR + * u8 Chnl_num; + * }RT_CHNL_PLAN_TYPE, *PRT_CHNL_PLAN_TYPE; */ + +/* + * 2.4G channel number + * channel definition & number + * */ +#define CHNL_RT_2G_NULL \ + {0}, 0 +#define CHNL_RT_2G_WORLD \ + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13 +#define CHNL_RT_2G_WORLD_TEST \ + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13 + +#define CHNL_RT_2G_EFSI1 \ + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13 +#define CHNL_RT_2G_FCC1 \ + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11 +#define CHNL_RT_2G_MKK1 \ + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14 +#define CHNL_RT_2G_ETSI2 \ + {10, 11, 12, 13}, 4 + +/* + * 2.4G channel active or passive scan. + * */ +#define CHNL_RT_2G_NULL_SCAN_TYPE \ + {SCAN_NULL} +#define CHNL_RT_2G_WORLD_SCAN_TYPE \ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0} +#define CHNL_RT_2G_EFSI1_SCAN_TYPE \ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} +#define CHNL_RT_2G_FCC1_SCAN_TYPE \ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} +#define CHNL_RT_2G_MKK1_SCAN_TYPE \ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} +#define CHNL_RT_2G_ETSI2_SCAN_TYPE \ + {1, 1, 1, 1} + + +/* + * 2.4G band & Frequency Section + * Freqency start & end / band number + * */ +#define FREQ_RT_2G_NULL \ + {0}, 0 +/* Passive scan CH 12, 13 */ +#define FREQ_RT_2G_WORLD \ + {2412, 2472}, 1 +#define FREQ_RT_2G_EFSI1 \ + {2412, 2472}, 1 +#define FREQ_RT_2G_FCC1 \ + {2412, 2462}, 1 +#define FREQ_RT_2G_MKK1 \ + {2412, 2484}, 1 +#define FREQ_RT_2G_ETSI2 \ + {2457, 2472}, 1 + + +/* + * 5G Regulatory Domains + * */ +enum rt_regulation_5g { + RT_5G_NULL, + RT_5G_WORLD, + RT_5G_ETSI1, + RT_5G_ETSI2, + RT_5G_ETSI3, + RT_5G_FCC1, + RT_5G_FCC2, + RT_5G_FCC3, + RT_5G_FCC4, + RT_5G_FCC5, + RT_5G_FCC6, + RT_5G_FCC7, + RT_5G_IC1, + RT_5G_KCC1, + RT_5G_MKK1, + RT_5G_MKK2, + RT_5G_MKK3, + RT_5G_NCC1, + +}; + +/* + * 5G channel number + * */ +#define CHNL_RT_5G_NULL \ + {0}, 0 +#define CHNL_RT_5G_WORLD \ + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19 +#define CHNL_RT_5G_ETSI1 \ + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24 +#define CHNL_RT_5G_ETSI2 \ + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22 +#define CHNL_RT_5G_ETSI3 \ + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24 +#define CHNL_RT_5G_FCC1 \ + {36, 40, 44, 48, 149, 153, 157, 161, 165}, 9 +#define CHNL_RT_5G_FCC2 \ + {36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13 +#define CHNL_RT_5G_FCC3 \ + {36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12 +#define CHNL_RT_5G_FCC4 \ + {149, 153, 157, 161, 165}, 5 +#define CHNL_RT_5G_FCC5 \ + {36, 40, 44, 48, 52, 56, 60, 64}, 8 +#define CHNL_RT_5G_FCC6 \ + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 20 +#define CHNL_RT_5G_FCC7 \ + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 20 +#define CHNL_RT_5G_IC1 \ + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, 165}, 20 +#define CHNL_RT_5G_KCC1 \ + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19 +#define CHNL_RT_5G_MKK1 \ + {36, 40, 44, 48, 52, 56, 60, 64}, 8 +#define CHNL_RT_5G_MKK2 \ + {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11 +#define CHNL_RT_5G_MKK3 \ + {56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 24 +#define CHNL_RT_5G_NCC1 \ + {56, 60, 64, 149, 153, 157, 161, 165}, 8 + +/* + * 5G channel active or passive scan. + * */ +#define CHNL_RT_5G_NULL_SCAN_TYPE \ + {SCAN_NULL} +#define CHNL_RT_5G_WORLD_SCAN_TYPE \ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} +#define CHNL_RT_5G_ETSI1_SCAN_TYPE \ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} +#define CHNL_RT_5G_ETSI2_SCAN_TYPE \ + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22 +#define CHNL_RT_5G_ETSI3_SCAN_TYPE \ + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24 +#define CHNL_RT_5G_FCC1_SCAN_TYPE \ + {36, 40, 44, 48, 149, 153, 157, 161, 165}, 9 +#define CHNL_RT_5G_FCC2_SCAN_TYPE \ + {36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13 +#define CHNL_RT_5G_FCC3_SCAN_TYPE \ + {36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12 +#define CHNL_RT_5G_FCC4_SCAN_TYPE \ + {149, 153, 157, 161, 165}, 5 +#define CHNL_RT_5G_FCC5_SCAN_TYPE \ + {36, 40, 44, 48, 52, 56, 60, 64}, 8 +#define CHNL_RT_5G_FCC6_SCAN_TYPE \ + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 20 +#define CHNL_RT_5G_FCC7_SCAN_TYPE \ + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 20 +#define CHNL_RT_5G_IC1_SCAN_TYPE \ + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, 165}, 20 +#define CHNL_RT_5G_KCC1_SCAN_TYPE \ + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19 +#define CHNL_RT_5G_MKK1_SCAN_TYPE \ + {36, 40, 44, 48, 52, 56, 60, 64}, 8 +#define CHNL_RT_5G_MKK2_SCAN_TYPE \ + {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11 +#define CHNL_RT_5G_MKK3_SCAN_TYPE \ + {56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 24 +#define CHNL_RT_5G_NCC1_SCAN_TYPE \ + {56, 60, 64, 149, 153, 157, 161, 165}, 8 + +/* + * Global regulation + * */ +enum rt_regulation_cmn { + RT_WORLD, + RT_FCC, + RT_MKK, + RT_ETSI, + RT_IC, + RT_CE, + RT_NCC, + +}; + + + +/* + * Special requirement for different regulation domain. + * For internal test or customerize special request. + * */ +enum rt_chnlplan_sreq { + RT_SREQ_NA = 0x0, + RT_SREQ_2G_ADHOC_11N = 0x00000001, + RT_SREQ_2G_ADHOC_11B = 0x00000002, + RT_SREQ_2G_ALL_PASS = 0x00000004, + RT_SREQ_2G_ALL_ACT = 0x00000008, + RT_SREQ_5G_ADHOC_11N = 0x00000010, + RT_SREQ_5G_ADHOC_11AC = 0x00000020, + RT_SREQ_5G_ALL_PASS = 0x00000040, + RT_SREQ_5G_ALL_ACT = 0x00000080, + RT_SREQ_C1_PLAN = 0x00000100, + RT_SREQ_C2_PLAN = 0x00000200, + RT_SREQ_C3_PLAN = 0x00000400, + RT_SREQ_C4_PLAN = 0x00000800, + RT_SREQ_NFC_ON = 0x00001000, + RT_SREQ_MASK = 0x0000FFFF, /* Requirements bit mask */ + +}; + + +/* + * enum rt_country_name & enum rt_regulation_2g & enum rt_regulation_5g transfer table + * + * */ +struct _RT_CHANNEL_PLAN_COUNTRY_TRANSFER_TABLE { + /* */ + /* Define countery domain and corresponding */ + /* */ + enum rt_country_name country_enum; + char country_name[3]; + + /* char Domain_Name[12]; */ + enum rt_regulation_2g domain_2g; + + enum rt_regulation_5g domain_5g; + + RT_CHANNEL_DOMAIN rt_ch_domain; + /* u8 Country_Area; */ + +}; + + +#define RT_MAX_CHNL_NUM_2G 13 +#define RT_MAX_CHNL_NUM_5G 44 + +/* Power table sample. */ + +struct _RT_CHNL_PLAN_PWR_LIMIT { + u16 chnl_start; + u16 chnl_end; + u8 db_max; + u16 m_w_max; +}; + + +#define RT_MAX_BAND_NUM 5 + +struct _RT_CHANNEL_PLAN_MAXPWR { + /* STRING_T */ + struct _RT_CHNL_PLAN_PWR_LIMIT chnl[RT_MAX_BAND_NUM]; + u8 band_useful_num; + + +}; + + +/* + * Power By rate Table. + * */ + + + +struct _RT_CHANNEL_PLAN_NEW { + /* */ + /* Define countery domain and corresponding */ + /* */ + /* char country_name[36]; */ + /* u8 country_enum; */ + + /* char Domain_Name[12]; */ + + + struct _RT_CHANNEL_PLAN_COUNTRY_TRANSFER_TABLE *p_ctry_transfer; + + RT_CHANNEL_DOMAIN rt_ch_domain; + + enum rt_regulation_2g domain_2g; + + enum rt_regulation_5g domain_5g; + + enum rt_regulation_cmn regulator; + + enum rt_chnlplan_sreq chnl_sreq; + + /* struct _RT_CHNL_PLAN_LIMIT RtChnl; */ + + u8 chnl_2g[MAX_CHANNEL_NUM]; /* CHNL_RT_2G_WORLD */ + u8 len_2g; + u8 chnl_2g_scan_tp[MAX_CHANNEL_NUM]; /* CHNL_RT_2G_WORLD_SCAN_TYPE */ + /* u8 Freq2G[2]; */ /* FREQ_RT_2G_WORLD */ + + u8 chnl_5g[MAX_CHANNEL_NUM]; + u8 len_5g; + u8 chnl_5g_scan_tp[MAX_CHANNEL_NUM]; + /* u8 Freq2G[2]; */ /* FREQ_RT_2G_WORLD */ + + struct _RT_CHANNEL_PLAN_MAXPWR chnl_max_pwr; + + +}; + + +#endif /* __RT_CHANNELPLAN_H__ */ diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c new file mode 100644 index 000000000000..51863cde7b1c --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c @@ -0,0 +1,790 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#define _RTL8188E_CMD_C_ + +#include +#include +#include "hal_com_h2c.h" + +#define CONFIG_H2C_EF + +#define RTL88E_MAX_H2C_BOX_NUMS 4 +#define RTL88E_MAX_CMD_LEN 7 +#define RTL88E_MESSAGE_BOX_SIZE 4 +#define RTL88E_EX_MESSAGE_BOX_SIZE 4 + +static u8 _is_fw_read_cmd_down(_adapter *padapter, u8 msgbox_num) +{ + u8 read_down = false; + int retry_cnts = 100; + + u8 valid; + + /* RTW_INFO(" _is_fw_read_cmd_down ,reg_1cc(%x),msg_box(%d)...\n",rtw_read8(padapter,REG_HMETFR),msgbox_num); */ + + do { + valid = rtw_read8(padapter, REG_HMETFR) & BIT(msgbox_num); + if (0 == valid) + read_down = true; + else + rtw_msleep_os(1); + } while ((!read_down) && (retry_cnts--)); + + return read_down; + +} + + +/***************************************** +* H2C Msg format : +* 0x1DF - 0x1D0 +*| 31 - 8 | 7-5 4 - 0 | +*| h2c_msg |Class_ID CMD_ID | +* +* Extend 0x1FF - 0x1F0 +*|31 - 0 | +*|ext_msg| +******************************************/ +s32 FillH2CCmd_88E(PADAPTER padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + u8 h2c_box_num; + u32 msgbox_addr; + u32 msgbox_ex_addr = 0; + u8 cmd_idx, ext_cmd_len; + u32 h2c_cmd = 0; + u32 h2c_cmd_ex = 0; + s32 ret = _FAIL; + + + padapter = GET_PRIMARY_ADAPTER(padapter); + pHalData = GET_HAL_DATA(padapter); + + if (padapter->bFWReady == false) { + RTW_INFO("FillH2CCmd_88E(): return H2C cmd because fw is not ready\n"); + return ret; + } + + _enter_critical_mutex(&(dvobj->h2c_fwcmd_mutex), NULL); + + if (!pCmdBuffer) + goto exit; + if (CmdLen > RTL88E_MAX_CMD_LEN) + goto exit; + if (rtw_is_surprise_removed(padapter)) + goto exit; + + /* pay attention to if race condition happened in H2C cmd setting. */ + do { + h2c_box_num = pHalData->LastHMEBoxNum; + + if (!_is_fw_read_cmd_down(padapter, h2c_box_num)) { + RTW_INFO(" fw read cmd failed...\n"); + goto exit; + } + + *(u8 *)(&h2c_cmd) = ElementID; + + if (CmdLen <= 3) + memcpy((u8 *)(&h2c_cmd) + 1, pCmdBuffer, CmdLen); + else { + memcpy((u8 *)(&h2c_cmd) + 1, pCmdBuffer, 3); + ext_cmd_len = CmdLen - 3; + memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer + 3, ext_cmd_len); + + /* Write Ext command */ + msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * RTL88E_EX_MESSAGE_BOX_SIZE); +#ifdef CONFIG_H2C_EF + for (cmd_idx = 0; cmd_idx < ext_cmd_len; cmd_idx++) + rtw_write8(padapter, msgbox_ex_addr + cmd_idx, *((u8 *)(&h2c_cmd_ex) + cmd_idx)); +#else + h2c_cmd_ex = le32_to_cpu(h2c_cmd_ex); + rtw_write32(padapter, msgbox_ex_addr, h2c_cmd_ex); +#endif + } + /* Write command */ + msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * RTL88E_MESSAGE_BOX_SIZE); +#ifdef CONFIG_H2C_EF + for (cmd_idx = 0; cmd_idx < RTL88E_MESSAGE_BOX_SIZE; cmd_idx++) + rtw_write8(padapter, msgbox_addr + cmd_idx, *((u8 *)(&h2c_cmd) + cmd_idx)); +#else + h2c_cmd = le32_to_cpu(h2c_cmd); + rtw_write32(padapter, msgbox_addr, h2c_cmd); +#endif + + + /* RTW_INFO("MSG_BOX:%d,CmdLen(%d), reg:0x%x =>h2c_cmd:0x%x, reg:0x%x =>h2c_cmd_ex:0x%x ..\n" */ + /* ,pHalData->LastHMEBoxNum ,CmdLen,msgbox_addr,h2c_cmd,msgbox_ex_addr,h2c_cmd_ex); */ + + pHalData->LastHMEBoxNum = (h2c_box_num + 1) % RTL88E_MAX_H2C_BOX_NUMS; + + } while (0); + + ret = _SUCCESS; + +exit: + + _exit_critical_mutex(&(dvobj->h2c_fwcmd_mutex), NULL); + + + return ret; +} + +static u8 rtl8192c_h2c_msg_hdl(_adapter *padapter, unsigned char *pbuf) +{ + u8 ElementID, CmdLen; + u8 *pCmdBuffer; + struct cmd_msg_parm *pcmdmsg; + + if (!pbuf) + return H2C_PARAMETERS_ERROR; + + pcmdmsg = (struct cmd_msg_parm *)pbuf; + ElementID = pcmdmsg->eid; + CmdLen = pcmdmsg->sz; + pCmdBuffer = pcmdmsg->buf; + + FillH2CCmd_88E(padapter, ElementID, CmdLen, pCmdBuffer); + + return H2C_SUCCESS; +} + +u8 rtl8188e_set_rssi_cmd(_adapter *padapter, u8 *param) +{ + u8 res = _SUCCESS; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + if (pHalData->fw_ractrl == false) { + RTW_INFO("==>%s fw dont support RA\n", __func__); + return _FAIL; + } + + *((__le32 *) param) = cpu_to_le32(*((u32 *) param)); + FillH2CCmd_88E(padapter, H2C_RSSI_REPORT, 3, param); + + return res; +} + +u8 rtl8188e_set_raid_cmd(_adapter *padapter, u32 bitmap, u8 *arg, u8 bw) +{ + u8 res = _SUCCESS; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct sta_info *psta = NULL; + struct macid_ctl_t *macid_ctl = &padapter->dvobj->macid_ctl; + u8 macid, init_rate, raid, shortGIrate = false; + u8 H2CCommand[7] = {0}; + u8 ignore_bw = false; + + if (pHalData->fw_ractrl == false) { + RTW_INFO("==>%s fw dont support RA\n", __func__); + return _FAIL; + } + + macid = arg[0]; + raid = arg[1]; + shortGIrate = arg[2] & 0x0F; + ignore_bw = arg[2] >> 4; + init_rate = arg[3]; + + if (macid < macid_ctl->num) + psta = macid_ctl->sta[macid]; + if (psta == NULL) { + RTW_PRINT(FUNC_ADPT_FMT" macid:%u, sta is NULL\n" + , FUNC_ADPT_ARG(padapter), macid); + return _FAIL; + } + + H2CCommand[0] = macid; + H2CCommand[1] = raid | (shortGIrate ? 0x80 : 0x00) ; + H2CCommand[2] = bw & 0x03; /* BW; */ + if (ignore_bw) + H2CCommand[2] |= BIT(3); + +#ifdef CONFIG_INTEL_PROXIM + if (padapter->proximity.proxim_on == true) + pHalData->bDisableTXPowerTraining = false; +#endif + + /* DisableTXPowerTraining */ + if (pHalData->bDisableTXPowerTraining) { + H2CCommand[2] |= BIT6; + RTW_INFO("%s,Disable PWT by driver\n", __func__); + } else { + struct PHY_DM_STRUCT *pDM_OutSrc = &pHalData->odmpriv; + + if (pDM_OutSrc->is_disable_power_training) { + H2CCommand[2] |= BIT6; + RTW_INFO("%s,Disable PWT by DM\n", __func__); + } + } + + H2CCommand[3] = (u8)(bitmap & 0x000000ff); + H2CCommand[4] = (u8)((bitmap & 0x0000ff00) >> 8); + H2CCommand[5] = (u8)((bitmap & 0x00ff0000) >> 16); + H2CCommand[6] = (u8)((bitmap & 0xff000000) >> 24); + + FillH2CCmd_88E(padapter, H2C_DM_MACID_CFG, 7, H2CCommand); + + /* The firmware Rate Adaption function is triggered by TBTT INT, so to */ + /* enable the rate adaption, we need to enable the hardware Beacon function Reg 0x550[3] */ + /* SetBcnCtrlReg(padapter, BIT3, 0); */ + rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL) | BIT3); + + return res; + +} + +void rtl8188e_set_FwPwrMode_cmd(PADAPTER padapter, u8 Mode) +{ + SETPWRMODE_PARM H2CSetPwrMode; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); + u8 RLBM = 0; /* 0:Min, 1:Max , 2:User define */ + + RTW_INFO("%s: Mode=%d SmartPS=%d UAPSD=%d\n", __func__, + Mode, pwrpriv->smart_ps, padapter->registrypriv.uapsd_enable); + + H2CSetPwrMode.AwakeInterval = 2; /* DTIM = 1 */ + + switch (Mode) { + case PS_MODE_ACTIVE: + H2CSetPwrMode.Mode = 0; + break; + case PS_MODE_MIN: + H2CSetPwrMode.Mode = 1; + break; + case PS_MODE_MAX: + RLBM = 1; + H2CSetPwrMode.Mode = 1; + break; + case PS_MODE_DTIM: + RLBM = 2; + H2CSetPwrMode.AwakeInterval = 3; /* DTIM = 2 */ + H2CSetPwrMode.Mode = 1; + break; + case PS_MODE_UAPSD_WMM: + H2CSetPwrMode.Mode = 2; + break; + default: + H2CSetPwrMode.Mode = 0; + break; + } + + /* H2CSetPwrMode.Mode = Mode; */ + + H2CSetPwrMode.SmartPS_RLBM = (((pwrpriv->smart_ps << 4) & 0xf0) | (RLBM & 0x0f)); + + H2CSetPwrMode.bAllQueueUAPSD = padapter->registrypriv.uapsd_enable; + + if (Mode > 0) { + H2CSetPwrMode.PwrState = 0x00;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */ +#ifdef CONFIG_EXT_CLK + H2CSetPwrMode.Mode |= BIT(7);/* supporting 26M XTAL CLK_Request feature. */ +#endif /* CONFIG_EXT_CLK */ + } else + H2CSetPwrMode.PwrState = 0x0C;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */ + + FillH2CCmd_88E(padapter, H2C_PS_PWR_MODE, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode); + + +} + +static void ConstructBeacon(_adapter *padapter, u8 *pframe, u32 *pLength) +{ + struct rtw_ieee80211_hdr *pwlanhdr; + __le16 *fctrl; + u32 rate_len, pktlen; + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); + u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + + /* RTW_INFO("%s\n", __func__); */ + + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + fctrl = &(pwlanhdr->frame_ctl); + *(fctrl) = 0; + + memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); + memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); + memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); + + SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); + /* pmlmeext->mgnt_seq++; */ + set_frame_sub_type(pframe, WIFI_BEACON); + + pframe += sizeof(struct rtw_ieee80211_hdr_3addr); + pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + + /* timestamp will be inserted by hardware */ + pframe += 8; + pktlen += 8; + + /* beacon interval: 2 bytes */ + memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); + + pframe += 2; + pktlen += 2; + + /* capability info: 2 bytes */ + memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); + + pframe += 2; + pktlen += 2; + + if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { + /* RTW_INFO("ie len=%d\n", cur_network->IELength); */ + pktlen += cur_network->IELength - sizeof(NDIS_802_11_FIXED_IEs); + memcpy(pframe, cur_network->IEs + sizeof(NDIS_802_11_FIXED_IEs), pktlen); + + goto _ConstructBeacon; + } + + /* below for ad-hoc mode */ + + /* SSID */ + pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen); + + /* supported rates... */ + rate_len = rtw_get_rateset_len(cur_network->SupportedRates); + pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pktlen); + + /* DS parameter set */ + pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen); + + if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) { + u32 ATIMWindow; + /* IBSS Parameter Set... */ + /* ATIMWindow = cur->Configuration.ATIMWindow; */ + ATIMWindow = 0; + pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen); + } + + + /* todo: ERP IE */ + + + /* EXTERNDED SUPPORTED RATE */ + if (rate_len > 8) + pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen); + + + /* todo:HT for adhoc */ + +_ConstructBeacon: + + if ((pktlen + TXDESC_SIZE) > 512) { + RTW_INFO("beacon frame too large\n"); + return; + } + + *pLength = pktlen; + + /* RTW_INFO("%s bcn_sz=%d\n", __func__, pktlen); */ + +} + +static void ConstructPSPoll(_adapter *padapter, u8 *pframe, u32 *pLength) +{ + struct rtw_ieee80211_hdr *pwlanhdr; + __le16 *fctrl; + u32 pktlen; + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + /* RTW_INFO("%s\n", __func__); */ + + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + /* Frame control. */ + fctrl = &(pwlanhdr->frame_ctl); + *(fctrl) = 0; + SetPwrMgt(fctrl); + set_frame_sub_type(pframe, WIFI_PSPOLL); + + /* AID. */ + set_duration(pframe, (pmlmeinfo->aid | 0xc000)); + + /* BSSID. */ + memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + + /* TA. */ + memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); + + *pLength = 16; +} + +static void ConstructNullFunctionData( + PADAPTER padapter, + u8 *pframe, + u32 *pLength, + u8 *StaAddr, + u8 bQoS, + u8 AC, + u8 bEosp, + u8 bForcePowerSave) +{ + struct rtw_ieee80211_hdr *pwlanhdr; + __le16 *fctrl; + u32 pktlen; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct wlan_network *cur_network = &pmlmepriv->cur_network; + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + + /* RTW_INFO("%s:%d\n", __func__, bForcePowerSave); */ + + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + fctrl = &pwlanhdr->frame_ctl; + *(fctrl) = 0; + if (bForcePowerSave) + SetPwrMgt(fctrl); + + switch (cur_network->network.InfrastructureMode) { + case Ndis802_11Infrastructure: + SetToDs(fctrl); + memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); + memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN); + break; + case Ndis802_11APMode: + SetFrDs(fctrl); + memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); + memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN); + break; + case Ndis802_11IBSS: + default: + memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); + memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); + memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + break; + } + + SetSeqNum(pwlanhdr, 0); + + if (bQoS == true) { + struct rtw_ieee80211_hdr_3addr_qos *pwlanqoshdr; + + set_frame_sub_type(pframe, WIFI_QOS_DATA_NULL); + + pwlanqoshdr = (struct rtw_ieee80211_hdr_3addr_qos *)pframe; + SetPriority(&pwlanqoshdr->qc, AC); + SetEOSP(&pwlanqoshdr->qc, bEosp); + + pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos); + } else { + set_frame_sub_type(pframe, WIFI_DATA_NULL); + + pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + } + + *pLength = pktlen; +} + +static void rtl8188e_set_FwRsvdPage_cmd(PADAPTER padapter, PRSVDPAGE_LOC rsvdpageloc) +{ + u8 u1H2CRsvdPageParm[H2C_RSVDPAGE_LOC_LEN] = {0}; + u8 u1H2CAoacRsvdPageParm[H2C_AOAC_RSVDPAGE_LOC_LEN] = {0}; + + /* RTW_INFO("8188RsvdPageLoc: PsPoll=%d Null=%d QoSNull=%d\n", */ + /* rsvdpageloc->LocPsPoll, rsvdpageloc->LocNullData, rsvdpageloc->LocQosNull); */ + + SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1H2CRsvdPageParm, rsvdpageloc->LocPsPoll); + SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocNullData); + SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocQosNull); + + FillH2CCmd_88E(padapter, H2C_COM_RSVD_PAGE, H2C_RSVDPAGE_LOC_LEN, u1H2CRsvdPageParm); + +#ifdef CONFIG_WOWLAN + /* RTW_INFO("8188E_AOACRsvdPageLoc: RWC=%d ArpRsp=%d\n", rsvdpageloc->LocRemoteCtrlInfo, rsvdpageloc->LocArpRsp); */ + SET_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1H2CAoacRsvdPageParm, rsvdpageloc->LocRemoteCtrlInfo); + SET_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1H2CAoacRsvdPageParm, rsvdpageloc->LocArpRsp); + + FillH2CCmd_88E(padapter, H2C_COM_AOAC_RSVD_PAGE, H2C_AOAC_RSVDPAGE_LOC_LEN, u1H2CAoacRsvdPageParm); +#endif +} + +/* To check if reserved page content is destroyed by beacon beacuse beacon is too large. + * 2010.06.23. Added by tynli. */ +void +CheckFwRsvdPageContent( + PADAPTER Adapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u32 MaxBcnPageNum; + + if (pHalData->FwRsvdPageStartOffset != 0) { + /*MaxBcnPageNum = PageNum_128(pMgntInfo->MaxBeaconSize); + RT_ASSERT((MaxBcnPageNum <= pHalData->FwRsvdPageStartOffset), + ("CheckFwRsvdPageContent(): The reserved page content has been"\ + "destroyed by beacon!!! MaxBcnPageNum(%d) FwRsvdPageStartOffset(%d)\n!", + MaxBcnPageNum, pHalData->FwRsvdPageStartOffset));*/ + } +} + +/* + * Description: Get the reserved page number in Tx packet buffer. + * Retrun value: the page number. + * 2012.08.09, by tynli. + * */ +u8 +GetTxBufferRsvdPageNum8188E(_adapter *padapter, bool wowlan) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + u8 RsvdPageNum = 0; + /* default reseved 1 page for the IC type which is undefined. */ + u8 TxPageBndy = LAST_ENTRY_OF_TX_PKT_BUFFER_8188E(padapter); + + rtw_hal_get_def_var(padapter, HAL_DEF_TX_PAGE_BOUNDARY, (u8 *)&TxPageBndy); + + RsvdPageNum = LAST_ENTRY_OF_TX_PKT_BUFFER_8188E(padapter) - TxPageBndy + 1; + + return RsvdPageNum; +} + +void rtl8188e_set_FwJoinBssReport_cmd(PADAPTER padapter, u8 mstatus) +{ + JOINBSSRPT_PARM_88E JoinBssRptParm; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); +#ifdef CONFIG_WOWLAN + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct sta_info *psta = NULL; +#endif + bool bSendBeacon = false; + bool bcn_valid = false; + u8 DLBcnCount = 0; + u32 poll = 0; + + + RTW_INFO("%s mstatus(%x)\n", __func__, mstatus); + + if (mstatus == 1) { + /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */ + /* Suggested by filen. Added by tynli. */ + rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000 | pmlmeinfo->aid)); + /* Do not set TSF again here or vWiFi beacon DMA INT will not work. */ + /* correct_TSF(padapter, pmlmeext); */ + /* Hw sequende enable by dedault. 2010.06.23. by tynli. */ + /* rtw_write16(padapter, REG_NQOS_SEQ, ((pmlmeext->mgnt_seq+100)&0xFFF)); */ + /* rtw_write8(padapter, REG_HWSEQ_CTRL, 0xFF); */ + + /* Set REG_CR bit 8. DMA beacon by SW. */ + pHalData->RegCR_1 |= BIT0; + rtw_write8(padapter, REG_CR + 1, pHalData->RegCR_1); + + /* Disable Hw protection for a time which revserd for Hw sending beacon. */ + /* Fix download reserved page packet fail that access collision with the protection time. */ + /* 2010.05.11. Added by tynli. */ + /* SetBcnCtrlReg(padapter, 0, BIT3); */ + /* SetBcnCtrlReg(padapter, BIT4, 0); */ + rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL) & (~BIT(3))); + rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL) | BIT(4)); + + if (pHalData->RegFwHwTxQCtrl & BIT6) { + RTW_INFO("HalDownloadRSVDPage(): There is an Adapter is sending beacon.\n"); + bSendBeacon = true; + } + + /* Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame. */ + rtw_write8(padapter, REG_FWHW_TXQ_CTRL + 2, (pHalData->RegFwHwTxQCtrl & (~BIT6))); + pHalData->RegFwHwTxQCtrl &= (~BIT6); + + /* Clear beacon valid check bit. */ + rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL); + DLBcnCount = 0; + poll = 0; + do { + /* download rsvd page.*/ + rtw_hal_set_fw_rsvd_page(padapter, false); + DLBcnCount++; + do { + rtw_yield_os(); + /* rtw_mdelay_os(10); */ + /* check rsvd page download OK. */ + rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bcn_valid)); + poll++; + } while (!bcn_valid && (poll % 10) != 0 && !RTW_CANNOT_RUN(padapter)); + + } while (!bcn_valid && DLBcnCount <= 100 && !RTW_CANNOT_RUN(padapter)); + + /* RT_ASSERT(bcn_valid, ("HalDownloadRSVDPage88ES(): 1 Download RSVD page failed!\n")); */ + if (RTW_CANNOT_RUN(padapter)) + ; + else if (!bcn_valid) + RTW_INFO(ADPT_FMT": 1 DL RSVD page failed! DLBcnCount:%u, poll:%u\n", + ADPT_ARG(padapter) , DLBcnCount, poll); + else { + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter); + pwrctl->fw_psmode_iface_id = padapter->iface_id; + RTW_INFO(ADPT_FMT": 1 DL RSVD page success! DLBcnCount:%u, poll:%u\n", + ADPT_ARG(padapter), DLBcnCount, poll); + } + + /* Enable Bcn */ + /* SetBcnCtrlReg(padapter, BIT3, 0); */ + /* SetBcnCtrlReg(padapter, 0, BIT4); */ + rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL) | BIT(3)); + rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL) & (~BIT(4))); + + /* To make sure that if there exists an adapter which would like to send beacon. */ + /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */ + /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */ + /* the beacon cannot be sent by HW. */ + /* 2010.06.23. Added by tynli. */ + if (bSendBeacon) { + rtw_write8(padapter, REG_FWHW_TXQ_CTRL + 2, (pHalData->RegFwHwTxQCtrl | BIT6)); + pHalData->RegFwHwTxQCtrl |= BIT6; + } + + /* */ + /* Update RSVD page location H2C to Fw. */ + /* */ + if (bcn_valid) { + rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL); + RTW_INFO("Set RSVD page location to Fw.\n"); + /* FillH2CCmd88E(Adapter, H2C_88E_RSVDPAGE, H2C_RSVDPAGE_LOC_LENGTH, pMgntInfo->u1RsvdPageLoc); */ + } + + /* Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli. */ + /* if(!padapter->bEnterPnpSleep) */ + { + /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */ + pHalData->RegCR_1 &= (~BIT0); + rtw_write8(padapter, REG_CR + 1, pHalData->RegCR_1); + } + } +} + +#ifdef CONFIG_P2P_PS +void rtl8188e_set_p2p_ps_offload_cmd(_adapter *padapter, u8 p2p_ps_state) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); + struct wifidirect_info *pwdinfo = &(padapter->wdinfo); + struct P2P_PS_Offload_t *p2p_ps_offload = (struct P2P_PS_Offload_t *)(&pHalData->p2p_ps_offload); + u8 i; + + switch (p2p_ps_state) { + case P2P_PS_DISABLE: + RTW_INFO("P2P_PS_DISABLE\n"); + memset(p2p_ps_offload, 0 , 1); + break; + case P2P_PS_ENABLE: + RTW_INFO("P2P_PS_ENABLE\n"); + /* update CTWindow value. */ + if (pwdinfo->ctwindow > 0) { + p2p_ps_offload->CTWindow_En = 1; + rtw_write8(padapter, REG_P2P_CTWIN, pwdinfo->ctwindow); + } + + /* hw only support 2 set of NoA */ + for (i = 0 ; i < pwdinfo->noa_num ; i++) { + /* To control the register setting for which NOA */ + rtw_write8(padapter, REG_NOA_DESC_SEL, (i << 4)); + if (i == 0) + p2p_ps_offload->NoA0_En = 1; + else + p2p_ps_offload->NoA1_En = 1; + + /* config P2P NoA Descriptor Register */ + /* RTW_INFO("%s(): noa_duration = %x\n",__func__,pwdinfo->noa_duration[i]); */ + rtw_write32(padapter, REG_NOA_DESC_DURATION, pwdinfo->noa_duration[i]); + + /* RTW_INFO("%s(): noa_interval = %x\n",__func__,pwdinfo->noa_interval[i]); */ + rtw_write32(padapter, REG_NOA_DESC_INTERVAL, pwdinfo->noa_interval[i]); + + /* RTW_INFO("%s(): start_time = %x\n",__func__,pwdinfo->noa_start_time[i]); */ + rtw_write32(padapter, REG_NOA_DESC_START, pwdinfo->noa_start_time[i]); + + /* RTW_INFO("%s(): noa_count = %x\n",__func__,pwdinfo->noa_count[i]); */ + rtw_write8(padapter, REG_NOA_DESC_COUNT, pwdinfo->noa_count[i]); + } + + if ((pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0)) { + /* rst p2p circuit */ + rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(4)); + + p2p_ps_offload->Offload_En = 1; + + if (pwdinfo->role == P2P_ROLE_GO) { + p2p_ps_offload->role = 1; + p2p_ps_offload->AllStaSleep = 0; + } else + p2p_ps_offload->role = 0; + + p2p_ps_offload->discovery = 0; + } + break; + case P2P_PS_SCAN: + RTW_INFO("P2P_PS_SCAN\n"); + p2p_ps_offload->discovery = 1; + break; + case P2P_PS_SCAN_DONE: + RTW_INFO("P2P_PS_SCAN_DONE\n"); + p2p_ps_offload->discovery = 0; + pwdinfo->p2p_ps_state = P2P_PS_ENABLE; + break; + default: + break; + } + + FillH2CCmd_88E(padapter, H2C_PS_P2P_OFFLOAD, 1, (u8 *)p2p_ps_offload); +} +#endif /* CONFIG_P2P_PS */ + +#ifdef CONFIG_TSF_RESET_OFFLOAD +/* + ask FW to Reset sync register at Beacon early interrupt +*/ +u8 rtl8188e_reset_tsf(_adapter *padapter, u8 reset_port) +{ + u8 buf[2]; + u8 res = _SUCCESS; + + s32 ret; + if (HW_PORT0 == reset_port) { + buf[0] = 0x1; + buf[1] = 0; + } else { + buf[0] = 0x0; + buf[1] = 0x1; + } + + ret = FillH2CCmd_88E(padapter, H2C_RESET_TSF, 2, buf); + + + return res; +} + +int reset_tsf(PADAPTER Adapter, u8 reset_port) +{ + u8 reset_cnt_before = 0, reset_cnt_after = 0, loop_cnt = 0; + u32 reg_reset_tsf_cnt = (HW_PORT0 == reset_port) ? + REG_FW_RESET_TSF_CNT_0 : REG_FW_RESET_TSF_CNT_1; + u32 reg_bcncrtl = (HW_PORT0 == reset_port) ? + REG_BCN_CTRL_1 : REG_BCN_CTRL; + + rtw_mi_buddy_scan_abort(Adapter, false); /* site survey will cause reset_tsf fail */ + reset_cnt_after = reset_cnt_before = rtw_read8(Adapter, reg_reset_tsf_cnt); + rtl8188e_reset_tsf(Adapter, reset_port); + + while ((reset_cnt_after == reset_cnt_before) && (loop_cnt < 10)) { + rtw_msleep_os(100); + loop_cnt++; + reset_cnt_after = rtw_read8(Adapter, reg_reset_tsf_cnt); + } + + return (loop_cnt >= 10) ? _FAIL : true; +} + + +#endif /* CONFIG_TSF_RESET_OFFLOAD */ diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c new file mode 100644 index 000000000000..36a0790908d9 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +/* ************************************************************ + * Description: + * + * This file is for 92CE/92CU dynamic mechanism only + * + * + * ************************************************************ */ +#define _RTL8188E_DM_C_ + +/* ************************************************************ + * include files + * ************************************************************ */ +#include +#include + +/* ************************************************************ + * Global var + * ************************************************************ */ + + +static void +dm_CheckProtection( + PADAPTER Adapter +) +{ +} + +static void +dm_CheckStatistics( + PADAPTER Adapter +) +{ +} + +#ifdef CONFIG_SUPPORT_HW_WPS_PBC +static void dm_CheckPbcGPIO(_adapter *padapter) +{ + u8 tmp1byte; + u8 bPbcPressed = false; + + if (!padapter->registrypriv.hw_wps_pbc) + return; + + tmp1byte = rtw_read8(padapter, GPIO_IO_SEL); + tmp1byte |= (HAL_8188E_HW_GPIO_WPS_BIT); + rtw_write8(padapter, GPIO_IO_SEL, tmp1byte); /* enable GPIO[2] as output mode */ + + tmp1byte &= ~(HAL_8188E_HW_GPIO_WPS_BIT); + rtw_write8(padapter, GPIO_IN, tmp1byte); /* reset the floating voltage level */ + + tmp1byte = rtw_read8(padapter, GPIO_IO_SEL); + tmp1byte &= ~(HAL_8188E_HW_GPIO_WPS_BIT); + rtw_write8(padapter, GPIO_IO_SEL, tmp1byte); /* enable GPIO[2] as input mode */ + + tmp1byte = rtw_read8(padapter, GPIO_IN); + + if (tmp1byte == 0xff) + return ; + + if (tmp1byte & HAL_8188E_HW_GPIO_WPS_BIT) + bPbcPressed = true; + + if (bPbcPressed) { + /* Here we only set bPbcPressed to true */ + /* After trigger PBC, the variable will be set to false */ + RTW_INFO("CheckPbcGPIO - PBC is pressed\n"); + rtw_request_wps_pbc_event(padapter); + } +} +#endif/* #ifdef CONFIG_SUPPORT_HW_WPS_PBC */ + +/* Initialize GPIO setting registers */ +static void +dm_InitGPIOSetting( + PADAPTER Adapter +) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter); + + u8 tmp1byte; + + tmp1byte = rtw_read8(Adapter, REG_GPIO_MUXCFG); + tmp1byte &= (GPIOSEL_GPIO | ~GPIOSEL_ENBT); + + rtw_write8(Adapter, REG_GPIO_MUXCFG, tmp1byte); + +} + +/* ************************************************************ + * functions + * ************************************************************ */ +static void Init_ODM_ComInfo_88E(PADAPTER Adapter) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter); + struct PHY_DM_STRUCT *pDM_Odm = &(pHalData->odmpriv); + u32 SupportAbility = 0; + u8 cut_ver, fab_ver; + + Init_ODM_ComInfo(Adapter); + + fab_ver = ODM_TSMC; + cut_ver = ODM_CUT_A; + + if (IS_VENDOR_8188E_I_CUT_SERIES(Adapter)) + cut_ver = ODM_CUT_I; + + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_FAB_VER, fab_ver); + odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_CUT_VER, cut_ver); + +#ifdef CONFIG_DISABLE_ODM + SupportAbility = 0; +#else + SupportAbility = ODM_RF_CALIBRATION | + ODM_RF_TX_PWR_TRACK + ; +#endif + + odm_cmn_info_update(pDM_Odm, ODM_CMNINFO_ABILITY, SupportAbility); + +} +static void Update_ODM_ComInfo_88E(PADAPTER Adapter) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter); + struct PHY_DM_STRUCT *pDM_Odm = &(pHalData->odmpriv); + u32 SupportAbility = 0; + int i; + + SupportAbility = 0 + | ODM_BB_DIG + | ODM_BB_RA_MASK + | ODM_BB_DYNAMIC_TXPWR + | ODM_BB_FA_CNT + | ODM_BB_RSSI_MONITOR + | ODM_BB_CCK_PD + /* | ODM_BB_PWR_SAVE */ + | ODM_BB_CFO_TRACKING + | ODM_RF_CALIBRATION + | ODM_RF_TX_PWR_TRACK + | ODM_BB_NHM_CNT + | ODM_BB_PRIMARY_CCA + /* | ODM_BB_PWR_TRAIN */ + ; + + if (rtw_odm_adaptivity_needed(Adapter) == true) { + rtw_odm_adaptivity_config_msg(RTW_DBGDUMP, Adapter); + SupportAbility |= ODM_BB_ADAPTIVITY; + } + + if (!Adapter->registrypriv.qos_opt_enable) + SupportAbility |= ODM_MAC_EDCA_TURBO; + +#ifdef CONFIG_ANTENNA_DIVERSITY + if (pHalData->AntDivCfg) + SupportAbility |= ODM_BB_ANT_DIV; +#endif + +#if (MP_DRIVER == 1) + if (Adapter->registrypriv.mp_mode == 1) { + SupportAbility = 0 + | ODM_RF_CALIBRATION + | ODM_RF_TX_PWR_TRACK + ; + } +#endif/* (MP_DRIVER==1) */ + +#ifdef CONFIG_DISABLE_ODM + SupportAbility = 0; +#endif/* CONFIG_DISABLE_ODM */ + + odm_cmn_info_update(pDM_Odm, ODM_CMNINFO_ABILITY, SupportAbility); +} + +void +rtl8188e_InitHalDm( + PADAPTER Adapter +) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter); + struct PHY_DM_STRUCT *pDM_Odm = &(pHalData->odmpriv); + u8 i; + + dm_InitGPIOSetting(Adapter); + + pHalData->DM_Type = dm_type_by_driver; + + Update_ODM_ComInfo_88E(Adapter); + odm_dm_init(pDM_Odm); +} + + +void +rtl8188e_HalDmWatchDog( + PADAPTER Adapter +) +{ + bool bFwCurrentInPSMode = false; + bool bFwPSAwake = true; + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter); + struct PHY_DM_STRUCT *pDM_Odm = &(pHalData->odmpriv); + + + if (!rtw_is_hw_init_completed(Adapter)) + goto skip_dm; + +#ifdef CONFIG_LPS + bFwCurrentInPSMode = adapter_to_pwrctl(Adapter)->bFwCurrentInPSMode; + rtw_hal_get_hwreg(Adapter, HW_VAR_FWLPS_RF_ON, (u8 *)(&bFwPSAwake)); +#endif + +#ifdef CONFIG_P2P_PS + /* Fw is under p2p powersaving mode, driver should stop dynamic mechanism. */ + /* modifed by thomas. 2011.06.11. */ + if (Adapter->wdinfo.p2p_ps_mode) + bFwPSAwake = false; +#endif /* CONFIG_P2P_PS */ + + if ((rtw_is_hw_init_completed(Adapter)) + && ((!bFwCurrentInPSMode) && bFwPSAwake)) { + /* Calculate Tx/Rx statistics. */ + dm_CheckStatistics(Adapter); + + rtw_hal_check_rxfifo_full(Adapter); + } + + /* ODM */ + if (rtw_is_hw_init_completed(Adapter)) { + u8 bLinked = false; + u8 bsta_state = false; +#ifdef CONFIG_DISABLE_ODM + pHalData->odmpriv.support_ability = 0; +#endif + + if (rtw_mi_check_status(Adapter, MI_ASSOC)) { + bLinked = true; + if (rtw_mi_check_status(Adapter, MI_STA_LINKED)) + bsta_state = true; + } + + odm_cmn_info_update(&pHalData->odmpriv , ODM_CMNINFO_LINK, bLinked); + odm_cmn_info_update(&pHalData->odmpriv , ODM_CMNINFO_STATION_STATE, bsta_state); + + + odm_dm_watchdog(&pHalData->odmpriv); + + } + +skip_dm: + +#ifdef CONFIG_SUPPORT_HW_WPS_PBC + /* Check GPIO to determine current Pbc status. */ + dm_CheckPbcGPIO(Adapter); +#endif + return; +} + +void rtl8188e_init_dm_priv(PADAPTER Adapter) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter); + struct PHY_DM_STRUCT *podmpriv = &pHalData->odmpriv; + + /* spin_lock_init(&(pHalData->odm_stainfo_lock)); */ + Init_ODM_ComInfo_88E(Adapter); + odm_init_all_timers(podmpriv); + +} + +void rtl8188e_deinit_dm_priv(PADAPTER Adapter) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter); + struct PHY_DM_STRUCT *podmpriv = &pHalData->odmpriv; + odm_cancel_all_timers(podmpriv); +} diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c new file mode 100644 index 000000000000..f039dd816e08 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -0,0 +1,4629 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#define _HAL_INIT_C_ + +#include +#include +#ifdef CONFIG_SFW_SUPPORTED +#include "hal8188e_s_fw.h" +#endif +#include "hal8188e_t_fw.h" + + +#if defined(CONFIG_IOL) +static void iol_mode_enable(PADAPTER padapter, u8 enable) +{ + u8 reg_0xf0 = 0; + + if (enable) { + /* Enable initial offload */ + reg_0xf0 = rtw_read8(padapter, REG_SYS_CFG); + /* RTW_INFO("%s reg_0xf0:0x%02x, write 0x%02x\n", __func__, reg_0xf0, reg_0xf0|SW_OFFLOAD_EN); */ + rtw_write8(padapter, REG_SYS_CFG, reg_0xf0 | SW_OFFLOAD_EN); + + if (padapter->bFWReady == false) { + RTW_INFO("bFWReady == false call reset 8051...\n"); + _8051Reset88E(padapter); + } + + } else { + /* disable initial offload */ + reg_0xf0 = rtw_read8(padapter, REG_SYS_CFG); + /* RTW_INFO("%s reg_0xf0:0x%02x, write 0x%02x\n", __func__, reg_0xf0, reg_0xf0& ~SW_OFFLOAD_EN); */ + rtw_write8(padapter, REG_SYS_CFG, reg_0xf0 & ~SW_OFFLOAD_EN); + } +} + +static s32 iol_execute(PADAPTER padapter, u8 control) +{ + s32 status = _FAIL; + u8 reg_0x88 = 0, reg_1c7 = 0; + u32 start = 0, passing_time = 0; + + u32 t1, t2; + control = control & 0x0f; + reg_0x88 = rtw_read8(padapter, REG_HMEBOX_E0); + /* RTW_INFO("%s reg_0x88:0x%02x, write 0x%02x\n", __func__, reg_0x88, reg_0x88|control); */ + rtw_write8(padapter, REG_HMEBOX_E0, reg_0x88 | control); + + t1 = start = jiffies; + while ( + /* (reg_1c7 = rtw_read8(padapter, 0x1c7) >1) && */ + (reg_0x88 = rtw_read8(padapter, REG_HMEBOX_E0)) & control + && (passing_time = rtw_get_passing_time_ms(start)) < 1000 + ) { + /* RTW_INFO("%s polling reg_0x88:0x%02x,reg_0x1c7:0x%02x\n", __func__, reg_0x88,rtw_read8(padapter, 0x1c7) ); */ + /* rtw_udelay_os(100); */ + } + + reg_0x88 = rtw_read8(padapter, REG_HMEBOX_E0); + status = (reg_0x88 & control) ? _FAIL : _SUCCESS; + if (reg_0x88 & control << 4) + status = _FAIL; + t2 = jiffies; + + return status; +} + +static s32 iol_InitLLTTable( + PADAPTER padapter, + u8 txpktbuf_bndy +) +{ + s32 rst = _SUCCESS; + iol_mode_enable(padapter, 1); + /* RTW_INFO("%s txpktbuf_bndy:%u\n", __func__, txpktbuf_bndy); */ + rtw_write8(padapter, REG_TDECTRL + 1, txpktbuf_bndy); + rst = iol_execute(padapter, CMD_INIT_LLT); + iol_mode_enable(padapter, 0); + return rst; +} + +static void +efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) +{ + u8 *efuseTbl = NULL; + u8 rtemp8; + u16 eFuse_Addr = 0; + u8 offset, wren; + u16 i, j; + u16 **eFuseWord = NULL; + u16 efuse_utilized = 0; + u8 efuse_usage = 0; + u8 u1temp = 0; + + + efuseTbl = (u8 *)rtw_zmalloc(EFUSE_MAP_LEN_88E); + if (efuseTbl == NULL) { + RTW_INFO("%s: alloc efuseTbl fail!\n", __func__); + goto exit; + } + + eFuseWord = (u16 **)rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, 2); + if (eFuseWord == NULL) { + RTW_INFO("%s: alloc eFuseWord fail!\n", __func__); + goto exit; + } + + /* 0. Refresh efuse init map as all oxFF. */ + for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) + for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) + eFuseWord[i][j] = 0xFFFF; + + /* */ + /* 1. Read the first byte to check if efuse is empty!!! */ + /* */ + /* */ + rtemp8 = *(phymap + eFuse_Addr); + if (rtemp8 != 0xFF) { + efuse_utilized++; + eFuse_Addr++; + } else { + RTW_INFO("EFUSE is empty efuse_Addr-%d efuse_data=%x\n", eFuse_Addr, rtemp8); + goto exit; + } + + + /* */ + /* 2. Read real efuse content. Filter PG header and every section data. */ + /* */ + while ((rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("efuse_Addr-%d efuse_data=%x\n", eFuse_Addr-1, *rtemp8)); */ + + /* Check PG header for section num. */ + if ((rtemp8 & 0x1F) == 0x0F) { /* extended header */ + u1temp = ((rtemp8 & 0xE0) >> 5); + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("extended header u1temp=%x *rtemp&0xE0 0x%x\n", u1temp, *rtemp8 & 0xE0)); */ + + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("extended header u1temp=%x\n", u1temp)); */ + + rtemp8 = *(phymap + eFuse_Addr); + + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("extended header efuse_Addr-%d efuse_data=%x\n", eFuse_Addr, *rtemp8)); */ + + if ((rtemp8 & 0x0F) == 0x0F) { + eFuse_Addr++; + rtemp8 = *(phymap + eFuse_Addr); + + if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) + eFuse_Addr++; + continue; + } else { + offset = ((rtemp8 & 0xF0) >> 1) | u1temp; + wren = (rtemp8 & 0x0F); + eFuse_Addr++; + } + } else { + offset = ((rtemp8 >> 4) & 0x0f); + wren = (rtemp8 & 0x0f); + } + + if (offset < EFUSE_MAX_SECTION_88E) { + /* Get word enable value from PG header */ + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("Offset-%d Worden=%x\n", offset, wren)); */ + + for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { + /* Check word enable condition in the section */ + if (!(wren & 0x01)) { + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("Addr=%d\n", eFuse_Addr)); */ + rtemp8 = *(phymap + eFuse_Addr); + eFuse_Addr++; + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("Data=0x%x\n", *rtemp8)); */ + efuse_utilized++; + eFuseWord[offset][i] = (rtemp8 & 0xff); + + + if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) + break; + + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("Addr=%d", eFuse_Addr)); */ + rtemp8 = *(phymap + eFuse_Addr); + eFuse_Addr++; + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("Data=0x%x\n", *rtemp8)); */ + + efuse_utilized++; + eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00); + + if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) + break; + } + + wren >>= 1; + + } + } + + /* Read next PG header */ + rtemp8 = *(phymap + eFuse_Addr); + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("Addr=%d rtemp 0x%x\n", eFuse_Addr, *rtemp8)); */ + + if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { + efuse_utilized++; + eFuse_Addr++; + } + } + + /* */ + /* 3. Collect 16 sections and 4 word unit into Efuse map. */ + /* */ + for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) { + for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { + efuseTbl[(i * 8) + (j * 2)] = (eFuseWord[i][j] & 0xff); + efuseTbl[(i * 8) + ((j * 2) + 1)] = ((eFuseWord[i][j] >> 8) & 0xff); + } + } + + + /* */ + /* 4. Copy from Efuse map to output pointer memory!!! */ + /* */ + for (i = 0; i < _size_byte; i++) + pbuf[i] = efuseTbl[_offset + i]; + + /* */ + /* 5. Calculate Efuse utilization. */ + /* */ + efuse_usage = (u8)((efuse_utilized * 100) / EFUSE_REAL_CONTENT_LEN_88E); + /* rtw_hal_set_hwreg(Adapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_utilized); */ + +exit: + if (efuseTbl) + rtw_mfree(efuseTbl, EFUSE_MAP_LEN_88E); + + if (eFuseWord) + rtw_mfree2d((void *)eFuseWord, EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16)); +} + +static void efuse_read_phymap_from_txpktbuf( + ADAPTER *adapter, + int bcnhead, /* beacon head, where FW store len(2-byte) and efuse physical map. */ + u8 *content, /* buffer to store efuse physical map */ + u16 *size /* for efuse content: the max byte to read. will update to byte read */ +) +{ + u16 dbg_addr = 0; + u32 start = 0, passing_time = 0; + u8 reg_0x143 = 0; + u8 reg_0x106 = 0; + u32 lo32 = 0, hi32 = 0; + u16 len = 0, count = 0; + int i = 0; + u16 limit = *size; + + u8 *pos = content; + + if (bcnhead < 0) /* if not valid */ + bcnhead = rtw_read8(adapter, REG_TDECTRL + 1); + + RTW_INFO("%s bcnhead:%d\n", __func__, bcnhead); + + /* reg_0x106 = rtw_read8(adapter, REG_PKT_BUFF_ACCESS_CTRL); */ + /* RTW_INFO("%s reg_0x106:0x%02x, write 0x%02x\n", __func__, reg_0x106, 0x69); */ + rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); + /* RTW_INFO("%s reg_0x106:0x%02x\n", __func__, rtw_read8(adapter, 0x106)); */ + + dbg_addr = bcnhead * 128 / 8; /* 8-bytes addressing */ + + while (1) { + /* RTW_INFO("%s dbg_addr:0x%x\n", __func__, dbg_addr+i); */ + rtw_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr + i); + + /* RTW_INFO("%s write reg_0x143:0x00\n", __func__); */ + rtw_write8(adapter, REG_TXPKTBUF_DBG, 0); + start = jiffies; + while (!(reg_0x143 = rtw_read8(adapter, REG_TXPKTBUF_DBG)) /* dbg */ + /* while(rtw_read8(adapter, REG_TXPKTBUF_DBG) & BIT0 */ + && (passing_time = rtw_get_passing_time_ms(start)) < 1000 + ) { + RTW_INFO("%s polling reg_0x143:0x%02x, reg_0x106:0x%02x\n", __func__, reg_0x143, rtw_read8(adapter, 0x106)); + rtw_usleep_os(100); + } + + + lo32 = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_L); + hi32 = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_H); + + if (i == 0) { + u8 lenc[2]; + u16 lenbak, aaabak; + u16 aaa; + lenc[0] = rtw_read8(adapter, REG_PKTBUF_DBG_DATA_L); + lenc[1] = rtw_read8(adapter, REG_PKTBUF_DBG_DATA_L + 1); + + aaabak = le16_to_cpup((__le16 *)lenc); + lenbak = le16_to_cpu(*((__le16 *)lenc)); + aaa = le16_to_cpup((__le16 *)&lo32); + len = le16_to_cpu(*((__le16 *)&lo32)); + + limit = (len - 2 < limit) ? len - 2 : limit; + + RTW_INFO("%s len:%u, lenbak:%u, aaa:%u, aaabak:%u\n", __func__, len, lenbak, aaa, aaabak); + + memcpy(pos, ((u8 *)&lo32) + 2, (limit >= count + 2) ? 2 : limit - count); + count += (limit >= count + 2) ? 2 : limit - count; + pos = content + count; + + } else { + memcpy(pos, ((u8 *)&lo32), (limit >= count + 4) ? 4 : limit - count); + count += (limit >= count + 4) ? 4 : limit - count; + pos = content + count; + + + } + + if (limit > count && len - 2 > count) { + memcpy(pos, (u8 *)&hi32, (limit >= count + 4) ? 4 : limit - count); + count += (limit >= count + 4) ? 4 : limit - count; + pos = content + count; + } + + if (limit <= count || len - 2 <= count) + break; + + i++; + } + + rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, DISABLE_TRXPKT_BUF_ACCESS); + + RTW_INFO("%s read count:%u\n", __func__, count); + *size = count; + +} + + +static s32 iol_read_efuse( + PADAPTER padapter, + u8 txpktbuf_bndy, + u16 offset, + u16 size_byte, + u8 *logical_map +) +{ + s32 status = _FAIL; + u8 reg_0x106 = 0; + u8 physical_map[512]; + u16 size = 512; + int i; + + + rtw_write8(padapter, REG_TDECTRL + 1, txpktbuf_bndy); + memset(physical_map, 0xFF, 512); + + rtw_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); + + status = iol_execute(padapter, CMD_READ_EFUSE_MAP); + + if (status == _SUCCESS) + efuse_read_phymap_from_txpktbuf(padapter, txpktbuf_bndy, physical_map, &size); + + efuse_phymap_to_logical(physical_map, offset, size_byte, logical_map); + + return status; +} + +s32 rtl8188e_iol_efuse_patch(PADAPTER padapter) +{ + s32 result = _SUCCESS; + + if (rtw_IOL_applied(padapter)) { + iol_mode_enable(padapter, 1); + result = iol_execute(padapter, CMD_READ_EFUSE_MAP); + if (result == _SUCCESS) + result = iol_execute(padapter, CMD_EFUSE_PATCH); + + iol_mode_enable(padapter, 0); + } + return result; +} + +static s32 iol_ioconfig( + PADAPTER padapter, + u8 iocfg_bndy +) +{ + s32 rst = _SUCCESS; + + /* RTW_INFO("%s iocfg_bndy:%u\n", __func__, iocfg_bndy); */ + rtw_write8(padapter, REG_TDECTRL + 1, iocfg_bndy); + rst = iol_execute(padapter, CMD_IOCONFIG); + + return rst; +} + +static int rtl8188e_IOL_exec_cmds_sync(ADAPTER *adapter, struct xmit_frame *xmit_frame, u32 max_wating_ms, u32 bndy_cnt) +{ + + u32 start_time = jiffies; + u32 passing_time_ms; + u8 polling_ret, i; + int ret = _FAIL; + u32 t1, t2; + + if (rtw_IOL_append_END_cmd(xmit_frame) != _SUCCESS) + goto exit; + { + struct pkt_attrib *pattrib = &xmit_frame->attrib; + if (rtw_usb_bulk_size_boundary(adapter, TXDESC_SIZE + pattrib->last_txcmdsz)) { + if (rtw_IOL_append_END_cmd(xmit_frame) != _SUCCESS) + goto exit; + } + } + + /* rtw_IOL_cmd_buf_dump(adapter,xmit_frame->attrib.pktlen+TXDESC_OFFSET,xmit_frame->buf_addr); */ + /* rtw_hal_mgnt_xmit(adapter, xmit_frame); */ + /* rtw_dump_xframe_sync(adapter, xmit_frame); */ + + dump_mgntframe_and_wait(adapter, xmit_frame, max_wating_ms); + + t1 = jiffies; + iol_mode_enable(adapter, 1); + for (i = 0; i < bndy_cnt; i++) { + u8 page_no = 0; + page_no = i * 2 ; + ret = iol_ioconfig(adapter, page_no); + if (ret != _SUCCESS) + break; + } + iol_mode_enable(adapter, 0); + t2 = jiffies; +exit: + /* restore BCN_HEAD */ + rtw_write8(adapter, REG_TDECTRL + 1, 0); + return ret; +} + +void rtw_IOL_cmd_tx_pkt_buf_dump(ADAPTER *Adapter, int data_len) +{ + u32 fifo_data, reg_140; + u32 addr, rstatus, loop = 0; + + u16 data_cnts = (data_len / 8) + 1; + u8 *pbuf = rtw_zvmalloc(data_len + 10); + RTW_INFO("###### %s ######\n", __func__); + + rtw_write8(Adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); + if (pbuf) { + for (addr = 0; addr < data_cnts; addr++) { + rtw_write32(Adapter, 0x140, addr); + rtw_usleep_os(2); + loop = 0; + do { + rstatus = (reg_140 = rtw_read32(Adapter, REG_PKTBUF_DBG_CTRL) & BIT24); + if (rstatus) { + fifo_data = rtw_read32(Adapter, REG_PKTBUF_DBG_DATA_L); + memcpy(pbuf + (addr * 8), &fifo_data , 4); + + fifo_data = rtw_read32(Adapter, REG_PKTBUF_DBG_DATA_H); + memcpy(pbuf + (addr * 8 + 4), &fifo_data, 4); + + } + rtw_usleep_os(2); + } while (!rstatus && (loop++ < 10)); + } + rtw_IOL_cmd_buf_dump(Adapter, data_len, pbuf); + rtw_vmfree(pbuf, data_len + 10); + + } + RTW_INFO("###### %s ######\n", __func__); +} + +#endif /* defined(CONFIG_IOL) */ + + +static void +_FWDownloadEnable_8188E( + PADAPTER padapter, + bool enable +) +{ + u8 tmp; + + if (enable) { + /* MCU firmware download enable. */ + tmp = rtw_read8(padapter, REG_MCUFWDL); + rtw_write8(padapter, REG_MCUFWDL, tmp | 0x01); + + /* 8051 reset */ + tmp = rtw_read8(padapter, REG_MCUFWDL + 2); + rtw_write8(padapter, REG_MCUFWDL + 2, tmp & 0xf7); + } else { + + /* MCU firmware download disable. */ + tmp = rtw_read8(padapter, REG_MCUFWDL); + rtw_write8(padapter, REG_MCUFWDL, tmp & 0xfe); + + /* Reserved for fw extension. */ + rtw_write8(padapter, REG_MCUFWDL + 1, 0x00); + } +} +#define MAX_REG_BOLCK_SIZE 196 +static int +_BlockWrite( + PADAPTER padapter, + void * buffer, + u32 buffSize +) +{ + int ret = _SUCCESS; + + u32 blockSize_p1 = 4; /* (Default) Phase #1 : PCI muse use 4-byte write to download FW */ + u32 blockSize_p2 = 8; /* Phase #2 : Use 8-byte, if Phase#1 use big size to write FW. */ + u32 blockSize_p3 = 1; /* Phase #3 : Use 1-byte, the remnant of FW image. */ + u32 blockCount_p1 = 0, blockCount_p2 = 0, blockCount_p3 = 0; + u32 remainSize_p1 = 0, remainSize_p2 = 0; + u8 *bufferPtr = (u8 *)buffer; + u32 i = 0, offset = 0; + + blockSize_p1 = MAX_REG_BOLCK_SIZE; + + /* 3 Phase #1 */ + blockCount_p1 = buffSize / blockSize_p1; + remainSize_p1 = buffSize % blockSize_p1; + + + + for (i = 0; i < blockCount_p1; i++) { + ret = rtw_writeN(padapter, (FW_8188E_START_ADDRESS + i * blockSize_p1), blockSize_p1, (bufferPtr + i * blockSize_p1)); + + if (ret == _FAIL) + goto exit; + } + + /* 3 Phase #2 */ + if (remainSize_p1) { + offset = blockCount_p1 * blockSize_p1; + + blockCount_p2 = remainSize_p1 / blockSize_p2; + remainSize_p2 = remainSize_p1 % blockSize_p2; + + + + for (i = 0; i < blockCount_p2; i++) { + ret = rtw_writeN(padapter, (FW_8188E_START_ADDRESS + offset + i * blockSize_p2), blockSize_p2, (bufferPtr + offset + i * blockSize_p2)); + + if (ret == _FAIL) + goto exit; + } + } + + /* 3 Phase #3 */ + if (remainSize_p2) { + offset = (blockCount_p1 * blockSize_p1) + (blockCount_p2 * blockSize_p2); + + blockCount_p3 = remainSize_p2 / blockSize_p3; + + + for (i = 0 ; i < blockCount_p3 ; i++) { + ret = rtw_write8(padapter, (FW_8188E_START_ADDRESS + offset + i), *(bufferPtr + offset + i)); + + if (ret == _FAIL) + goto exit; + } + } + +exit: + return ret; +} + +static int +_PageWrite( + PADAPTER padapter, + u32 page, + void * buffer, + u32 size +) +{ + u8 value8; + u8 u8Page = (u8)(page & 0x07) ; + + value8 = (rtw_read8(padapter, REG_MCUFWDL + 2) & 0xF8) | u8Page ; + rtw_write8(padapter, REG_MCUFWDL + 2, value8); + + return _BlockWrite(padapter, buffer, size); +} + +static void +_FillDummy( + u8 *pFwBuf, + u32 *pFwLen +) +{ + u32 FwLen = *pFwLen; + u8 remain = (u8)(FwLen % 4); + remain = (remain == 0) ? 0 : (4 - remain); + + while (remain > 0) { + pFwBuf[FwLen] = 0; + FwLen++; + remain--; + } + + *pFwLen = FwLen; +} + +static int +_WriteFW( + PADAPTER padapter, + void * buffer, + u32 size +) +{ + /* Since we need dynamic decide method of dwonload fw, so we call this function to get chip version. */ + int ret = _SUCCESS; + u32 pageNums, remainSize ; + u32 page, offset; + u8 *bufferPtr = (u8 *)buffer; + + pageNums = size / MAX_DLFW_PAGE_SIZE ; + /* RT_ASSERT((pageNums <= 4), ("Page numbers should not greater then 4\n")); */ + remainSize = size % MAX_DLFW_PAGE_SIZE; + + for (page = 0; page < pageNums; page++) { + offset = page * MAX_DLFW_PAGE_SIZE; + ret = _PageWrite(padapter, page, bufferPtr + offset, MAX_DLFW_PAGE_SIZE); + + if (ret == _FAIL) + goto exit; + } + if (remainSize) { + offset = pageNums * MAX_DLFW_PAGE_SIZE; + page = pageNums; + ret = _PageWrite(padapter, page, bufferPtr + offset, remainSize); + + if (ret == _FAIL) + goto exit; + + } + +exit: + return ret; +} + +static void _MCUIO_Reset88E(PADAPTER padapter, u8 bReset) +{ + u8 u1bTmp; + + if (bReset == true) { + u1bTmp = rtw_read8(padapter, REG_RSV_CTRL); + rtw_write8(padapter, REG_RSV_CTRL, (u1bTmp & (~BIT1))); + /* Reset MCU IO Wrapper- sugggest by SD1-Gimmy */ + u1bTmp = rtw_read8(padapter, REG_RSV_CTRL + 1); + rtw_write8(padapter, REG_RSV_CTRL + 1, (u1bTmp & (~BIT3))); + } else { + u1bTmp = rtw_read8(padapter, REG_RSV_CTRL); + rtw_write8(padapter, REG_RSV_CTRL, (u1bTmp & (~BIT1))); + /* Enable MCU IO Wrapper */ + u1bTmp = rtw_read8(padapter, REG_RSV_CTRL + 1); + rtw_write8(padapter, REG_RSV_CTRL + 1, u1bTmp | BIT3); + } + +} + +void _8051Reset88E(PADAPTER padapter) +{ + u8 u1bTmp; + + _MCUIO_Reset88E(padapter, true); + u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN + 1); + rtw_write8(padapter, REG_SYS_FUNC_EN + 1, u1bTmp & (~BIT2)); + _MCUIO_Reset88E(padapter, false); + rtw_write8(padapter, REG_SYS_FUNC_EN + 1, u1bTmp | (BIT2)); + + RTW_INFO("=====> _8051Reset88E(): 8051 reset success .\n"); +} + +static s32 polling_fwdl_chksum(_adapter *adapter, u32 min_cnt, u32 timeout_ms) +{ + s32 ret = _FAIL; + u32 value32; + u32 start = jiffies; + u32 cnt = 0; + + /* polling CheckSum report */ + do { + cnt++; + value32 = rtw_read32(adapter, REG_MCUFWDL); + if (value32 & FWDL_ChkSum_rpt || RTW_CANNOT_IO(adapter)) + break; + rtw_yield_os(); + } while (rtw_get_passing_time_ms(start) < timeout_ms || cnt < min_cnt); + + if (!(value32 & FWDL_ChkSum_rpt)) + goto exit; + + if (rtw_fwdl_test_trigger_chksum_fail()) + goto exit; + + ret = _SUCCESS; + +exit: + RTW_INFO("%s: Checksum report %s! (%u, %dms), REG_MCUFWDL:0x%08x\n", __func__ + , (ret == _SUCCESS) ? "OK" : "Fail", cnt, rtw_get_passing_time_ms(start), value32); + + return ret; +} + +static s32 _FWFreeToGo(_adapter *adapter, u32 min_cnt, u32 timeout_ms) +{ + s32 ret = _FAIL; + u32 value32; + u32 start = jiffies; + u32 cnt = 0; + + value32 = rtw_read32(adapter, REG_MCUFWDL); + value32 |= MCUFWDL_RDY; + value32 &= ~WINTINI_RDY; + rtw_write32(adapter, REG_MCUFWDL, value32); + + _8051Reset88E(adapter); + + /* polling for FW ready */ + do { + cnt++; + value32 = rtw_read32(adapter, REG_MCUFWDL); + if (value32 & WINTINI_RDY || RTW_CANNOT_IO(adapter)) + break; + rtw_yield_os(); + } while (rtw_get_passing_time_ms(start) < timeout_ms || cnt < min_cnt); + + if (!(value32 & WINTINI_RDY)) + goto exit; + + if (rtw_fwdl_test_trigger_wintint_rdy_fail()) + goto exit; + + ret = _SUCCESS; + +exit: + RTW_INFO("%s: Polling FW ready %s! (%u, %dms), REG_MCUFWDL:0x%08x\n", __func__ + , (ret == _SUCCESS) ? "OK" : "Fail", cnt, rtw_get_passing_time_ms(start), value32); + return ret; +} + +#define IS_FW_81xxC(padapter) (((GET_HAL_DATA(padapter))->FirmwareSignature & 0xFFF0) == 0x88C0) + + +#ifdef CONFIG_FILE_FWIMG + extern char *rtw_fw_file_path; + extern char *rtw_fw_wow_file_path; + u8 FwBuffer8188E[FW_8188E_SIZE]; +#endif /* CONFIG_FILE_FWIMG */ + +/* + * Description: + * Download 8192C firmware code. + * + * */ +s32 rtl8188e_FirmwareDownload(PADAPTER padapter, bool bUsedWoWLANFw) +{ + s32 rtStatus = _SUCCESS; + u8 write_fw = 0; + u32 fwdl_start_time; + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + + PRT_FIRMWARE_8188E pFirmware = NULL; + PRT_8188E_FIRMWARE_HDR pFwHdr = NULL; + + u8 *pFirmwareBuf; + u32 FirmwareLen, tmp_fw_len = 0; +#ifdef CONFIG_FILE_FWIMG + u8 *fwfilepath; +#endif /* CONFIG_FILE_FWIMG */ + +#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); +#endif + + pFirmware = (PRT_FIRMWARE_8188E)rtw_zmalloc(sizeof(RT_FIRMWARE_8188E)); + if (!pFirmware) { + rtStatus = _FAIL; + goto exit; + } + + + +#ifdef CONFIG_FILE_FWIMG +#ifdef CONFIG_WOWLAN + if (bUsedWoWLANFw) + fwfilepath = rtw_fw_wow_file_path; + else +#endif /* CONFIG_WOWLAN */ + { + fwfilepath = rtw_fw_file_path; + } +#endif /* CONFIG_FILE_FWIMG */ + +#ifdef CONFIG_FILE_FWIMG + if (rtw_is_file_readable(fwfilepath) == true) { + RTW_INFO("%s accquire FW from file:%s\n", __func__, fwfilepath); + pFirmware->eFWSource = FW_SOURCE_IMG_FILE; + } else +#endif /* CONFIG_FILE_FWIMG */ + { + pFirmware->eFWSource = FW_SOURCE_HEADER_FILE; + } + + switch (pFirmware->eFWSource) { + case FW_SOURCE_IMG_FILE: +#ifdef CONFIG_FILE_FWIMG + rtStatus = rtw_retrieve_from_file(fwfilepath, FwBuffer8188E, FW_8188E_SIZE); + pFirmware->ulFwLength = rtStatus >= 0 ? rtStatus : 0; + pFirmware->szFwBuffer = FwBuffer8188E; +#endif /* CONFIG_FILE_FWIMG */ + break; + case FW_SOURCE_HEADER_FILE: + if (bUsedWoWLANFw) { +#ifdef CONFIG_WOWLAN + if (pwrpriv->wowlan_mode) { + #ifdef CONFIG_SFW_SUPPORTED + if (IS_VENDOR_8188E_I_CUT_SERIES(padapter)) { + pFirmware->szFwBuffer = array_mp_8188e_s_fw_wowlan; + pFirmware->ulFwLength = array_length_mp_8188e_s_fw_wowlan; + } else + #endif + { + pFirmware->szFwBuffer = array_mp_8188e_t_fw_wowlan; + pFirmware->ulFwLength = array_length_mp_8188e_t_fw_wowlan; + } + RTW_INFO("%s fw:%s, size: %d\n", __func__, + "WoWLAN", pFirmware->ulFwLength); + } +#endif /*CONFIG_WOWLAN*/ + +#ifdef CONFIG_AP_WOWLAN + if (pwrpriv->wowlan_ap_mode) { + pFirmware->szFwBuffer = array_mp_8188e_t_fw_ap; + pFirmware->ulFwLength = array_length_mp_8188e_t_fw_ap; + + RTW_INFO("%s fw: %s, size: %d\n", __func__, + "AP_WoWLAN", pFirmware->ulFwLength); + } +#endif /*CONFIG_AP_WOWLAN*/ + } else { +#ifdef CONFIG_SFW_SUPPORTED + if (IS_VENDOR_8188E_I_CUT_SERIES(padapter)) { + pFirmware->szFwBuffer = array_mp_8188e_s_fw_nic; + pFirmware->ulFwLength = array_length_mp_8188e_s_fw_nic; + } else +#endif + { + pFirmware->szFwBuffer = array_mp_8188e_t_fw_nic; + pFirmware->ulFwLength = array_length_mp_8188e_t_fw_nic; + } + RTW_INFO("%s fw:%s, size: %d\n", __func__, "NIC", pFirmware->ulFwLength); + } + break; + } + + tmp_fw_len = IS_VENDOR_8188E_I_CUT_SERIES(padapter) ? FW_8188E_SIZE_2 : FW_8188E_SIZE; + + if ((pFirmware->ulFwLength - 32) > tmp_fw_len) { + rtStatus = _FAIL; + RTW_ERR("Firmware size:%u exceed %u\n", pFirmware->ulFwLength, tmp_fw_len); + goto exit; + } + + pFirmwareBuf = pFirmware->szFwBuffer; + FirmwareLen = pFirmware->ulFwLength; + + /* To Check Fw header. Added by tynli. 2009.12.04. */ + pFwHdr = (PRT_8188E_FIRMWARE_HDR)pFirmwareBuf; + + pHalData->firmware_version = le16_to_cpu(pFwHdr->Version); + pHalData->firmware_sub_version = pFwHdr->Subversion; + pHalData->FirmwareSignature = le16_to_cpu(pFwHdr->Signature); + + RTW_INFO("%s: fw_ver=%x fw_subver=%04x sig=0x%x, Month=%02x, Date=%02x, Hour=%02x, Minute=%02x\n", + __func__, pHalData->firmware_version, + pHalData->firmware_sub_version, pHalData->FirmwareSignature, + pFwHdr->Month, pFwHdr->Date, pFwHdr->Hour, pFwHdr->Minute); + + if (IS_FW_HEADER_EXIST_88E(pFwHdr)) { + /* Shift 32 bytes for FW header */ + pFirmwareBuf = pFirmwareBuf + 32; + FirmwareLen = FirmwareLen - 32; + } + + /* Suggested by Filen. If 8051 is running in RAM code, driver should inform Fw to reset by itself, */ + /* or it will cause download Fw fail. 2010.02.01. by tynli. */ + if (rtw_read8(padapter, REG_MCUFWDL) & RAM_DL_SEL) { /* 8051 RAM code */ + rtw_write8(padapter, REG_MCUFWDL, 0x00); + _8051Reset88E(padapter); + } + + _FWDownloadEnable_8188E(padapter, true); + fwdl_start_time = jiffies; + while (!RTW_CANNOT_IO(padapter) + && (write_fw++ < 3 || rtw_get_passing_time_ms(fwdl_start_time) < 500)) { + /* reset FWDL chksum */ + rtw_write8(padapter, REG_MCUFWDL, rtw_read8(padapter, REG_MCUFWDL) | FWDL_ChkSum_rpt); + + rtStatus = _WriteFW(padapter, pFirmwareBuf, FirmwareLen); + if (rtStatus != _SUCCESS) + continue; + + rtStatus = polling_fwdl_chksum(padapter, 5, 50); + if (rtStatus == _SUCCESS) + break; + } + _FWDownloadEnable_8188E(padapter, false); + if (_SUCCESS != rtStatus) + goto fwdl_stat; + + rtStatus = _FWFreeToGo(padapter, 10, 200); + if (_SUCCESS != rtStatus) + goto fwdl_stat; + +fwdl_stat: + RTW_INFO("FWDL %s. write_fw:%u, %dms\n" + , (rtStatus == _SUCCESS) ? "success" : "fail" + , write_fw + , rtw_get_passing_time_ms(fwdl_start_time) + ); + +exit: + if (pFirmware) + rtw_mfree((u8 *)pFirmware, sizeof(RT_FIRMWARE_8188E)); + + rtl8188e_InitializeFirmwareVars(padapter); + + return rtStatus; +} + +void rtl8188e_InitializeFirmwareVars(PADAPTER padapter) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); + + /* Init Fw LPS related. */ + pwrpriv->bFwCurrentInPSMode = false; + + /* Init H2C cmd. */ + rtw_write8(padapter, REG_HMETFR, 0x0f); + + /* Init H2C counter. by tynli. 2009.12.09. */ + pHalData->LastHMEBoxNum = 0; +} + +/* *********************************************************** + * Efuse related code + * *********************************************************** */ +enum { + VOLTAGE_V25 = 0x03, + LDOE25_SHIFT = 28 , +}; + +static bool +hal_EfusePgPacketWrite2ByteHeader( + PADAPTER pAdapter, + u8 efuseType, + u16 *pAddr, + PPGPKT_STRUCT pTargetPkt, + bool bPseudoTest); +static bool +hal_EfusePgPacketWrite1ByteHeader( + PADAPTER pAdapter, + u8 efuseType, + u16 *pAddr, + PPGPKT_STRUCT pTargetPkt, + bool bPseudoTest); +static bool +hal_EfusePgPacketWriteData( + PADAPTER pAdapter, + u8 efuseType, + u16 *pAddr, + PPGPKT_STRUCT pTargetPkt, + bool bPseudoTest); + +static void +hal_EfusePowerSwitch_RTL8188E( + PADAPTER pAdapter, + u8 bWrite, + u8 PwrState) +{ + u8 tempval; + u16 tmpV16; + + if (PwrState == true) { + rtw_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON); + /* Reset: 0x0000h[28], default valid */ + tmpV16 = rtw_read16(pAdapter, REG_SYS_FUNC_EN); + if (!(tmpV16 & FEN_ELDR)) { + tmpV16 |= FEN_ELDR ; + rtw_write16(pAdapter, REG_SYS_FUNC_EN, tmpV16); + } + + /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */ + tmpV16 = rtw_read16(pAdapter, REG_SYS_CLKR); + if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) { + tmpV16 |= (LOADER_CLK_EN | ANA8M) ; + rtw_write16(pAdapter, REG_SYS_CLKR, tmpV16); + } + + if (bWrite == true) { + /* Enable LDO 2.5V before read/write action */ + tempval = rtw_read8(pAdapter, EFUSE_TEST + 3); + if (IS_VENDOR_8188E_I_CUT_SERIES(pAdapter)) { + tempval &= 0x87; + tempval |= 0x38; /* 0x34[30:27] = 0b'0111, Use LDO 2.25V, Suggested by SD1 Pisa */ + } else { + tempval &= 0x0F; + tempval |= (VOLTAGE_V25 << 4); + } + rtw_write8(pAdapter, EFUSE_TEST + 3, (tempval | 0x80)); + } + } else { + rtw_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF); + + if (bWrite == true) { + /* Disable LDO 2.5V after read/write action */ + tempval = rtw_read8(pAdapter, EFUSE_TEST + 3); + rtw_write8(pAdapter, EFUSE_TEST + 3, (tempval & 0x7F)); + } + } +} + +static void +rtl8188e_EfusePowerSwitch( + PADAPTER pAdapter, + u8 bWrite, + u8 PwrState) +{ + hal_EfusePowerSwitch_RTL8188E(pAdapter, bWrite, PwrState); +} + + + +static bool efuse_read_phymap( + PADAPTER Adapter, + u8 *pbuf, /* buffer to store efuse physical map */ + u16 *size /* the max byte to read. will update to byte read */ +) +{ + u8 *pos = pbuf; + u16 limit = *size; + u16 addr = 0; + bool reach_end = false; + + /* */ + /* Refresh efuse init map as all 0xFF. */ + /* */ + memset(pbuf, 0xFF, limit); + + + /* */ + /* Read physical efuse content. */ + /* */ + while (addr < limit) { + ReadEFuseByte(Adapter, addr, pos, false); + if (*pos != 0xFF) { + pos++; + addr++; + } else { + reach_end = true; + break; + } + } + + *size = addr; + + return reach_end; + +} + +static void +Hal_EfuseReadEFuse88E( + PADAPTER Adapter, + u16 _offset, + u16 _size_byte, + u8 *pbuf, + bool bPseudoTest +) +{ + /* u8 efuseTbl[EFUSE_MAP_LEN_88E]; */ + u8 *efuseTbl = NULL; + u8 rtemp8[1]; + u16 eFuse_Addr = 0; + u8 offset, wren; + u16 i, j; + /* u16 eFuseWord[EFUSE_MAX_SECTION_88E][EFUSE_MAX_WORD_UNIT]; */ + u16 **eFuseWord = NULL; + u16 efuse_utilized = 0; + u8 efuse_usage = 0; + u8 u1temp = 0; + + /* */ + /* Do NOT excess total size of EFuse table. Added by Roger, 2008.11.10. */ + /* */ + if ((_offset + _size_byte) > EFUSE_MAP_LEN_88E) { + /* total E-Fuse table is 512bytes */ + RTW_INFO("Hal_EfuseReadEFuse88E(): Invalid offset(%#x) with read bytes(%#x)!!\n", _offset, _size_byte); + goto exit; + } + + efuseTbl = (u8 *)rtw_zmalloc(EFUSE_MAP_LEN_88E); + if (efuseTbl == NULL) { + RTW_INFO("%s: alloc efuseTbl fail!\n", __func__); + goto exit; + } + + eFuseWord = (u16 **)rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, 2); + if (eFuseWord == NULL) { + RTW_INFO("%s: alloc eFuseWord fail!\n", __func__); + goto exit; + } + + /* 0. Refresh efuse init map as all oxFF. */ + for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) + for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) + eFuseWord[i][j] = 0xFFFF; + + /* */ + /* 1. Read the first byte to check if efuse is empty!!! */ + /* */ + /* */ + ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest); + if (*rtemp8 != 0xFF) { + efuse_utilized++; + /* RTW_INFO("efuse_Addr-%d efuse_data=%x\n", eFuse_Addr, *rtemp8); */ + eFuse_Addr++; + } else { + RTW_INFO("EFUSE is empty efuse_Addr-%d efuse_data=%x\n", eFuse_Addr, *rtemp8); + goto exit; + } + + + /* */ + /* 2. Read real efuse content. Filter PG header and every section data. */ + /* */ + while ((*rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("efuse_Addr-%d efuse_data=%x\n", eFuse_Addr-1, *rtemp8)); */ + + /* Check PG header for section num. */ + if ((*rtemp8 & 0x1F) == 0x0F) { /* extended header */ + u1temp = ((*rtemp8 & 0xE0) >> 5); + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("extended header u1temp=%x *rtemp&0xE0 0x%x\n", u1temp, *rtemp8 & 0xE0)); */ + + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("extended header u1temp=%x\n", u1temp)); */ + + ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest); + + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("extended header efuse_Addr-%d efuse_data=%x\n", eFuse_Addr, *rtemp8)); */ + + if ((*rtemp8 & 0x0F) == 0x0F) { + eFuse_Addr++; + ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest); + + if (*rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) + eFuse_Addr++; + continue; + } else { + offset = ((*rtemp8 & 0xF0) >> 1) | u1temp; + wren = (*rtemp8 & 0x0F); + eFuse_Addr++; + } + } else { + offset = ((*rtemp8 >> 4) & 0x0f); + wren = (*rtemp8 & 0x0f); + } + + if (offset < EFUSE_MAX_SECTION_88E) { + /* Get word enable value from PG header */ + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("Offset-%d Worden=%x\n", offset, wren)); */ + + for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { + /* Check word enable condition in the section */ + if (!(wren & 0x01)) { + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("Addr=%d\n", eFuse_Addr)); */ + ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest); + eFuse_Addr++; + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("Data=0x%x\n", *rtemp8)); */ + efuse_utilized++; + eFuseWord[offset][i] = (*rtemp8 & 0xff); + + + if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) + break; + + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("Addr=%d", eFuse_Addr)); */ + ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest); + eFuse_Addr++; + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("Data=0x%x\n", *rtemp8)); */ + + efuse_utilized++; + eFuseWord[offset][i] |= (((u16)*rtemp8 << 8) & 0xff00); + + if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) + break; + } + + wren >>= 1; + + } + } else { /* deal with error offset,skip error data */ + RTW_PRINT("invalid offset:0x%02x\n", offset); + for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { + /* Check word enable condition in the section */ + if (!(wren & 0x01)) { + eFuse_Addr++; + efuse_utilized++; + if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) + break; + eFuse_Addr++; + efuse_utilized++; + if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) + break; + } + } + } + /* Read next PG header */ + ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest); + /* RTPRINT(FEEPROM, EFUSE_READ_ALL, ("Addr=%d rtemp 0x%x\n", eFuse_Addr, *rtemp8)); */ + + if (*rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { + efuse_utilized++; + eFuse_Addr++; + } + } + + /* */ + /* 3. Collect 16 sections and 4 word unit into Efuse map. */ + /* */ + for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) { + for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { + efuseTbl[(i * 8) + (j * 2)] = (eFuseWord[i][j] & 0xff); + efuseTbl[(i * 8) + ((j * 2) + 1)] = ((eFuseWord[i][j] >> 8) & 0xff); + } + } + + + /* */ + /* 4. Copy from Efuse map to output pointer memory!!! */ + /* */ + for (i = 0; i < _size_byte; i++) + pbuf[i] = efuseTbl[_offset + i]; + + /* */ + /* 5. Calculate Efuse utilization. */ + /* */ + efuse_usage = (u8)((eFuse_Addr * 100) / EFUSE_REAL_CONTENT_LEN_88E); + rtw_hal_set_hwreg(Adapter, HW_VAR_EFUSE_BYTES, (u8 *)&eFuse_Addr); + +exit: + if (efuseTbl) + rtw_mfree(efuseTbl, EFUSE_MAP_LEN_88E); + + if (eFuseWord) + rtw_mfree2d((void *)eFuseWord, EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16)); +} + + +static bool +Hal_EfuseSwitchToBank( + PADAPTER pAdapter, + u8 bank, + bool bPseudoTest +) +{ + bool bRet = false; + u32 value32 = 0; + + /* RTPRINT(FEEPROM, EFUSE_PG, ("Efuse switch bank to %d\n", bank)); */ + if (bPseudoTest) { + fakeEfuseBank = bank; + bRet = true; + } else + bRet = true; + return bRet; +} + + + +static void +ReadEFuseByIC( + PADAPTER Adapter, + u8 efuseType, + u16 _offset, + u16 _size_byte, + u8 *pbuf, + bool bPseudoTest +) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter); +#ifdef DBG_IOL_READ_EFUSE_MAP + u8 logical_map[512]; +#endif + +#ifdef CONFIG_IOL_READ_EFUSE_MAP + if (!bPseudoTest) { /* && rtw_IOL_applied(Adapter)) */ + int ret = _FAIL; + if (rtw_IOL_applied(Adapter)) { + rtw_hal_power_on(Adapter); + + iol_mode_enable(Adapter, 1); +#ifdef DBG_IOL_READ_EFUSE_MAP + iol_read_efuse(Adapter, 0, _offset, _size_byte, logical_map); +#else + ret = iol_read_efuse(Adapter, 0, _offset, _size_byte, pbuf); +#endif + iol_mode_enable(Adapter, 0); + + if (_SUCCESS == ret) + goto exit; + } + } +#endif + Hal_EfuseReadEFuse88E(Adapter, _offset, _size_byte, pbuf, bPseudoTest); + +exit: + +#ifdef DBG_IOL_READ_EFUSE_MAP + if (!memcmp(logical_map, pHalData->efuse_eeprom_data, 0x130) == false) { + int i; + RTW_INFO("%s compare first 0x130 byte fail\n", __func__); + for (i = 0; i < 512; i++) { + if (i % 16 == 0) + RTW_INFO("0x%03x: ", i); + RTW_INFO("%02x ", logical_map[i]); + if (i % 16 == 15) + RTW_INFO("\n"); + } + RTW_INFO("\n"); + } +#endif + + return; +} + +static void +ReadEFuse_Pseudo( + PADAPTER Adapter, + u8 efuseType, + u16 _offset, + u16 _size_byte, + u8 *pbuf, + bool bPseudoTest +) +{ + Hal_EfuseReadEFuse88E(Adapter, _offset, _size_byte, pbuf, bPseudoTest); +} + +static void +rtl8188e_ReadEFuse( + PADAPTER Adapter, + u8 efuseType, + u16 _offset, + u16 _size_byte, + u8 *pbuf, + bool bPseudoTest +) +{ + if (bPseudoTest) + ReadEFuse_Pseudo(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest); + else + ReadEFuseByIC(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest); +} + +/* Do not support BT */ +static void +Hal_EFUSEGetEfuseDefinition88E( + PADAPTER pAdapter, + u8 efuseType, + u8 type, + void * pOut +) +{ + switch (type) { + case TYPE_EFUSE_MAX_SECTION: { + u8 *pMax_section; + pMax_section = (u8 *)pOut; + *pMax_section = EFUSE_MAX_SECTION_88E; + } + break; + case TYPE_EFUSE_REAL_CONTENT_LEN: { + u16 *pu2Tmp; + pu2Tmp = (u16 *)pOut; + *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E; + } + break; + case TYPE_EFUSE_CONTENT_LEN_BANK: { + u16 *pu2Tmp; + pu2Tmp = (u16 *)pOut; + *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E; + } + break; + case TYPE_AVAILABLE_EFUSE_BYTES_BANK: { + u16 *pu2Tmp; + pu2Tmp = (u16 *)pOut; + *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E); + } + break; + case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL: { + u16 *pu2Tmp; + pu2Tmp = (u16 *)pOut; + *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E); + } + break; + case TYPE_EFUSE_MAP_LEN: { + u16 *pu2Tmp; + pu2Tmp = (u16 *)pOut; + *pu2Tmp = (u16)EFUSE_MAP_LEN_88E; + } + break; + case TYPE_EFUSE_PROTECT_BYTES_BANK: { + u8 *pu1Tmp; + pu1Tmp = (u8 *)pOut; + *pu1Tmp = (u8)(EFUSE_OOB_PROTECT_BYTES_88E); + } + break; + default: { + u8 *pu1Tmp; + pu1Tmp = (u8 *)pOut; + *pu1Tmp = 0; + } + break; + } +} + +static void +Hal_EFUSEGetEfuseDefinition_Pseudo88E( + PADAPTER pAdapter, + u8 efuseType, + u8 type, + void * pOut +) +{ + switch (type) { + case TYPE_EFUSE_MAX_SECTION: { + u8 *pMax_section; + pMax_section = (u8 *)pOut; + *pMax_section = EFUSE_MAX_SECTION_88E; + } + break; + case TYPE_EFUSE_REAL_CONTENT_LEN: { + u16 *pu2Tmp; + pu2Tmp = (u16 *)pOut; + *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E; + } + break; + case TYPE_EFUSE_CONTENT_LEN_BANK: { + u16 *pu2Tmp; + pu2Tmp = (u16 *)pOut; + *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E; + } + break; + case TYPE_AVAILABLE_EFUSE_BYTES_BANK: { + u16 *pu2Tmp; + pu2Tmp = (u16 *)pOut; + *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E); + } + break; + case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL: { + u16 *pu2Tmp; + pu2Tmp = (u16 *)pOut; + *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E); + } + break; + case TYPE_EFUSE_MAP_LEN: { + u16 *pu2Tmp; + pu2Tmp = (u16 *)pOut; + *pu2Tmp = (u16)EFUSE_MAP_LEN_88E; + } + break; + case TYPE_EFUSE_PROTECT_BYTES_BANK: { + u8 *pu1Tmp; + pu1Tmp = (u8 *)pOut; + *pu1Tmp = (u8)(EFUSE_OOB_PROTECT_BYTES_88E); + } + break; + default: { + u8 *pu1Tmp; + pu1Tmp = (u8 *)pOut; + *pu1Tmp = 0; + } + break; + } +} + + +static void +rtl8188e_EFUSE_GetEfuseDefinition( + PADAPTER pAdapter, + u8 efuseType, + u8 type, + void *pOut, + bool bPseudoTest +) +{ + if (bPseudoTest) + Hal_EFUSEGetEfuseDefinition_Pseudo88E(pAdapter, efuseType, type, pOut); + else + Hal_EFUSEGetEfuseDefinition88E(pAdapter, efuseType, type, pOut); +} + +static u8 +Hal_EfuseWordEnableDataWrite(PADAPTER pAdapter, + u16 efuse_addr, + u8 word_en, + u8 *data, + bool bPseudoTest) +{ + u16 tmpaddr = 0; + u16 start_addr = efuse_addr; + u8 badworden = 0x0F; + u8 tmpdata[8]; + + memset((void *)tmpdata, 0xff, PGPKT_DATA_SIZE); + + if (!(word_en & BIT0)) { + tmpaddr = start_addr; + efuse_OneByteWrite(pAdapter, start_addr++, data[0], bPseudoTest); + efuse_OneByteWrite(pAdapter, start_addr++, data[1], bPseudoTest); + phy_set_mac_reg(pAdapter, EFUSE_TEST, BIT26, 0); + + efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0], bPseudoTest); + efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[1], bPseudoTest); + phy_set_mac_reg(pAdapter, EFUSE_TEST, BIT26, 1); + + if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) + badworden &= (~BIT0); + } + if (!(word_en & BIT1)) { + tmpaddr = start_addr; + efuse_OneByteWrite(pAdapter, start_addr++, data[2], bPseudoTest); + efuse_OneByteWrite(pAdapter, start_addr++, data[3], bPseudoTest); + phy_set_mac_reg(pAdapter, EFUSE_TEST, BIT26, 0); + + efuse_OneByteRead(pAdapter, tmpaddr , &tmpdata[2], bPseudoTest); + efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[3], bPseudoTest); + phy_set_mac_reg(pAdapter, EFUSE_TEST, BIT26, 1); + + if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) + badworden &= (~BIT1); + } + if (!(word_en & BIT2)) { + tmpaddr = start_addr; + efuse_OneByteWrite(pAdapter, start_addr++, data[4], bPseudoTest); + efuse_OneByteWrite(pAdapter, start_addr++, data[5], bPseudoTest); + phy_set_mac_reg(pAdapter, EFUSE_TEST, BIT26, 0); + + efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4], bPseudoTest); + efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[5], bPseudoTest); + phy_set_mac_reg(pAdapter, EFUSE_TEST, BIT26, 1); + + if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) + badworden &= (~BIT2); + } + if (!(word_en & BIT3)) { + tmpaddr = start_addr; + efuse_OneByteWrite(pAdapter, start_addr++, data[6], bPseudoTest); + efuse_OneByteWrite(pAdapter, start_addr++, data[7], bPseudoTest); + phy_set_mac_reg(pAdapter, EFUSE_TEST, BIT26, 0); + + efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6], bPseudoTest); + efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[7], bPseudoTest); + phy_set_mac_reg(pAdapter, EFUSE_TEST, BIT26, 1); + + if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) + badworden &= (~BIT3); + } + return badworden; +} + +static u8 +Hal_EfuseWordEnableDataWrite_Pseudo(PADAPTER pAdapter, + u16 efuse_addr, + u8 word_en, + u8 *data, + bool bPseudoTest) +{ + u8 ret = 0; + + ret = Hal_EfuseWordEnableDataWrite(pAdapter, efuse_addr, word_en, data, bPseudoTest); + + return ret; +} + +static u8 +rtl8188e_Efuse_WordEnableDataWrite(PADAPTER pAdapter, + u16 efuse_addr, + u8 word_en, + u8 *data, + bool bPseudoTest) +{ + u8 ret = 0; + + if (bPseudoTest) + ret = Hal_EfuseWordEnableDataWrite_Pseudo(pAdapter, efuse_addr, word_en, data, bPseudoTest); + else + ret = Hal_EfuseWordEnableDataWrite(pAdapter, efuse_addr, word_en, data, bPseudoTest); + + return ret; +} + + +static u16 +hal_EfuseGetCurrentSize_8188e(PADAPTER pAdapter, + bool bPseudoTest) +{ + int bContinual = true; + + u16 efuse_addr = 0; + u8 hoffset = 0, hworden = 0; + u8 efuse_data, word_cnts = 0; + + if (bPseudoTest) + efuse_addr = (u16)(fakeEfuseUsedBytes); + else + rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr); + /* RTPRINT(FEEPROM, EFUSE_PG, ("hal_EfuseGetCurrentSize_8723A(), start_efuse_addr = %d\n", efuse_addr)); */ + + while (bContinual && + efuse_OneByteRead(pAdapter, efuse_addr , &efuse_data, bPseudoTest) && + AVAILABLE_EFUSE_ADDR(efuse_addr)) { + if (efuse_data != 0xFF) { + if ((efuse_data & 0x1F) == 0x0F) { /* extended header */ + hoffset = efuse_data; + efuse_addr++; + efuse_OneByteRead(pAdapter, efuse_addr , &efuse_data, bPseudoTest); + if ((efuse_data & 0x0F) == 0x0F) { + efuse_addr++; + continue; + } else { + hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); + hworden = efuse_data & 0x0F; + } + } else { + hoffset = (efuse_data >> 4) & 0x0F; + hworden = efuse_data & 0x0F; + } + word_cnts = Efuse_CalculateWordCnts(hworden); + /* read next header */ + efuse_addr = efuse_addr + (word_cnts * 2) + 1; + } else + bContinual = false ; + } + + if (bPseudoTest) { + fakeEfuseUsedBytes = efuse_addr; + /* RTPRINT(FEEPROM, EFUSE_PG, ("hal_EfuseGetCurrentSize_8723A(), return %d\n", fakeEfuseUsedBytes)); */ + } else { + rtw_hal_set_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr); + /* RTPRINT(FEEPROM, EFUSE_PG, ("hal_EfuseGetCurrentSize_8723A(), return %d\n", efuse_addr)); */ + } + + return efuse_addr; +} + +static u16 +Hal_EfuseGetCurrentSize_Pseudo(PADAPTER pAdapter, + bool bPseudoTest) +{ + u16 ret = 0; + + ret = hal_EfuseGetCurrentSize_8188e(pAdapter, bPseudoTest); + + return ret; +} + + +static u16 +rtl8188e_EfuseGetCurrentSize( + PADAPTER pAdapter, + u8 efuseType, + bool bPseudoTest) +{ + u16 ret = 0; + + if (bPseudoTest) + ret = Hal_EfuseGetCurrentSize_Pseudo(pAdapter, bPseudoTest); + else + ret = hal_EfuseGetCurrentSize_8188e(pAdapter, bPseudoTest); + + + return ret; +} + + +static int +hal_EfusePgPacketRead_8188e( + PADAPTER pAdapter, + u8 offset, + u8 *data, + bool bPseudoTest) +{ + u8 ReadState = PG_STATE_HEADER; + + int bContinual = true; + int bDataEmpty = true ; + + u8 efuse_data, word_cnts = 0; + u16 efuse_addr = 0; + u8 hoffset = 0, hworden = 0; + u8 tmpidx = 0; + u8 tmpdata[8]; + u8 max_section = 0; + u8 tmp_header = 0; + + EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, (void *)&max_section, bPseudoTest); + + if (data == NULL) + return false; + if (offset > max_section) + return false; + + memset((void *)data, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); + memset((void *)tmpdata, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); + + + /* */ + /* Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */ + /* Skip dummy parts to prevent unexpected data read from Efuse. */ + /* By pass right now. 2009.02.19. */ + /* */ + while (bContinual && AVAILABLE_EFUSE_ADDR(efuse_addr)) { + /* ------- Header Read ------------- */ + if (ReadState & PG_STATE_HEADER) { + if (efuse_OneByteRead(pAdapter, efuse_addr , &efuse_data, bPseudoTest) && (efuse_data != 0xFF)) { + if (EXT_HEADER(efuse_data)) { + tmp_header = efuse_data; + efuse_addr++; + efuse_OneByteRead(pAdapter, efuse_addr , &efuse_data, bPseudoTest); + if (!ALL_WORDS_DISABLED(efuse_data)) { + hoffset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); + hworden = efuse_data & 0x0F; + } else { + RTW_INFO("Error, All words disabled\n"); + efuse_addr++; + continue; + } + } else { + hoffset = (efuse_data >> 4) & 0x0F; + hworden = efuse_data & 0x0F; + } + word_cnts = Efuse_CalculateWordCnts(hworden); + bDataEmpty = true ; + + if (hoffset == offset) { + for (tmpidx = 0; tmpidx < word_cnts * 2 ; tmpidx++) { + if (efuse_OneByteRead(pAdapter, efuse_addr + 1 + tmpidx , &efuse_data, bPseudoTest)) { + tmpdata[tmpidx] = efuse_data; + if (efuse_data != 0xff) + bDataEmpty = false; + } + } + if (bDataEmpty == false) + ReadState = PG_STATE_DATA; + else { /* read next header */ + efuse_addr = efuse_addr + (word_cnts * 2) + 1; + ReadState = PG_STATE_HEADER; + } + } else { /* read next header */ + efuse_addr = efuse_addr + (word_cnts * 2) + 1; + ReadState = PG_STATE_HEADER; + } + + } else + bContinual = false ; + } + /* ------- Data section Read ------------- */ + else if (ReadState & PG_STATE_DATA) { + efuse_WordEnableDataRead(hworden, tmpdata, data); + efuse_addr = efuse_addr + (word_cnts * 2) + 1; + ReadState = PG_STATE_HEADER; + } + + } + + if ((data[0] == 0xff) && (data[1] == 0xff) && (data[2] == 0xff) && (data[3] == 0xff) && + (data[4] == 0xff) && (data[5] == 0xff) && (data[6] == 0xff) && (data[7] == 0xff)) + return false; + else + return true; + +} + +static int +Hal_EfusePgPacketRead(PADAPTER pAdapter, + u8 offset, + u8 *data, + bool bPseudoTest) +{ + int ret = 0; + + ret = hal_EfusePgPacketRead_8188e(pAdapter, offset, data, bPseudoTest); + + + return ret; +} + +static int +Hal_EfusePgPacketRead_Pseudo(PADAPTER pAdapter, + u8 offset, + u8 *data, + bool bPseudoTest) +{ + int ret = 0; + + ret = hal_EfusePgPacketRead_8188e(pAdapter, offset, data, bPseudoTest); + + return ret; +} + +static int +rtl8188e_Efuse_PgPacketRead(PADAPTER pAdapter, + u8 offset, + u8 *data, + bool bPseudoTest) +{ + int ret = 0; + + if (bPseudoTest) + ret = Hal_EfusePgPacketRead_Pseudo(pAdapter, offset, data, bPseudoTest); + else + ret = Hal_EfusePgPacketRead(pAdapter, offset, data, bPseudoTest); + + return ret; +} + +static bool +hal_EfuseFixHeaderProcess( + PADAPTER pAdapter, + u8 efuseType, + PPGPKT_STRUCT pFixPkt, + u16 *pAddr, + bool bPseudoTest +) +{ + u8 originaldata[8], badworden = 0; + u16 efuse_addr = *pAddr; + u32 PgWriteSuccess = 0; + + memset((void *)originaldata, 0xff, 8); + + if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata, bPseudoTest)) { + /* check if data exist */ + badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pFixPkt->word_en, originaldata, bPseudoTest); + + if (badworden != 0xf) { /* write fail */ + PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata, bPseudoTest); + + if (!PgWriteSuccess) + return false; + else + efuse_addr = Efuse_GetCurrentSize(pAdapter, efuseType, bPseudoTest); + } else + efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1; + } else + efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1; + *pAddr = efuse_addr; + return true; +} + +static bool +hal_EfusePgPacketWrite2ByteHeader( + PADAPTER pAdapter, + u8 efuseType, + u16 *pAddr, + PPGPKT_STRUCT pTargetPkt, + bool bPseudoTest) +{ + bool bRet = false, bContinual = true; + u16 efuse_addr = *pAddr, efuse_max_available_len = 0; + u8 pg_header = 0, tmp_header = 0, pg_header_temp = 0; + u8 repeatcnt = 0; + + /* RTPRINT(FEEPROM, EFUSE_PG, ("Wirte 2byte header\n")); */ + EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len, bPseudoTest); + + while (efuse_addr < efuse_max_available_len) { + pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F; + /* RTPRINT(FEEPROM, EFUSE_PG, ("pg_header = 0x%x\n", pg_header)); */ + efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest); + phy_set_mac_reg(pAdapter, EFUSE_TEST, BIT26, 0); + efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest); + phy_set_mac_reg(pAdapter, EFUSE_TEST, BIT26, 1); + while (tmp_header == 0xFF || pg_header != tmp_header) { + if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) { + /* RTPRINT(FEEPROM, EFUSE_PG, ("Repeat over limit for pg_header!!\n")); */ + return false; + } + + efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest); + efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest); + } + + /* to write ext_header */ + if (tmp_header == pg_header) { + efuse_addr++; + pg_header_temp = pg_header; + pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en; + + efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest); + phy_set_mac_reg(pAdapter, EFUSE_TEST, BIT26, 0); + efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest); + phy_set_mac_reg(pAdapter, EFUSE_TEST, BIT26, 1); + while (tmp_header == 0xFF || pg_header != tmp_header) { + if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) { + /* RTPRINT(FEEPROM, EFUSE_PG, ("Repeat over limit for ext_header!!\n")); */ + return false; + } + + efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest); + efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest); + } + + if ((tmp_header & 0x0F) == 0x0F) { /* word_en PG fail */ + if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) { + /* RTPRINT(FEEPROM, EFUSE_PG, ("Repeat over limit for word_en!!\n")); */ + return false; + } else { + efuse_addr++; + continue; + } + } else if (pg_header != tmp_header) { /* offset PG fail */ + PGPKT_STRUCT fixPkt; + /* RTPRINT(FEEPROM, EFUSE_PG, ("Error condition for offset PG fail, need to cover the existed data\n")); */ + fixPkt.offset = ((pg_header_temp & 0xE0) >> 5) | ((tmp_header & 0xF0) >> 1); + fixPkt.word_en = tmp_header & 0x0F; + fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en); + if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr, bPseudoTest)) + return false; + } else { + bRet = true; + break; + } + } else if ((tmp_header & 0x1F) == 0x0F) { /* wrong extended header */ + efuse_addr += 2; + continue; + } + } + + *pAddr = efuse_addr; + return bRet; +} + +static bool +hal_EfusePgPacketWrite1ByteHeader( + PADAPTER pAdapter, + u8 efuseType, + u16 *pAddr, + PPGPKT_STRUCT pTargetPkt, + bool bPseudoTest) +{ + bool bRet = false; + u8 pg_header = 0, tmp_header = 0; + u16 efuse_addr = *pAddr; + u8 repeatcnt = 0; + + /* RTPRINT(FEEPROM, EFUSE_PG, ("Wirte 1byte header\n")); */ + pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en; + + efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest); + phy_set_mac_reg(pAdapter, EFUSE_TEST, BIT26, 0); + + efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest); + + phy_set_mac_reg(pAdapter, EFUSE_TEST, BIT26, 1); + + while (tmp_header == 0xFF || pg_header != tmp_header) { + if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) + return false; + efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest); + efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest); + } + + if (pg_header == tmp_header) + bRet = true; + else { + PGPKT_STRUCT fixPkt; + /* RTPRINT(FEEPROM, EFUSE_PG, ("Error condition for fixed PG packet, need to cover the existed data\n")); */ + fixPkt.offset = (tmp_header >> 4) & 0x0F; + fixPkt.word_en = tmp_header & 0x0F; + fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en); + if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr, bPseudoTest)) + return false; + } + + *pAddr = efuse_addr; + return bRet; +} + +static bool +hal_EfusePgPacketWriteData( + PADAPTER pAdapter, + u8 efuseType, + u16 *pAddr, + PPGPKT_STRUCT pTargetPkt, + bool bPseudoTest) +{ + bool bRet = false; + u16 efuse_addr = *pAddr; + u8 badworden = 0; + u32 PgWriteSuccess = 0; + + badworden = 0x0f; + badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pTargetPkt->word_en, pTargetPkt->data, bPseudoTest); + if (badworden == 0x0F) { + /* write ok */ + /* RTPRINT(FEEPROM, EFUSE_PG, ("hal_EfusePgPacketWriteData ok!!\n")); */ + return true; + } else { + /* RTPRINT(FEEPROM, EFUSE_PG, ("hal_EfusePgPacketWriteData Fail!!\n")); */ + /* reorganize other pg packet */ + + PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest); + + if (!PgWriteSuccess) + return false; + else + return true; + } + + return bRet; +} + +static bool +hal_EfusePgPacketWriteHeader( + PADAPTER pAdapter, + u8 efuseType, + u16 *pAddr, + PPGPKT_STRUCT pTargetPkt, + bool bPseudoTest) +{ + bool bRet = false; + + if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE) + bRet = hal_EfusePgPacketWrite2ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt, bPseudoTest); + else + bRet = hal_EfusePgPacketWrite1ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt, bPseudoTest); + + return bRet; +} + +static bool +wordEnMatched( + PPGPKT_STRUCT pTargetPkt, + PPGPKT_STRUCT pCurPkt, + u8 *pWden +) +{ + u8 match_word_en = 0x0F; /* default all words are disabled */ + u8 i; + + /* check if the same words are enabled both target and current PG packet */ + if (((pTargetPkt->word_en & BIT0) == 0) && + ((pCurPkt->word_en & BIT0) == 0)) { + match_word_en &= ~BIT0; /* enable word 0 */ + } + if (((pTargetPkt->word_en & BIT1) == 0) && + ((pCurPkt->word_en & BIT1) == 0)) { + match_word_en &= ~BIT1; /* enable word 1 */ + } + if (((pTargetPkt->word_en & BIT2) == 0) && + ((pCurPkt->word_en & BIT2) == 0)) { + match_word_en &= ~BIT2; /* enable word 2 */ + } + if (((pTargetPkt->word_en & BIT3) == 0) && + ((pCurPkt->word_en & BIT3) == 0)) { + match_word_en &= ~BIT3; /* enable word 3 */ + } + + *pWden = match_word_en; + + if (match_word_en != 0xf) + return true; + else + return false; +} + +static bool +hal_EfuseCheckIfDatafollowed( + PADAPTER pAdapter, + u8 word_cnts, + u16 startAddr, + bool bPseudoTest +) +{ + bool bRet = false; + u8 i, efuse_data; + + for (i = 0; i < (word_cnts * 2) ; i++) { + if (efuse_OneByteRead(pAdapter, (startAddr + i) , &efuse_data, bPseudoTest) && (efuse_data != 0xFF)) + bRet = true; + } + + return bRet; +} + +static bool +hal_EfusePartialWriteCheck( + PADAPTER pAdapter, + u8 efuseType, + u16 *pAddr, + PPGPKT_STRUCT pTargetPkt, + bool bPseudoTest +) +{ + bool bRet = false; + u8 i, efuse_data = 0, cur_header = 0; + u8 new_wden = 0, matched_wden = 0, badworden = 0; + u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0; + PGPKT_STRUCT curPkt; + + EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len, bPseudoTest); + EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&efuse_max, bPseudoTest); + + if (efuseType == EFUSE_WIFI) { + if (bPseudoTest) + startAddr = (u16)(fakeEfuseUsedBytes % EFUSE_REAL_CONTENT_LEN); + else { + rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr); + startAddr %= EFUSE_REAL_CONTENT_LEN; + } + } else { + if (bPseudoTest) + startAddr = (u16)(fakeBTEfuseUsedBytes % EFUSE_REAL_CONTENT_LEN); + else + startAddr = (u16)(BTEfuseUsedBytes % EFUSE_REAL_CONTENT_LEN); + } + /* RTPRINT(FEEPROM, EFUSE_PG, ("hal_EfusePartialWriteCheck(), startAddr=%d\n", startAddr)); */ + + while (1) { + if (startAddr >= efuse_max_available_len) { + bRet = false; + break; + } + + if (efuse_OneByteRead(pAdapter, startAddr, &efuse_data, bPseudoTest) && (efuse_data != 0xFF)) { + if (EXT_HEADER(efuse_data)) { + cur_header = efuse_data; + startAddr++; + efuse_OneByteRead(pAdapter, startAddr, &efuse_data, bPseudoTest); + if (ALL_WORDS_DISABLED(efuse_data)) { + /* RTPRINT(FEEPROM, EFUSE_PG, ("Error condition, all words disabled")); */ + bRet = false; + break; + } else { + curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); + curPkt.word_en = efuse_data & 0x0F; + } + } else { + cur_header = efuse_data; + curPkt.offset = (cur_header >> 4) & 0x0F; + curPkt.word_en = cur_header & 0x0F; + } + + curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en); + /* if same header is found but no data followed */ + /* write some part of data followed by the header. */ + if ((curPkt.offset == pTargetPkt->offset) && + (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr + 1, bPseudoTest)) && + wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) { + /* RTPRINT(FEEPROM, EFUSE_PG, ("Need to partial write data by the previous wrote header\n")); */ + /* Here to write partial data */ + badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr + 1, matched_wden, pTargetPkt->data, bPseudoTest); + if (badworden != 0x0F) { + u32 PgWriteSuccess = 0; + /* if write fail on some words, write these bad words again */ + + PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest); + + if (!PgWriteSuccess) { + bRet = false; /* write fail, return */ + break; + } + } + /* partial write ok, update the target packet for later use */ + for (i = 0; i < 4; i++) { + if ((matched_wden & (0x1 << i)) == 0) { /* this word has been written */ + pTargetPkt->word_en |= (0x1 << i); /* disable the word */ + } + } + pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en); + } + /* read from next header */ + startAddr = startAddr + (curPkt.word_cnts * 2) + 1; + } else { + /* not used header, 0xff */ + *pAddr = startAddr; + /* RTPRINT(FEEPROM, EFUSE_PG, ("Started from unused header offset=%d\n", startAddr)); */ + bRet = true; + break; + } + } + return bRet; +} + +static bool +hal_EfusePgCheckAvailableAddr( + PADAPTER pAdapter, + u8 efuseType, + bool bPseudoTest +) +{ + u16 efuse_max_available_len = 0; + + /* Change to check TYPE_EFUSE_MAP_LEN ,beacuse 8188E raw 256,logic map over 256. */ + EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&efuse_max_available_len, false); + + /* EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&efuse_max_available_len, bPseudoTest); */ + /* RTPRINT(FEEPROM, EFUSE_PG, ("efuse_max_available_len = %d\n", efuse_max_available_len)); */ + + if (Efuse_GetCurrentSize(pAdapter, efuseType, bPseudoTest) >= efuse_max_available_len) { + /* RTPRINT(FEEPROM, EFUSE_PG, ("hal_EfusePgCheckAvailableAddr error!!\n")); */ + return false; + } + return true; +} + +static void +hal_EfuseConstructPGPkt( + u8 offset, + u8 word_en, + u8 *pData, + PPGPKT_STRUCT pTargetPkt + +) +{ + memset((void *)pTargetPkt->data, 0xFF, sizeof(u8) * 8); + pTargetPkt->offset = offset; + pTargetPkt->word_en = word_en; + efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data); + pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en); + + /* RTPRINT(FEEPROM, EFUSE_PG, ("hal_EfuseConstructPGPkt(), targetPkt, offset=%d, word_en=0x%x, word_cnts=%d\n", pTargetPkt->offset, pTargetPkt->word_en, pTargetPkt->word_cnts)); */ +} + +static bool +hal_EfusePgPacketWrite_BT( + PADAPTER pAdapter, + u8 offset, + u8 word_en, + u8 *pData, + bool bPseudoTest +) +{ + PGPKT_STRUCT targetPkt; + u16 startAddr = 0; + u8 efuseType = EFUSE_BT; + + if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType, bPseudoTest)) + return false; + + hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt); + + if (!hal_EfusePartialWriteCheck(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest)) + return false; + + if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest)) + return false; + + if (!hal_EfusePgPacketWriteData(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest)) + return false; + + return true; +} + +static bool +hal_EfusePgPacketWrite_8188e( + PADAPTER pAdapter, + u8 offset, + u8 word_en, + u8 *pData, + bool bPseudoTest +) +{ + PGPKT_STRUCT targetPkt; + u16 startAddr = 0; + u8 efuseType = EFUSE_WIFI; + + if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType, bPseudoTest)) + return false; + + hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt); + + if (!hal_EfusePartialWriteCheck(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest)) + return false; + + if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest)) + return false; + + if (!hal_EfusePgPacketWriteData(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest)) + return false; + + return true; +} + + +static int +Hal_EfusePgPacketWrite_Pseudo(PADAPTER pAdapter, + u8 offset, + u8 word_en, + u8 *data, + bool bPseudoTest) +{ + int ret; + + ret = hal_EfusePgPacketWrite_8188e(pAdapter, offset, word_en, data, bPseudoTest); + + return ret; +} + +static int +Hal_EfusePgPacketWrite(PADAPTER pAdapter, + u8 offset, + u8 word_en, + u8 *data, + bool bPseudoTest) +{ + int ret = 0; + ret = hal_EfusePgPacketWrite_8188e(pAdapter, offset, word_en, data, bPseudoTest); + + + return ret; +} + +static int +rtl8188e_Efuse_PgPacketWrite(PADAPTER pAdapter, + u8 offset, + u8 word_en, + u8 *data, + bool bPseudoTest) +{ + int ret; + + if (bPseudoTest) + ret = Hal_EfusePgPacketWrite_Pseudo(pAdapter, offset, word_en, data, bPseudoTest); + else + ret = Hal_EfusePgPacketWrite(pAdapter, offset, word_en, data, bPseudoTest); + return ret; +} + +static void read_chip_version_8188e(PADAPTER padapter) +{ + u32 value32; + HAL_DATA_TYPE *pHalData; + + pHalData = GET_HAL_DATA(padapter); + + value32 = rtw_read32(padapter, REG_SYS_CFG); + pHalData->version_id.ICType = CHIP_8188E; + pHalData->version_id.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP); + + pHalData->version_id.RFType = RF_TYPE_1T1R; + pHalData->version_id.VendorType = ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC); + pHalData->version_id.CUTVersion = (value32 & CHIP_VER_RTL_MASK) >> CHIP_VER_RTL_SHIFT; /* IC version (CUT) */ + + /* For regulator mode. by tynli. 2011.01.14 */ + pHalData->RegulatorMode = ((value32 & TRP_BT_EN) ? RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR); + + pHalData->version_id.ROMVer = 0; /* ROM code version. */ + pHalData->MultiFunc = RT_MULTI_FUNC_NONE; + + rtw_hal_config_rftype(padapter); + dump_chip_info(pHalData->version_id); +} + +void rtl8188e_start_thread(_adapter *padapter) +{ +} + +void rtl8188e_stop_thread(_adapter *padapter) +{ +} + +static void hal_notch_filter_8188e(_adapter *adapter, bool enable) +{ + if (enable) { + RTW_INFO("Enable notch filter\n"); + rtw_write8(adapter, rOFDM0_RxDSP + 1, rtw_read8(adapter, rOFDM0_RxDSP + 1) | BIT1); + } else { + RTW_INFO("Disable notch filter\n"); + rtw_write8(adapter, rOFDM0_RxDSP + 1, rtw_read8(adapter, rOFDM0_RxDSP + 1) & ~BIT1); + } +} + +static void update_ra_mask_8188e(_adapter *padapter, struct sta_info *psta, struct macid_cfg *h2c_macid_cfg) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter); + + if (hal_data->fw_ractrl == true) { + u8 arg[4] = {0}; + + arg[0] = h2c_macid_cfg->mac_id;/* MACID */ + arg[1] = h2c_macid_cfg->rate_id; + arg[2] = (h2c_macid_cfg->ignore_bw << 4) | h2c_macid_cfg->short_gi; + arg[3] = psta->init_rate; + rtl8188e_set_raid_cmd(padapter, h2c_macid_cfg->ra_mask, arg, h2c_macid_cfg->bandwidth); + } else { + +#if (RATE_ADAPTIVE_SUPPORT == 1) + + odm_ra_update_rate_info_8188e( + &(hal_data->odmpriv), + h2c_macid_cfg->mac_id, + h2c_macid_cfg->rate_id, + h2c_macid_cfg->ra_mask, + h2c_macid_cfg->short_gi + ); + +#endif + } + +} + +void init_hal_spec_8188e(_adapter *adapter) +{ + struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter); + + hal_spec->ic_name = "rtl8188e"; + hal_spec->macid_num = 64; + hal_spec->sec_cam_ent_num = 32; + hal_spec->sec_cap = 0; + hal_spec->rfpath_num_2g = 1; + hal_spec->rfpath_num_5g = 0; + hal_spec->max_tx_cnt = 1; + hal_spec->tx_nss_num = 1; + hal_spec->rx_nss_num = 1; + hal_spec->band_cap = BAND_CAP_2G; + hal_spec->bw_cap = BW_CAP_20M | BW_CAP_40M; + hal_spec->port_num = 2; + hal_spec->proto_cap = PROTO_CAP_11B | PROTO_CAP_11G | PROTO_CAP_11N; + hal_spec->wl_func = 0 + | WL_FUNC_P2P + | WL_FUNC_MIRACAST + | WL_FUNC_TDLS + ; +} + +#ifdef CONFIG_RFKILL_POLL +bool rtl8188e_gpio_radio_on_off_check(_adapter *adapter, u8 *valid) +{ + u32 tmp32; + bool ret; + + *valid = 0; + return false; /* unblock */ +} +#endif + +void rtl8188e_init_default_value(_adapter *adapter) +{ + HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter); + + adapter->registrypriv.wireless_mode = WIRELESS_11BG_24N; +} + +void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) +{ + pHalFunc->dm_init = &rtl8188e_init_dm_priv; + pHalFunc->dm_deinit = &rtl8188e_deinit_dm_priv; + + pHalFunc->read_chip_version = read_chip_version_8188e; + + pHalFunc->update_ra_mask_handler = update_ra_mask_8188e; + + pHalFunc->set_chnl_bw_handler = &PHY_SetSwChnlBWMode8188E; + + pHalFunc->set_tx_power_level_handler = &PHY_SetTxPowerLevel8188E; + pHalFunc->get_tx_power_level_handler = &PHY_GetTxPowerLevel8188E; + + pHalFunc->get_tx_power_index_handler = &PHY_GetTxPowerIndex_8188E; + + pHalFunc->hal_dm_watchdog = &rtl8188e_HalDmWatchDog; + + pHalFunc->run_thread = &rtl8188e_start_thread; + pHalFunc->cancel_thread = &rtl8188e_stop_thread; + + pHalFunc->read_bbreg = &PHY_QueryBBReg8188E; + pHalFunc->write_bbreg = &PHY_SetBBReg8188E; + pHalFunc->read_rfreg = &PHY_QueryRFReg8188E; + pHalFunc->write_rfreg = &PHY_SetRFReg8188E; + + + /* Efuse related function */ + pHalFunc->EfusePowerSwitch = &rtl8188e_EfusePowerSwitch; + pHalFunc->ReadEFuse = &rtl8188e_ReadEFuse; + pHalFunc->EFUSEGetEfuseDefinition = &rtl8188e_EFUSE_GetEfuseDefinition; + pHalFunc->EfuseGetCurrentSize = &rtl8188e_EfuseGetCurrentSize; + pHalFunc->Efuse_PgPacketRead = &rtl8188e_Efuse_PgPacketRead; + pHalFunc->Efuse_PgPacketWrite = &rtl8188e_Efuse_PgPacketWrite; + pHalFunc->Efuse_WordEnableDataWrite = &rtl8188e_Efuse_WordEnableDataWrite; + +#ifdef DBG_CONFIG_ERROR_DETECT + pHalFunc->sreset_init_value = &sreset_init_value; + pHalFunc->sreset_reset_value = &sreset_reset_value; + pHalFunc->silentreset = &sreset_reset; + pHalFunc->sreset_xmit_status_check = &rtl8188e_sreset_xmit_status_check; + pHalFunc->sreset_linked_status_check = &rtl8188e_sreset_linked_status_check; + pHalFunc->sreset_get_wifi_status = &sreset_get_wifi_status; + pHalFunc->sreset_inprogress = &sreset_inprogress; +#endif /* DBG_CONFIG_ERROR_DETECT */ + + pHalFunc->GetHalODMVarHandler = GetHalODMVar; + pHalFunc->SetHalODMVarHandler = SetHalODMVar; + +#ifdef CONFIG_IOL + pHalFunc->IOL_exec_cmds_sync = &rtl8188e_IOL_exec_cmds_sync; +#endif + + pHalFunc->hal_notch_filter = &hal_notch_filter_8188e; + pHalFunc->fill_h2c_cmd = &FillH2CCmd_88E; + pHalFunc->fill_fake_txdesc = &rtl8188e_fill_fake_txdesc; + pHalFunc->fw_dl = &rtl8188e_FirmwareDownload; + pHalFunc->hal_get_tx_buff_rsvd_page_num = &GetTxBufferRsvdPageNum8188E; + +#ifdef CONFIG_GPIO_API + pHalFunc->hal_gpio_func_check = &rtl8188e_GpioFuncCheck; +#endif +#ifdef CONFIG_RFKILL_POLL + pHalFunc->hal_radio_onoff_check = rtl8188e_gpio_radio_on_off_check; +#endif +} + +u8 GetEEPROMSize8188E(PADAPTER padapter) +{ + u8 size = 0; + u32 cr; + + cr = rtw_read16(padapter, REG_9346CR); + /* 6: EEPROM used is 93C46, 4: boot from E-Fuse. */ + size = (cr & BOOT_FROM_EEPROM) ? 6 : 4; + + RTW_INFO("EEPROM type is %s\n", size == 4 ? "E-FUSE" : "93C46"); + + return size; +} + +/* ------------------------------------------------------------------------- + * + * LLT R/W/Init function + * + * ------------------------------------------------------------------------- */ +static s32 _LLTWrite(PADAPTER padapter, u32 address, u32 data) +{ + s32 status = _SUCCESS; + s8 count = POLLING_LLT_THRESHOLD; + u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS); + + rtw_write32(padapter, REG_LLT_INIT, value); + + /* polling */ + do { + value = rtw_read32(padapter, REG_LLT_INIT); + if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) + break; + } while (--count); + + if (count <= 0) { + RTW_INFO("Failed to polling write LLT done at address %d!\n", address); + status = _FAIL; + } + + return status; +} + +static u8 _LLTRead(PADAPTER padapter, u32 address) +{ + s32 count = POLLING_LLT_THRESHOLD; + u32 value = _LLT_INIT_ADDR(address) | _LLT_OP(_LLT_READ_ACCESS); + u16 LLTReg = REG_LLT_INIT; + + + rtw_write32(padapter, LLTReg, value); + + /* polling and get value */ + do { + value = rtw_read32(padapter, LLTReg); + if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) + return (u8)value; + } while (--count); + + + + + return 0xFF; +} + +s32 InitLLTTable(PADAPTER padapter, u8 txpktbuf_bndy) +{ + s32 status = _FAIL; + u32 i; + u32 Last_Entry_Of_TxPktBuf = LAST_ENTRY_OF_TX_PKT_BUFFER_8188E(padapter);/* 176, 22k */ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + +#if defined(CONFIG_IOL_LLT) + if (rtw_IOL_applied(padapter)) + status = iol_InitLLTTable(padapter, txpktbuf_bndy); + else +#endif + { + for (i = 0; i < (txpktbuf_bndy - 1); i++) { + status = _LLTWrite(padapter, i, i + 1); + if (_SUCCESS != status) + return status; + } + + /* end of list */ + status = _LLTWrite(padapter, (txpktbuf_bndy - 1), 0xFF); + if (_SUCCESS != status) + return status; + + /* Make the other pages as ring buffer */ + /* This ring buffer is used as beacon buffer if we config this MAC as two MAC transfer. */ + /* Otherwise used as local loopback buffer. */ + for (i = txpktbuf_bndy; i < Last_Entry_Of_TxPktBuf; i++) { + status = _LLTWrite(padapter, i, (i + 1)); + if (_SUCCESS != status) + return status; + } + + /* Let last entry point to the start entry of ring buffer */ + status = _LLTWrite(padapter, Last_Entry_Of_TxPktBuf, txpktbuf_bndy); + if (_SUCCESS != status) + return status; + } + + return status; +} + +void +Hal_InitPGData88E(PADAPTER padapter) +{ + + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + u32 i; + u16 value16; + + if (false == pHalData->bautoload_fail_flag) { + /* autoload OK. */ + if (is_boot_from_eeprom(padapter)) { + /* Read all Content from EEPROM or EFUSE. */ + for (i = 0; i < HWSET_MAX_SIZE; i += 2) { + /* value16 = EF2Byte(ReadEEprom(pAdapter, (u16) (i>>1))); + * *((u16*)(&PROMContent[i])) = value16; */ + } + } else { + /* Read EFUSE real map to shadow. */ + EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI, false); + } + } else { + /* autoload fail */ + /* pHalData->AutoloadFailFlag = true; */ + /* update to default value 0xFF */ + if (!is_boot_from_eeprom(padapter)) + EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI, false); + } + +#ifdef CONFIG_EFUSE_CONFIG_FILE + if (check_phy_efuse_tx_power_info_valid(padapter) == false) { + if (Hal_readPGDataFromConfigFile(padapter) != _SUCCESS) + RTW_ERR("invalid phy efuse and read from file fail, will use driver default!!\n"); + } +#endif +} + +void +Hal_EfuseParseIDCode88E( + PADAPTER padapter, + u8 *hwinfo +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + u16 EEPROMId; + + + /* Checl 0x8129 again for making sure autoload status!! */ + EEPROMId = le16_to_cpu(*((__le16 *)hwinfo)); + if (EEPROMId != RTL_EEPROM_ID) { + RTW_INFO("EEPROM ID(%#x) is invalid!!\n", EEPROMId); + pHalData->bautoload_fail_flag = true; + } else + pHalData->bautoload_fail_flag = false; + + RTW_INFO("EEPROM ID=0x%04x\n", EEPROMId); +} + +void Hal_ReadPowerSavingMode88E( + PADAPTER padapter, + u8 *hwinfo, + bool AutoLoadFail +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter); + u8 tmpvalue; + + if (AutoLoadFail) { + pwrctl->bHWPowerdown = false; + pwrctl->bSupportRemoteWakeup = false; + } else { + + /* hw power down mode selection , 0:rf-off / 1:power down */ + + if (padapter->registrypriv.hwpdn_mode == 2) + pwrctl->bHWPowerdown = (hwinfo[EEPROM_RF_FEATURE_OPTION_88E] & BIT4); + else + pwrctl->bHWPowerdown = padapter->registrypriv.hwpdn_mode; + + /* decide hw if support remote wakeup function */ + /* if hw supported, 8051 (SIE) will generate WeakUP signal( D+/D- toggle) when autoresume */ + pwrctl->bSupportRemoteWakeup = (hwinfo[EEPROM_USB_OPTIONAL_FUNCTION0] & BIT1) ? true : false; + + RTW_INFO("%s...bHWPwrPindetect(%x)-bHWPowerdown(%x) ,bSupportRemoteWakeup(%x)\n", __func__, + pwrctl->bHWPwrPindetect, pwrctl->bHWPowerdown, pwrctl->bSupportRemoteWakeup); + + RTW_INFO("### PS params=> power_mgnt(%x),usbss_enable(%x) ###\n", padapter->registrypriv.power_mgnt, padapter->registrypriv.usbss_enable); + + } + +} + +void +Hal_ReadTxPowerInfo88E( + PADAPTER padapter, + u8 *PROMContent, + bool AutoLoadFail +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + TxPowerInfo24G pwrInfo24G; + + hal_load_txpwr_info(padapter, &pwrInfo24G, NULL, PROMContent); + + /* 2010/10/19 MH Add Regulator recognize for EU. */ + if (!AutoLoadFail) { + struct registry_priv *registry_par = &padapter->registrypriv; + + if (PROMContent[EEPROM_RF_BOARD_OPTION_88E] == 0xFF) + pHalData->EEPROMRegulatory = (EEPROM_DEFAULT_BOARD_OPTION & 0x7); /* bit0~2 */ + else + pHalData->EEPROMRegulatory = (PROMContent[EEPROM_RF_BOARD_OPTION_88E] & 0x7); /* bit0~2 */ + + } else + pHalData->EEPROMRegulatory = 0; + RTW_INFO("EEPROMRegulatory = 0x%x\n", pHalData->EEPROMRegulatory); + +} + + +void +Hal_EfuseParseXtal_8188E( + PADAPTER pAdapter, + u8 *hwinfo, + bool AutoLoadFail +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + + if (!AutoLoadFail) { + pHalData->crystal_cap = hwinfo[EEPROM_XTAL_88E]; + if (pHalData->crystal_cap == 0xFF) + pHalData->crystal_cap = EEPROM_Default_CrystalCap_88E; + } else + pHalData->crystal_cap = EEPROM_Default_CrystalCap_88E; + RTW_INFO("crystal_cap: 0x%2x\n", pHalData->crystal_cap); +} + +void +Hal_ReadPAType_8188E( + PADAPTER Adapter, + u8 *PROMContent, + bool AutoloadFail +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u8 PA_LNAType_2G = 0; + + if (!AutoloadFail) { + if (GetRegAmplifierType2G(Adapter) == 0) { /* AUTO*/ + + /* PA & LNA Type */ + PA_LNAType_2G = LE_BITS_TO_1BYTE(&PROMContent[EEPROM_RFE_OPTION_8188E], 2, 2); /* 0xCA[3:2] */ + /* + ePA/eLNA sel.(ePA+eLNA=0x0, ePA+iLNA enable = 0x1, iPA+eLNA enable =0x2, iPA+iLNA=0x3) + */ + switch (PA_LNAType_2G) { + case 0: + pHalData->ExternalPA_2G = 1; + pHalData->ExternalLNA_2G = 1; + break; + case 1: + pHalData->ExternalPA_2G = 1; + pHalData->ExternalLNA_2G = 0; + break; + case 2: + pHalData->ExternalPA_2G = 0; + pHalData->ExternalLNA_2G = 1; + break; + case 3: + default: + pHalData->ExternalPA_2G = 0; + pHalData->ExternalLNA_2G = 0; + break; + } + } else { + pHalData->ExternalPA_2G = (GetRegAmplifierType2G(Adapter) & ODM_BOARD_EXT_PA) ? 1 : 0; + pHalData->ExternalLNA_2G = (GetRegAmplifierType2G(Adapter) & ODM_BOARD_EXT_LNA) ? 1 : 0; + } + } else { + pHalData->ExternalPA_2G = EEPROM_Default_PAType; + pHalData->external_pa_5g = EEPROM_Default_PAType; + pHalData->ExternalLNA_2G = EEPROM_Default_LNAType; + pHalData->external_lna_5g = EEPROM_Default_LNAType; + + if (GetRegAmplifierType2G(Adapter) == 0) { + /* AUTO*/ + pHalData->ExternalPA_2G = EEPROM_Default_PAType; + pHalData->ExternalLNA_2G = EEPROM_Default_LNAType; + } else { + pHalData->ExternalPA_2G = (GetRegAmplifierType2G(Adapter) & ODM_BOARD_EXT_PA) ? 1 : 0; + pHalData->ExternalLNA_2G = (GetRegAmplifierType2G(Adapter) & ODM_BOARD_EXT_LNA) ? 1 : 0; + } + } + RTW_INFO("pHalData->ExternalPA_2G = %d , pHalData->ExternalLNA_2G = %d\n", pHalData->ExternalPA_2G, pHalData->ExternalLNA_2G); +} + +void +Hal_ReadAmplifierType_8188E( + PADAPTER Adapter, + u8 * PROMContent, + bool AutoloadFail +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u8 GLNA_type = 0; + + if (!AutoloadFail) { + if (GetRegGLNAType(Adapter) == 0) /* AUTO */ + GLNA_type = LE_BITS_TO_1BYTE(&PROMContent[EEPROM_RFE_OPTION_8188E], 4, 3); /* 0xCA[6:4] */ + else + GLNA_type = GetRegGLNAType(Adapter) & 0x7; + } else { + if (GetRegGLNAType(Adapter) == 0) /* AUTO */ + GLNA_type = 0; + else + GLNA_type = GetRegGLNAType(Adapter) & 0x7; + } + /* + Ext-LNA Gain sel.(form 10dB to 24dB, 1table/2dB,ext: 000=10dB, 001=12dB...) + */ + switch (GLNA_type) { + case 0: + pHalData->TypeGLNA = 0x1; /* (10dB) */ + break; + case 2: + pHalData->TypeGLNA = 0x2; /* (14dB) */ + break; + default: + pHalData->TypeGLNA = 0x0; /* (others not support) */ + break; + } + RTW_INFO("pHalData->TypeGLNA is 0x%x\n", pHalData->TypeGLNA); +} + +void +Hal_ReadRFEType_8188E( + PADAPTER Adapter, + u8 * PROMContent, + bool AutoloadFail +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + /* Keep the same flow as 8192EU to be extensible */ + const u8 RFETypeMaxVal = 1, RFETypeMask = 0x1; + + if (!AutoloadFail) { + if (GetRegRFEType(Adapter) != 64) { + pHalData->rfe_type = GetRegRFEType(Adapter); + /* + Above 1, rfe_type is filled the default value. + */ + if (pHalData->rfe_type > RFETypeMaxVal) + pHalData->rfe_type = EEPROM_DEFAULT_RFE_OPTION_8188E; + + } else if ((0xFF == PROMContent[EEPROM_RFE_OPTION_8188E]) || + ((pHalData->ExternalPA_2G == 0) && (pHalData->ExternalLNA_2G == 0))) + pHalData->rfe_type = EEPROM_DEFAULT_RFE_OPTION_8188E; + else { + /* + type 0:0x00 for 88EE/ER_HP RFE control + */ + pHalData->rfe_type = PROMContent[EEPROM_RFE_OPTION_8188E] & RFETypeMask; /* 0xCA[1:0] */ + } + } else { + if (GetRegRFEType(Adapter) != 64) { + pHalData->rfe_type = GetRegRFEType(Adapter); + /* + Above 3, rfe_type is filled the default value. + */ + if (pHalData->rfe_type > RFETypeMaxVal) + pHalData->rfe_type = EEPROM_DEFAULT_RFE_OPTION_8188E; + + } else + pHalData->rfe_type = EEPROM_DEFAULT_RFE_OPTION_8188E; + + } + + RTW_INFO("pHalData->rfe_type is 0x%x\n", pHalData->rfe_type); +} + +void +Hal_EfuseParseBoardType88E( + PADAPTER pAdapter, + u8 *hwinfo, + bool AutoLoadFail +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + + if (!AutoLoadFail) { + pHalData->InterfaceSel = ((hwinfo[EEPROM_RF_BOARD_OPTION_88E] & 0xE0) >> 5); + if (hwinfo[EEPROM_RF_BOARD_OPTION_88E] == 0xFF) + pHalData->InterfaceSel = (EEPROM_DEFAULT_BOARD_OPTION & 0xE0) >> 5; + } else + pHalData->InterfaceSel = 0; + RTW_INFO("Board Type: 0x%2x\n", pHalData->InterfaceSel); +} + +void +Hal_EfuseParseEEPROMVer88E( + PADAPTER padapter, + u8 *hwinfo, + bool AutoLoadFail +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + if (!AutoLoadFail) { + pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_88E]; + if (pHalData->EEPROMVersion == 0xFF) + pHalData->EEPROMVersion = EEPROM_Default_Version; + } else + pHalData->EEPROMVersion = 1; +} + +void +rtl8188e_EfuseParseChnlPlan( + PADAPTER padapter, + u8 *hwinfo, + bool AutoLoadFail +) +{ + padapter->mlmepriv.ChannelPlan = hal_com_config_channel_plan( + padapter + , hwinfo ? &hwinfo[EEPROM_COUNTRY_CODE_88E] : NULL + , hwinfo ? hwinfo[EEPROM_ChannelPlan_88E] : 0xFF + , padapter->registrypriv.alpha2 + , padapter->registrypriv.channel_plan + , RTW_CHPLAN_WORLD_NULL + , AutoLoadFail + ); +} + +void +Hal_EfuseParseCustomerID88E( + PADAPTER padapter, + u8 *hwinfo, + bool AutoLoadFail +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + if (!AutoLoadFail) { + pHalData->EEPROMCustomerID = hwinfo[EEPROM_CustomID_88E]; + /* pHalData->EEPROMSubCustomerID = hwinfo[EEPROM_CustomID_88E]; */ + } else { + pHalData->EEPROMCustomerID = 0; + pHalData->EEPROMSubCustomerID = 0; + } + RTW_INFO("EEPROM Customer ID: 0x%2x\n", pHalData->EEPROMCustomerID); + /* RTW_INFO("EEPROM SubCustomer ID: 0x%02x\n", pHalData->EEPROMSubCustomerID); */ +} + + +void +Hal_ReadAntennaDiversity88E( + PADAPTER pAdapter, + u8 *PROMContent, + bool AutoLoadFail +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + struct registry_priv *registry_par = &pAdapter->registrypriv; + + if (!AutoLoadFail) { + /* Antenna Diversity setting. */ + if (registry_par->antdiv_cfg == 2) { /* 2:By EFUSE */ + pHalData->AntDivCfg = (PROMContent[EEPROM_RF_BOARD_OPTION_88E] & 0x18) >> 3; + if (PROMContent[EEPROM_RF_BOARD_OPTION_88E] == 0xFF) + pHalData->AntDivCfg = (EEPROM_DEFAULT_BOARD_OPTION & 0x18) >> 3; + } else { + pHalData->AntDivCfg = registry_par->antdiv_cfg ; /* 0:OFF , 1:ON, 2:By EFUSE */ + } + + if (registry_par->antdiv_type == 0) { /* If TRxAntDivType is AUTO in advanced setting, use EFUSE value instead. */ + pHalData->TRxAntDivType = PROMContent[EEPROM_RF_ANTENNA_OPT_88E]; + if (pHalData->TRxAntDivType == 0xFF) + pHalData->TRxAntDivType = CG_TRX_HW_ANTDIV; /* For 88EE, 1Tx and 1RxCG are fixed.(1Ant, Tx and RxCG are both on aux port) */ + } else + pHalData->TRxAntDivType = registry_par->antdiv_type ; + + if (pHalData->TRxAntDivType == CG_TRX_HW_ANTDIV || pHalData->TRxAntDivType == CGCS_RX_HW_ANTDIV) + pHalData->AntDivCfg = 1; /* 0xC1[3] is ignored. */ + } else + pHalData->AntDivCfg = 0; + + RTW_INFO("EEPROM : AntDivCfg = %x, TRxAntDivType = %x\n", pHalData->AntDivCfg, pHalData->TRxAntDivType); + + +} + +void +Hal_ReadThermalMeter_88E( + PADAPTER Adapter, + u8 *PROMContent, + bool AutoloadFail +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u8 tempval; + + /* */ + /* ThermalMeter from EEPROM */ + /* */ + if (!AutoloadFail) + pHalData->eeprom_thermal_meter = PROMContent[EEPROM_THERMAL_METER_88E]; + else + pHalData->eeprom_thermal_meter = EEPROM_Default_ThermalMeter_88E; + /* pHalData->eeprom_thermal_meter = (tempval&0x1f); */ /* [4:0] */ + + if (pHalData->eeprom_thermal_meter == 0xff || AutoloadFail) { + pHalData->odmpriv.rf_calibrate_info.is_apk_thermal_meter_ignore = true; + pHalData->eeprom_thermal_meter = EEPROM_Default_ThermalMeter_88E; + } + + /* pHalData->ThermalMeter[0] = pHalData->eeprom_thermal_meter; */ + RTW_INFO("ThermalMeter = 0x%x\n", pHalData->eeprom_thermal_meter); + +} + +#ifdef CONFIG_RF_POWER_TRIM +void Hal_ReadRFGainOffset( + PADAPTER Adapter, + u8 *PROMContent, + bool AutoloadFail) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u8 thermal_offset = 0; + /* */ + /* BB_RF Gain Offset from EEPROM */ + /* */ + + if (!AutoloadFail) { + pHalData->EEPROMRFGainOffset = PROMContent[EEPROM_RF_GAIN_OFFSET]; + + if ((pHalData->EEPROMRFGainOffset != 0xFF) && + (pHalData->EEPROMRFGainOffset & BIT4)) + efuse_OneByteRead(Adapter, EEPROM_RF_GAIN_VAL, &pHalData->EEPROMRFGainVal, false); + else { + pHalData->EEPROMRFGainOffset = 0; + pHalData->EEPROMRFGainVal = 0; + } + + RTW_INFO("pHalData->EEPROMRFGainVal=%x\n", pHalData->EEPROMRFGainVal); + } else { + efuse_OneByteRead(Adapter, EEPROM_RF_GAIN_VAL, &pHalData->EEPROMRFGainVal, false); + + if (pHalData->EEPROMRFGainVal != 0xFF) + pHalData->EEPROMRFGainOffset = BIT4; + else + pHalData->EEPROMRFGainOffset = 0; + RTW_INFO("else AutoloadFail =%x,\n", AutoloadFail); + } + + if (Adapter->registrypriv.RegPwrTrimEnable == 1) { + efuse_OneByteRead(Adapter, EEPROM_RF_GAIN_VAL, &pHalData->EEPROMRFGainVal, false); + RTW_INFO("pHalData->EEPROMRFGainVal=%x\n", pHalData->EEPROMRFGainVal); + + } + /* */ + /* BB_RF Thermal Offset from EEPROM */ + /* */ + if (((pHalData->EEPROMRFGainOffset != 0xFF) && (pHalData->EEPROMRFGainOffset & BIT4)) || (Adapter->registrypriv.RegPwrTrimEnable == 1)) { + + efuse_OneByteRead(Adapter, EEPROM_THERMAL_OFFSET, &thermal_offset, false); + if (thermal_offset != 0xFF) { + if (thermal_offset & BIT0) + pHalData->eeprom_thermal_meter += ((thermal_offset >> 1) & 0x0F); + else + pHalData->eeprom_thermal_meter -= ((thermal_offset >> 1) & 0x0F); + + RTW_INFO("%s =>thermal_offset:0x%02x pHalData->eeprom_thermal_meter=0x%02x\n", __func__ , thermal_offset, pHalData->eeprom_thermal_meter); + } + } + + RTW_INFO("%s => EEPRORFGainOffset = 0x%02x,EEPROMRFGainVal=0x%02x,thermal_offset:0x%02x\n", + __func__, pHalData->EEPROMRFGainOffset, pHalData->EEPROMRFGainVal, thermal_offset); + +} + +#endif /*CONFIG_RF_POWER_TRIM*/ + +bool HalDetectPwrDownMode88E(PADAPTER Adapter) +{ + u8 tmpvalue = 0; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(Adapter); + + EFUSE_ShadowRead(Adapter, 1, EEPROM_RF_FEATURE_OPTION_88E, (u32 *)&tmpvalue); + + /* 2010/08/25 MH INF priority > PDN Efuse value. */ + if (tmpvalue & BIT(4) && pwrctrlpriv->reg_pdnmode) + pHalData->pwrdown = true; + else + pHalData->pwrdown = false; + + RTW_INFO("HalDetectPwrDownMode(): PDN=%d\n", pHalData->pwrdown); + + return pHalData->pwrdown; +} /* HalDetectPwrDownMode */ + +#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) +void Hal_DetectWoWMode(PADAPTER pAdapter) +{ + adapter_to_pwrctl(pAdapter)->bSupportRemoteWakeup = true; +} +#endif + +/* ************************************************************************************ + * + * 20100209 Joseph: + * This function is used only for 92C to set REG_BCN_CTRL(0x550) register. + * We just reserve the value of the register in variable pHalData->RegBcnCtrlVal and then operate + * the value of the register via atomic operation. + * This prevents from race condition when setting this register. + * The value of pHalData->RegBcnCtrlVal is initialized in HwConfigureRTL8192CE() function. + * */ +void SetBcnCtrlReg( + PADAPTER padapter, + u8 SetBits, + u8 ClearBits) +{ + PHAL_DATA_TYPE pHalData; + + + pHalData = GET_HAL_DATA(padapter); + + pHalData->RegBcnCtrlVal |= SetBits; + pHalData->RegBcnCtrlVal &= ~ClearBits; + + rtw_write8(padapter, REG_BCN_CTRL, (u8)pHalData->RegBcnCtrlVal); +} + +void _InitTransferPageSize(PADAPTER padapter) +{ + /* Tx page size is always 128. */ + + u8 value8; + value8 = _PSRX(PBP_128) | _PSTX(PBP_128); + rtw_write8(padapter, REG_PBP, value8); +} + + +static void hw_var_set_monitor(PADAPTER Adapter, u8 variable, u8 *val) +{ + u32 value_rcr, rcr_bits; + u16 value_rxfltmap2; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv); + + if (*((u8 *)val) == _HW_STATE_MONITOR_) { + + /* Receive all type */ + rcr_bits = RCR_AAP | RCR_APM | RCR_AM | RCR_AB | RCR_APWRMGT | RCR_ADF | RCR_ACF | RCR_AMF | RCR_APP_PHYST_RXFF; + + /* Append FCS */ + rcr_bits |= RCR_APPFCS; + + /* Receive all data frames */ + value_rxfltmap2 = 0xFFFF; + + value_rcr = rcr_bits; + rtw_write32(Adapter, REG_RCR, value_rcr); + + rtw_write16(Adapter, REG_RXFLTMAP2, value_rxfltmap2); + } else { + /* do nothing */ + } +} + +static void hw_var_set_opmode(PADAPTER Adapter, u8 variable, u8 *val) +{ + u8 val8; + u8 mode = *((u8 *)val); + static u8 isMonitor = false; + + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + if (isMonitor == true) { + /* reset RCR */ + rtw_write32(Adapter, REG_RCR, pHalData->ReceiveConfig); + isMonitor = false; + } + + RTW_INFO(ADPT_FMT "- Port-%d set opmode = %d\n", ADPT_ARG(Adapter), + get_hw_port(Adapter), mode); + + if (mode == _HW_STATE_MONITOR_) { + isMonitor = true; + /* set net_type */ + Set_MSR(Adapter, _HW_STATE_NOLINK_); + + hw_var_set_monitor(Adapter, variable, val); + return; + } + + rtw_hal_set_hwreg(Adapter, HW_VAR_MAC_ADDR, adapter_mac_addr(Adapter)); /* set mac addr to mac register */ + +#ifdef CONFIG_CONCURRENT_MODE + if (Adapter->hw_port == HW_PORT1) { + /* disable Port1 TSF update */ + rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1) | BIT(4)); + + /* set net_type */ + Set_MSR(Adapter, mode); + + if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) { + if (!rtw_mi_check_status(Adapter, MI_AP_MODE)) { +#ifdef CONFIG_INTERRUPT_BASED_TXBCN +#ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + rtw_write8(Adapter, REG_DRVERLYINT, 0x05);/* restore early int time to 5ms */ + + UpdateInterruptMask8188EU(Adapter, true, 0, IMR_BCNDMAINT0_88E); + +#endif /* CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT */ + +#ifdef CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR + UpdateInterruptMask8188EU(Adapter, true , 0, (IMR_TBDER_88E | IMR_TBDOK_88E)); + +#endif/* CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR */ +#endif /* CONFIG_INTERRUPT_BASED_TXBCN */ + + StopTxBeacon(Adapter); + } + + rtw_write8(Adapter, REG_BCN_CTRL_1, 0x11); /* disable atim wnd and disable beacon function */ + /* rtw_write8(Adapter,REG_BCN_CTRL_1, 0x18); */ + } else if ((mode == _HW_STATE_ADHOC_) /*|| (mode == _HW_STATE_AP_)*/) { + /* Beacon is polled to TXBUF */ + rtw_write32(Adapter, REG_CR, rtw_read32(Adapter, REG_CR) | BIT(8)); + + ResumeTxBeacon(Adapter); + rtw_write8(Adapter, REG_BCN_CTRL_1, 0x1a); + /* BIT4 - If set 0, hw will clr bcnq when tx becon ok/fail or port 1 */ + rtw_write8(Adapter, REG_MBID_NUM, rtw_read8(Adapter, REG_MBID_NUM) | BIT(3) | BIT(4)); + } else if (mode == _HW_STATE_AP_) { +#ifdef CONFIG_INTERRUPT_BASED_TXBCN +#ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + UpdateInterruptMask8188EU(Adapter, true , IMR_BCNDMAINT0_88E, 0); +#endif/* CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT */ + +#ifdef CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR + UpdateInterruptMask8188EU(Adapter, true , (IMR_TBDER_88E | IMR_TBDOK_88E), 0); +#endif/* CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR */ + +#endif /* CONFIG_INTERRUPT_BASED_TXBCN */ + + ResumeTxBeacon(Adapter); + + rtw_write8(Adapter, REG_BCN_CTRL_1, 0x12); + + /* Beacon is polled to TXBUF */ + rtw_write32(Adapter, REG_CR, rtw_read32(Adapter, REG_CR) | BIT(8)); + + /* Set RCR */ + /* rtw_write32(padapter, REG_RCR, 0x70002a8e); */ /* CBSSID_DATA must set to 0 */ + if (Adapter->registrypriv.wifi_spec) + /* for 11n Logo 4.2.31/4.2.32, disable BSSID BCN check for AP mode */ + rtw_write32(Adapter, REG_RCR, (0x7000208e & ~(RCR_CBSSID_BCN))); + else + rtw_write32(Adapter, REG_RCR, 0x7000208e);/* CBSSID_DATA must set to 0,Reject ICV_ERROR packets */ + + /* enable to rx data frame */ + rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); + /* enable to rx ps-poll */ + rtw_write16(Adapter, REG_RXFLTMAP1, 0x0400); + + /* Beacon Control related register for first time */ + rtw_write8(Adapter, REG_BCNDMATIM, 0x02); /* 2ms */ + rtw_write8(Adapter, REG_DRVERLYINT, 0x05);/* 5ms */ + /* rtw_write8(Adapter, REG_BCN_MAX_ERR, 0xFF); */ + rtw_write8(Adapter, REG_ATIMWND_1, 0x0c); /* 13ms for port1 */ + rtw_write16(Adapter, REG_BCNTCFG, 0x00); + + /* TBTT setup time:128 us */ + rtw_write8(Adapter, REG_TBTT_PROHIBIT, 0x04); + + /*TBTT hold time :4ms 0x540[19:8]*/ + rtw_write8(Adapter, REG_TBTT_PROHIBIT + 1, + TBTT_PROBIHIT_HOLD_TIME & 0xFF); + rtw_write8(Adapter, REG_TBTT_PROHIBIT + 2, + (rtw_read8(Adapter, REG_TBTT_PROHIBIT + 2) & 0xF0) | (TBTT_PROBIHIT_HOLD_TIME >> 8)); + + rtw_write16(Adapter, REG_TSFTR_SYN_OFFSET, 0x7fff);/* +32767 (~32ms) */ + + /* reset TSF2 */ + rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(1)); + + + /* BIT4 - If set 0, hw will clr bcnq when tx becon ok/fail or port 1 */ + rtw_write8(Adapter, REG_MBID_NUM, rtw_read8(Adapter, REG_MBID_NUM) | BIT(3) | BIT(4)); + /* enable BCN1 Function for if2 */ + /* don't enable update TSF1 for if2 (due to TSF update when beacon/probe rsp are received) */ + rtw_write8(Adapter, REG_BCN_CTRL_1, (DIS_TSF_UDT0_NORMAL_CHIP | EN_BCN_FUNCTION | EN_TXBCN_RPT | BIT(1))); + + if (!rtw_mi_buddy_check_fwstate(Adapter, WIFI_FW_ASSOC_SUCCESS)) + rtw_write8(Adapter, REG_BCN_CTRL, + rtw_read8(Adapter, REG_BCN_CTRL) & ~EN_BCN_FUNCTION); + + /* BCN1 TSF will sync to BCN0 TSF with offset(0x518) if if1_sta linked */ + /* rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1)|BIT(5)); */ + /* rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(3)); */ + + /* dis BCN0 ATIM WND if if1 is station */ + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL) | BIT(0)); + +#ifdef CONFIG_TSF_RESET_OFFLOAD + /* Reset TSF for STA+AP concurrent mode */ + if (rtw_mi_buddy_check_fwstate(Adapter, (WIFI_STATION_STATE | WIFI_ASOC_STATE))) { + if (reset_tsf(Adapter, HW_PORT1) == false) + RTW_INFO("ERROR! %s()-%d: Reset port1 TSF fail\n", + __func__, __LINE__); + } +#endif /* CONFIG_TSF_RESET_OFFLOAD */ + } + } else /* (Adapter->hw_port == HW_PORT1)*/ +#endif /* CONFIG_CONCURRENT_MODE */ + { +#ifdef CONFIG_MI_WITH_MBSSID_CAM /*For Port0 - MBSS CAM*/ + hw_var_set_opmode_mbid(Adapter, mode); +#else + /* disable Port0 TSF update */ + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL) | BIT(4)); + + /* set net_type */ + Set_MSR(Adapter, mode); + + if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) { +#ifdef CONFIG_CONCURRENT_MODE + if (!rtw_mi_check_status(Adapter, MI_AP_MODE)) +#endif /*CONFIG_CONCURRENT_MODE*/ + { +#ifdef CONFIG_INTERRUPT_BASED_TXBCN +#ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + rtw_write8(Adapter, REG_DRVERLYINT, 0x05);/* restore early int time to 5ms */ + UpdateInterruptMask8188EU(Adapter, true, 0, IMR_BCNDMAINT0_88E); +#endif/* CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT */ + +#ifdef CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR + UpdateInterruptMask8188EU(Adapter, true , 0, (IMR_TBDER_88E | IMR_TBDOK_88E)); +#endif /* CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR */ + +#endif /* CONFIG_INTERRUPT_BASED_TXBCN */ + StopTxBeacon(Adapter); + } + + rtw_write8(Adapter, REG_BCN_CTRL, 0x19); /* disable atim wnd */ + /* rtw_write8(Adapter,REG_BCN_CTRL, 0x18); */ + } else if ((mode == _HW_STATE_ADHOC_) /*|| (mode == _HW_STATE_AP_)*/) { + /* Beacon is polled to TXBUF */ + rtw_write16(Adapter, REG_CR, rtw_read16(Adapter, REG_CR) | BIT(8)); + + ResumeTxBeacon(Adapter); + rtw_write8(Adapter, REG_BCN_CTRL, 0x1a); + /* BIT3 - If set 0, hw will clr bcnq when tx becon ok/fail or port 0 */ + rtw_write8(Adapter, REG_MBID_NUM, rtw_read8(Adapter, REG_MBID_NUM) | BIT(3) | BIT(4)); + } else if (mode == _HW_STATE_AP_) { +#ifdef CONFIG_INTERRUPT_BASED_TXBCN +#ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + UpdateInterruptMask8188EU(Adapter, true , IMR_BCNDMAINT0_88E, 0); +#endif/* CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT */ + +#ifdef CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR + UpdateInterruptMask8188EU(Adapter, true , (IMR_TBDER_88E | IMR_TBDOK_88E), 0); +#endif/* CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR */ + +#endif /* CONFIG_INTERRUPT_BASED_TXBCN */ + + ResumeTxBeacon(Adapter); + + rtw_write8(Adapter, REG_BCN_CTRL, 0x12); + + /* Beacon is polled to TXBUF */ + rtw_write32(Adapter, REG_CR, rtw_read32(Adapter, REG_CR) | BIT(8)); + + /* Set RCR */ + /* rtw_write32(padapter, REG_RCR, 0x70002a8e); */ /* CBSSID_DATA must set to 0 */ + if (Adapter->registrypriv.wifi_spec) + /* for 11n Logo 4.2.31/4.2.32, disable BSSID BCN check for AP mode */ + rtw_write32(Adapter, REG_RCR, (0x7000208e & ~(RCR_CBSSID_BCN))); + else + rtw_write32(Adapter, REG_RCR, 0x7000208e);/* CBSSID_DATA must set to 0,reject ICV_ERR packet */ + /* enable to rx data frame */ + rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); + /* enable to rx ps-poll */ + rtw_write16(Adapter, REG_RXFLTMAP1, 0x0400); + + /* Beacon Control related register for first time */ + rtw_write8(Adapter, REG_BCNDMATIM, 0x02); /* 2ms */ + rtw_write8(Adapter, REG_DRVERLYINT, 0x05);/* 5ms */ + /* rtw_write8(Adapter, REG_BCN_MAX_ERR, 0xFF); */ + rtw_write8(Adapter, REG_ATIMWND, 0x0c); /* 13ms */ + rtw_write16(Adapter, REG_BCNTCFG, 0x00); + + /* TBTT setup time:128 us */ + rtw_write8(Adapter, REG_TBTT_PROHIBIT, 0x04); + + /*TBTT hold time :4ms 0x540[19:8]*/ + rtw_write8(Adapter, REG_TBTT_PROHIBIT + 1, + TBTT_PROBIHIT_HOLD_TIME & 0xFF); + rtw_write8(Adapter, REG_TBTT_PROHIBIT + 2, + (rtw_read8(Adapter, REG_TBTT_PROHIBIT + 2) & 0xF0) | (TBTT_PROBIHIT_HOLD_TIME >> 8)); + + rtw_write16(Adapter, REG_TSFTR_SYN_OFFSET, 0x7fff);/* +32767 (~32ms) */ + + /* reset TSF */ + rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(0)); + + /* BIT3 - If set 0, hw will clr bcnq when tx becon ok/fail or port 0 */ + rtw_write8(Adapter, REG_MBID_NUM, rtw_read8(Adapter, REG_MBID_NUM) | BIT(3) | BIT(4)); + + /* enable BCN0 Function for if1 */ + /* don't enable update TSF0 for if1 (due to TSF update when beacon/probe rsp are received) */ +#if defined(CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR) + rtw_write8(Adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP | EN_BCN_FUNCTION | EN_TXBCN_RPT | BIT(1))); +#else + rtw_write8(Adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP | EN_BCN_FUNCTION | BIT(1))); +#endif + +#ifdef CONFIG_CONCURRENT_MODE + if (!rtw_mi_buddy_check_fwstate(Adapter, WIFI_FW_ASSOC_SUCCESS)) + rtw_write8(Adapter, REG_BCN_CTRL_1, + rtw_read8(Adapter, REG_BCN_CTRL_1) & ~EN_BCN_FUNCTION); +#endif + + /* dis BCN1 ATIM WND if if2 is station */ + rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1) | BIT(0)); +#ifdef CONFIG_TSF_RESET_OFFLOAD + /* Reset TSF for STA+AP concurrent mode */ + if (rtw_mi_buddy_check_fwstate(Adapter, (WIFI_STATION_STATE | WIFI_ASOC_STATE))) { + if (reset_tsf(Adapter, HW_PORT0) == false) + RTW_INFO("ERROR! %s()-%d: Reset port0 TSF fail\n", + __func__, __LINE__); + } +#endif /* CONFIG_TSF_RESET_OFFLOAD */ + } +#endif + } +} + +static void hw_var_set_bcn_func(PADAPTER Adapter, u8 variable, u8 *val) +{ + u32 bcn_ctrl_reg; + +#ifdef CONFIG_CONCURRENT_MODE + if (Adapter->hw_port == HW_PORT1) + bcn_ctrl_reg = REG_BCN_CTRL_1; + else +#endif + bcn_ctrl_reg = REG_BCN_CTRL; + + + if (*((u8 *)val)) + rtw_write8(Adapter, bcn_ctrl_reg, (EN_BCN_FUNCTION | EN_TXBCN_RPT)); + else + rtw_write8(Adapter, bcn_ctrl_reg, rtw_read8(Adapter, bcn_ctrl_reg) & (~(EN_BCN_FUNCTION | EN_TXBCN_RPT))); + + +} + +static void hw_var_set_correct_tsf(PADAPTER Adapter, u8 variable, u8 *val) +{ +#ifdef CONFIG_MI_WITH_MBSSID_CAM + /*do nothing*/ +#else + u64 tsf; + struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) { + /* pHalData->RegTxPause |= STOP_BCNQ;BIT(6) */ + /* rtw_write8(Adapter, REG_TXPAUSE, (rtw_read8(Adapter, REG_TXPAUSE)|BIT(6))); */ + StopTxBeacon(Adapter); + } + + /*tsf = pmlmeext->TSFValue - ((u32)pmlmeext->TSFValue % (pmlmeinfo->bcn_interval*1024)) -1024; //us */ + tsf = pmlmeext->TSFValue - rtw_modular64(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval * 1024)) - 1024; /*us*/ + + rtw_hal_correct_tsf(Adapter, Adapter->hw_port, tsf); + +#ifdef CONFIG_CONCURRENT_MODE + /* Update buddy port's TSF if it is SoftAP for beacon TX issue!*/ + if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE + && rtw_mi_check_status(Adapter, MI_AP_MODE)) { + + struct dvobj_priv *dvobj = adapter_to_dvobj(Adapter); + int i; + _adapter *iface; + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (!iface) + continue; + if (iface == Adapter) + continue; + + if (check_fwstate(&iface->mlmepriv, WIFI_AP_STATE) == true + && check_fwstate(&iface->mlmepriv, WIFI_ASOC_STATE) == true + ) { + rtw_hal_correct_tsf(iface, iface->hw_port, tsf); +#ifdef CONFIG_TSF_RESET_OFFLOAD + if (reset_tsf(iface, iface->hw_port) == false) + RTW_INFO("%s-[ERROR] "ADPT_FMT" Reset port%d TSF fail\n", __func__, ADPT_ARG(iface), iface->hw_port); +#endif /* CONFIG_TSF_RESET_OFFLOAD*/ + } + } + } +#endif/*CONFIG_CONCURRENT_MODE*/ + if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) { + /* pHalData->RegTxPause &= (~STOP_BCNQ); */ + /* rtw_write8(Adapter, REG_TXPAUSE, (rtw_read8(Adapter, REG_TXPAUSE)&(~BIT(6)))); */ + ResumeTxBeacon(Adapter); + } +#endif /*CONFIG_MI_WITH_MBSSID_CAM*/ +} + +static void hw_var_set_mlme_disconnect(PADAPTER Adapter, u8 variable, u8 *val) +{ + /*Set RCR to not to receive data frame when NO LINK state + rtw_write32(Adapter, REG_RCR, rtw_read32(padapter, REG_RCR) & ~RCR_ADF); + reject all data frames */ +#ifdef CONFIG_CONCURRENT_MODE + if (rtw_mi_check_status(Adapter, MI_LINKED) == false) +#endif + rtw_write16(Adapter, REG_RXFLTMAP2, 0x00); + +#ifdef CONFIG_CONCURRENT_MODE + if (Adapter->hw_port == HW_PORT1) { + /*reset TSF1*/ + rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(1)); + + /*disable update TSF1*/ + rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1) | DIS_TSF_UDT); + + /* disable Port1's beacon function*/ + rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1) & (~BIT(3))); + } else +#endif + { + /*reset TSF*/ + rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(0)); + + /*disable update TSF*/ + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL) | DIS_TSF_UDT); + } + +} + + +static void hw_var_set_mlme_sitesurvey(PADAPTER Adapter, u8 variable, u8 *val) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(Adapter); + u32 value_rcr, rcr_clear_bit; + u16 value_rxfltmap2; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + int i; + _adapter *iface; + +#ifdef DBG_IFACE_STATUS + DBG_IFACE_STATUS_DUMP(Adapter); +#endif + + +#ifdef CONFIG_FIND_BEST_CHANNEL + + rcr_clear_bit = (RCR_CBSSID_BCN | RCR_CBSSID_DATA); + + /* Receive all data frames */ + value_rxfltmap2 = 0xFFFF; + +#else /* CONFIG_FIND_BEST_CHANNEL */ + + rcr_clear_bit = RCR_CBSSID_BCN; + + /* config RCR to receive different BSSID & not to receive data frame */ + value_rxfltmap2 = 0; + +#endif /* CONFIG_FIND_BEST_CHANNEL */ + + if (rtw_mi_check_fwstate(Adapter, WIFI_AP_STATE)) + rcr_clear_bit = RCR_CBSSID_BCN; + +#ifdef CONFIG_TDLS + /* TDLS will clear RCR_CBSSID_DATA bit for connection.*/ + else if (Adapter->tdlsinfo.link_established == true) + rcr_clear_bit = RCR_CBSSID_BCN; +#endif /*CONFIG_TDLS*/ + + value_rcr = rtw_read32(Adapter, REG_RCR); + + if (*((u8 *)val)) {/*under sitesurvey*/ + /* + * 1. configure REG_RXFLTMAP2 + * 2. disable TSF update & buddy TSF update to avoid updating wrong TSF due to clear RCR_CBSSID_BCN + * 3. config RCR to receive different BSSID BCN or probe rsp + */ + + rtw_write16(Adapter, REG_RXFLTMAP2, value_rxfltmap2); + +#ifdef CONFIG_MI_WITH_MBSSID_CAM + /*do nothing~~*/ +#else + + /* disable update TSF */ + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (!iface) + continue; + + if (rtw_linked_check(iface) && + check_fwstate(&(iface->mlmepriv), WIFI_AP_STATE) != true) { + if (iface->hw_port == HW_PORT1) + rtw_write8(iface, REG_BCN_CTRL_1, rtw_read8(iface, REG_BCN_CTRL_1) | DIS_TSF_UDT); + else + rtw_write8(iface, REG_BCN_CTRL, rtw_read8(iface, REG_BCN_CTRL) | DIS_TSF_UDT); + + iface->mlmeextpriv.en_hw_update_tsf = false; + } + + } +#endif/*CONFIG_MI_WITH_MBSSID_CAM*/ + + value_rcr &= ~(rcr_clear_bit); + rtw_write32(Adapter, REG_RCR, value_rcr); + + /* Save orignal RRSR setting.*/ + pHalData->RegRRSR = rtw_read16(Adapter, REG_RRSR); + + if (rtw_mi_check_status(Adapter, MI_AP_MODE)) + StopTxBeacon(Adapter); + } else {/*sitesurvey done*/ + /* + * 1. enable rx data frame + * 2. config RCR not to receive different BSSID BCN or probe rsp + * 3. doesn't enable TSF update & buddy TSF right now to avoid HW conflict + * so, we enable TSF update when rx first BCN after sitesurvey done + */ + + if (rtw_mi_check_fwstate(Adapter, _FW_LINKED | WIFI_AP_STATE)) + rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);/*enable to rx data frame*/ + +#ifdef CONFIG_MI_WITH_MBSSID_CAM + value_rcr &= ~(RCR_CBSSID_BCN | RCR_CBSSID_DATA); +#else + value_rcr |= rcr_clear_bit; +#endif + /* for 11n Logo 4.2.31/4.2.32, disable BSSID BCN check for AP mode */ + if (Adapter->registrypriv.wifi_spec && MLME_IS_AP(Adapter)) + value_rcr &= ~(RCR_CBSSID_BCN); + + rtw_write32(Adapter, REG_RCR, value_rcr); + +#ifdef CONFIG_MI_WITH_MBSSID_CAM + /*if ((rtw_mi_get_assoced_sta_num(Adapter) == 1) && (!rtw_mi_check_status(Adapter, MI_AP_MODE))) + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)&(~DIS_TSF_UDT));*/ +#else + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (!iface) + continue; + if (rtw_linked_check(iface) && + check_fwstate(&(iface->mlmepriv), WIFI_AP_STATE) != true) { + /* enable HW TSF update when recive beacon*/ + /*if (iface->hw_port == HW_PORT1) + rtw_write8(iface, REG_BCN_CTRL_1, rtw_read8(iface, REG_BCN_CTRL_1)&(~(DIS_TSF_UDT))); + else + rtw_write8(iface, REG_BCN_CTRL, rtw_read8(iface, REG_BCN_CTRL)&(~(DIS_TSF_UDT))); + */ + iface->mlmeextpriv.en_hw_update_tsf = true; + } + } +#endif + + /* Restore orignal RRSR setting. */ + rtw_write16(Adapter, REG_RRSR, pHalData->RegRRSR); + + if (rtw_mi_get_ap_num(Adapter)) { + ResumeTxBeacon(Adapter); + rtw_mi_tx_beacon_hdl(Adapter); + } + } +} + +static void hw_var_set_mlme_join(PADAPTER Adapter, u8 variable, u8 *val) +{ +#ifdef CONFIG_CONCURRENT_MODE + u8 RetryLimit = 0x30; + u8 type = *((u8 *)val); + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; + + if (type == 0) { /* prepare to join */ + if (rtw_mi_check_status(Adapter, MI_AP_MODE)) + StopTxBeacon(Adapter); + + /*enable to rx data frame.Accept all data frame*/ + /*rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR)|RCR_ADF);*/ + rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); +#ifdef CONFIG_MI_WITH_MBSSID_CAM + /* + if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && (rtw_mi_get_assoced_sta_num(Adapter) == 1)) + rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR)|RCR_CBSSID_DATA|RCR_CBSSID_BCN); + else if ((rtw_mi_get_ap_num(Adapter) == 1) && (rtw_mi_get_assoced_sta_num(Adapter) == 1)) + rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN); + else*/ + rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR) & (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN))); +#else + if (rtw_mi_check_status(Adapter, MI_AP_MODE)) + rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR) | RCR_CBSSID_BCN); + else + rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN); +#endif + if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) + RetryLimit = (pHalData->CustomerID == RT_CID_CCX) ? 7 : 48; + else /* Ad-hoc Mode */ + RetryLimit = 0x7; + } else if (type == 1) { /* joinbss_event call back when join res < 0 */ + if (rtw_mi_check_status(Adapter, MI_LINKED) == false) + rtw_write16(Adapter, REG_RXFLTMAP2, 0x00); + + if (rtw_mi_check_status(Adapter, MI_AP_MODE)) { + ResumeTxBeacon(Adapter); + + /* reset TSF 1/2 after ResumeTxBeacon */ + rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(1) | BIT(0)); + + } + } else if (type == 2) { /* sta add event call back */ +#ifdef CONFIG_MI_WITH_MBSSID_CAM + /*if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && (rtw_mi_get_assoced_sta_num(Adapter) == 1)) + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL)&(~DIS_TSF_UDT));*/ +#else + /* enable update TSF */ + if (Adapter->hw_port == HW_PORT1) + rtw_write8(Adapter, REG_BCN_CTRL_1, rtw_read8(Adapter, REG_BCN_CTRL_1) & (~DIS_TSF_UDT)); + else + rtw_write8(Adapter, REG_BCN_CTRL, rtw_read8(Adapter, REG_BCN_CTRL) & (~DIS_TSF_UDT)); + +#endif + if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) { + /* fixed beacon issue for 8191su........... */ + rtw_write8(Adapter, 0x542 , 0x02); + RetryLimit = 0x7; + } + + + if (rtw_mi_check_status(Adapter, MI_AP_MODE)) { + ResumeTxBeacon(Adapter); + + /* reset TSF 1/2 after ResumeTxBeacon */ + rtw_write8(Adapter, REG_DUAL_TSF_RST, BIT(1) | BIT(0)); + } + + } + + rtw_write16(Adapter, REG_RL, RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << RETRY_LIMIT_LONG_SHIFT); + +#endif +} + + + +void SetHwReg8188E(_adapter *adapter, u8 variable, u8 *val) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter); + struct PHY_DM_STRUCT *podmpriv = &pHalData->odmpriv; + + switch (variable) { + + case HW_VAR_SET_OPMODE: + hw_var_set_opmode(adapter, variable, val); + break; + case HW_VAR_BASIC_RATE: { + struct mlme_ext_info *mlmext_info = &adapter->mlmeextpriv.mlmext_info; + u16 input_b = 0, masked = 0, ioted = 0, BrateCfg = 0; + u16 rrsr_2g_force_mask = RRSR_CCK_RATES; + u16 rrsr_2g_allow_mask = (RRSR_24M | RRSR_12M | RRSR_6M | RRSR_CCK_RATES); + + HalSetBrateCfg(adapter, val, &BrateCfg); + input_b = BrateCfg; + + /* apply force and allow mask */ + BrateCfg |= rrsr_2g_force_mask; + BrateCfg &= rrsr_2g_allow_mask; + masked = BrateCfg; + + /* IOT consideration */ + if (mlmext_info->assoc_AP_vendor == HT_IOT_PEER_CISCO) { + /* if peer is cisco and didn't use ofdm rate, we enable 6M ack */ + if ((BrateCfg & (RRSR_24M | RRSR_12M | RRSR_6M)) == 0) + BrateCfg |= RRSR_6M; + } + ioted = BrateCfg; + + pHalData->BasicRateSet = BrateCfg; + + RTW_INFO("HW_VAR_BASIC_RATE: %#x->%#x->%#x\n", input_b, masked, ioted); + + /* Set RRSR rate table. */ + rtw_write16(adapter, REG_RRSR, BrateCfg); + rtw_write8(adapter, REG_RRSR + 2, rtw_read8(adapter, REG_RRSR + 2) & 0xf0); + + rtw_hal_set_hwreg(adapter, HW_VAR_INIT_RTS_RATE, (u8 *)&BrateCfg); + } + break; + case HW_VAR_TXPAUSE: + rtw_write8(adapter, REG_TXPAUSE, *((u8 *)val)); + break; + case HW_VAR_BCN_FUNC: + hw_var_set_bcn_func(adapter, variable, val); + break; + + case HW_VAR_CORRECT_TSF: + hw_var_set_correct_tsf(adapter, variable, val); + break; + + case HW_VAR_CHECK_BSSID: + if (*((u8 *)val)) + rtw_write32(adapter, REG_RCR, rtw_read32(adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN); + else { + u32 val32; + + val32 = rtw_read32(adapter, REG_RCR); + + val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); + + rtw_write32(adapter, REG_RCR, val32); + } + break; + + case HW_VAR_MLME_DISCONNECT: + hw_var_set_mlme_disconnect(adapter, variable, val); + break; + + case HW_VAR_MLME_SITESURVEY: + hw_var_set_mlme_sitesurvey(adapter, variable, val); + break; + + case HW_VAR_MLME_JOIN: +#ifdef CONFIG_CONCURRENT_MODE + hw_var_set_mlme_join(adapter, variable, val); +#else + { + u8 RetryLimit = 0x30; + u8 type = *((u8 *)val); + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + + if (type == 0) { /* prepare to join */ + /* enable to rx data frame.Accept all data frame */ + /* rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR)|RCR_ADF); */ + rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF); + + if (adapter->in_cta_test) { + u32 v = rtw_read32(adapter, REG_RCR); + v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); /* | RCR_ADF */ + rtw_write32(adapter, REG_RCR, v); + } else + rtw_write32(adapter, REG_RCR, rtw_read32(adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN); + + if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) + RetryLimit = (pHalData->CustomerID == RT_CID_CCX) ? 7 : 48; + else /* Ad-hoc Mode */ + RetryLimit = 0x7; + } else if (type == 1) /* joinbss_event call back when join res < 0 */ + rtw_write16(adapter, REG_RXFLTMAP2, 0x00); + else if (type == 2) { /* sta add event call back */ + /* enable update TSF */ + rtw_write8(adapter, REG_BCN_CTRL, rtw_read8(adapter, REG_BCN_CTRL) & (~BIT(4))); + + if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) + RetryLimit = 0x7; + } + + rtw_write16(adapter, REG_RL, RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << RETRY_LIMIT_LONG_SHIFT); + } +#endif + break; + + case HW_VAR_ON_RCR_AM: + rtw_write32(adapter, REG_RCR, rtw_read32(adapter, REG_RCR) | RCR_AM); + RTW_INFO("%s, %d, RCR= %x\n", __func__, __LINE__, rtw_read32(adapter, REG_RCR)); + break; + case HW_VAR_OFF_RCR_AM: + rtw_write32(adapter, REG_RCR, rtw_read32(adapter, REG_RCR) & (~RCR_AM)); + RTW_INFO("%s, %d, RCR= %x\n", __func__, __LINE__, rtw_read32(adapter, REG_RCR)); + break; + case HW_VAR_BEACON_INTERVAL: + rtw_write16(adapter, REG_BCN_INTERVAL, *((u16 *)val)); +#ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + { + struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + u16 bcn_interval = *((u16 *)val); + if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { + RTW_INFO("%s==> bcn_interval:%d, eraly_int:%d\n", __func__, bcn_interval, bcn_interval >> 1); + rtw_write8(adapter, REG_DRVERLYINT, bcn_interval >> 1); /* 50ms for sdio */ + } + } +#endif/* CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT */ + + break; + case HW_VAR_SLOT_TIME: { + rtw_write8(adapter, REG_SLOT, val[0]); + } + break; + case HW_VAR_ACK_PREAMBLE: { + u8 regTmp; + u8 bShortPreamble = *((bool *)val); + /* Joseph marked out for Netgear 3500 TKIP channel 7 issue.(Temporarily) */ + regTmp = (pHalData->nCur40MhzPrimeSC) << 5; + rtw_write8(adapter, REG_RRSR + 2, regTmp); + + regTmp = rtw_read8(adapter, REG_WMAC_TRXPTCL_CTL + 2); + if (bShortPreamble) + regTmp |= BIT1; + else + regTmp &= (~BIT1); + rtw_write8(adapter, REG_WMAC_TRXPTCL_CTL + 2, regTmp); + } + break; + case HW_VAR_CAM_EMPTY_ENTRY: { + u8 ucIndex = *((u8 *)val); + u8 i; + u32 ulCommand = 0; + u32 ulContent = 0; + u32 ulEncAlgo = CAM_AES; + + for (i = 0; i < CAM_CONTENT_COUNT; i++) { + /* filled id in CAM config 2 byte */ + if (i == 0) { + ulContent |= (ucIndex & 0x03) | ((u16)(ulEncAlgo) << 2); + /* ulContent |= CAM_VALID; */ + } else + ulContent = 0; + /* polling bit, and No Write enable, and address */ + ulCommand = CAM_CONTENT_COUNT * ucIndex + i; + ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE; + /* write content 0 is equall to mark invalid */ + rtw_write32(adapter, WCAMI, ulContent); /* delay_ms(40); */ + rtw_write32(adapter, RWCAM, ulCommand); /* delay_ms(40); */ + } + } + break; + case HW_VAR_CAM_INVALID_ALL: + rtw_write32(adapter, RWCAM, BIT(31) | BIT(30)); + break; + case HW_VAR_AC_PARAM_VO: + rtw_write32(adapter, REG_EDCA_VO_PARAM, ((u32 *)(val))[0]); + break; + case HW_VAR_AC_PARAM_VI: + rtw_write32(adapter, REG_EDCA_VI_PARAM, ((u32 *)(val))[0]); + break; + case HW_VAR_AC_PARAM_BE: + pHalData->ac_param_be = ((u32 *)(val))[0]; + rtw_write32(adapter, REG_EDCA_BE_PARAM, ((u32 *)(val))[0]); + break; + case HW_VAR_AC_PARAM_BK: + rtw_write32(adapter, REG_EDCA_BK_PARAM, ((u32 *)(val))[0]); + break; + case HW_VAR_ACM_CTRL: { + u8 acm_ctrl = *((u8 *)val); + u8 AcmCtrl = rtw_read8(adapter, REG_ACMHWCTRL); + + if (acm_ctrl > 1) + AcmCtrl = AcmCtrl | 0x1; + + if (acm_ctrl & BIT(3)) + AcmCtrl |= AcmHw_VoqEn; + else + AcmCtrl &= (~AcmHw_VoqEn); + + if (acm_ctrl & BIT(2)) + AcmCtrl |= AcmHw_ViqEn; + else + AcmCtrl &= (~AcmHw_ViqEn); + + if (acm_ctrl & BIT(1)) + AcmCtrl |= AcmHw_BeqEn; + else + AcmCtrl &= (~AcmHw_BeqEn); + + RTW_INFO("[HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl); + rtw_write8(adapter, REG_ACMHWCTRL, AcmCtrl); + } + break; + case HW_VAR_AMPDU_FACTOR: { + u8 RegToSet_Normal[4] = {0x41, 0xa8, 0x72, 0xb9}; + u8 RegToSet_BT[4] = {0x31, 0x74, 0x42, 0x97}; + u8 FactorToSet; + u8 *pRegToSet; + u8 index = 0; + +#ifdef CONFIG_BT_COEXIST + if ((pHalData->bt_coexist.BT_Coexist) && + (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC4)) + pRegToSet = RegToSet_BT; /* 0x97427431; */ + else +#endif + pRegToSet = RegToSet_Normal; /* 0xb972a841; */ + + FactorToSet = *((u8 *)val); + if (FactorToSet <= 3) { + FactorToSet = (1 << (FactorToSet + 2)); + if (FactorToSet > 0xf) + FactorToSet = 0xf; + + for (index = 0; index < 4; index++) { + if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4)) + pRegToSet[index] = (pRegToSet[index] & 0x0f) | (FactorToSet << 4); + + if ((pRegToSet[index] & 0x0f) > FactorToSet) + pRegToSet[index] = (pRegToSet[index] & 0xf0) | (FactorToSet); + + rtw_write8(adapter, (REG_AGGLEN_LMT + index), pRegToSet[index]); + } + + } + } + break; + case HW_VAR_H2C_FW_PWRMODE: { + u8 psmode = (*(u8 *)val); + + /* Forece leave RF low power mode for 1T1R to prevent conficting setting in Fw power */ + /* saving sequence. 2010.06.07. Added by tynli. Suggested by SD3 yschang. */ + if (psmode != PS_MODE_ACTIVE) + odm_rf_saving(podmpriv, true); + rtl8188e_set_FwPwrMode_cmd(adapter, psmode); + } + break; + case HW_VAR_H2C_FW_JOINBSSRPT: { + u8 mstatus = (*(u8 *)val); + rtl8188e_set_FwJoinBssReport_cmd(adapter, mstatus); + } + break; +#ifdef CONFIG_P2P_PS + case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: { + u8 p2p_ps_state = (*(u8 *)val); + rtl8188e_set_p2p_ps_offload_cmd(adapter, p2p_ps_state); + } + break; +#endif /* CONFIG_P2P_PS */ +#ifdef CONFIG_TDLS + case HW_VAR_TDLS_WRCR: + rtw_write32(adapter, REG_RCR, rtw_read32(adapter, REG_RCR) & (~RCR_CBSSID_DATA)); + break; + case HW_VAR_TDLS_RS_RCR: + rtw_write32(adapter, REG_RCR, rtw_read32(adapter, REG_RCR) | (RCR_CBSSID_DATA)); + break; +#endif /* CONFIG_TDLS */ +#ifdef CONFIG_BT_COEXIST + case HW_VAR_BT_SET_COEXIST: { + u8 bStart = (*(u8 *)val); + rtl8192c_set_dm_bt_coexist(adapter, bStart); + } + break; + case HW_VAR_BT_ISSUE_DELBA: { + u8 dir = (*(u8 *)val); + rtl8192c_issue_delete_ba(adapter, dir); + } + break; +#endif +#if (RATE_ADAPTIVE_SUPPORT == 1) + case HW_VAR_RPT_TIMER_SETTING: { + u16 min_rpt_time = (*(u16 *)val); + + odm_ra_set_tx_rpt_time(podmpriv, min_rpt_time); + } + break; +#endif + + case HW_VAR_EFUSE_BYTES: /* To set EFUE total used bytes, added by Roger, 2008.12.22. */ + pHalData->EfuseUsedBytes = *((u16 *)val); + break; + case HW_VAR_FIFO_CLEARN_UP: { + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter); + u8 trycnt = 100; + + /* pause tx */ + rtw_write8(adapter, REG_TXPAUSE, 0xff); + + /* keep sn */ + adapter->xmitpriv.nqos_ssn = rtw_read16(adapter, REG_NQOS_SEQ); + + if (pwrpriv->bkeepfwalive != true) { + /* RX DMA stop */ + rtw_write32(adapter, REG_RXPKT_NUM, (rtw_read32(adapter, REG_RXPKT_NUM) | RW_RELEASE_EN)); + do { + if (!(rtw_read32(adapter, REG_RXPKT_NUM) & RXDMA_IDLE)) + break; + } while (trycnt--); + if (trycnt == 0) + RTW_INFO("Stop RX DMA failed......\n"); + + /* RQPN Load 0 */ + rtw_write16(adapter, REG_RQPN_NPQ, 0x0); + rtw_write32(adapter, REG_RQPN, 0x80000000); + rtw_mdelay_os(10); + } + } + break; + + case HW_VAR_RESTORE_HW_SEQ: + /* restore Sequence No. */ + rtw_write8(adapter, 0x4dc, adapter->xmitpriv.nqos_ssn); + break; + +#if (RATE_ADAPTIVE_SUPPORT == 1) + case HW_VAR_TX_RPT_MAX_MACID: { + u8 maxMacid = *val; + + RTW_INFO("### MacID(%d),Set Max Tx RPT MID(%d)\n", maxMacid, maxMacid + 1); + rtw_write8(adapter, REG_TX_RPT_CTRL + 1, maxMacid + 1); + } + break; +#endif /* (RATE_ADAPTIVE_SUPPORT == 1) */ + + case HW_VAR_BCN_VALID: + /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, write 1 to clear, Clear by sw */ + rtw_write8(adapter, REG_TDECTRL + 2, rtw_read8(adapter, REG_TDECTRL + 2) | BIT0); + break; + + + case HW_VAR_CHECK_TXBUF: { + u8 retry_limit; + u16 val16; + u32 reg_200 = 0, reg_204 = 0; + u32 init_reg_200 = 0, init_reg_204 = 0; + u32 start = jiffies; + u32 pass_ms; + int i = 0; + + retry_limit = 0x01; + + val16 = retry_limit << RETRY_LIMIT_SHORT_SHIFT | retry_limit << RETRY_LIMIT_LONG_SHIFT; + rtw_write16(adapter, REG_RL, val16); + + while (rtw_get_passing_time_ms(start) < 2000 + && !RTW_CANNOT_RUN(adapter) + ) { + reg_200 = rtw_read32(adapter, 0x200); + reg_204 = rtw_read32(adapter, 0x204); + + if (i == 0) { + init_reg_200 = reg_200; + init_reg_204 = reg_204; + } + + i++; + if ((reg_200 & 0x00ffffff) != (reg_204 & 0x00ffffff)) { + /* RTW_INFO("%s: (HW_VAR_CHECK_TXBUF)TXBUF NOT empty - 0x204=0x%x, 0x200=0x%x (%d)\n", __func__, reg_204, reg_200, i); */ + rtw_msleep_os(10); + } else + break; + } + + pass_ms = rtw_get_passing_time_ms(start); + + if (RTW_CANNOT_RUN(adapter)) + ; + else if (pass_ms >= 2000 || (reg_200 & 0x00ffffff) != (reg_204 & 0x00ffffff)) { + RTW_PRINT("%s:(HW_VAR_CHECK_TXBUF)NOT empty(%d) in %d ms\n", __func__, i, pass_ms); + RTW_PRINT("%s:(HW_VAR_CHECK_TXBUF)0x200=0x%08x, 0x204=0x%08x (0x%08x, 0x%08x)\n", + __func__, reg_200, reg_204, init_reg_200, init_reg_204); + /* rtw_warn_on(1); */ + } else + RTW_INFO("%s:(HW_VAR_CHECK_TXBUF)TXBUF Empty(%d) in %d ms\n", __func__, i, pass_ms); + + retry_limit = 0x30; + val16 = retry_limit << RETRY_LIMIT_SHORT_SHIFT | retry_limit << RETRY_LIMIT_LONG_SHIFT; + rtw_write16(adapter, REG_RL, val16); + } + break; + case HW_VAR_RESP_SIFS: { + struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; + + if ((pmlmeext->cur_wireless_mode == WIRELESS_11G) || + (pmlmeext->cur_wireless_mode == WIRELESS_11BG)) { /* WIRELESS_MODE_G){ */ + val[0] = 0x0a; + val[1] = 0x0a; + } else { + val[0] = 0x0e; + val[1] = 0x0e; + } + + /* SIFS for OFDM Data ACK */ + rtw_write8(adapter, REG_SIFS_CTX + 1, val[0]); + /* SIFS for OFDM consecutive tx like CTS data! */ + rtw_write8(adapter, REG_SIFS_TRX + 1, val[1]); + + rtw_write8(adapter, REG_SPEC_SIFS + 1, val[0]); + rtw_write8(adapter, REG_MAC_SPEC_SIFS + 1, val[0]); + + /* RESP_SIFS for OFDM */ + rtw_write8(adapter, REG_RESP_SIFS_OFDM, val[0]); + rtw_write8(adapter, REG_RESP_SIFS_OFDM + 1, val[0]); + } + break; + + case HW_VAR_MACID_LINK: { + u32 reg_macid_no_link; + u8 bit_shift; + u8 id = *(u8 *)val; + u32 val32; + + if (id < 32) { + reg_macid_no_link = REG_MACID_NO_LINK_0; + bit_shift = id; + } else if (id < 64) { + reg_macid_no_link = REG_MACID_NO_LINK_1; + bit_shift = id - 32; + } else { + rtw_warn_on(1); + break; + } + + val32 = rtw_read32(adapter, reg_macid_no_link); + if (!(val32 & BIT(bit_shift))) + break; + + val32 &= ~BIT(bit_shift); + rtw_write32(adapter, reg_macid_no_link, val32); + } + break; + + case HW_VAR_MACID_NOLINK: { + u32 reg_macid_no_link; + u8 bit_shift; + u8 id = *(u8 *)val; + u32 val32; + + if (id < 32) { + reg_macid_no_link = REG_MACID_NO_LINK_0; + bit_shift = id; + } else if (id < 64) { + reg_macid_no_link = REG_MACID_NO_LINK_1; + bit_shift = id - 32; + } else { + rtw_warn_on(1); + break; + } + + val32 = rtw_read32(adapter, reg_macid_no_link); + if (val32 & BIT(bit_shift)) + break; + + val32 |= BIT(bit_shift); + rtw_write32(adapter, reg_macid_no_link, val32); + } + break; + + case HW_VAR_MACID_SLEEP: { + u32 reg_macid_sleep; + u8 bit_shift; + u8 id = *(u8 *)val; + u32 val32; + + if (id < 32) { + reg_macid_sleep = REG_MACID_PAUSE_0; + bit_shift = id; + } else if (id < 64) { + reg_macid_sleep = REG_MACID_PAUSE_1; + bit_shift = id - 32; + } else { + rtw_warn_on(1); + break; + } + + val32 = rtw_read32(adapter, reg_macid_sleep); + RTW_INFO(FUNC_ADPT_FMT ": [HW_VAR_MACID_SLEEP] macid=%d, org reg_0x%03x=0x%08X\n", + FUNC_ADPT_ARG(adapter), id, reg_macid_sleep, val32); + + if (val32 & BIT(bit_shift)) + break; + + val32 |= BIT(bit_shift); + rtw_write32(adapter, reg_macid_sleep, val32); + } + break; + + case HW_VAR_MACID_WAKEUP: { + u32 reg_macid_sleep; + u8 bit_shift; + u8 id = *(u8 *)val; + u32 val32; + + if (id < 32) { + reg_macid_sleep = REG_MACID_PAUSE_0; + bit_shift = id; + } else if (id < 64) { + reg_macid_sleep = REG_MACID_PAUSE_1; + bit_shift = id - 32; + } else { + rtw_warn_on(1); + break; + } + + val32 = rtw_read32(adapter, reg_macid_sleep); + RTW_INFO(FUNC_ADPT_FMT ": [HW_VAR_MACID_WAKEUP] macid=%d, org reg_0x%03x=0x%08X\n", + FUNC_ADPT_ARG(adapter), id, reg_macid_sleep, val32); + + if (!(val32 & BIT(bit_shift))) + break; + + val32 &= ~BIT(bit_shift); + rtw_write32(adapter, reg_macid_sleep, val32); + } + break; + + default: + SetHwReg(adapter, variable, val); + break; + } + +} + +struct qinfo_88e { + u32 head:8; + u32 pkt_num:8; + u32 tail:8; + u32 ac:2; + u32 macid:6; +}; + +struct bcn_qinfo_88e { + u16 head:8; + u16 pkt_num:8; +}; + +static void dump_qinfo_88e(void *sel, struct qinfo_88e *info, const char *tag) +{ + /* if (info->pkt_num) */ + RTW_PRINT_SEL(sel, "%shead:0x%02x, tail:0x%02x, pkt_num:%u, macid:%u, ac:%u\n" + , tag ? tag : "", info->head, info->tail, info->pkt_num, info->macid, info->ac + ); +} + +static void dump_bcn_qinfo_88e(void *sel, struct bcn_qinfo_88e *info, const char *tag) +{ + /* if (info->pkt_num) */ + RTW_PRINT_SEL(sel, "%shead:0x%02x, pkt_num:%u\n" + , tag ? tag : "", info->head, info->pkt_num + ); +} + +static void dump_mac_qinfo_88e(void *sel, _adapter *adapter) +{ + u32 q0_info; + u32 q1_info; + u32 q2_info; + u32 q3_info; + /* + u32 q4_info; + u32 q5_info; + u32 q6_info; + u32 q7_info; + */ + u32 mg_q_info; + u32 hi_q_info; + u16 bcn_q_info; + + q0_info = rtw_read32(adapter, REG_Q0_INFO); + q1_info = rtw_read32(adapter, REG_Q1_INFO); + q2_info = rtw_read32(adapter, REG_Q2_INFO); + q3_info = rtw_read32(adapter, REG_Q3_INFO); + /* + q4_info = rtw_read32(adapter, REG_Q4_INFO); + q5_info = rtw_read32(adapter, REG_Q5_INFO); + q6_info = rtw_read32(adapter, REG_Q6_INFO); + q7_info = rtw_read32(adapter, REG_Q7_INFO); + */ + mg_q_info = rtw_read32(adapter, REG_MGQ_INFO); + hi_q_info = rtw_read32(adapter, REG_HGQ_INFO); + bcn_q_info = rtw_read16(adapter, REG_BCNQ_INFO); + + dump_qinfo_88e(sel, (struct qinfo_88e *)&q0_info, "Q0 "); + dump_qinfo_88e(sel, (struct qinfo_88e *)&q1_info, "Q1 "); + dump_qinfo_88e(sel, (struct qinfo_88e *)&q2_info, "Q2 "); + dump_qinfo_88e(sel, (struct qinfo_88e *)&q3_info, "Q3 "); + /* + dump_qinfo_88e(sel, (struct qinfo_88e *)&q4_info, "Q4 "); + dump_qinfo_88e(sel, (struct qinfo_88e *)&q5_info, "Q5 "); + dump_qinfo_88e(sel, (struct qinfo_88e *)&q6_info, "Q6 "); + dump_qinfo_88e(sel, (struct qinfo_88e *)&q7_info, "Q7 "); + */ + dump_qinfo_88e(sel, (struct qinfo_88e *)&mg_q_info, "MG "); + dump_qinfo_88e(sel, (struct qinfo_88e *)&hi_q_info, "HI "); + dump_bcn_qinfo_88e(sel, (struct bcn_qinfo_88e *)&bcn_q_info, "BCN "); +} + +void GetHwReg8188E(_adapter *adapter, u8 variable, u8 *val) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter); + + + switch (variable) { + case HW_VAR_SYS_CLKR: + *val = rtw_read8(adapter, REG_SYS_CLKR); + break; + + case HW_VAR_TXPAUSE: + val[0] = rtw_read8(adapter, REG_TXPAUSE); + break; + case HW_VAR_BCN_VALID: + /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */ + val[0] = (BIT0 & rtw_read8(adapter, REG_TDECTRL + 2)) ? true : false; + break; + case HW_VAR_FWLPS_RF_ON: { + /* When we halt NIC, we should check if FW LPS is leave. */ + if (adapter_to_pwrctl(adapter)->rf_pwrstate == rf_off) { + /* If it is in HW/SW Radio OFF or IPS state, we do not check Fw LPS Leave, */ + /* because Fw is unload. */ + val[0] = true; + } else { + u32 valRCR; + valRCR = rtw_read32(adapter, REG_RCR); + valRCR &= 0x00070000; + if (valRCR) + val[0] = false; + else + val[0] = true; + } + } + break; + case HW_VAR_EFUSE_BYTES: /* To get EFUE total used bytes, added by Roger, 2008.12.22. */ + *((u16 *)(val)) = pHalData->EfuseUsedBytes; + break; + case HW_VAR_CHK_HI_QUEUE_EMPTY: + *val = ((rtw_read32(adapter, REG_HGQ_INFO) & 0x0000ff00) == 0) ? true : false; + break; + case HW_VAR_DUMP_MAC_QUEUE_INFO: + dump_mac_qinfo_88e(val, adapter); + break; + default: + GetHwReg(adapter, variable, val); + break; + } + +} + +static void hal_ra_info_dump(_adapter *padapter , void *sel) +{ + int i; + u8 mac_id; + u8 bLinked = false; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj); + _adapter *iface; + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if ((iface) && rtw_is_adapter_up(iface)) { + if (rtw_linked_check(iface)) { + bLinked = true; + break; + } + } + } + + for (i = 0; i < macid_ctl->num; i++) { + + if (rtw_macid_is_used(macid_ctl, i) && !rtw_macid_is_bmc(macid_ctl, i)) { + + mac_id = (u8) i; + + if (bLinked) { + _RTW_PRINT_SEL(sel , "============ RA status - Mac_id:%d ===================\n", mac_id); + if (pHalData->fw_ractrl == false) { +#if (RATE_ADAPTIVE_SUPPORT == 1) + _RTW_PRINT_SEL(sel , "Mac_id:%d ,RSSI:%d(%%)\n", mac_id, pHalData->odmpriv.ra_info[mac_id].rssi_sta_ra); + + _RTW_PRINT_SEL(sel , "rate_sgi = %d, decision_rate = %s\n", pHalData->odmpriv.ra_info[mac_id].rate_sgi, + HDATA_RATE(pHalData->odmpriv.ra_info[mac_id].decision_rate)); + + _RTW_PRINT_SEL(sel , "pt_stage = %d\n", pHalData->odmpriv.ra_info[mac_id].pt_stage); + + _RTW_PRINT_SEL(sel , "rate_id = %d,ra_use_rate = 0x%08x\n", pHalData->odmpriv.ra_info[mac_id].rate_id, pHalData->odmpriv.ra_info[mac_id].ra_use_rate); + +#endif /* (RATE_ADAPTIVE_SUPPORT == 1)*/ + } else { + u8 cur_rate = rtw_read8(padapter, REG_ADAPTIVE_DATA_RATE_0 + mac_id); + u8 sgi = (cur_rate & BIT7) ? true : false; + + cur_rate &= 0x7f; + + _RTW_PRINT_SEL(sel , "Mac_id:%d ,SGI:%d ,Rate:%s\n", mac_id, sgi, HDATA_RATE(cur_rate)); + } + } + } + } +} + +u8 +GetHalDefVar8188E( + PADAPTER Adapter, + HAL_DEF_VARIABLE eVariable, + void * pValue +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u8 bResult = _SUCCESS; + + switch (eVariable) { + case HAL_DEF_IS_SUPPORT_ANT_DIV: +#ifdef CONFIG_ANTENNA_DIVERSITY + *((u8 *)pValue) = (pHalData->AntDivCfg == 0) ? false : true; +#endif + break; + case HAL_DEF_DRVINFO_SZ: + *((u32 *)pValue) = DRVINFO_SZ; + break; + case HAL_DEF_MAX_RECVBUF_SZ: + *((u32 *)pValue) = MAX_RECVBUF_SZ; + break; + case HAL_DEF_RX_PACKET_OFFSET: + *((u32 *)pValue) = RXDESC_SIZE + DRVINFO_SZ * 8; + break; +#if (RATE_ADAPTIVE_SUPPORT == 1) + case HAL_DEF_RA_DECISION_RATE: { + u8 MacID = *((u8 *)pValue); + *((u8 *)pValue) = odm_ra_get_decision_rate_8188e(&(pHalData->odmpriv), MacID); + } + break; + + case HAL_DEF_RA_SGI: { + u8 MacID = *((u8 *)pValue); + *((u8 *)pValue) = odm_ra_get_sgi_8188e(&(pHalData->odmpriv), MacID); + } + break; +#endif + + + case HAL_DEF_PT_PWR_STATUS: +#if (POWER_TRAINING_ACTIVE == 1) + { + u8 MacID = *((u8 *)pValue); + *((u8 *)pValue) = odm_ra_get_hw_pwr_status_8188e(&(pHalData->odmpriv), MacID); + } +#endif /* (POWER_TRAINING_ACTIVE==1) */ + break; + case HAL_DEF_EXPLICIT_BEAMFORMEE: + case HAL_DEF_EXPLICIT_BEAMFORMER: + *((u8 *)pValue) = false; + break; + + case HW_DEF_RA_INFO_DUMP: + hal_ra_info_dump(Adapter, pValue); + break; + + case HAL_DEF_TX_PAGE_SIZE: + *((u32 *)pValue) = PAGE_SIZE_128; + break; + case HAL_DEF_TX_PAGE_BOUNDARY: + if (!Adapter->registrypriv.wifi_spec) + *(u8 *)pValue = TX_PAGE_BOUNDARY_88E(Adapter); + else + *(u8 *)pValue = WMM_NORMAL_TX_PAGE_BOUNDARY_88E(Adapter); + break; + case HAL_DEF_MACID_SLEEP: + *(u8 *)pValue = true; /* support macid sleep */ + break; + case HAL_DEF_RX_DMA_SZ_WOW: + *(u32 *)pValue = RX_DMA_SIZE_88E(Adapter) - RESV_FMWF; + break; + case HAL_DEF_RX_DMA_SZ: + *(u32 *)pValue = MAX_RX_DMA_BUFFER_SIZE_88E(Adapter); + break; + case HAL_DEF_RX_PAGE_SIZE: + *(u32 *)pValue = PAGE_SIZE_128; + break; + case HW_VAR_BEST_AMPDU_DENSITY: + *((u32 *)pValue) = AMPDU_DENSITY_VALUE_7; + break; + default: + bResult = GetHalDefVar(Adapter, eVariable, pValue); + break; + } + + return bResult; +} + +#ifdef CONFIG_GPIO_API +int rtl8188e_GpioFuncCheck(PADAPTER adapter, u8 gpio_num) +{ + int ret = _SUCCESS; + + if (IS_HARDWARE_TYPE_8188E(adapter) == _FAIL) { + if ((gpio_num > 7) || (gpio_num < 4)) { + RTW_INFO("%s The gpio number does not included 4~7.\n",__func__); + ret = _FAIL; + } + } + + return ret; +} +#endif diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c b/drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c new file mode 100644 index 000000000000..907434cb011b --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c @@ -0,0 +1,1713 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#define _RTL8188E_PHYCFG_C_ + +#include +#include + + +/*---------------------------Define Local Constant---------------------------*/ +/* Channel switch:The size of command tables for switch channel*/ +#define MAX_PRECMD_CNT 16 +#define MAX_RFDEPENDCMD_CNT 16 +#define MAX_POSTCMD_CNT 16 + +#define MAX_DOZE_WAITING_TIMES_9x 64 + +/*---------------------------Define Local Constant---------------------------*/ + + +/*------------------------Define global variable-----------------------------*/ + +/*------------------------Define local variable------------------------------*/ + + +/*--------------------Define export function prototype-----------------------*/ +/* Please refer to header file + *--------------------Define export function prototype-----------------------*/ + +/*----------------------------Function Body----------------------------------*/ +/* + * 1. BB register R/W API + * */ + +#if (SIC_ENABLE == 1) +static bool +sic_IsSICReady( + PADAPTER Adapter +) +{ + bool bRet = false; + u32 retryCnt = 0; + u8 sic_cmd = 0xff; + + while (1) { + if (retryCnt++ >= SIC_MAX_POLL_CNT) { + /* RTPRINT(FPHY, (PHY_SICR|PHY_SICW), ("[SIC], sic_IsSICReady() return false\n")); */ + return false; + } + + /* if(RT_SDIO_CANNOT_IO(Adapter)) */ + /* return false; */ + + sic_cmd = rtw_read8(Adapter, SIC_CMD_REG); + /* sic_cmd = PlatformEFIORead1Byte(Adapter, SIC_CMD_REG); */ +#if (SIC_HW_SUPPORT == 1) + sic_cmd &= 0xf0; /* [7:4] */ +#endif + /* RTPRINT(FPHY, (PHY_SICR|PHY_SICW), ("[SIC], sic_IsSICReady(), readback 0x%x=0x%x\n", SIC_CMD_REG, sic_cmd)); */ + if (sic_cmd == SIC_CMD_READY) + return true; + else { + rtw_msleep_os(1); + /* delay_ms(1); */ + } + } + + return bRet; +} + +/* +u32 +sic_CalculateBitShift( + u32 BitMask + ) +{ + u32 i; + + for(i=0; i<=31; i++) + { + if ( ((BitMask>>i) & 0x1 ) == 1) + break; + } + + return i; +} +*/ + +static u32 +sic_Read4Byte( + Pvoid Adapter, + u32 offset +) +{ + u32 u4ret = 0xffffffff; +#if RTL8188E_SUPPORT == 1 + u8 retry = 0; +#endif + + /* RTPRINT(FPHY, PHY_SICR, ("[SIC], sic_Read4Byte(): read offset(%#x)\n", offset)); */ + + if (sic_IsSICReady(Adapter)) { +#if (SIC_HW_SUPPORT == 1) + rtw_write8(Adapter, SIC_CMD_REG, SIC_CMD_PREREAD); + /* PlatformEFIOWrite1Byte(Adapter, SIC_CMD_REG, SIC_CMD_PREREAD); */ + /* RTPRINT(FPHY, PHY_SICR, ("write cmdreg 0x%x = 0x%x\n", SIC_CMD_REG, SIC_CMD_PREREAD)); */ +#endif + rtw_write8(Adapter, SIC_ADDR_REG, (u8)(offset & 0xff)); + /* PlatformEFIOWrite1Byte(Adapter, SIC_ADDR_REG, (u8)(offset&0xff)); */ + /* RTPRINT(FPHY, PHY_SICR, ("write 0x%x = 0x%x\n", SIC_ADDR_REG, (u8)(offset&0xff))); */ + rtw_write8(Adapter, SIC_ADDR_REG + 1, (u8)((offset & 0xff00) >> 8)); + /* PlatformEFIOWrite1Byte(Adapter, SIC_ADDR_REG+1, (u8)((offset&0xff00)>>8)); */ + /* RTPRINT(FPHY, PHY_SICR, ("write 0x%x = 0x%x\n", SIC_ADDR_REG+1, (u8)((offset&0xff00)>>8))); */ + rtw_write8(Adapter, SIC_CMD_REG, SIC_CMD_READ); + /* PlatformEFIOWrite1Byte(Adapter, SIC_CMD_REG, SIC_CMD_READ); */ + /* RTPRINT(FPHY, PHY_SICR, ("write cmdreg 0x%x = 0x%x\n", SIC_CMD_REG, SIC_CMD_READ)); */ + +#if RTL8188E_SUPPORT == 1 + retry = 4; + while (retry--) { + rtw_udelay_os(50); + /* PlatformStallExecution(50); */ + } +#else + rtw_udelay_os(200); + /* PlatformStallExecution(200); */ +#endif + + if (sic_IsSICReady(Adapter)) { + u4ret = rtw_read32(Adapter, SIC_DATA_REG); + /* u4ret = PlatformEFIORead4Byte(Adapter, SIC_DATA_REG); */ + /* RTPRINT(FPHY, PHY_SICR, ("read 0x%x = 0x%x\n", SIC_DATA_REG, u4ret)); */ + /* DbgPrint("<===Read 0x%x = 0x%x\n", offset, u4ret); */ + } + } + + return u4ret; +} + +static void +sic_Write4Byte( + Pvoid Adapter, + u32 offset, + u32 data +) +{ +#if RTL8188E_SUPPORT == 1 + u8 retry = 6; +#endif + /* DbgPrint("=>Write 0x%x = 0x%x\n", offset, data); */ + /* RTPRINT(FPHY, PHY_SICW, ("[SIC], sic_Write4Byte(): write offset(%#x)=0x%x\n", offset, data)); */ + if (sic_IsSICReady(Adapter)) { +#if (SIC_HW_SUPPORT == 1) + rtw_write8(Adapter, SIC_CMD_REG, SIC_CMD_PREWRITE); + /* PlatformEFIOWrite1Byte(Adapter, SIC_CMD_REG, SIC_CMD_PREWRITE); */ + /* RTPRINT(FPHY, PHY_SICW, ("write data 0x%x = 0x%x\n", SIC_CMD_REG, SIC_CMD_PREWRITE)); */ +#endif + rtw_write8(Adapter, SIC_ADDR_REG, (u8)(offset & 0xff)); + /* PlatformEFIOWrite1Byte(Adapter, SIC_ADDR_REG, (u8)(offset&0xff)); */ + /* RTPRINT(FPHY, PHY_SICW, ("write 0x%x=0x%x\n", SIC_ADDR_REG, (u8)(offset&0xff))); */ + rtw_write8(Adapter, SIC_ADDR_REG + 1, (u8)((offset & 0xff00) >> 8)); + /* PlatformEFIOWrite1Byte(Adapter, SIC_ADDR_REG+1, (u8)((offset&0xff00)>>8)); */ + /* RTPRINT(FPHY, PHY_SICW, ("write 0x%x=0x%x\n", (SIC_ADDR_REG+1), (u8)((offset&0xff00)>>8))); */ + rtw_write32(Adapter, SIC_DATA_REG, (u32)data); + /* PlatformEFIOWrite4Byte(Adapter, SIC_DATA_REG, (u32)data); */ + /* RTPRINT(FPHY, PHY_SICW, ("write data 0x%x = 0x%x\n", SIC_DATA_REG, data)); */ + rtw_write8(Adapter, SIC_CMD_REG, SIC_CMD_WRITE); + /* PlatformEFIOWrite1Byte(Adapter, SIC_CMD_REG, SIC_CMD_WRITE); */ + /* RTPRINT(FPHY, PHY_SICW, ("write data 0x%x = 0x%x\n", SIC_CMD_REG, SIC_CMD_WRITE)); */ +#if RTL8188E_SUPPORT == 1 + while (retry--) { + rtw_udelay_os(50); + /* PlatformStallExecution(50); */ + } +#else + rtw_udelay_os(150); + /* PlatformStallExecution(150); */ +#endif + + } +} +/* ************************************************************ + * extern function + * ************************************************************ */ +static void +SIC_SetBBReg( + PADAPTER Adapter, + u32 RegAddr, + u32 BitMask, + u32 Data +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u32 OriginalValue, BitShift; + u16 BBWaitCounter = 0; + + if (BitMask != bMaskDWord) { /* if not "double word" write */ + OriginalValue = sic_Read4Byte(Adapter, RegAddr); + /* BitShift = sic_CalculateBitShift(BitMask); */ + BitShift = PHY_CalculateBitShift(BitMask); + Data = (((OriginalValue)&(~BitMask)) | (Data << BitShift)); + } + + sic_Write4Byte(Adapter, RegAddr, Data); +} + +static u32 +SIC_QueryBBReg( + PADAPTER Adapter, + u32 RegAddr, + u32 BitMask +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u32 ReturnValue = 0, OriginalValue, BitShift; + u16 BBWaitCounter = 0; + + OriginalValue = sic_Read4Byte(Adapter, RegAddr); + BitShift = PHY_CalculateBitShift(BitMask); + ReturnValue = (OriginalValue & BitMask) >> BitShift; + + return ReturnValue; +} + +void +SIC_Init( + PADAPTER Adapter +) +{ + /* Here we need to write 0x1b8~0x1bf = 0 after fw is downloaded */ + /* because for 8723E at beginning 0x1b8=0x1e, that will cause */ + /* sic always not be ready */ +#if (SIC_HW_SUPPORT == 1) + /* RTPRINT(FPHY, PHY_SICR, ("[SIC], SIC_Init(), write 0x%x = 0x%x\n", */ + /* SIC_INIT_REG, SIC_INIT_VAL)); */ + rtw_write8(Adapter, SIC_INIT_REG, SIC_INIT_VAL); + /* PlatformEFIOWrite1Byte(Adapter, SIC_INIT_REG, SIC_INIT_VAL); */ + /* RTPRINT(FPHY, PHY_SICR, ("[SIC], SIC_Init(), write 0x%x = 0x%x\n", */ + /* SIC_CMD_REG, SIC_CMD_INIT)); */ + rtw_write8(Adapter, SIC_CMD_REG, SIC_CMD_INIT); + /* PlatformEFIOWrite1Byte(Adapter, SIC_CMD_REG, SIC_CMD_INIT); */ +#else + /* RTPRINT(FPHY, PHY_SICR, ("[SIC], SIC_Init(), write 0x1b8~0x1bf = 0x0\n")); */ + rtw_write32(Adapter, SIC_CMD_REG, 0); + /* PlatformEFIOWrite4Byte(Adapter, SIC_CMD_REG, 0); */ + rtw_write32(Adapter, SIC_CMD_REG + 4, 0); + /* PlatformEFIOWrite4Byte(Adapter, SIC_CMD_REG+4, 0); */ +#endif +} + +static bool +SIC_LedOff( + PADAPTER Adapter +) +{ + /* When SIC is enabled, led pin will be used as debug pin, */ + /* so don't execute led function when SIC is enabled. */ + return true; +} +#endif + +/** +* Function: PHY_QueryBBReg +* +* OverView: Read "sepcific bits" from BB register +* +* Input: +* PADAPTER Adapter, +* u32 RegAddr, //The target address to be readback +* u32 BitMask //The target bit position in the target address +* //to be readback +* Output: None +* Return: u32 Data //The readback register value +* Note: This function is equal to "GetRegSetting" in PHY programming guide +*/ +u32 +PHY_QueryBBReg8188E( + PADAPTER Adapter, + u32 RegAddr, + u32 BitMask +) +{ + u32 ReturnValue = 0, OriginalValue, BitShift; + u16 BBWaitCounter = 0; + +#if (DISABLE_BB_RF == 1) + return 0; +#endif + +#if (SIC_ENABLE == 1) + return SIC_QueryBBReg(Adapter, RegAddr, BitMask); +#endif + + + OriginalValue = rtw_read32(Adapter, RegAddr); + BitShift = PHY_CalculateBitShift(BitMask); + ReturnValue = (OriginalValue & BitMask) >> BitShift; + + /* RTPRINT(FPHY, PHY_BBR, ("BBR MASK=0x%lx Addr[0x%lx]=0x%lx\n", BitMask, RegAddr, OriginalValue)); */ + + return ReturnValue; + +} + + +/** +* Function: PHY_SetBBReg +* +* OverView: Write "Specific bits" to BB register (page 8~) +* +* Input: +* PADAPTER Adapter, +* u32 RegAddr, //The target address to be modified +* u32 BitMask //The target bit position in the target address +* //to be modified +* u32 Data //The new register value in the target bit position +* //of the target address +* +* Output: None +* Return: None +* Note: This function is equal to "PutRegSetting" in PHY programming guide +*/ + +void +PHY_SetBBReg8188E( + PADAPTER Adapter, + u32 RegAddr, + u32 BitMask, + u32 Data +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + /* u16 BBWaitCounter = 0; */ + u32 OriginalValue, BitShift; + +#if (DISABLE_BB_RF == 1) + return; +#endif + +#if (SIC_ENABLE == 1) + SIC_SetBBReg(Adapter, RegAddr, BitMask, Data); + return; +#endif + + + if (BitMask != bMaskDWord) { /* if not "double word" write */ + OriginalValue = rtw_read32(Adapter, RegAddr); + BitShift = PHY_CalculateBitShift(BitMask); + Data = ((OriginalValue & (~BitMask)) | ((Data << BitShift) & BitMask)); + } + + rtw_write32(Adapter, RegAddr, Data); + + /* RTPRINT(FPHY, PHY_BBW, ("BBW MASK=0x%lx Addr[0x%lx]=0x%lx\n", BitMask, RegAddr, Data)); */ + +} + + +/* + * 2. RF register R/W API + * + ** +* Function: phy_RFSerialRead +* +* OverView: Read regster from RF chips +* +* Input: +* PADAPTER Adapter, +* u8 eRFPath, //Radio path of A/B/C/D +* u32 Offset, //The target address to be read +* +* Output: None +* Return: u32 reback value +* Note: Threre are three types of serial operations: +* 1. Software serial write +* 2. Hardware LSSI-Low Speed Serial Interface +* 3. Hardware HSSI-High speed +* serial write. Driver need to implement (1) and (2). +* This function is equal to the combination of RF_ReadReg() and RFLSSIRead() +*/ +static u32 +phy_RFSerialRead( + PADAPTER Adapter, + u8 eRFPath, + u32 Offset +) +{ + u32 retValue = 0; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + BB_REGISTER_DEFINITION_T *pPhyReg = &pHalData->PHYRegDef[eRFPath]; + u32 NewOffset; + u32 tmplong, tmplong2; + u8 RfPiEnable = 0; + + _enter_critical_mutex(&(adapter_to_dvobj(Adapter)->rf_read_reg_mutex) , NULL); + /* Make sure RF register offset is correct */ + Offset &= 0xff; + + /* Switch page for 8256 RF IC */ + NewOffset = Offset; + + /* 2009/06/17 MH We can not execute IO for power save or other accident mode. */ + /* if(RT_CANNOT_IO(Adapter)) */ + /* { */ + /* RTPRINT(FPHY, PHY_RFR, ("phy_RFSerialRead return all one\n")); */ + /* return 0xFFFFFFFF; */ + /* } */ + + /* For 92S LSSI Read RFLSSIRead */ + /* For RF A/B write 0x824/82c(does not work in the future) */ + /* We must use 0x824 for RF A and B to execute read trigger */ + tmplong = phy_query_bb_reg(Adapter, rFPGA0_XA_HSSIParameter2, bMaskDWord); + if (eRFPath == RF_PATH_A) + tmplong2 = tmplong; + else + tmplong2 = phy_query_bb_reg(Adapter, pPhyReg->rfHSSIPara2, bMaskDWord); + + tmplong2 = (tmplong2 & (~bLSSIReadAddress)) | (NewOffset << 23) | bLSSIReadEdge; /* T65 RF */ + + phy_set_bb_reg(Adapter, rFPGA0_XA_HSSIParameter2, bMaskDWord, tmplong & (~bLSSIReadEdge)); + rtw_udelay_os(10);/* PlatformStallExecution(10); */ + + phy_set_bb_reg(Adapter, pPhyReg->rfHSSIPara2, bMaskDWord, tmplong2); + rtw_udelay_os(100);/* PlatformStallExecution(100); */ + + /* phy_set_bb_reg(Adapter, rFPGA0_XA_HSSIParameter2, bMaskDWord, tmplong|bLSSIReadEdge); */ + rtw_udelay_os(10);/* PlatformStallExecution(10); */ + + if (eRFPath == RF_PATH_A) + RfPiEnable = (u8)phy_query_bb_reg(Adapter, rFPGA0_XA_HSSIParameter1, BIT8); + else if (eRFPath == RF_PATH_B) + RfPiEnable = (u8)phy_query_bb_reg(Adapter, rFPGA0_XB_HSSIParameter1, BIT8); + + if (RfPiEnable) { + /* Read from BBreg8b8, 12 bits for 8190, 20bits for T65 RF */ + retValue = phy_query_bb_reg(Adapter, pPhyReg->rfLSSIReadBackPi, bLSSIReadBackData); + /* RTW_INFO("Readback from RF-PI : 0x%x\n", retValue); */ + } else { + /* Read from BBreg8a0, 12 bits for 8190, 20 bits for T65 RF */ + retValue = phy_query_bb_reg(Adapter, pPhyReg->rfLSSIReadBack, bLSSIReadBackData); + /* RTW_INFO("Readback from RF-SI : 0x%x\n", retValue); */ + } + /* RTW_INFO("RFR-%d Addr[0x%x]=0x%x\n", eRFPath, pPhyReg->rfLSSIReadBack, retValue); */ + _exit_critical_mutex(&(adapter_to_dvobj(Adapter)->rf_read_reg_mutex) , NULL); + return retValue; + +} + + + +/** +* Function: phy_RFSerialWrite +* +* OverView: Write data to RF register (page 8~) +* +* Input: +* PADAPTER Adapter, +* u8 eRFPath, //Radio path of A/B/C/D +* u32 Offset, //The target address to be read +* u32 Data //The new register Data in the target bit position +* //of the target to be read +* +* Output: None +* Return: None +* Note: Threre are three types of serial operations: +* 1. Software serial write +* 2. Hardware LSSI-Low Speed Serial Interface +* 3. Hardware HSSI-High speed +* serial write. Driver need to implement (1) and (2). +* This function is equal to the combination of RF_ReadReg() and RFLSSIRead() + * + * Note: For RF8256 only + * The total count of RTL8256(Zebra4) register is around 36 bit it only employs + * 4-bit RF address. RTL8256 uses "register mode control bit" (Reg00[12], Reg00[10]) + * to access register address bigger than 0xf. See "Appendix-4 in PHY Configuration + * programming guide" for more details. + * Thus, we define a sub-finction for RTL8526 register address conversion + * =========================================================== + * Register Mode RegCTL[1] RegCTL[0] Note + * (Reg00[12]) (Reg00[10]) + * =========================================================== + * Reg_Mode0 0 x Reg 0 ~15(0x0 ~ 0xf) + * ------------------------------------------------------------------ + * Reg_Mode1 1 0 Reg 16 ~30(0x1 ~ 0xf) + * ------------------------------------------------------------------ + * Reg_Mode2 1 1 Reg 31 ~ 45(0x1 ~ 0xf) + * ------------------------------------------------------------------ + * + * 2008/09/02 MH Add 92S RF definition + * + * + * +*/ +static void +phy_RFSerialWrite( + PADAPTER Adapter, + u8 eRFPath, + u32 Offset, + u32 Data +) +{ + u32 DataAndAddr = 0; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + BB_REGISTER_DEFINITION_T *pPhyReg = &pHalData->PHYRegDef[eRFPath]; + u32 NewOffset; + + Offset &= 0xff; + + /* Switch page for 8256 RF IC */ + NewOffset = Offset; + + /* Put write addr in [5:0] and write data in [31:16] */ + DataAndAddr = ((NewOffset << 20) | (Data & 0x000fffff)) & 0x0fffffff; /* T65 RF */ + + /* Write Operation */ + phy_set_bb_reg(Adapter, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr); +} + +/** +* Function: PHY_QueryRFReg +* +* OverView: Query "Specific bits" to RF register (page 8~) +* +* Input: +* PADAPTER Adapter, +* u8 eRFPath, //Radio path of A/B/C/D +* u32 RegAddr, //The target address to be read +* u32 BitMask //The target bit position in the target address +* //to be read +* +* Output: None +* Return: u32 Readback value +* Note: This function is equal to "GetRFRegSetting" in PHY programming guide +*/ +u32 +PHY_QueryRFReg8188E( + PADAPTER Adapter, + u8 eRFPath, + u32 RegAddr, + u32 BitMask +) +{ + u32 Original_Value, Readback_Value, BitShift; + /* HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); */ + /* u8 RFWaitCounter = 0; */ + /* unsigned long irqL; */ + +#if (DISABLE_BB_RF == 1) + return 0; +#endif + + + Original_Value = phy_RFSerialRead(Adapter, eRFPath, RegAddr); + + BitShift = PHY_CalculateBitShift(BitMask); + Readback_Value = (Original_Value & BitMask) >> BitShift; + + return Readback_Value; +} + +/** +* Function: PHY_SetRFReg +* +* OverView: Write "Specific bits" to RF register (page 8~) +* +* Input: +* PADAPTER Adapter, +* u8 eRFPath, //Radio path of A/B/C/D +* u32 RegAddr, //The target address to be modified +* u32 BitMask //The target bit position in the target address +* //to be modified +* u32 Data //The new register Data in the target bit position +* //of the target address +* +* Output: None +* Return: None +* Note: This function is equal to "PutRFRegSetting" in PHY programming guide +*/ +void +PHY_SetRFReg8188E( + PADAPTER Adapter, + u8 eRFPath, + u32 RegAddr, + u32 BitMask, + u32 Data +) +{ + + /* HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); */ + /* u8 RFWaitCounter = 0; */ + u32 Original_Value, BitShift; + /* unsigned long irqL; */ + +#if (DISABLE_BB_RF == 1) + return; +#endif + + /* RF data is 12 bits only */ + if (BitMask != bRFRegOffsetMask) { + Original_Value = phy_RFSerialRead(Adapter, eRFPath, RegAddr); + BitShift = PHY_CalculateBitShift(BitMask); + Data = ((Original_Value & (~BitMask)) | (Data << BitShift)); + } + + phy_RFSerialWrite(Adapter, eRFPath, RegAddr, Data); +} + + +/* + * 3. Initial MAC/BB/RF config by reading MAC/BB/RF txt. + * */ + +/*----------------------------------------------------------------------------- + * Function: PHY_MACConfig8192C + * + * Overview: Condig MAC by header file or parameter file. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 08/12/2008 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +s32 PHY_MACConfig8188E(PADAPTER Adapter) +{ + int rtStatus = _SUCCESS; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u16 val = 0; + + /* */ + /* Config MAC */ + /* */ +#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE + rtStatus = phy_ConfigMACWithParaFile(Adapter, PHY_FILE_MAC_REG); + if (rtStatus == _FAIL) +#endif + { +#ifdef CONFIG_EMBEDDED_FWIMG + if (HAL_STATUS_FAILURE == odm_config_mac_with_header_file(&pHalData->odmpriv)) + rtStatus = _FAIL; + else + rtStatus = _SUCCESS; +#endif/* CONFIG_EMBEDDED_FWIMG */ + } + + /* 2010.07.13 AMPDU aggregation number B */ + val |= MAX_AGGR_NUM; + val = val << 8; + val |= MAX_AGGR_NUM; + rtw_write16(Adapter, REG_MAX_AGGR_NUM, val); + /* rtw_write8(Adapter, REG_MAX_AGGR_NUM, 0x0B); */ + + return rtStatus; + +} + +/*----------------------------------------------------------------------------- +* Function: phy_InitBBRFRegisterDefinition +* +* OverView: Initialize Register definition offset for Radio Path A/B/C/D +* +* Input: +* PADAPTER Adapter, +* +* Output: None +* Return: None +* Note: The initialization value is constant and it should never be changes +-----------------------------------------------------------------------------*/ +static void +phy_InitBBRFRegisterDefinition( + PADAPTER Adapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + /* RF Interface Sowrtware Control */ + pHalData->PHYRegDef[RF_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW; /* 16 LSBs if read 32-bit from 0x870 */ + pHalData->PHYRegDef[RF_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW; /* 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) */ + pHalData->PHYRegDef[RF_PATH_C].rfintfs = rFPGA0_XCD_RFInterfaceSW;/* 16 LSBs if read 32-bit from 0x874 */ + pHalData->PHYRegDef[RF_PATH_D].rfintfs = rFPGA0_XCD_RFInterfaceSW;/* 16 MSBs if read 32-bit from 0x874 (16-bit for 0x876) */ + + /* RF Interface Output (and Enable) */ + pHalData->PHYRegDef[RF_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE; /* 16 LSBs if read 32-bit from 0x860 */ + pHalData->PHYRegDef[RF_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE; /* 16 LSBs if read 32-bit from 0x864 */ + + /* RF Interface (Output and) Enable */ + pHalData->PHYRegDef[RF_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE; /* 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */ + pHalData->PHYRegDef[RF_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE; /* 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) */ + + /* Addr of LSSI. Wirte RF register by driver */ + pHalData->PHYRegDef[RF_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter; /* LSSI Parameter */ + pHalData->PHYRegDef[RF_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter; + + /* Tranceiver A~D HSSI Parameter-2 */ + pHalData->PHYRegDef[RF_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2; /* wire control parameter2 */ + pHalData->PHYRegDef[RF_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2; /* wire control parameter2 */ + + /* Tranceiver LSSI Readback SI mode */ + pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack; + pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack; + pHalData->PHYRegDef[RF_PATH_C].rfLSSIReadBack = rFPGA0_XC_LSSIReadBack; + pHalData->PHYRegDef[RF_PATH_D].rfLSSIReadBack = rFPGA0_XD_LSSIReadBack; + + /* Tranceiver LSSI Readback PI mode */ + pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBackPi = TransceiverA_HSPI_Readback; + pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBackPi = TransceiverB_HSPI_Readback; +} + +static void +phy_BB8192C_Config_1T( + PADAPTER Adapter +) +{ + /* for path - B */ + phy_set_bb_reg(Adapter, rFPGA0_TxInfo, 0x3, 0x2); + phy_set_bb_reg(Adapter, rFPGA1_TxInfo, 0x300033, 0x200022); + + /* 20100519 Joseph: Add for 1T2R config. Suggested by Kevin, Jenyu and Yunan. */ + phy_set_bb_reg(Adapter, rCCK0_AFESetting, bMaskByte3, 0x45); + phy_set_bb_reg(Adapter, rOFDM0_TRxPathEnable, bMaskByte0, 0x23); + phy_set_bb_reg(Adapter, rOFDM0_AGCParameter1, 0x30, 0x1); /* B path first AGC */ + + phy_set_bb_reg(Adapter, 0xe74, 0x0c000000, 0x2); + phy_set_bb_reg(Adapter, 0xe78, 0x0c000000, 0x2); + phy_set_bb_reg(Adapter, 0xe7c, 0x0c000000, 0x2); + phy_set_bb_reg(Adapter, 0xe80, 0x0c000000, 0x2); + phy_set_bb_reg(Adapter, 0xe88, 0x0c000000, 0x2); + + +} + +/* Joseph test: new initialize order!! + * Test only!! This part need to be re-organized. + * Now it is just for 8256. */ +static int +phy_BB8190_Config_HardCode( + PADAPTER Adapter +) +{ + /* RT_ASSERT(false, ("This function is not implement yet!!\n")); */ + return _SUCCESS; +} + +static int +phy_BB8188E_Config_ParaFile( + PADAPTER Adapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + int rtStatus = _SUCCESS; + + /* */ + /* 1. Read PHY_REG.TXT BB INIT!! */ + /* */ +#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE + if (phy_ConfigBBWithParaFile(Adapter, PHY_FILE_PHY_REG, CONFIG_BB_PHY_REG) == _FAIL) +#endif + { +#ifdef CONFIG_EMBEDDED_FWIMG + if (HAL_STATUS_FAILURE == odm_config_bb_with_header_file(&pHalData->odmpriv, CONFIG_BB_PHY_REG)) + rtStatus = _FAIL; +#endif + } + + if (rtStatus != _SUCCESS) { + goto phy_BB8190_Config_ParaFile_Fail; + } + +#if (MP_DRIVER == 1) + /* */ + /* 1.1 Read PHY_REG_MP.TXT BB INIT!! */ + /* */ + if (Adapter->registrypriv.mp_mode == 1) { + /* 3 Read PHY_REG.TXT BB INIT!! */ +#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE + if (phy_ConfigBBWithMpParaFile(Adapter, PHY_FILE_PHY_REG_MP) == _FAIL) +#endif + { +#ifdef CONFIG_EMBEDDED_FWIMG + if (HAL_STATUS_SUCCESS != odm_config_bb_with_header_file(&pHalData->odmpriv, CONFIG_BB_PHY_REG_MP)) + rtStatus = _FAIL; +#endif + } + + if (rtStatus != _SUCCESS) { + RTW_INFO("phy_BB8188E_Config_ParaFile():Write BB Reg MP Fail!!"); + goto phy_BB8190_Config_ParaFile_Fail; + } + } +#endif /* #if (MP_DRIVER == 1) */ + + /* */ + /* 3. BB AGC table Initialization */ + /* */ +#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE + if (phy_ConfigBBWithParaFile(Adapter, PHY_FILE_AGC_TAB, CONFIG_BB_AGC_TAB) == _FAIL) +#endif + { +#ifdef CONFIG_EMBEDDED_FWIMG + if (HAL_STATUS_FAILURE == odm_config_bb_with_header_file(&pHalData->odmpriv, CONFIG_BB_AGC_TAB)) + rtStatus = _FAIL; +#endif + } + + if (rtStatus != _SUCCESS) { + goto phy_BB8190_Config_ParaFile_Fail; + } + + +phy_BB8190_Config_ParaFile_Fail: + + return rtStatus; +} + + +int +PHY_BBConfig8188E( + PADAPTER Adapter +) +{ + int rtStatus = _SUCCESS; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u32 RegVal; + u8 TmpU1B = 0; + u8 value8; + + phy_InitBBRFRegisterDefinition(Adapter); + + + /* Enable BB and RF */ + RegVal = rtw_read16(Adapter, REG_SYS_FUNC_EN); + rtw_write16(Adapter, REG_SYS_FUNC_EN, (u16)(RegVal | BIT13 | BIT0 | BIT1)); + + /* 20090923 Joseph: Advised by Steven and Jenyu. Power sequence before init RF. */ + /* rtw_write8(Adapter, REG_AFE_PLL_CTRL, 0x83); */ + /* rtw_write8(Adapter, REG_AFE_PLL_CTRL+1, 0xdb); */ + + rtw_write8(Adapter, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); + + rtw_write8(Adapter, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD | FEN_BB_GLB_RSTn | FEN_BBRSTB); + + /* Config BB and AGC */ + rtStatus = phy_BB8188E_Config_ParaFile(Adapter); + + hal_set_crystal_cap(Adapter, pHalData->crystal_cap); + + return rtStatus; +} + +int +PHY_RFConfig8188E( + PADAPTER Adapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + int rtStatus = _SUCCESS; + + /* RF config */ + rtStatus = PHY_RF6052_Config8188E(Adapter); + return rtStatus; +} + + +/*----------------------------------------------------------------------------- + * Function: PHY_ConfigRFWithParaFile() + * + * Overview: This function read RF parameters from general file format, and do RF 3-wire + * + * Input: PADAPTER Adapter + * ps1Byte pFileName + * u8 eRFPath + * + * Output: NONE + * + * Return: RT_STATUS_SUCCESS: configuration file exist + * + * Note: Delay may be required for RF configuration + *---------------------------------------------------------------------------*/ +int +rtl8188e_PHY_ConfigRFWithParaFile( + PADAPTER Adapter, + u8 *pFileName, + u8 eRFPath +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + int rtStatus = _SUCCESS; + + + return rtStatus; + +} + +/* **************************************** + * The following is for High Power PA + * **************************************** */ +#define HighPowerRadioAArrayLen 22 +/* This is for High power PA */ +static u32 Rtl8192S_HighPower_RadioA_Array[HighPowerRadioAArrayLen] = { + 0x013, 0x00029ea4, + 0x013, 0x00025e74, + 0x013, 0x00020ea4, + 0x013, 0x0001ced0, + 0x013, 0x00019f40, + 0x013, 0x00014e70, + 0x013, 0x000106a0, + 0x013, 0x0000c670, + 0x013, 0x000082a0, + 0x013, 0x00004270, + 0x013, 0x00000240, +}; + +/* **************************************** + *----------------------------------------------------------------------------- + * Function: GetTxPowerLevel8190() + * + * Overview: This function is export to "common" moudule + * + * Input: PADAPTER Adapter + * psByte Power Level + * + * Output: NONE + * + * Return: NONE + * + *---------------------------------------------------------------------------*/ +void +PHY_GetTxPowerLevel8188E( + PADAPTER Adapter, + s32 *powerlevel +) +{ +} + +/*----------------------------------------------------------------------------- + * Function: SetTxPowerLevel8190() + * + * Overview: This function is export to "HalCommon" moudule + * We must consider RF path later!!!!!!! + * + * Input: PADAPTER Adapter + * u8 channel + * + * Output: NONE + * + * Return: NONE + * 2008/11/04 MHC We remove EEPROM_93C56. + * We need to move CCX relative code to independet file. + * 2009/01/21 MHC Support new EEPROM format from SD3 requirement. + * + *---------------------------------------------------------------------------*/ +void +PHY_SetTxPowerLevel8188E( + PADAPTER Adapter, + u8 Channel +) +{ + /* RTW_INFO("==>PHY_SetTxPowerLevel8188E()\n"); */ + + phy_set_tx_power_level_by_path(Adapter, Channel, ODM_RF_PATH_A); + + /* RTW_INFO("<==PHY_SetTxPowerLevel8188E()\n"); */ +} + +void +PHY_SetTxPowerIndex_8188E( + PADAPTER Adapter, + u32 PowerIndex, + u8 RFPath, + u8 Rate +) +{ + if (RFPath == ODM_RF_PATH_A) { + switch (Rate) { + case MGN_1M: + phy_set_bb_reg(Adapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, PowerIndex); + break; + case MGN_2M: + phy_set_bb_reg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte1, PowerIndex); + break; + case MGN_5_5M: + phy_set_bb_reg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte2, PowerIndex); + break; + case MGN_11M: + phy_set_bb_reg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte3, PowerIndex); + break; + + case MGN_6M: + phy_set_bb_reg(Adapter, rTxAGC_A_Rate18_06, bMaskByte0, PowerIndex); + break; + case MGN_9M: + phy_set_bb_reg(Adapter, rTxAGC_A_Rate18_06, bMaskByte1, PowerIndex); + break; + case MGN_12M: + phy_set_bb_reg(Adapter, rTxAGC_A_Rate18_06, bMaskByte2, PowerIndex); + break; + case MGN_18M: + phy_set_bb_reg(Adapter, rTxAGC_A_Rate18_06, bMaskByte3, PowerIndex); + break; + + case MGN_24M: + phy_set_bb_reg(Adapter, rTxAGC_A_Rate54_24, bMaskByte0, PowerIndex); + break; + case MGN_36M: + phy_set_bb_reg(Adapter, rTxAGC_A_Rate54_24, bMaskByte1, PowerIndex); + break; + case MGN_48M: + phy_set_bb_reg(Adapter, rTxAGC_A_Rate54_24, bMaskByte2, PowerIndex); + break; + case MGN_54M: + phy_set_bb_reg(Adapter, rTxAGC_A_Rate54_24, bMaskByte3, PowerIndex); + break; + + case MGN_MCS0: + phy_set_bb_reg(Adapter, rTxAGC_A_Mcs03_Mcs00, bMaskByte0, PowerIndex); + break; + case MGN_MCS1: + phy_set_bb_reg(Adapter, rTxAGC_A_Mcs03_Mcs00, bMaskByte1, PowerIndex); + break; + case MGN_MCS2: + phy_set_bb_reg(Adapter, rTxAGC_A_Mcs03_Mcs00, bMaskByte2, PowerIndex); + break; + case MGN_MCS3: + phy_set_bb_reg(Adapter, rTxAGC_A_Mcs03_Mcs00, bMaskByte3, PowerIndex); + break; + + case MGN_MCS4: + phy_set_bb_reg(Adapter, rTxAGC_A_Mcs07_Mcs04, bMaskByte0, PowerIndex); + break; + case MGN_MCS5: + phy_set_bb_reg(Adapter, rTxAGC_A_Mcs07_Mcs04, bMaskByte1, PowerIndex); + break; + case MGN_MCS6: + phy_set_bb_reg(Adapter, rTxAGC_A_Mcs07_Mcs04, bMaskByte2, PowerIndex); + break; + case MGN_MCS7: + phy_set_bb_reg(Adapter, rTxAGC_A_Mcs07_Mcs04, bMaskByte3, PowerIndex); + break; + + case MGN_MCS8: + phy_set_bb_reg(Adapter, rTxAGC_A_Mcs11_Mcs08, bMaskByte0, PowerIndex); + break; + case MGN_MCS9: + phy_set_bb_reg(Adapter, rTxAGC_A_Mcs11_Mcs08, bMaskByte1, PowerIndex); + break; + case MGN_MCS10: + phy_set_bb_reg(Adapter, rTxAGC_A_Mcs11_Mcs08, bMaskByte2, PowerIndex); + break; + case MGN_MCS11: + phy_set_bb_reg(Adapter, rTxAGC_A_Mcs11_Mcs08, bMaskByte3, PowerIndex); + break; + + case MGN_MCS12: + phy_set_bb_reg(Adapter, rTxAGC_A_Mcs15_Mcs12, bMaskByte0, PowerIndex); + break; + case MGN_MCS13: + phy_set_bb_reg(Adapter, rTxAGC_A_Mcs15_Mcs12, bMaskByte1, PowerIndex); + break; + case MGN_MCS14: + phy_set_bb_reg(Adapter, rTxAGC_A_Mcs15_Mcs12, bMaskByte2, PowerIndex); + break; + case MGN_MCS15: + phy_set_bb_reg(Adapter, rTxAGC_A_Mcs15_Mcs12, bMaskByte3, PowerIndex); + break; + + default: + RTW_INFO("Invalid Rate!!\n"); + break; + } + } else if (RFPath == ODM_RF_PATH_B) { + switch (Rate) { + case MGN_1M: + phy_set_bb_reg(Adapter, rTxAGC_B_CCK1_55_Mcs32, bMaskByte1, PowerIndex); + break; + case MGN_2M: + phy_set_bb_reg(Adapter, rTxAGC_B_CCK1_55_Mcs32, bMaskByte2, PowerIndex); + break; + case MGN_5_5M: + phy_set_bb_reg(Adapter, rTxAGC_B_CCK1_55_Mcs32, bMaskByte3, PowerIndex); + break; + case MGN_11M: + phy_set_bb_reg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, PowerIndex); + break; + + case MGN_6M: + phy_set_bb_reg(Adapter, rTxAGC_B_Rate18_06, bMaskByte0, PowerIndex); + break; + case MGN_9M: + phy_set_bb_reg(Adapter, rTxAGC_B_Rate18_06, bMaskByte1, PowerIndex); + break; + case MGN_12M: + phy_set_bb_reg(Adapter, rTxAGC_B_Rate18_06, bMaskByte2, PowerIndex); + break; + case MGN_18M: + phy_set_bb_reg(Adapter, rTxAGC_B_Rate18_06, bMaskByte3, PowerIndex); + break; + + case MGN_24M: + phy_set_bb_reg(Adapter, rTxAGC_B_Rate54_24, bMaskByte0, PowerIndex); + break; + case MGN_36M: + phy_set_bb_reg(Adapter, rTxAGC_B_Rate54_24, bMaskByte1, PowerIndex); + break; + case MGN_48M: + phy_set_bb_reg(Adapter, rTxAGC_B_Rate54_24, bMaskByte2, PowerIndex); + break; + case MGN_54M: + phy_set_bb_reg(Adapter, rTxAGC_B_Rate54_24, bMaskByte3, PowerIndex); + break; + + case MGN_MCS0: + phy_set_bb_reg(Adapter, rTxAGC_B_Mcs03_Mcs00, bMaskByte0, PowerIndex); + break; + case MGN_MCS1: + phy_set_bb_reg(Adapter, rTxAGC_B_Mcs03_Mcs00, bMaskByte1, PowerIndex); + break; + case MGN_MCS2: + phy_set_bb_reg(Adapter, rTxAGC_B_Mcs03_Mcs00, bMaskByte2, PowerIndex); + break; + case MGN_MCS3: + phy_set_bb_reg(Adapter, rTxAGC_B_Mcs03_Mcs00, bMaskByte3, PowerIndex); + break; + + case MGN_MCS4: + phy_set_bb_reg(Adapter, rTxAGC_B_Mcs07_Mcs04, bMaskByte0, PowerIndex); + break; + case MGN_MCS5: + phy_set_bb_reg(Adapter, rTxAGC_B_Mcs07_Mcs04, bMaskByte1, PowerIndex); + break; + case MGN_MCS6: + phy_set_bb_reg(Adapter, rTxAGC_B_Mcs07_Mcs04, bMaskByte2, PowerIndex); + break; + case MGN_MCS7: + phy_set_bb_reg(Adapter, rTxAGC_B_Mcs07_Mcs04, bMaskByte3, PowerIndex); + break; + + case MGN_MCS8: + phy_set_bb_reg(Adapter, rTxAGC_B_Mcs11_Mcs08, bMaskByte0, PowerIndex); + break; + case MGN_MCS9: + phy_set_bb_reg(Adapter, rTxAGC_B_Mcs11_Mcs08, bMaskByte1, PowerIndex); + break; + case MGN_MCS10: + phy_set_bb_reg(Adapter, rTxAGC_B_Mcs11_Mcs08, bMaskByte2, PowerIndex); + break; + case MGN_MCS11: + phy_set_bb_reg(Adapter, rTxAGC_B_Mcs11_Mcs08, bMaskByte3, PowerIndex); + break; + + case MGN_MCS12: + phy_set_bb_reg(Adapter, rTxAGC_B_Mcs15_Mcs12, bMaskByte0, PowerIndex); + break; + case MGN_MCS13: + phy_set_bb_reg(Adapter, rTxAGC_B_Mcs15_Mcs12, bMaskByte1, PowerIndex); + break; + case MGN_MCS14: + phy_set_bb_reg(Adapter, rTxAGC_B_Mcs15_Mcs12, bMaskByte2, PowerIndex); + break; + case MGN_MCS15: + phy_set_bb_reg(Adapter, rTxAGC_B_Mcs15_Mcs12, bMaskByte3, PowerIndex); + break; + + default: + RTW_INFO("Invalid Rate!!\n"); + break; + } + } else + RTW_INFO("Invalid RFPath!!\n"); +} + +static u8 +phy_GetCurrentTxNum_8188E( + PADAPTER pAdapter, + u8 Rate +) +{ + u8 tmpByte = 0; + u32 tmpDWord = 0; + u8 TxNum = RF_TX_NUM_NONIMPLEMENT; + + if ((Rate >= MGN_MCS8 && Rate <= MGN_MCS15)) + TxNum = RF_2TX; + else + TxNum = RF_1TX; + + return TxNum; +} + +static s8 tx_power_extra_bias( + u8 RFPath, + u8 Rate, + CHANNEL_WIDTH BandWidth, + u8 Channel +) +{ + s8 bias = 0; + + if (Rate == MGN_2M) + bias = -9; + + return bias; +} + +u8 +PHY_GetTxPowerIndex_8188E( + PADAPTER pAdapter, + u8 RFPath, + u8 Rate, + u8 BandWidth, + u8 Channel, + struct txpwr_idx_comp *tic +) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter); + u8 base_idx = 0, power_idx = 0; + s8 by_rate_diff = 0, limit = 0, tpt_offset = 0, extra_bias = 0; + u8 txNum = phy_GetCurrentTxNum_8188E(pAdapter, Rate); + bool bIn24G = false; + + base_idx = PHY_GetTxPowerIndexBase(pAdapter, RFPath, Rate, BandWidth, Channel, &bIn24G); + + by_rate_diff = PHY_GetTxPowerByRate(pAdapter, BAND_ON_2_4G, RFPath, txNum, Rate); + limit = PHY_GetTxPowerLimit(pAdapter, pAdapter->registrypriv.RegPwrTblSel, (u8)(!bIn24G), pHalData->current_channel_bw, RFPath, Rate, pHalData->current_channel); + + tpt_offset = PHY_GetTxPowerTrackingOffset(pAdapter, RFPath, Rate); + + if (pAdapter->registrypriv.mp_mode != 1) + extra_bias = tx_power_extra_bias(RFPath, Rate, BandWidth, Channel); + + if (tic) { + tic->base = base_idx; + tic->by_rate = by_rate_diff; + tic->limit = limit; + tic->tpt = tpt_offset; + tic->ebias = extra_bias; + } + + by_rate_diff = by_rate_diff > limit ? limit : by_rate_diff; + power_idx = base_idx + by_rate_diff + tpt_offset + extra_bias; + + if (power_idx > MAX_POWER_INDEX) + power_idx = MAX_POWER_INDEX; + + return power_idx; +} + +/* + * Description: + * Update transmit power level of all channel supported. + * + * TODO: + * A mode. + * By Bruce, 2008-02-04. + * */ +bool +PHY_UpdateTxPowerDbm8188E( + PADAPTER Adapter, + int powerInDbm +) +{ + return true; +} + +static void +PHY_ScanOperationBackup8188E( + PADAPTER Adapter, + u8 Operation +) +{ +} + +static void +phy_SpurCalibration_8188E( + PADAPTER Adapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + struct PHY_DM_STRUCT *p_dm_odm = &(pHalData->odmpriv); + + if (pHalData->current_channel_bw == CHANNEL_WIDTH_20 && (pHalData->current_channel == 13 || pHalData->current_channel == 14)) { + phy_set_bb_reg(Adapter, rOFDM0_RxDSP, BIT(9), 0x1);/* enable notch filter */ + phy_set_bb_reg(Adapter, rOFDM1_IntfDet, BIT(8) | BIT(7) | BIT(6), 0x2); /* intf_TH */ + phy_set_bb_reg(Adapter, rOFDM0_RxDSP, BIT(28) | BIT(27) | BIT(26) | BIT(25) | BIT(24), 0x1f); + p_dm_odm->is_receiver_blocking_en = false; + } else if (pHalData->current_channel_bw == CHANNEL_WIDTH_40 && pHalData->current_channel == 11) { + phy_set_bb_reg(Adapter, rOFDM0_RxDSP, BIT(9), 0x1);/* enable notch filter */ + phy_set_bb_reg(Adapter, rOFDM1_IntfDet, BIT(8) | BIT(7) | BIT(6), 0x2); /* intf_TH */ + phy_set_bb_reg(Adapter, rOFDM0_RxDSP, BIT(28) | BIT(27) | BIT(26) | BIT(25) | BIT(24), 0x1f); + p_dm_odm->is_receiver_blocking_en = false; + } else { + if (Adapter->registrypriv.notch_filter == 0) + phy_set_bb_reg(Adapter, rOFDM0_RxDSP, BIT(9), 0x0);/* disable notch filter */ + } +} + +/*----------------------------------------------------------------------------- + * Function: PHY_SetBWModeCallback8192C() + * + * Overview: Timer callback function for SetSetBWMode + * + * Input: PRT_TIMER pTimer + * + * Output: NONE + * + * Return: NONE + * + * Note: (1) We do not take j mode into consideration now + * (2) Will two workitem of "switch channel" and "switch channel bandwidth" run + * concurrently? + *---------------------------------------------------------------------------*/ +static void +_PHY_SetBWMode88E( + PADAPTER Adapter +) +{ + /* PADAPTER Adapter = (PADAPTER)pTimer->Adapter; */ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u8 regBwOpMode; + u8 regRRSR_RSC; + + /* return; */ + + /* Added it for 20/40 mhz switch time evaluation by guangan 070531 */ + /* u32 NowL, NowH; */ + /* u64 BeginTime, EndTime; */ + + if (pHalData->rf_chip == RF_PSEUDO_11N) { + /* pHalData->SetBWModeInProgress= false; */ + return; + } + + /* There is no 40MHz mode in RF_8225. */ + if (pHalData->rf_chip == RF_8225) + return; + + if (rtw_is_drv_stopped(Adapter)) + return; + + /* Added it for 20/40 mhz switch time evaluation by guangan 070531 */ + /* NowL = PlatformEFIORead4Byte(Adapter, TSFR); */ + /* NowH = PlatformEFIORead4Byte(Adapter, TSFR+4); */ + /* BeginTime = ((u64)NowH << 32) + NowL; */ + + /* 3 */ + /* 3 */ /* <1>Set MAC register */ + /* 3 */ + /* Adapter->hal_func.SetBWModeHandler(); */ + + regBwOpMode = rtw_read8(Adapter, REG_BWOPMODE); + regRRSR_RSC = rtw_read8(Adapter, REG_RRSR + 2); + /* regBwOpMode = rtw_hal_get_hwreg(Adapter,HW_VAR_BWMODE,(u8 *)®BwOpMode); */ + + switch (pHalData->current_channel_bw) { + case CHANNEL_WIDTH_20: + regBwOpMode |= BW_OPMODE_20MHZ; + /* 2007/02/07 Mark by Emily becasue we have not verify whether this register works */ + rtw_write8(Adapter, REG_BWOPMODE, regBwOpMode); + break; + + case CHANNEL_WIDTH_40: + regBwOpMode &= ~BW_OPMODE_20MHZ; + /* 2007/02/07 Mark by Emily becasue we have not verify whether this register works */ + rtw_write8(Adapter, REG_BWOPMODE, regBwOpMode); + + regRRSR_RSC = (regRRSR_RSC & 0x90) | (pHalData->nCur40MhzPrimeSC << 5); + rtw_write8(Adapter, REG_RRSR + 2, regRRSR_RSC); + break; + + default: + break; + } + + /* 3 */ + /* 3 */ /* <2>Set PHY related register */ + /* 3 */ + switch (pHalData->current_channel_bw) { + /* 20 MHz channel*/ + case CHANNEL_WIDTH_20: + phy_set_bb_reg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x0); + phy_set_bb_reg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x0); + /* phy_set_bb_reg(Adapter, rFPGA0_AnalogParameter2, BIT10, 1); */ + + break; + + + /* 40 MHz channel*/ + case CHANNEL_WIDTH_40: + phy_set_bb_reg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x1); + phy_set_bb_reg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x1); + + /* Set Control channel to upper or lower. These settings are required only for 40MHz */ + phy_set_bb_reg(Adapter, rCCK0_System, bCCKSideBand, (pHalData->nCur40MhzPrimeSC >> 1)); + phy_set_bb_reg(Adapter, rOFDM1_LSTF, 0xC00, pHalData->nCur40MhzPrimeSC); + /* phy_set_bb_reg(Adapter, rFPGA0_AnalogParameter2, BIT10, 0); */ + + phy_set_bb_reg(Adapter, 0x818, (BIT26 | BIT27), (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); + + break; + + + + default: + break; + + } + /* Skip over setting of J-mode in BB register here. Default value is "None J mode". Emily 20070315 */ + + /* Added it for 20/40 mhz switch time evaluation by guangan 070531 */ + /* NowL = PlatformEFIORead4Byte(Adapter, TSFR); */ + /* NowH = PlatformEFIORead4Byte(Adapter, TSFR+4); */ + /* EndTime = ((u64)NowH << 32) + NowL; */ + + /* 3<3>Set RF related register */ + switch (pHalData->rf_chip) { + case RF_8225: + /* PHY_SetRF8225Bandwidth(Adapter, pHalData->current_channel_bw); */ + break; + + case RF_8256: + /* Please implement this function in Hal8190PciPhy8256.c */ + /* PHY_SetRF8256Bandwidth(Adapter, pHalData->current_channel_bw); */ + break; + + case RF_8258: + /* Please implement this function in Hal8190PciPhy8258.c */ + /* PHY_SetRF8258Bandwidth(); */ + break; + + case RF_PSEUDO_11N: + /* Do Nothing */ + break; + + case RF_6052: + rtl8188e_PHY_RF6052SetBandwidth(Adapter, pHalData->current_channel_bw); + break; + + default: + /* RT_ASSERT(false, ("Unknown RFChipID: %d\n", pHalData->RFChipID)); */ + break; + } + + /* pHalData->SetBWModeInProgress= false; */ + +} + +void +PHY_SetBWMode8188E( + PADAPTER Adapter, + CHANNEL_WIDTH Bandwidth, /* 20M or 40M */ + unsigned char Offset /* Upper, Lower, or Don't care */ +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + CHANNEL_WIDTH tmpBW = pHalData->current_channel_bw; + /* Modified it for 20/40 mhz switch by guangan 070531 */ + /* PMGNT_INFO pMgntInfo=&Adapter->MgntInfo; */ + + /* return; */ + + /* if(pHalData->SwChnlInProgress) + * if(pMgntInfo->bScanInProgress) + * { + * return; + * } */ + + /* if(pHalData->SetBWModeInProgress) + * { + * */ /* Modified it for 20/40 mhz switch by guangan 070531 + * PlatformCancelTimer(Adapter, &pHalData->SetBWModeTimer); + * */ /* return; + * } */ + + /* if(pHalData->SetBWModeInProgress) */ + /* return; */ + + /* pHalData->SetBWModeInProgress= true; */ + + pHalData->current_channel_bw = Bandwidth; + + pHalData->nCur40MhzPrimeSC = Offset; + + if (!RTW_CANNOT_RUN(Adapter)) { + _PHY_SetBWMode88E(Adapter); + if (IS_VENDOR_8188E_I_CUT_SERIES(Adapter)) + phy_SpurCalibration_8188E(Adapter); + } else { + /* pHalData->SetBWModeInProgress= false; */ + pHalData->current_channel_bw = tmpBW; + } + +} + + +static void _PHY_SwChnl8188E(PADAPTER Adapter, u8 channel) +{ + u8 eRFPath; + u32 param1, param2; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + if (Adapter->bNotifyChannelChange) + RTW_INFO("[%s] ch = %d\n", __func__, channel); + + /* s1. pre common command - CmdID_SetTxPowerLevel */ + PHY_SetTxPowerLevel8188E(Adapter, channel); + + /* s2. RF dependent command - CmdID_RF_WriteReg, param1=RF_CHNLBW, param2=channel */ + param1 = RF_CHNLBW; + param2 = channel; + for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) { + pHalData->RfRegChnlVal[eRFPath] = ((pHalData->RfRegChnlVal[eRFPath] & 0xfffffc00) | param2); + phy_set_rf_reg(Adapter, eRFPath, param1, bRFRegOffsetMask, pHalData->RfRegChnlVal[eRFPath]); + } + + + /* s3. post common command - CmdID_End, None */ + +} +void +PHY_SwChnl8188E(/* Call after initialization */ + PADAPTER Adapter, + u8 channel +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u8 tmpchannel = pHalData->current_channel; + bool bResult = true; + + if (pHalData->rf_chip == RF_PSEUDO_11N) + return; /* return immediately if it is peudo-phy */ + + while (pHalData->odmpriv.rf_calibrate_info.is_lck_in_progress) + rtw_msleep_os(50); + + /* -------------------------------------------- */ + switch (pHalData->CurrentWirelessMode) { + case WIRELESS_MODE_A: + case WIRELESS_MODE_N_5G: + break; + case WIRELESS_MODE_B: + break; + case WIRELESS_MODE_G: + case WIRELESS_MODE_N_24G: + break; + default: + break; + } + /* -------------------------------------------- */ + + if (channel == 0) + channel = 1; + + pHalData->current_channel = channel; + + if (!RTW_CANNOT_RUN(Adapter)) { + _PHY_SwChnl8188E(Adapter, channel); + + if (IS_VENDOR_8188E_I_CUT_SERIES(Adapter)) + phy_SpurCalibration_8188E(Adapter); + + + + if (!bResult) + pHalData->current_channel = tmpchannel; + } else { + pHalData->current_channel = tmpchannel; + } +} + +void +PHY_SetSwChnlBWMode8188E( + PADAPTER Adapter, + u8 channel, + CHANNEL_WIDTH Bandwidth, + u8 Offset40, + u8 Offset80 +) +{ + /* RTW_INFO("%s()===>\n",__func__); */ + + PHY_SwChnl8188E(Adapter, channel); + PHY_SetBWMode8188E(Adapter, Bandwidth, Offset40); + + /* RTW_INFO("<==%s()\n",__func__); */ +} + +static void _PHY_SetRFPathSwitch( + PADAPTER pAdapter, + bool bMain, + bool is2T +) +{ + u8 u1bTmp; + + if (!rtw_is_hw_init_completed(pAdapter)) { + u1bTmp = rtw_read8(pAdapter, REG_LEDCFG2) | BIT7; + rtw_write8(pAdapter, REG_LEDCFG2, u1bTmp); + /* phy_set_bb_reg(pAdapter, REG_LEDCFG0, BIT23, 0x01); */ + phy_set_bb_reg(pAdapter, rFPGA0_XAB_RFParameter, BIT13, 0x01); + } + + if (is2T) { + if (bMain) + phy_set_bb_reg(pAdapter, rFPGA0_XB_RFInterfaceOE, BIT5 | BIT6, 0x1); /* 92C_Path_A */ + else + phy_set_bb_reg(pAdapter, rFPGA0_XB_RFInterfaceOE, BIT5 | BIT6, 0x2); /* BT */ + } else { + + if (bMain) + phy_set_bb_reg(pAdapter, rFPGA0_XA_RFInterfaceOE, 0x300, 0x2); /* Main */ + else + phy_set_bb_reg(pAdapter, rFPGA0_XA_RFInterfaceOE, 0x300, 0x1); /* Aux */ + } + +} + +/* return value true => Main; false => Aux */ + +static bool _PHY_QueryRFPathSwitch( + PADAPTER pAdapter, + bool is2T +) +{ + /* if(is2T) + * return true; */ + + if (!rtw_is_hw_init_completed(pAdapter)) { + phy_set_bb_reg(pAdapter, REG_LEDCFG0, BIT23, 0x01); + phy_set_bb_reg(pAdapter, rFPGA0_XAB_RFParameter, BIT13, 0x01); + } + + if (is2T) { + if (phy_query_bb_reg(pAdapter, rFPGA0_XB_RFInterfaceOE, BIT5 | BIT6) == 0x01) + return true; + else + return false; + } else { + if (phy_query_bb_reg(pAdapter, rFPGA0_XA_RFInterfaceOE, 0x300) == 0x02) + return true; + else + return false; + } +} + + +static void +_PHY_DumpRFReg(PADAPTER pAdapter) +{ + u32 rfRegValue, rfRegOffset; + + /* RTPRINT(FINIT, INIT_RF, ("PHY_DumpRFReg()====>\n")); */ + + for (rfRegOffset = 0x00; rfRegOffset <= 0x30; rfRegOffset++) { + rfRegValue = phy_query_rf_reg(pAdapter, RF_PATH_A, rfRegOffset, bMaskDWord); + /* RTPRINT(FINIT, INIT_RF, (" 0x%02x = 0x%08x\n",rfRegOffset,rfRegValue)); */ + } + /* RTPRINT(FINIT, INIT_RF, ("<===== PHY_DumpRFReg()\n")); */ +} + + +/* + * Move from phycfg.c to gen.c to be code independent later + * + * -------------------------Move to other DIR later---------------------------- */ + +/* + * Description: + * To dump all Tx FIFO LLT related link-list table. + * Added by Roger, 2009.03.10. + * */ +static void DumpBBDbgPort_92CU(PADAPTER Adapter) +{ + phy_set_bb_reg(Adapter, 0x0908, 0xffff, 0x0000); + + phy_set_bb_reg(Adapter, 0x0908, 0xffff, 0x0803); + + phy_set_bb_reg(Adapter, 0x0908, 0xffff, 0x0a06); + + phy_set_bb_reg(Adapter, 0x0908, 0xffff, 0x0007); + + phy_set_bb_reg(Adapter, 0x0908, 0xffff, 0x0100); + phy_set_bb_reg(Adapter, 0x0a28, 0x00ff0000, 0x000f0000); + + phy_set_bb_reg(Adapter, 0x0908, 0xffff, 0x0100); + phy_set_bb_reg(Adapter, 0x0a28, 0x00ff0000, 0x00150000); +} + +void +PHY_SetRFEReg_8188E( + PADAPTER Adapter +) +{ + u8 u1tmp = 0; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + if ((pHalData->ExternalPA_2G == 0) && (pHalData->ExternalLNA_2G == 0)) + return; + + switch (pHalData->rfe_type) { + /* 88EU rfe_type should always be 0 */ + case 0: + default: + phy_set_bb_reg(Adapter, 0x40, BIT2|BIT3, 0x3); /*0x3 << 2*/ + phy_set_bb_reg(Adapter, 0xEE8, BIT28, 0x1); + phy_set_bb_reg(Adapter, 0x87C, BIT0, 0x0); + break; + } +} diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c new file mode 100644 index 000000000000..b69680087422 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +/****************************************************************************** + * + * + * Module: rtl8188e_rf6052.c ( Source C File) + * + * Note: Provide RF 6052 series relative API. + * + * Function: + * + * Export: + * + * Abbrev: + * + * History: + * Data Who Remark + * + * 09/25/2008 MHC Create initial version. + * 11/05/2008 MHC Add API for tw power setting. + * + * +******************************************************************************/ + +#define _RTL8188E_RF6052_C_ + +#include +#include + +/*---------------------------Define Local Constant---------------------------*/ + +/*---------------------------Define Local Constant---------------------------*/ + + +/*------------------------Define global variable-----------------------------*/ +/*------------------------Define global variable-----------------------------*/ + + +/*------------------------Define local variable------------------------------*/ + +/*------------------------Define local variable------------------------------*/ + + +/*----------------------------------------------------------------------------- + * Function: RF_ChangeTxPath + * + * Overview: For RL6052, we must change some RF settign for 1T or 2T. + * + * Input: u16 DataRate // 0x80-8f, 0x90-9f + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 09/25/2008 MHC Create Version 0. + * Firmwaer support the utility later. + * + *---------------------------------------------------------------------------*/ +void rtl8188e_RF_ChangeTxPath(PADAPTER Adapter, + u16 DataRate) +{ + /* We do not support gain table change inACUT now !!!! Delete later !!! */ +} /* RF_ChangeTxPath */ + +/*----------------------------------------------------------------------------- + * Function: PHY_RF6052SetBandwidth() + * + * Overview: This function is called by SetBWModeCallback8190Pci() only + * + * Input: PADAPTER Adapter + * WIRELESS_BANDWIDTH_E Bandwidth //20M or 40M + * + * Output: NONE + * + * Return: NONE + * + * Note: For RF type 0222D + *---------------------------------------------------------------------------*/ +void +rtl8188e_PHY_RF6052SetBandwidth( + PADAPTER Adapter, + CHANNEL_WIDTH Bandwidth) /* 20M or 40M */ +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + switch (Bandwidth) { + case CHANNEL_WIDTH_20: + pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | BIT(10) | BIT(11)); + phy_set_rf_reg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]); + break; + + case CHANNEL_WIDTH_40: + pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | BIT(10)); + phy_set_rf_reg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]); + break; + + default: + break; + } + +} + +static int +phy_RF6052_Config_ParaFile( + PADAPTER Adapter +) +{ + u32 u4RegValue = 0; + u8 eRFPath; + BB_REGISTER_DEFINITION_T *pPhyReg; + + int rtStatus = _SUCCESS; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + /* 3 */ /* ----------------------------------------------------------------- */ + /* 3 */ /* <2> Initialize RF */ + /* 3 */ /* ----------------------------------------------------------------- */ + /* for(eRFPath = RF_PATH_A; eRFPath NumTotalRFPath; eRFPath++) */ + for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) { + + pPhyReg = &pHalData->PHYRegDef[eRFPath]; + + /*----Store original RFENV control type----*/ + switch (eRFPath) { + case RF_PATH_A: + case RF_PATH_C: + u4RegValue = phy_query_bb_reg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV); + break; + case RF_PATH_B: + case RF_PATH_D: + u4RegValue = phy_query_bb_reg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV << 16); + break; + } + + /*----Set RF_ENV enable----*/ + phy_set_bb_reg(Adapter, pPhyReg->rfintfe, bRFSI_RFENV << 16, 0x1); + rtw_udelay_os(1);/* PlatformStallExecution(1); */ + + /*----Set RF_ENV output high----*/ + phy_set_bb_reg(Adapter, pPhyReg->rfintfo, bRFSI_RFENV, 0x1); + rtw_udelay_os(1);/* PlatformStallExecution(1); */ + + /* Set bit number of Address and Data for RF register */ + phy_set_bb_reg(Adapter, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); /* Set 1 to 4 bits for 8255 */ + rtw_udelay_os(1);/* PlatformStallExecution(1); */ + + phy_set_bb_reg(Adapter, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); /* Set 0 to 12 bits for 8255 */ + rtw_udelay_os(1);/* PlatformStallExecution(1); */ + + /*----Initialize RF fom connfiguration file----*/ + switch (eRFPath) { + case RF_PATH_A: +#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE + if (PHY_ConfigRFWithParaFile(Adapter, PHY_FILE_RADIO_A, eRFPath) == _FAIL) +#endif + { +#ifdef CONFIG_EMBEDDED_FWIMG + if (HAL_STATUS_FAILURE == odm_config_rf_with_header_file(&pHalData->odmpriv, CONFIG_RF_RADIO, (enum odm_rf_radio_path_e)eRFPath)) + rtStatus = _FAIL; +#endif + } + break; + case RF_PATH_B: +#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE + if (PHY_ConfigRFWithParaFile(Adapter, PHY_FILE_RADIO_B, eRFPath) == _FAIL) +#endif + { +#ifdef CONFIG_EMBEDDED_FWIMG + if (HAL_STATUS_FAILURE == odm_config_rf_with_header_file(&pHalData->odmpriv, CONFIG_RF_RADIO, (enum odm_rf_radio_path_e)eRFPath)) + rtStatus = _FAIL; +#endif + } + break; + case RF_PATH_C: + break; + case RF_PATH_D: + break; + } + + /*----Restore RFENV control type----*/; + switch (eRFPath) { + case RF_PATH_A: + case RF_PATH_C: + phy_set_bb_reg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue); + break; + case RF_PATH_B: + case RF_PATH_D: + phy_set_bb_reg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV << 16, u4RegValue); + break; + } + + if (rtStatus != _SUCCESS) { + goto phy_RF6052_Config_ParaFile_Fail; + } + + } + + + /* 3 ----------------------------------------------------------------- */ + /* 3 Configuration of Tx Power Tracking */ + /* 3 ----------------------------------------------------------------- */ + +#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE + if (PHY_ConfigRFWithTxPwrTrackParaFile(Adapter, PHY_FILE_TXPWR_TRACK) == _FAIL) +#endif + { +#ifdef CONFIG_EMBEDDED_FWIMG + odm_config_rf_with_tx_pwr_track_header_file(&pHalData->odmpriv); +#endif + } + + return rtStatus; + +phy_RF6052_Config_ParaFile_Fail: + return rtStatus; +} + + +int +PHY_RF6052_Config8188E( + PADAPTER Adapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + int rtStatus = _SUCCESS; + + /* */ + /* Initialize general global value */ + /* */ + /* TODO: Extend RF_PATH_C and RF_PATH_D in the future */ + if (pHalData->rf_type == RF_1T1R) + pHalData->NumTotalRFPath = 1; + else + pHalData->NumTotalRFPath = 2; + + /* */ + /* Config BB and RF */ + /* */ + rtStatus = phy_RF6052_Config_ParaFile(Adapter); + return rtStatus; +} + +/* End of HalRf6052.c */ diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c new file mode 100644 index 000000000000..e6b0f77bcdc2 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#define _RTL8188E_REDESC_C_ + +#include +#include + +void rtl8188e_query_rx_desc_status( + union recv_frame *precvframe, + struct recv_stat *prxstat) +{ + struct rx_pkt_attrib *pattrib; + struct recv_stat report; + PRXREPORT prxreport; + /* struct recv_frame_hdr *phdr; */ + + /* phdr = &precvframe->u.hdr; */ + + report.rxdw0 = prxstat->rxdw0; + report.rxdw1 = prxstat->rxdw1; + report.rxdw2 = prxstat->rxdw2; + report.rxdw3 = prxstat->rxdw3; + report.rxdw4 = prxstat->rxdw4; + report.rxdw5 = prxstat->rxdw5; + + prxreport = (PRXREPORT)&report; + + pattrib = &precvframe->u.hdr.attrib; + memset(pattrib, 0, sizeof(struct rx_pkt_attrib)); + + pattrib->crc_err = (u8)((le32_to_cpu(report.rxdw0) >> 14) & 0x1);;/* (u8)prxreport->crc32; */ + + /* update rx report to recv_frame attribute */ + pattrib->pkt_rpt_type = (u8)((le32_to_cpu(report.rxdw3) >> 14) & 0x3);/* prxreport->rpt_sel; */ + + if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */ + pattrib->pkt_len = cpu_to_le16(le32_to_cpu(report.rxdw0) & 0x00003fff); /* (u16)prxreport->pktlen; */ + pattrib->drvinfo_sz = (u8)((le32_to_cpu(report.rxdw0) >> 16) & 0xf) * 8;/* (u8)(prxreport->drvinfosize << 3); */ + + pattrib->physt = (u8)((le32_to_cpu(report.rxdw0) >> 26) & 0x1); /* (u8)prxreport->physt; */ + + pattrib->bdecrypted = (le32_to_cpu(report.rxdw0) & BIT(27)) ? 0 : 1; /* (u8)(prxreport->swdec ? 0 : 1); */ + pattrib->encrypt = (u8)((le32_to_cpu(report.rxdw0) >> 20) & 0x7);/* (u8)prxreport->security; */ + + pattrib->qos = (u8)((le32_to_cpu(report.rxdw0) >> 23) & 0x1);/* (u8)prxreport->qos; */ + pattrib->priority = (u8)((le32_to_cpu(report.rxdw1) >> 8) & 0xf);/* (u8)prxreport->tid; */ + + pattrib->amsdu = (u8)((le32_to_cpu(report.rxdw1) >> 13) & 0x1);/* (u8)prxreport->amsdu; */ + + pattrib->seq_num = cpu_to_le16(le32_to_cpu(report.rxdw2) & 0x00000fff);/* (u16)prxreport->seq; */ + pattrib->frag_num = (u8)((le32_to_cpu(report.rxdw2) >> 12) & 0xf);/* (u8)prxreport->frag; */ + pattrib->mfrag = (u8)((le32_to_cpu(report.rxdw1) >> 27) & 0x1);/* (u8)prxreport->mf; */ + pattrib->mdata = (u8)((le32_to_cpu(report.rxdw1) >> 26) & 0x1);/* (u8)prxreport->md; */ + + pattrib->data_rate = (u8)(le32_to_cpu(report.rxdw3) & 0x3f);/* (u8)prxreport->rxmcs; */ + + pattrib->icv_err = (u8)((le32_to_cpu(report.rxdw0) >> 15) & 0x1);/* (u8)prxreport->icverr; */ + pattrib->shift_sz = (u8)((le32_to_cpu(report.rxdw0) >> 24) & 0x3); + } else if (pattrib->pkt_rpt_type == TX_REPORT1) { /* CCX */ + pattrib->pkt_len = cpu_to_le16(TX_RPT1_PKT_LEN); + pattrib->drvinfo_sz = 0; + } else if (pattrib->pkt_rpt_type == TX_REPORT2) { /* TX RPT */ + pattrib->pkt_len = cpu_to_le16(le32_to_cpu(report.rxdw0) & 0x3FF); /* Rx length[9:0] */ + pattrib->drvinfo_sz = 0; + + /* */ + /* Get TX report MAC ID valid. */ + /* */ + pattrib->MacIDValidEntry[0] = report.rxdw4; + pattrib->MacIDValidEntry[1] = report.rxdw5; + } else if (pattrib->pkt_rpt_type == HIS_REPORT) { /* USB HISR RPT */ + pattrib->pkt_len = cpu_to_le16(le32_to_cpu(report.rxdw0) & 0x00003fff); /* (u16)prxreport->pktlen; */ + } + +} diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_sreset.c b/drivers/staging/rtl8188eu/hal/rtl8188e_sreset.c new file mode 100644 index 000000000000..8879174915ae --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_sreset.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#define _RTL8188E_SRESET_C_ + +/* #include */ +#include + +#ifdef DBG_CONFIG_ERROR_DETECT + +void rtl8188e_sreset_xmit_status_check(_adapter *padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct sreset_priv *psrtpriv = &pHalData->srestpriv; + + unsigned long current_time; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + unsigned int diff_time; + u32 txdma_status; + + txdma_status = rtw_read32(padapter, REG_TXDMA_STATUS); + if (txdma_status != 0x00 && txdma_status != 0xeaeaeaea) { + RTW_INFO("%s REG_TXDMA_STATUS:0x%08x\n", __func__, txdma_status); + rtw_hal_sreset_reset(padapter); + } + current_time = jiffies; + + if (0 == pxmitpriv->free_xmitbuf_cnt || 0 == pxmitpriv->free_xmit_extbuf_cnt) { + + diff_time = rtw_get_passing_time_ms(psrtpriv->last_tx_time); + + if (diff_time > 2000) { + if (psrtpriv->last_tx_complete_time == 0) + psrtpriv->last_tx_complete_time = current_time; + else { + diff_time = rtw_get_passing_time_ms(psrtpriv->last_tx_complete_time); + if (diff_time > 4000) { + u32 ability = 0; + + /* padapter->Wifi_Error_Status = WIFI_TX_HANG; */ + ability = rtw_phydm_ability_get(padapter); + RTW_INFO("%s tx hang %s\n", __func__, + (ability & ODM_BB_ADAPTIVITY) ? "ODM_BB_ADAPTIVITY" : ""); + + if (!(ability & ODM_BB_ADAPTIVITY)) + rtw_hal_sreset_reset(padapter); + } + } + } + } + + if (psrtpriv->dbg_trigger_point == SRESET_TGP_XMIT_STATUS) { + psrtpriv->dbg_trigger_point = SRESET_TGP_NULL; + rtw_hal_sreset_reset(padapter); + return; + } +} + +void rtl8188e_sreset_linked_status_check(_adapter *padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct sreset_priv *psrtpriv = &pHalData->srestpriv; + + u32 rx_dma_status = 0; + u8 fw_status = 0; + rx_dma_status = rtw_read32(padapter, REG_RXDMA_STATUS); + if (rx_dma_status != 0x00) { + RTW_INFO("%s REG_RXDMA_STATUS:0x%08x\n", __func__, rx_dma_status); + rtw_write32(padapter, REG_RXDMA_STATUS, rx_dma_status); + } + fw_status = rtw_read8(padapter, REG_FMETHR); + if (fw_status != 0x00) { + if (fw_status == 1) + RTW_INFO("%s REG_FW_STATUS (0x%02x), Read_Efuse_Fail !!\n", __func__, fw_status); + else if (fw_status == 2) + RTW_INFO("%s REG_FW_STATUS (0x%02x), Condition_No_Match !!\n", __func__, fw_status); + } + if (psrtpriv->dbg_trigger_point == SRESET_TGP_LINK_STATUS) { + psrtpriv->dbg_trigger_point = SRESET_TGP_NULL; + rtw_hal_sreset_reset(padapter); + return; + } +} +#endif diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c new file mode 100644 index 000000000000..cad2ac0ce2ee --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#define _RTL8188E_XMIT_C_ + +#include +#include + +#ifdef CONFIG_XMIT_ACK +void dump_txrpt_ccx_88e(void *buf) +{ + struct txrpt_ccx_88e *txrpt_ccx = (struct txrpt_ccx_88e *)buf; + + RTW_INFO("%s:\n" + "tag1:%u, pkt_num:%u, txdma_underflow:%u, int_bt:%u, int_tri:%u, int_ccx:%u\n" + "mac_id:%u, pkt_ok:%u, bmc:%u\n" + "retry_cnt:%u, lifetime_over:%u, retry_over:%u\n" + "ccx_qtime:%u\n" + "final_data_rate:0x%02x\n" + "qsel:%u, sw:0x%03x\n" + , __func__ + , txrpt_ccx->tag1, txrpt_ccx->pkt_num, txrpt_ccx->txdma_underflow, txrpt_ccx->int_bt, txrpt_ccx->int_tri, txrpt_ccx->int_ccx + , txrpt_ccx->mac_id, txrpt_ccx->pkt_ok, txrpt_ccx->bmc + , txrpt_ccx->retry_cnt, txrpt_ccx->lifetime_over, txrpt_ccx->retry_over + , txrpt_ccx_qtime_88e(txrpt_ccx) + , txrpt_ccx->final_data_rate + , txrpt_ccx->qsel, txrpt_ccx_sw_88e(txrpt_ccx) + ); +} + +void handle_txrpt_ccx_88e(_adapter *adapter, u8 *buf) +{ + struct txrpt_ccx_88e *txrpt_ccx = (struct txrpt_ccx_88e *)buf; + +#ifdef DBG_CCX + dump_txrpt_ccx_88e(buf); +#endif + + if (txrpt_ccx->int_ccx) { + if (txrpt_ccx->pkt_ok) + rtw_ack_tx_done(&adapter->xmitpriv, RTW_SCTX_DONE_SUCCESS); + else + rtw_ack_tx_done(&adapter->xmitpriv, RTW_SCTX_DONE_CCX_PKT_FAIL); + } +} +#endif /* CONFIG_XMIT_ACK */ + +void _dbg_dump_tx_info(_adapter *padapter, int frame_tag, struct tx_desc *ptxdesc) +{ + u8 bDumpTxPkt; + u8 bDumpTxDesc = false; + rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(bDumpTxPkt)); + + if (bDumpTxPkt == 1) { /* dump txdesc for data frame */ + RTW_INFO("dump tx_desc for data frame\n"); + if ((frame_tag & 0x0f) == DATA_FRAMETAG) + bDumpTxDesc = true; + } else if (bDumpTxPkt == 2) { /* dump txdesc for mgnt frame */ + RTW_INFO("dump tx_desc for mgnt frame\n"); + if ((frame_tag & 0x0f) == MGNT_FRAMETAG) + bDumpTxDesc = true; + } else if (bDumpTxPkt == 3) { /* dump early info */ + } + + if (bDumpTxDesc) { + /* ptxdesc->txdw4 = cpu_to_le32(0x00001006); */ /* RTS Rate=24M */ + /* ptxdesc->txdw6 = 0x6666f800; */ + RTW_INFO("=====================================\n"); + RTW_INFO("txdw0(0x%08x)\n", ptxdesc->txdw0); + RTW_INFO("txdw1(0x%08x)\n", ptxdesc->txdw1); + RTW_INFO("txdw2(0x%08x)\n", ptxdesc->txdw2); + RTW_INFO("txdw3(0x%08x)\n", ptxdesc->txdw3); + RTW_INFO("txdw4(0x%08x)\n", ptxdesc->txdw4); + RTW_INFO("txdw5(0x%08x)\n", ptxdesc->txdw5); + RTW_INFO("txdw6(0x%08x)\n", ptxdesc->txdw6); + RTW_INFO("txdw7(0x%08x)\n", ptxdesc->txdw7); + RTW_INFO("=====================================\n"); + } + +} + +/* + * Description: + * Aggregation packets and send to hardware + * + * Return: + * 0 Success + * -1 Hardware resource(TX FIFO) not ready + * -2 Software resource(xmitbuf) not ready + */ +#ifdef CONFIG_TX_EARLY_MODE + +/* #define DBG_EMINFO */ + +#if RTL8188E_EARLY_MODE_PKT_NUM_10 == 1 + #define EARLY_MODE_MAX_PKT_NUM 10 +#else + #define EARLY_MODE_MAX_PKT_NUM 5 +#endif + + +struct EMInfo { + u8 EMPktNum; + u16 EMPktLen[EARLY_MODE_MAX_PKT_NUM]; +}; + + +void +InsertEMContent_8188E( + struct EMInfo *pEMInfo, + IN u8 * VirtualAddress) +{ + +#if RTL8188E_EARLY_MODE_PKT_NUM_10 == 1 + u8 index = 0; + u32 dwtmp = 0; +#endif + + memset(VirtualAddress, 0, EARLY_MODE_INFO_SIZE); + if (pEMInfo->EMPktNum == 0) + return; + +#ifdef DBG_EMINFO + { + int i; + RTW_INFO("\n%s ==> pEMInfo->EMPktNum =%d\n", __func__, pEMInfo->EMPktNum); + for (i = 0; i < EARLY_MODE_MAX_PKT_NUM; i++) + RTW_INFO("%s ==> pEMInfo->EMPktLen[%d] =%d\n", __func__, i, pEMInfo->EMPktLen[i]); + + } +#endif + +#if RTL8188E_EARLY_MODE_PKT_NUM_10 == 1 + SET_EARLYMODE_PKTNUM(VirtualAddress, pEMInfo->EMPktNum); + + if (pEMInfo->EMPktNum == 1) + dwtmp = pEMInfo->EMPktLen[0]; + else { + dwtmp = pEMInfo->EMPktLen[0]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; + dwtmp += pEMInfo->EMPktLen[1]; + } + SET_EARLYMODE_LEN0(VirtualAddress, dwtmp); + if (pEMInfo->EMPktNum <= 3) + dwtmp = pEMInfo->EMPktLen[2]; + else { + dwtmp = pEMInfo->EMPktLen[2]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; + dwtmp += pEMInfo->EMPktLen[3]; + } + SET_EARLYMODE_LEN1(VirtualAddress, dwtmp); + if (pEMInfo->EMPktNum <= 5) + dwtmp = pEMInfo->EMPktLen[4]; + else { + dwtmp = pEMInfo->EMPktLen[4]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; + dwtmp += pEMInfo->EMPktLen[5]; + } + SET_EARLYMODE_LEN2_1(VirtualAddress, dwtmp & 0xF); + SET_EARLYMODE_LEN2_2(VirtualAddress, dwtmp >> 4); + if (pEMInfo->EMPktNum <= 7) + dwtmp = pEMInfo->EMPktLen[6]; + else { + dwtmp = pEMInfo->EMPktLen[6]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; + dwtmp += pEMInfo->EMPktLen[7]; + } + SET_EARLYMODE_LEN3(VirtualAddress, dwtmp); + if (pEMInfo->EMPktNum <= 9) + dwtmp = pEMInfo->EMPktLen[8]; + else { + dwtmp = pEMInfo->EMPktLen[8]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; + dwtmp += pEMInfo->EMPktLen[9]; + } + SET_EARLYMODE_LEN4(VirtualAddress, dwtmp); +#else + SET_EARLYMODE_PKTNUM(VirtualAddress, pEMInfo->EMPktNum); + SET_EARLYMODE_LEN0(VirtualAddress, pEMInfo->EMPktLen[0]); + SET_EARLYMODE_LEN1(VirtualAddress, pEMInfo->EMPktLen[1]); + SET_EARLYMODE_LEN2_1(VirtualAddress, pEMInfo->EMPktLen[2] & 0xF); + SET_EARLYMODE_LEN2_2(VirtualAddress, pEMInfo->EMPktLen[2] >> 4); + SET_EARLYMODE_LEN3(VirtualAddress, pEMInfo->EMPktLen[3]); + SET_EARLYMODE_LEN4(VirtualAddress, pEMInfo->EMPktLen[4]); +#endif + +} + + + +void UpdateEarlyModeInfo8188E(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) +{ + /* _adapter *padapter, struct xmit_frame *pxmitframe,struct tx_servq *ptxservq */ + int index, j; + u16 offset, pktlen; + PTXDESC_8188E ptxdesc; + + u8 *pmem, *pEMInfo_mem; + s8 node_num_0 = 0, node_num_1 = 0; + struct EMInfo eminfo; + struct agg_pkt_info *paggpkt; + struct xmit_frame *pframe = (struct xmit_frame *)pxmitbuf->priv_data; + pmem = pframe->buf_addr; + +#ifdef DBG_EMINFO + RTW_INFO("\n%s ==> agg_num:%d\n", __func__, pframe->agg_num); + for (index = 0; index < pframe->agg_num; index++) { + offset = pxmitpriv->agg_pkt[index].offset; + pktlen = pxmitpriv->agg_pkt[index].pkt_len; + RTW_INFO("%s ==> agg_pkt[%d].offset=%d\n", __func__, index, offset); + RTW_INFO("%s ==> agg_pkt[%d].pkt_len=%d\n", __func__, index, pktlen); + } +#endif + + if (pframe->agg_num > EARLY_MODE_MAX_PKT_NUM) { + node_num_0 = pframe->agg_num; + node_num_1 = EARLY_MODE_MAX_PKT_NUM - 1; + } + + for (index = 0; index < pframe->agg_num; index++) { + + offset = pxmitpriv->agg_pkt[index].offset; + pktlen = pxmitpriv->agg_pkt[index].pkt_len; + + memset(&eminfo, 0, sizeof(struct EMInfo)); + if (pframe->agg_num > EARLY_MODE_MAX_PKT_NUM) { + if (node_num_0 > EARLY_MODE_MAX_PKT_NUM) { + eminfo.EMPktNum = EARLY_MODE_MAX_PKT_NUM; + node_num_0--; + } else { + eminfo.EMPktNum = node_num_1; + node_num_1--; + } + } else + eminfo.EMPktNum = pframe->agg_num - (index + 1); + for (j = 0; j < eminfo.EMPktNum ; j++) { + eminfo.EMPktLen[j] = pxmitpriv->agg_pkt[index + 1 + j].pkt_len + 4; /* 4 bytes CRC */ + } + + if (pmem) { + if (index == 0) { + ptxdesc = (PTXDESC_8188E)(pmem); + pEMInfo_mem = ((u8 *)ptxdesc) + TXDESC_SIZE; + } else { + pmem = pmem + pxmitpriv->agg_pkt[index - 1].offset; + ptxdesc = (PTXDESC_8188E)(pmem); + pEMInfo_mem = ((u8 *)ptxdesc) + TXDESC_SIZE; + } + +#ifdef DBG_EMINFO + RTW_INFO("%s ==> desc.pkt_len=%d\n", __func__, ptxdesc->pktlen); +#endif + InsertEMContent_8188E(&eminfo, pEMInfo_mem); + } + + + } + memset(pxmitpriv->agg_pkt, 0, sizeof(struct agg_pkt_info) * MAX_AGG_PKT_NUM); + +} +#endif + +#if defined(CONFIG_CONCURRENT_MODE) +void fill_txdesc_force_bmc_camid(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc) +{ + if ((pattrib->encrypt > 0) && (!pattrib->bswenc) + && (pattrib->bmc_camid != INVALID_SEC_MAC_CAM_ID)) { + + ptxdesc->txdw1 |= cpu_to_le32((0x01 << 21) & 0x00200000); + ptxdesc->txdw1 |= cpu_to_le32((pattrib->bmc_camid) & 0x1f); + } +} +#endif + +void rtl8188e_cal_txdesc_chksum(struct tx_desc *ptxdesc) +{ + __le16 *usPtr = (__le16 *)ptxdesc; + u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */ + u32 index; + u16 checksum = 0; + + + /* Clear first */ + ptxdesc->txdw7 &= cpu_to_le32(0xffff0000); + + for (index = 0; index < count; index++) + checksum ^= le16_to_cpu(*(usPtr + index)); + + ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff); +} diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c new file mode 100644 index 000000000000..d787787c4e50 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + + +#include +#include + +/* ******************************************************************************** + * LED object. + * ******************************************************************************** */ + + +/* ******************************************************************************** + * Prototype of protected function. + * ******************************************************************************** */ + + +/* ******************************************************************************** + * LED_819xUsb routines. + * ******************************************************************************** */ + +/* + * Description: + * Turn on LED according to LedPin specified. + * */ +static void +SwLedOn_8188EU( + _adapter *padapter, + PLED_USB pLed +) +{ + u8 LedCfg; + /* HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); */ + + if (RTW_CANNOT_RUN(padapter)) + return; + + LedCfg = rtw_read8(padapter, REG_LEDCFG2); + switch (pLed->LedPin) { + case LED_PIN_LED0: + rtw_write8(padapter, REG_LEDCFG2, (LedCfg & 0xf0) | BIT5 | BIT6); /* SW control led0 on. */ + break; + + case LED_PIN_LED1: + rtw_write8(padapter, REG_LEDCFG2, (LedCfg & 0x0f) | BIT5); /* SW control led1 on. */ + break; + + default: + break; + } + + pLed->bLedOn = true; +} + + +/* + * Description: + * Turn off LED according to LedPin specified. + * */ +static void +SwLedOff_8188EU( + _adapter *padapter, + PLED_USB pLed +) +{ + u8 LedCfg; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + if (RTW_CANNOT_RUN(padapter)) + goto exit; + + + LedCfg = rtw_read8(padapter, REG_LEDCFG2);/* 0x4E */ + + switch (pLed->LedPin) { + case LED_PIN_LED0: + if (pHalData->bLedOpenDrain == true) { /* Open-drain arrangement for controlling the LED) */ + LedCfg &= 0x90; /* Set to software control. */ + rtw_write8(padapter, REG_LEDCFG2, (LedCfg | BIT3)); + LedCfg = rtw_read8(padapter, REG_MAC_PINMUX_CFG); + LedCfg &= 0xFE; + rtw_write8(padapter, REG_MAC_PINMUX_CFG, LedCfg); + } else + rtw_write8(padapter, REG_LEDCFG2, (LedCfg | BIT3 | BIT5 | BIT6)); + break; + + case LED_PIN_LED1: + LedCfg &= 0x0f; /* Set to software control. */ + rtw_write8(padapter, REG_LEDCFG2, (LedCfg | BIT3)); + break; + + default: + break; + } +exit: + pLed->bLedOn = false; + +} + +/* ******************************************************************************** + * Interface to manipulate LED objects. + * ******************************************************************************** */ + + +/* ******************************************************************************** + * Default LED behavior. + * ******************************************************************************** */ + +/* + * Description: + * Initialize all LED_871x objects. + * */ +void +rtl8188eu_InitSwLeds( + _adapter *padapter +) +{ + struct led_priv *pledpriv = &(padapter->ledpriv); + + pledpriv->LedControlHandler = LedControlUSB; + + pledpriv->SwLedOn = SwLedOn_8188EU; + pledpriv->SwLedOff = SwLedOff_8188EU; + + InitLed(padapter, &(pledpriv->SwLed0), LED_PIN_LED0); + + InitLed(padapter, &(pledpriv->SwLed1), LED_PIN_LED1); +} + + +/* + * Description: + * DeInitialize all LED_819xUsb objects. + * */ +void +rtl8188eu_DeInitSwLeds( + _adapter *padapter +) +{ + struct led_priv *ledpriv = &(padapter->ledpriv); + + DeInitLed(&(ledpriv->SwLed0)); + DeInitLed(&(ledpriv->SwLed1)); +} diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c new file mode 100644 index 000000000000..6c2e04222d88 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#define _RTL8188EU_RECV_C_ + +#include +#include + +int rtl8188eu_init_recv_priv(_adapter *padapter) +{ + return usb_init_recv_priv(padapter, INTERRUPT_MSG_FORMAT_LEN); +} + +void rtl8188eu_free_recv_priv(_adapter *padapter) +{ + usb_free_recv_priv(padapter, INTERRUPT_MSG_FORMAT_LEN); +} diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c new file mode 100644 index 000000000000..ed9a5fa6e76c --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c @@ -0,0 +1,1261 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#define _RTL8188E_XMIT_C_ + +#include +#include + + +s32 rtl8188eu_init_xmit_priv(_adapter *padapter) +{ + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + tasklet_init(&pxmitpriv->xmit_tasklet, + (void(*)(unsigned long))rtl8188eu_xmit_tasklet, + (unsigned long)padapter); +#ifdef CONFIG_TX_EARLY_MODE + pHalData->bEarlyModeEnable = padapter->registrypriv.early_mode; +#endif + + return _SUCCESS; +} + +void rtl8188eu_free_xmit_priv(_adapter *padapter) +{ +} + +static u8 urb_zero_packet_chk(_adapter *padapter, int sz) +{ + u8 blnSetTxDescOffset; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + blnSetTxDescOffset = (((sz + TXDESC_SIZE) % pHalData->UsbBulkOutSize) == 0) ? 1 : 0; + + return blnSetTxDescOffset; +} + +static void rtl8188eu_cal_txdesc_chksum(struct tx_desc *ptxdesc) +{ + __le16 *usPtr = (__le16 *)ptxdesc; + u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */ + u32 index; + u16 checksum = 0; + + /* Clear first */ + ptxdesc->txdw7 &= cpu_to_le32(0xffff0000); + + for (index = 0 ; index < count ; index++) + checksum = checksum ^ le16_to_cpu(*(usPtr + index)); + + ptxdesc->txdw7 |= cpu_to_le32(0x0000ffff & checksum); + +} +/* + * Description: In normal chip, we should send some packet to Hw which will be used by Fw + * in FW LPS mode. The function is to fill the Tx descriptor of this packets, then + * Fw can tell Hw to send these packet derectly. + * */ +void rtl8188e_fill_fake_txdesc( + PADAPTER padapter, + u8 *pDesc, + u32 BufferLen, + u8 IsPsPoll, + u8 IsBTQosNull, + u8 bDataFrame) +{ + struct tx_desc *ptxdesc; + + + /* Clear all status */ + ptxdesc = (struct tx_desc *)pDesc; + memset(pDesc, 0, TXDESC_SIZE); + + /* offset 0 */ + ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); /* own, bFirstSeg, bLastSeg; */ + + ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) & 0x00ff0000); /* 32 bytes for TX Desc */ + + ptxdesc->txdw0 |= cpu_to_le32(BufferLen & 0x0000ffff); /* Buffer size + command header */ + + /* offset 4 */ + ptxdesc->txdw1 |= cpu_to_le32((QSLT_MGNT << QSEL_SHT) & 0x00001f00); /* Fixed queue of Mgnt queue */ + + /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error vlaue by Hw. */ + if (IsPsPoll) + ptxdesc->txdw1 |= cpu_to_le32(NAVUSEHDR); + else { + ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); /* Hw set sequence number */ + ptxdesc->txdw3 |= cpu_to_le32((8 << 28)); /* set bit3 to 1. Suugested by TimChen. 2009.12.29. */ + } + + if (IsBTQosNull) { + ptxdesc->txdw2 |= cpu_to_le32(BIT(23)); /* BT NULL */ + } + + /* offset 16 */ + ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */ + + /* */ + /* Encrypt the data frame if under security mode excepct null data. Suggested by CCW. */ + /* */ + if (bDataFrame) { + u32 EncAlg; + + EncAlg = padapter->securitypriv.dot11PrivacyAlgrthm; + switch (EncAlg) { + case _NO_PRIVACY_: + SET_TX_DESC_SEC_TYPE_8188E(pDesc, 0x0); + break; + case _WEP40_: + case _WEP104_: + case _TKIP_: + SET_TX_DESC_SEC_TYPE_8188E(pDesc, 0x1); + break; + case _SMS4_: + SET_TX_DESC_SEC_TYPE_8188E(pDesc, 0x2); + break; + case _AES_: + SET_TX_DESC_SEC_TYPE_8188E(pDesc, 0x3); + break; + default: + SET_TX_DESC_SEC_TYPE_8188E(pDesc, 0x0); + break; + } + } + /* USB interface drop packet if the checksum of descriptor isn't correct. */ + /* Using this checksum can let hardware recovery from packet bulk out error (e.g. Cancel URC, Bulk out error.). */ + rtl8188eu_cal_txdesc_chksum(ptxdesc); +} + +static void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc) +{ + if ((pattrib->encrypt > 0) && !pattrib->bswenc) { + switch (pattrib->encrypt) { + /* SEC_TYPE : 0:NO_ENC,1:WEP40/TKIP,2:WAPI,3:AES */ + case _WEP40_: + case _WEP104_: + ptxdesc->txdw1 |= cpu_to_le32((0x01 << SEC_TYPE_SHT) & 0x00c00000); + ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT); + break; + case _TKIP_: + case _TKIP_WTMIC_: + ptxdesc->txdw1 |= cpu_to_le32((0x01 << SEC_TYPE_SHT) & 0x00c00000); + ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT); + break; +#ifdef CONFIG_WAPI_SUPPORT + case _SMS4_: + ptxdesc->txdw1 |= cpu_to_le32((0x02 << SEC_TYPE_SHT) & 0x00c00000); + ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT); + break; +#endif + case _AES_: + ptxdesc->txdw1 |= cpu_to_le32((0x03 << SEC_TYPE_SHT) & 0x00c00000); + ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT); + break; + case _NO_PRIVACY_: + default: + break; + + } + + } + +} + +static void fill_txdesc_vcs(struct pkt_attrib *pattrib, __le32 *pdw) +{ + /* RTW_INFO("cvs_mode=%d\n", pattrib->vcs_mode); */ + + switch (pattrib->vcs_mode) { + case RTS_CTS: + *pdw |= cpu_to_le32(RTS_EN); + break; + case CTS_TO_SELF: + *pdw |= cpu_to_le32(CTS_2_SELF); + break; + case NONE_VCS: + default: + break; + } + + if (pattrib->vcs_mode) { + *pdw |= cpu_to_le32(HW_RTS_EN); + + /* Set RTS BW */ + if (pattrib->ht_en) { + *pdw |= (pattrib->bwmode & CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(27)) : 0; + + if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) + *pdw |= cpu_to_le32((0x01 << 28) & 0x30000000); + else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) + *pdw |= cpu_to_le32((0x02 << 28) & 0x30000000); + else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) + *pdw |= 0; + else + *pdw |= cpu_to_le32((0x03 << 28) & 0x30000000); + } + } +} + +static void fill_txdesc_phy(struct pkt_attrib *pattrib, __le32 *pdw) +{ + /* RTW_INFO("bwmode=%d, ch_off=%d\n", pattrib->bwmode, pattrib->ch_offset); */ + + if (pattrib->ht_en) { + *pdw |= (pattrib->bwmode & CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0; + + if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) + *pdw |= cpu_to_le32((0x01 << DATA_SC_SHT) & 0x003f0000); + else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) + *pdw |= cpu_to_le32((0x02 << DATA_SC_SHT) & 0x003f0000); + else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) + *pdw |= 0; + else + *pdw |= cpu_to_le32((0x03 << DATA_SC_SHT) & 0x003f0000); + } +} + + +static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz , u8 bagg_pkt) +{ + int pull = 0; + uint qsel; + bool sgi = 0; + u8 data_rate = 0, pwr_status, offset; + _adapter *padapter = pxmitframe->padapter; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct pkt_attrib *pattrib = &pxmitframe->attrib; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + + struct tx_desc *ptxdesc = (struct tx_desc *)pmem; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + sint bmcst = IS_MCAST(pattrib->ra); +#ifdef CONFIG_P2P + struct wifidirect_info *pwdinfo = &padapter->wdinfo; +#endif /* CONFIG_P2P */ + +#ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX + if (padapter->registrypriv.mp_mode == 0) { + /* if((!bagg_pkt) &&(urb_zero_packet_chk(padapter, sz)==0)) */ /* (sz %512) != 0 */ + if ((PACKET_OFFSET_SZ != 0) && (!bagg_pkt) && (rtw_usb_bulk_size_boundary(padapter, TXDESC_SIZE + sz) == false)) { + ptxdesc = (struct tx_desc *)(pmem + PACKET_OFFSET_SZ); + /* RTW_INFO("==> non-agg-pkt,shift pointer...\n"); */ + pull = 1; + } + } +#endif /* CONFIG_USE_USB_BUFFER_ALLOC_TX */ + + memset(ptxdesc, 0, sizeof(struct tx_desc)); + + /* 4 offset 0 */ + ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); + /* RTW_INFO("%s==> pkt_len=%d,bagg_pkt=%02x\n",__func__,sz,bagg_pkt); */ + ptxdesc->txdw0 |= cpu_to_le32(sz & 0x0000ffff);/* update TXPKTSIZE */ + + offset = TXDESC_SIZE + OFFSET_SZ; + +#ifdef CONFIG_TX_EARLY_MODE + if (bagg_pkt) { + offset += EARLY_MODE_INFO_SIZE ;/* 0x28 */ + } +#endif + /* RTW_INFO("%s==>offset(0x%02x)\n",__func__,offset); */ + ptxdesc->txdw0 |= cpu_to_le32(((offset) << OFFSET_SHT) & 0x00ff0000);/* 32 bytes for TX Desc */ + + if (bmcst) + ptxdesc->txdw0 |= cpu_to_le32(BMC); + +#ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX + if (padapter->registrypriv.mp_mode == 0) { + if ((PACKET_OFFSET_SZ != 0) && (!bagg_pkt)) { + if ((pull) && (pxmitframe->pkt_offset > 0)) + pxmitframe->pkt_offset = pxmitframe->pkt_offset - 1; + } + } +#endif + /* RTW_INFO("%s, pkt_offset=0x%02x\n",__func__,pxmitframe->pkt_offset); */ + + /* pkt_offset, unit:8 bytes padding */ + if (pxmitframe->pkt_offset > 0) + ptxdesc->txdw1 |= cpu_to_le32((pxmitframe->pkt_offset << 26) & 0x7c000000); + + if ((pxmitframe->frame_tag & 0x0f) == DATA_FRAMETAG) { + /* RTW_INFO("pxmitframe->frame_tag == DATA_FRAMETAG\n"); */ + + /* offset 4 */ + ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id & 0x3F); + + qsel = (uint)(pattrib->qsel & 0x0000001f); + /* RTW_INFO("==> macid(%d) qsel:0x%02x\n",pattrib->mac_id,qsel); */ + ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); + + ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000F0000); + + fill_txdesc_sectype(pattrib, ptxdesc); + +#if defined(CONFIG_CONCURRENT_MODE) + if (bmcst) + fill_txdesc_force_bmc_camid(pattrib, ptxdesc); +#endif + + if (pattrib->ampdu_en == true) { + ptxdesc->txdw2 |= cpu_to_le32(AGG_EN);/* AGG EN */ + ptxdesc->txdw2 |= cpu_to_le32((pattrib->ampdu_spacing << + AMPDU_DENSITY_SHT) & 0x00700000); + + /* SET_TX_DESC_MAX_AGG_NUM_88E(pDesc, 0x1F); */ + /* SET_TX_DESC_MCSG1_MAX_LEN_88E(pDesc, 0x6); */ + /* SET_TX_DESC_MCSG2_MAX_LEN_88E(pDesc, 0x6); */ + /* SET_TX_DESC_MCSG3_MAX_LEN_88E(pDesc, 0x6); */ + /* SET_TX_DESC_MCS7_SGI_MAX_LEN_88E(pDesc, 0x6); */ + ptxdesc->txdw6 = cpu_to_le32(0x6666f800); + } else { + ptxdesc->txdw2 |= cpu_to_le32(AGG_BK);/* AGG BK */ + } + + /* offset 8 */ + + + /* offset 12 */ + ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum << SEQ_SHT) & 0x0FFF0000); + + + /* offset 16 , offset 20 */ + if (pattrib->qos_en) + ptxdesc->txdw4 |= cpu_to_le32(QOS);/* QoS */ + + /* offset 20 */ +#ifdef CONFIG_USB_TX_AGGREGATION + if (pxmitframe->agg_num > 1) { + /* RTW_INFO("%s agg_num:%d\n",__func__,pxmitframe->agg_num ); */ + ptxdesc->txdw5 |= cpu_to_le32((pxmitframe->agg_num << USB_TXAGG_NUM_SHT) & 0xFF000000); + } +#endif + + if ((pattrib->ether_type != 0x888e) && + (pattrib->ether_type != 0x0806) && + (pattrib->ether_type != 0x88b4) && + (pattrib->dhcp_pkt != 1)) { + /* Non EAP & ARP & DHCP type data packet */ + + fill_txdesc_vcs(pattrib, &ptxdesc->txdw4); + fill_txdesc_phy(pattrib, &ptxdesc->txdw4); + + ptxdesc->txdw4 |= cpu_to_le32(0x00000008);/* RTS Rate=24M */ + ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);/* DATA/RTS Rate FB LMT */ + +#if (RATE_ADAPTIVE_SUPPORT == 1) + if (pHalData->fw_ractrl == false) { + /* driver-based RA*/ + /* driver uses rate */ + ptxdesc->txdw4 |= cpu_to_le32(USERATE);/* rate control always by driver */ + if (pattrib->ht_en) + sgi = odm_ra_get_sgi_8188e(&pHalData->odmpriv, pattrib->mac_id); + + data_rate = odm_ra_get_decision_rate_8188e(&pHalData->odmpriv, pattrib->mac_id); + +#if (POWER_TRAINING_ACTIVE == 1) + pwr_status = odm_ra_get_hw_pwr_status_8188e(&pHalData->odmpriv, pattrib->mac_id); + ptxdesc->txdw4 |= cpu_to_le32((pwr_status & 0x7) << PWR_STATUS_SHT); +#endif + } else +#endif/* if (RATE_ADAPTIVE_SUPPORT == 1) */ + { + /* FW-based RA, TODO */ + if (pattrib->ht_en) + sgi = 1; + + data_rate = 0x13; /* default rate: MCS7 */ + } + + if (padapter->fix_rate != 0xFF) { + data_rate = padapter->fix_rate; + ptxdesc->txdw4 |= cpu_to_le32(USERATE); + if (!padapter->data_fb) + ptxdesc->txdw4 |= cpu_to_le32(DISDATAFB); + sgi = (padapter->fix_rate & BIT(7)) ? 1 : 0; + } + + if (sgi) + ptxdesc->txdw5 |= cpu_to_le32(SGI); + + ptxdesc->txdw5 |= cpu_to_le32(data_rate & 0x3F); + } else { + /* EAP data packet and ARP packet and DHCP. */ + /* Use the 1M data rate to send the EAP/ARP packet. */ + /* This will maybe make the handshake smooth. */ + + /* driver uses rate */ + ptxdesc->txdw4 |= cpu_to_le32(USERATE);/* rate control always by driver */ + ptxdesc->txdw2 |= cpu_to_le32(AGG_BK);/* AGG BK */ + + if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT) + ptxdesc->txdw4 |= cpu_to_le32(BIT(24));/* DATA_SHORT */ + + ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate)); + } + +#ifdef CONFIG_TCP_CSUM_OFFLOAD_TX + /* offset 24 */ + if (pattrib->hw_tcp_csum == 1) { + /* ptxdesc->txdw6 = 0; */ /* clear TCP_CHECKSUM and IP_CHECKSUM. It's zero already!! */ + u8 ip_hdr_offset = 32 + pattrib->hdrlen + pattrib->iv_len + 8; + ptxdesc->txdw7 = (1 << 31) | (ip_hdr_offset << 16); + RTW_INFO("ptxdesc->txdw7 = %08x\n", ptxdesc->txdw7); + } +#endif + +#ifdef CONFIG_TDLS +#ifdef CONFIG_XMIT_ACK + /* CCX-TXRPT ack for xmit mgmt frames. */ + if (pxmitframe->ack_report) { +#ifdef DBG_CCX + static u16 ccx_sw = 0x123; + + ptxdesc->txdw7 |= cpu_to_le32(((ccx_sw) << 16) & 0x0fff0000); + RTW_INFO("%s set ccx, sw:0x%03x\n", __func__, ccx_sw); + ccx_sw = (ccx_sw + 1) % 0xfff; +#endif + ptxdesc->txdw2 |= cpu_to_le32(BIT(19)); + } +#endif /* CONFIG_XMIT_ACK */ +#endif + } else if ((pxmitframe->frame_tag & 0x0f) == MGNT_FRAMETAG) { + /* RTW_INFO("pxmitframe->frame_tag == MGNT_FRAMETAG\n"); */ + /* driver uses rate */ + ptxdesc->txdw4 |= cpu_to_le32(USERATE);/* rate control always by driver */ + + /* offset 4 */ + ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id & 0x3f); + + qsel = (uint)(pattrib->qsel & 0x0000001f); + ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); + + ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000f0000); + + /* fill_txdesc_sectype(pattrib, ptxdesc); */ + + /* offset 8 */ +#ifdef CONFIG_XMIT_ACK + /* CCX-TXRPT ack for xmit mgmt frames. */ + if (pxmitframe->ack_report) { +#ifdef DBG_CCX + static u16 ccx_sw = 0x123; + ptxdesc->txdw7 |= cpu_to_le32(((ccx_sw) << 16) & 0x0fff0000); + RTW_INFO("%s set ccx, sw:0x%03x\n", __func__, ccx_sw); + ccx_sw = (ccx_sw + 1) % 0xfff; +#endif + ptxdesc->txdw2 |= cpu_to_le32(BIT(19)); + } +#endif /* CONFIG_XMIT_ACK */ + + /* offset 12 */ + ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum << SEQ_SHT) & 0x0FFF0000); + + /* offset 20 */ + ptxdesc->txdw5 |= cpu_to_le32(RTY_LMT_EN);/* retry limit enable */ + if (pattrib->retry_ctrl == true) + ptxdesc->txdw5 |= cpu_to_le32(0x00180000);/* retry limit = 6 */ + else + ptxdesc->txdw5 |= cpu_to_le32(0x00300000);/* retry limit = 12 */ + + ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pattrib->rate)); + + } else if ((pxmitframe->frame_tag & 0x0f) == TXAGG_FRAMETAG) + RTW_INFO("pxmitframe->frame_tag == TXAGG_FRAMETAG\n"); +#ifdef CONFIG_MP_INCLUDED + else if (((pxmitframe->frame_tag & 0x0f) == MP_FRAMETAG) && + (padapter->registrypriv.mp_mode == 1)) + fill_txdesc_for_mp(padapter, (u8 *)ptxdesc); +#endif + else { + RTW_INFO("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag); + + /* offset 4 */ + ptxdesc->txdw1 |= cpu_to_le32((4) & 0x3f); /* CAM_ID(MAC_ID) */ + + ptxdesc->txdw1 |= cpu_to_le32((6 << RATE_ID_SHT) & 0x000f0000); /* raid */ + + /* offset 8 */ + + /* offset 12 */ + ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum << SEQ_SHT) & 0x0fff0000); + + /* offset 20 */ + ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate)); + } + + /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. */ + /* (1) The sequence number of each non-Qos frame / broadcast / multicast / */ + /* mgnt frame should be controled by Hw because Fw will also send null data */ + /* which we cannot control when Fw LPS enable. */ + /* --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */ + /* (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */ + /* (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. */ + /* 2010.06.23. Added by tynli. */ + if (!pattrib->qos_en) { + /* ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); */ /* Hw set sequence number */ + /* ptxdesc->txdw3 |= cpu_to_le32((8 <<28)); */ /* set bit3 to 1. Suugested by TimChen. 2009.12.29. */ + + ptxdesc->txdw3 |= cpu_to_le32(EN_HWSEQ); /* Hw set sequence number */ + ptxdesc->txdw4 |= cpu_to_le32(HW_SSN); /* Hw set sequence number */ + + } + +#ifdef CONFIG_ANTENNA_DIVERSITY + odm_set_tx_ant_by_tx_info(&pHalData->odmpriv, pmem, pattrib->mac_id); +#endif + + rtl8188eu_cal_txdesc_chksum(ptxdesc); + _dbg_dump_tx_info(padapter, pxmitframe->frame_tag, ptxdesc); + return pull; + +} + + +#ifdef CONFIG_XMIT_THREAD_MODE +/* + * Description + * Transmit xmitbuf to hardware tx fifo + * + * Return + * _SUCCESS ok + * _FAIL something error + */ +s32 rtl8188eu_xmit_buf_handler(PADAPTER padapter) +{ + /* PHAL_DATA_TYPE phal; */ + struct xmit_priv *pxmitpriv; + struct xmit_buf *pxmitbuf; + s32 ret; + + + /* phal = GET_HAL_DATA(padapter); */ + pxmitpriv = &padapter->xmitpriv; + + ret = _rtw_down_sema(&pxmitpriv->xmit_sema); + if (_FAIL == ret) { + return _FAIL; + } + if (RTW_CANNOT_RUN(padapter)) { + return _FAIL; + } + + if (rtw_mi_check_pending_xmitbuf(padapter) == 0) + return _SUCCESS; + +#ifdef CONFIG_LPS_LCLK + ret = rtw_register_tx_alive(padapter); + if (ret != _SUCCESS) { + return _SUCCESS; + } +#endif + + do { + pxmitbuf = dequeue_pending_xmitbuf(pxmitpriv); + if (pxmitbuf == NULL) + break; + + rtw_write_port(padapter, pxmitbuf->ff_hwaddr, pxmitbuf->len, (unsigned char *)pxmitbuf); + + } while (1); + +#ifdef CONFIG_LPS_LCLK + rtw_unregister_tx_alive(padapter); +#endif + + return _SUCCESS; +} +#endif + +#ifdef CONFIG_IOL_IOREG_CFG_DBG + #include +#endif +/* for non-agg data frame or management frame */ +static s32 rtw_dump_xframe(_adapter *padapter, struct xmit_frame *pxmitframe) +{ + s32 ret = _SUCCESS; + s32 inner_ret = _SUCCESS; + int t, sz, w_sz, pull = 0; + u8 *mem_addr; + u32 ff_hwaddr; + struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf; + struct pkt_attrib *pattrib = &pxmitframe->attrib; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct security_priv *psecuritypriv = &padapter->securitypriv; + if ((pxmitframe->frame_tag == DATA_FRAMETAG) && + (pxmitframe->attrib.ether_type != 0x0806) && + (pxmitframe->attrib.ether_type != 0x888e) && + (pxmitframe->attrib.ether_type != 0x88b4) && + (pxmitframe->attrib.dhcp_pkt != 1)) + rtw_issue_addbareq_cmd(padapter, pxmitframe); + mem_addr = pxmitframe->buf_addr; + + + for (t = 0; t < pattrib->nr_frags; t++) { + if (inner_ret != _SUCCESS && ret == _SUCCESS) + ret = _FAIL; + + if (t != (pattrib->nr_frags - 1)) { + + sz = pxmitpriv->frag_len; + sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 : pattrib->icv_len); + } else /* no frag */ + sz = pattrib->last_txcmdsz; + + pull = update_txdesc(pxmitframe, mem_addr, sz, false); + + if (pull) { + mem_addr += PACKET_OFFSET_SZ; /* pull txdesc head */ + + /* pxmitbuf->pbuf = mem_addr; */ + pxmitframe->buf_addr = mem_addr; + + w_sz = sz + TXDESC_SIZE; + } else + w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ; +#ifdef CONFIG_IOL_IOREG_CFG_DBG + rtw_IOL_cmd_buf_dump(padapter, w_sz, pxmitframe->buf_addr); +#endif + ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe); + +#ifdef CONFIG_XMIT_THREAD_MODE + pxmitbuf->len = w_sz; + pxmitbuf->ff_hwaddr = ff_hwaddr; + enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf); +#else + /* RTW_INFO("%s: rtw_write_port size =%d\n", __func__,w_sz); */ + inner_ret = rtw_write_port(padapter, ff_hwaddr, w_sz, (unsigned char *)pxmitbuf); +#endif + + rtw_count_tx_stats(padapter, pxmitframe, sz); + + /* RTW_INFO("rtw_write_port, w_sz=%d, sz=%d, txdesc_sz=%d, tid=%d\n", w_sz, sz, w_sz-sz, pattrib->priority); */ + + mem_addr += w_sz; + + mem_addr = (u8 *)RND4(((SIZE_PTR)(mem_addr))); + + } + + rtw_free_xmitframe(pxmitpriv, pxmitframe); + + if (ret != _SUCCESS) + rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN); + + return ret; +} + +#ifdef CONFIG_USB_TX_AGGREGATION +static u32 xmitframe_need_length(struct xmit_frame *pxmitframe) +{ + struct pkt_attrib *pattrib = &pxmitframe->attrib; + + u32 len = 0; + + /* no consider fragement */ + len = pattrib->hdrlen + pattrib->iv_len + + SNAP_SIZE + sizeof(u16) + + pattrib->pktlen + + ((pattrib->bswenc) ? pattrib->icv_len : 0); + + if (pattrib->encrypt == _TKIP_) + len += 8; + + return len; +} + +#define IDEA_CONDITION 1 /* check all packets before enqueue */ +s32 rtl8188eu_xmitframe_complete(_adapter *padapter, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct xmit_frame *pxmitframe = NULL; + struct xmit_frame *pfirstframe = NULL; + + /* aggregate variable */ + struct hw_xmit *phwxmit; + struct sta_info *psta = NULL; + struct tx_servq *ptxservq = NULL; + + unsigned long irqL; + _list *xmitframe_plist = NULL, *xmitframe_phead = NULL; + + u32 pbuf; /* next pkt address */ + u32 pbuf_tail; /* last pkt tail */ + u32 len; /* packet length, except TXDESC_SIZE and PKT_OFFSET */ + + u32 bulkSize = pHalData->UsbBulkOutSize; + u8 descCount; + u32 bulkPtr; + + /* dump frame variable */ + u32 ff_hwaddr; + + _list *sta_plist, *sta_phead; + u8 single_sta_in_queue = false; + +#ifndef IDEA_CONDITION + int res = _SUCCESS; +#endif + + + + /* check xmitbuffer is ok */ + if (pxmitbuf == NULL) { + pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); + if (pxmitbuf == NULL) { + /* RTW_INFO("%s #1, connot alloc xmitbuf!!!!\n",__func__); */ + return false; + } + } + + /* RTW_INFO("%s =====================================\n",__func__); */ + /* 3 1. pick up first frame */ + do { + rtw_free_xmitframe(pxmitpriv, pxmitframe); + + pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); + if (pxmitframe == NULL) { + /* no more xmit frame, release xmit buffer */ + /* RTW_INFO("no more xmit frame ,return\n"); */ + rtw_free_xmitbuf(pxmitpriv, pxmitbuf); + return false; + } + +#ifndef IDEA_CONDITION + if (pxmitframe->frame_tag != DATA_FRAMETAG) { + /* rtw_free_xmitframe(pxmitpriv, pxmitframe); */ + continue; + } + + /* TID 0~15 */ + if ((pxmitframe->attrib.priority < 0) || + (pxmitframe->attrib.priority > 15)) { + /* rtw_free_xmitframe(pxmitpriv, pxmitframe); */ + continue; + } +#endif + /* RTW_INFO("==> pxmitframe->attrib.priority:%d\n",pxmitframe->attrib.priority); */ + pxmitframe->pxmitbuf = pxmitbuf; + pxmitframe->buf_addr = pxmitbuf->pbuf; + pxmitbuf->priv_data = pxmitframe; + + pxmitframe->agg_num = 1; /* alloc xmitframe should assign to 1. */ +#ifdef CONFIG_TX_EARLY_MODE + pxmitframe->pkt_offset = (PACKET_OFFSET_SZ / 8) + 1; /* 2; */ /* first frame of aggregation, reserve one offset for EM info ,another for usb bulk-out block check */ +#else + pxmitframe->pkt_offset = (PACKET_OFFSET_SZ / 8); /* 1; */ /* first frame of aggregation, reserve offset */ +#endif + + if (rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe) == false) { + RTW_INFO("%s coalesce 1st xmitframe failed\n", __func__); + continue; + } + + /* always return ndis_packet after rtw_xmitframe_coalesce */ + rtw_os_xmit_complete(padapter, pxmitframe); + + break; + } while (1); + + /* 3 2. aggregate same priority and same DA(AP or STA) frames */ + pfirstframe = pxmitframe; + len = xmitframe_need_length(pfirstframe) + TXDESC_SIZE + (pfirstframe->pkt_offset * PACKET_OFFSET_SZ); + pbuf_tail = len; + pbuf = _RND8(pbuf_tail); + + /* check pkt amount in one bulk */ + descCount = 0; + bulkPtr = bulkSize; + if (pbuf < bulkPtr) { + descCount++; + if (descCount == pHalData->UsbTxAggDescNum) + goto agg_end; + } else { + descCount = 0; + bulkPtr = ((pbuf / bulkSize) + 1) * bulkSize; /* round to next bulkSize */ + } + + /* dequeue same priority packet from station tx queue */ + /* psta = pfirstframe->attrib.psta; */ + psta = rtw_get_stainfo(&padapter->stapriv, pfirstframe->attrib.ra); + if (pfirstframe->attrib.psta != psta) + RTW_INFO("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pfirstframe->attrib.psta, psta); + if (psta == NULL) + RTW_INFO("rtw_xmit_classifier: psta == NULL\n"); + if (!(psta->state & _FW_LINKED)) + RTW_INFO("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state); + + switch (pfirstframe->attrib.priority) { + case 1: + case 2: + ptxservq = &(psta->sta_xmitpriv.bk_q); + phwxmit = pxmitpriv->hwxmits + 3; + break; + + case 4: + case 5: + ptxservq = &(psta->sta_xmitpriv.vi_q); + phwxmit = pxmitpriv->hwxmits + 1; + break; + + case 6: + case 7: + ptxservq = &(psta->sta_xmitpriv.vo_q); + phwxmit = pxmitpriv->hwxmits; + break; + + case 0: + case 3: + default: + ptxservq = &(psta->sta_xmitpriv.be_q); + phwxmit = pxmitpriv->hwxmits + 2; + break; + } + /* RTW_INFO("==> pkt_no=%d,pkt_len=%d,len=%d,RND8_LEN=%d,pkt_offset=0x%02x\n", */ + /* pxmitframe->agg_num,pxmitframe->attrib.last_txcmdsz,len,pbuf,pxmitframe->pkt_offset ); */ + + _enter_critical_bh(&pxmitpriv->lock, &irqL); + + sta_phead = get_list_head(phwxmit->sta_queue); + sta_plist = get_next(sta_phead); + single_sta_in_queue = rtw_end_of_queue_search(sta_phead, get_next(sta_plist)); + + xmitframe_phead = get_list_head(&ptxservq->sta_pending); + xmitframe_plist = get_next(xmitframe_phead); + + while (rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist) == false) { + pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list); + xmitframe_plist = get_next(xmitframe_plist); + + if (_FAIL == rtw_hal_busagg_qsel_check(padapter, pfirstframe->attrib.qsel, pxmitframe->attrib.qsel)) + break; + + pxmitframe->agg_num = 0; /* not first frame of aggregation */ +#ifdef CONFIG_TX_EARLY_MODE + pxmitframe->pkt_offset = 1;/* not first frame of aggregation,reserve offset for EM Info */ +#else + pxmitframe->pkt_offset = 0; /* not first frame of aggregation, no need to reserve offset */ +#endif + + len = xmitframe_need_length(pxmitframe) + TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ); + + if (_RND8(pbuf + len) > MAX_XMITBUF_SZ) + /* if (_RND8(pbuf + len) > (MAX_XMITBUF_SZ/2))//to do : for TX TP finial tune , Georgia 2012-0323 */ + { + /* RTW_INFO("%s....len> MAX_XMITBUF_SZ\n",__func__); */ + pxmitframe->agg_num = 1; + pxmitframe->pkt_offset = 1; + break; + } + list_del_init(&pxmitframe->list); + ptxservq->qcnt--; + phwxmit->accnt--; + +#ifndef IDEA_CONDITION + /* suppose only data frames would be in queue */ + if (pxmitframe->frame_tag != DATA_FRAMETAG) { + rtw_free_xmitframe(pxmitpriv, pxmitframe); + continue; + } + + /* TID 0~15 */ + if ((pxmitframe->attrib.priority < 0) || + (pxmitframe->attrib.priority > 15)) { + rtw_free_xmitframe(pxmitpriv, pxmitframe); + continue; + } +#endif + + /* pxmitframe->pxmitbuf = pxmitbuf; */ + pxmitframe->buf_addr = pxmitbuf->pbuf + pbuf; + + if (rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe) == false) { + RTW_INFO("%s coalesce failed\n", __func__); + rtw_free_xmitframe(pxmitpriv, pxmitframe); + continue; + } + + /* RTW_INFO("==> pxmitframe->attrib.priority:%d\n",pxmitframe->attrib.priority); */ + /* always return ndis_packet after rtw_xmitframe_coalesce */ + rtw_os_xmit_complete(padapter, pxmitframe); + + /* (len - TXDESC_SIZE) == pxmitframe->attrib.last_txcmdsz */ + update_txdesc(pxmitframe, pxmitframe->buf_addr, pxmitframe->attrib.last_txcmdsz, true); + + /* don't need xmitframe any more */ + rtw_free_xmitframe(pxmitpriv, pxmitframe); + + /* handle pointer and stop condition */ + pbuf_tail = pbuf + len; + pbuf = _RND8(pbuf_tail); + + + pfirstframe->agg_num++; +#ifdef CONFIG_TX_EARLY_MODE + pxmitpriv->agg_pkt[pfirstframe->agg_num - 1].offset = _RND8(len); + pxmitpriv->agg_pkt[pfirstframe->agg_num - 1].pkt_len = pxmitframe->attrib.last_txcmdsz; +#endif + if (MAX_TX_AGG_PACKET_NUMBER == pfirstframe->agg_num) + break; + + if (pbuf < bulkPtr) { + descCount++; + if (descCount == pHalData->UsbTxAggDescNum) + break; + } else { + descCount = 0; + bulkPtr = ((pbuf / bulkSize) + 1) * bulkSize; + } + } /* end while( aggregate same priority and same DA(AP or STA) frames) */ + if (_rtw_queue_empty(&ptxservq->sta_pending) == true) + list_del_init(&ptxservq->tx_pending); + else if (single_sta_in_queue == false) { + /* Re-arrange the order of stations in this ac queue to balance the service for these stations */ + list_del_init(&ptxservq->tx_pending); + list_add_tail(&ptxservq->tx_pending, get_list_head(phwxmit->sta_queue)); + } + + _exit_critical_bh(&pxmitpriv->lock, &irqL); + +agg_end: + + if ((pfirstframe->attrib.ether_type != 0x0806) && + (pfirstframe->attrib.ether_type != 0x888e) && + (pfirstframe->attrib.ether_type != 0x88b4) && + (pfirstframe->attrib.dhcp_pkt != 1)) + rtw_issue_addbareq_cmd(padapter, pfirstframe); +#ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX + /* 3 3. update first frame txdesc */ + if ((PACKET_OFFSET_SZ != 0) && ((pbuf_tail % bulkSize) == 0)) { + /* remove pkt_offset */ + pbuf_tail -= PACKET_OFFSET_SZ; + pfirstframe->buf_addr += PACKET_OFFSET_SZ; + pfirstframe->pkt_offset--; + /* RTW_INFO("$$$$$ buf size equal to USB block size $$$$$$\n"); */ + } +#endif /* CONFIG_USE_USB_BUFFER_ALLOC_TX */ + + update_txdesc(pfirstframe, pfirstframe->buf_addr, pfirstframe->attrib.last_txcmdsz, true); + +#ifdef CONFIG_TX_EARLY_MODE + /* prepare EM info for first frame, agg_num value start from 1 */ + pxmitpriv->agg_pkt[0].offset = _RND8(pfirstframe->attrib.last_txcmdsz + TXDESC_SIZE + (pfirstframe->pkt_offset * PACKET_OFFSET_SZ)); + pxmitpriv->agg_pkt[0].pkt_len = pfirstframe->attrib.last_txcmdsz;/* get from rtw_xmitframe_coalesce */ + + UpdateEarlyModeInfo8188E(pxmitpriv, pxmitbuf); +#endif + + /* 3 4. write xmit buffer to USB FIFO */ + ff_hwaddr = rtw_get_ff_hwaddr(pfirstframe); + /* RTW_INFO("%s ===================================== write port,buf_size(%d)\n",__func__,pbuf_tail); */ + /* xmit address == ((xmit_frame*)pxmitbuf->priv_data)->buf_addr */ + rtw_write_port(padapter, ff_hwaddr, pbuf_tail, (u8 *)pxmitbuf); + + + /* 3 5. update statisitc */ + pbuf_tail -= (pfirstframe->agg_num * TXDESC_SIZE); + pbuf_tail -= (pfirstframe->pkt_offset * PACKET_OFFSET_SZ); + + + rtw_count_tx_stats(padapter, pfirstframe, pbuf_tail); + + rtw_free_xmitframe(pxmitpriv, pfirstframe); + + return true; +} + +#else + +s32 rtl8188eu_xmitframe_complete(_adapter *padapter, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) +{ + + struct hw_xmit *phwxmits; + sint hwentry; + struct xmit_frame *pxmitframe = NULL; + int res = _SUCCESS, xcnt = 0; + + phwxmits = pxmitpriv->hwxmits; + hwentry = pxmitpriv->hwxmit_entry; + + + if (pxmitbuf == NULL) { + pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); + if (!pxmitbuf) + return false; + } + + + do { + pxmitframe = rtw_dequeue_xframe(pxmitpriv, phwxmits, hwentry); + + if (pxmitframe) { + pxmitframe->pxmitbuf = pxmitbuf; + + pxmitframe->buf_addr = pxmitbuf->pbuf; + + pxmitbuf->priv_data = pxmitframe; + + if ((pxmitframe->frame_tag & 0x0f) == DATA_FRAMETAG) { + if (pxmitframe->attrib.priority <= 15) /* TID0~15 */ + res = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); + /* RTW_INFO("==> pxmitframe->attrib.priority:%d\n",pxmitframe->attrib.priority); */ + rtw_os_xmit_complete(padapter, pxmitframe);/* always return ndis_packet after rtw_xmitframe_coalesce */ + } + + + + + if (res == _SUCCESS) + rtw_dump_xframe(padapter, pxmitframe); + else { + rtw_free_xmitbuf(pxmitpriv, pxmitbuf); + rtw_free_xmitframe(pxmitpriv, pxmitframe); + } + + xcnt++; + + } else { + rtw_free_xmitbuf(pxmitpriv, pxmitbuf); + return false; + } + + break; + + } while (0/*xcnt < (NR_XMITFRAME >> 3)*/); + + return true; + +} +#endif + + + +static s32 xmitframe_direct(_adapter *padapter, struct xmit_frame *pxmitframe) +{ + s32 res = _SUCCESS; + /* RTW_INFO("==> %s\n",__func__); */ + + res = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); + if (res == _SUCCESS) + rtw_dump_xframe(padapter, pxmitframe); + else + RTW_INFO("==> %s xmitframe_coalsece failed\n", __func__); + + return res; +} + +/* + * Return + * true dump packet directly + * false enqueue packet + */ +static s32 pre_xmitframe(_adapter *padapter, struct xmit_frame *pxmitframe) +{ + unsigned long irqL; + s32 res; + struct xmit_buf *pxmitbuf = NULL; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct pkt_attrib *pattrib = &pxmitframe->attrib; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + + _enter_critical_bh(&pxmitpriv->lock, &irqL); + + /* RTW_INFO("==> %s\n",__func__); */ + + if (rtw_txframes_sta_ac_pending(padapter, pattrib) > 0) { + /* RTW_INFO("enqueue AC(%d)\n",pattrib->priority); */ + goto enqueue; + } + + if (rtw_xmit_ac_blocked(padapter) == true) + goto enqueue; + + if (DEV_STA_LG_NUM(padapter->dvobj)) + goto enqueue; + + pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv); + if (pxmitbuf == NULL) + goto enqueue; + + _exit_critical_bh(&pxmitpriv->lock, &irqL); + + pxmitframe->pxmitbuf = pxmitbuf; + pxmitframe->buf_addr = pxmitbuf->pbuf; + pxmitbuf->priv_data = pxmitframe; + + if (xmitframe_direct(padapter, pxmitframe) != _SUCCESS) { + rtw_free_xmitbuf(pxmitpriv, pxmitbuf); + rtw_free_xmitframe(pxmitpriv, pxmitframe); + } + + return true; + +enqueue: + res = rtw_xmitframe_enqueue(padapter, pxmitframe); + _exit_critical_bh(&pxmitpriv->lock, &irqL); + + if (res != _SUCCESS) { + rtw_free_xmitframe(pxmitpriv, pxmitframe); + + pxmitpriv->tx_drop++; + return true; + } + + return false; +} + +s32 rtl8188eu_mgnt_xmit(_adapter *padapter, struct xmit_frame *pmgntframe) +{ + return rtw_dump_xframe(padapter, pmgntframe); +} + +/* + * Return + * true dump packet directly ok + * false temporary can't transmit packets to hardware + */ +s32 rtl8188eu_hal_xmit(_adapter *padapter, struct xmit_frame *pxmitframe) +{ + return pre_xmitframe(padapter, pxmitframe); +} + +s32 rtl8188eu_hal_xmitframe_enqueue(_adapter *padapter, struct xmit_frame *pxmitframe) +{ + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + s32 err; + + err = rtw_xmitframe_enqueue(padapter, pxmitframe); + if (err != _SUCCESS) { + rtw_free_xmitframe(pxmitpriv, pxmitframe); + + pxmitpriv->tx_drop++; + } else { + tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); + } + + return err; + +} + + +#ifdef CONFIG_HOSTAPD_MLME + +static void rtl8188eu_hostap_mgnt_xmit_cb(struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *)urb->context; + + rtw_skb_free(skb); +} + +s32 rtl8188eu_hostap_mgnt_xmit_entry(_adapter *padapter, _pkt *pkt) +{ + u16 fc; + int rc, len, pipe; + unsigned int bmcst, tid, qsel; + struct sk_buff *skb, *pxmit_skb; + struct urb *urb; + unsigned char *pxmitbuf; + struct tx_desc *ptxdesc; + struct rtw_ieee80211_hdr *tx_hdr; + struct hostapd_priv *phostapdpriv = padapter->phostapdpriv; + struct net_device *pnetdev = padapter->pnetdev; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); + + + skb = pkt; + + len = skb->len; + tx_hdr = (struct rtw_ieee80211_hdr *)(skb->data); + fc = le16_to_cpu(tx_hdr->frame_ctl); + bmcst = IS_MCAST(tx_hdr->addr1); + + if ((fc & RTW_IEEE80211_FCTL_FTYPE) != RTW_IEEE80211_FTYPE_MGMT) + goto _exit; + + pxmit_skb = rtw_skb_alloc(len + TXDESC_SIZE); + + if (!pxmit_skb) + goto _exit; + + pxmitbuf = pxmit_skb->data; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) + goto _exit; + + /* ----- fill tx desc ----- */ + ptxdesc = (struct tx_desc *)pxmitbuf; + memset(ptxdesc, 0, sizeof(*ptxdesc)); + + /* offset 0 */ + ptxdesc->txdw0 |= cpu_to_le32(len & 0x0000ffff); + ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) & 0x00ff0000); /* default = 32 bytes for TX Desc */ + ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); + + if (bmcst) + ptxdesc->txdw0 |= cpu_to_le32(BIT(24)); + + /* offset 4 */ + ptxdesc->txdw1 |= cpu_to_le32(0x00);/* MAC_ID */ + + ptxdesc->txdw1 |= cpu_to_le32((0x12 << QSEL_SHT) & 0x00001f00); + + ptxdesc->txdw1 |= cpu_to_le32((0x06 << 16) & 0x000f0000); /* b mode */ + + /* offset 8 */ + + /* offset 12 */ + ptxdesc->txdw3 |= cpu_to_le32((le16_to_cpu(tx_hdr->seq_ctl) << 16) & 0xffff0000); + + /* offset 16 */ + ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */ + + /* offset 20 */ + + + /* HW append seq */ + ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); /* Hw set sequence number */ + ptxdesc->txdw3 |= cpu_to_le32((8 << 28)); /* set bit3 to 1. Suugested by TimChen. 2009.12.29. */ + + + rtl8188eu_cal_txdesc_chksum(ptxdesc); + /* ----- end of fill tx desc ----- */ + + /* */ + skb_put(pxmit_skb, len + TXDESC_SIZE); + pxmitbuf = pxmitbuf + TXDESC_SIZE; + memcpy(pxmitbuf, skb->data, len); + + /* RTW_INFO("mgnt_xmit, len=%x\n", pxmit_skb->len); */ + + + /* ----- prepare urb for submit ----- */ + + /* translate DMA FIFO addr to pipehandle */ + /* pipe = ffaddr2pipehdl(pdvobj, MGT_QUEUE_INX); */ + pipe = usb_sndbulkpipe(pdvobj->pusbdev, pHalData->Queue2EPNum[(u8)MGT_QUEUE_INX] & 0x0f); + + usb_fill_bulk_urb(urb, pdvobj->pusbdev, pipe, + pxmit_skb->data, pxmit_skb->len, rtl8192cu_hostap_mgnt_xmit_cb, pxmit_skb); + + urb->transfer_flags |= URB_ZERO_PACKET; + usb_anchor_urb(urb, &phostapdpriv->anchored); + rc = usb_submit_urb(urb, GFP_ATOMIC); + if (rc < 0) { + usb_unanchor_urb(urb); + kfree_skb(skb); + } + usb_free_urb(urb); + + +_exit: + + rtw_skb_free(skb); + + return 0; +} +#endif diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c new file mode 100644 index 000000000000..3e037e53b1a3 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -0,0 +1,2135 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#define _HCI_HAL_INIT_C_ + +#include +#include +#include "hal_com_h2c.h" + +static void +_ConfigNormalChipOutEP_8188E( + PADAPTER pAdapter, + u8 NumOutPipe +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + + switch (NumOutPipe) { + case 3: + pHalData->OutEpQueueSel = TX_SELE_HQ | TX_SELE_LQ | TX_SELE_NQ; + pHalData->OutEpNumber = 3; + break; + case 2: + pHalData->OutEpQueueSel = TX_SELE_HQ | TX_SELE_NQ; + pHalData->OutEpNumber = 2; + break; + case 1: + pHalData->OutEpQueueSel = TX_SELE_HQ; + pHalData->OutEpNumber = 1; + break; + default: + break; + + } + RTW_INFO("%s OutEpQueueSel(0x%02x), OutEpNumber(%d)\n", __func__, pHalData->OutEpQueueSel, pHalData->OutEpNumber); + +} + +static bool HalUsbSetQueuePipeMapping8188EUsb( + PADAPTER pAdapter, + u8 NumInPipe, + u8 NumOutPipe +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + bool result = false; + + _ConfigNormalChipOutEP_8188E(pAdapter, NumOutPipe); + + /* Normal chip with one IN and one OUT doesn't have interrupt IN EP. */ + if (1 == pHalData->OutEpNumber) { + if (1 != NumInPipe) + return result; + } + + /* All config other than above support one Bulk IN and one Interrupt IN. */ + /* if(2 != NumInPipe){ */ + /* return result; */ + /* } */ + + result = Hal_MappingOutPipe(pAdapter, NumOutPipe); + + return result; + +} + +static void rtl8188eu_interface_configure(_adapter *padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + struct registry_priv *registry_par = &padapter->registrypriv; + + if (IS_HIGH_SPEED_USB(padapter)) { + pHalData->UsbBulkOutSize = USB_HIGH_SPEED_BULK_SIZE;/* 512 bytes */ + } else { + pHalData->UsbBulkOutSize = USB_FULL_SPEED_BULK_SIZE;/* 64 bytes */ + } + + pHalData->interfaceIndex = pdvobjpriv->InterfaceNumber; + +#ifdef CONFIG_USB_TX_AGGREGATION + pHalData->UsbTxAggMode = 1; + pHalData->UsbTxAggDescNum = 0x1; /* only 4 bits */ +#endif + +#ifdef CONFIG_USB_RX_AGGREGATION + pHalData->rxagg_mode = registry_par->usb_rxagg_mode; + + if ((pHalData->rxagg_mode != RX_AGG_DMA) && (pHalData->rxagg_mode != RX_AGG_USB)) + pHalData->rxagg_mode = RX_AGG_DMA; + + if (pHalData->rxagg_mode == RX_AGG_DMA) { + pHalData->rxagg_dma_size = 48; /* uint: 128b, 0x0A = 10 = MAX_RX_DMA_BUFFER_SIZE/2/pHalData->UsbBulkOutSize */ + pHalData->rxagg_dma_timeout = 0x4; /* 6, absolute time = 34ms/(2^6) */ + } else if (pHalData->rxagg_mode == RX_AGG_USB) { + pHalData->rxagg_usb_size = 16; /* unit: 512b */ + pHalData->rxagg_usb_timeout = 0x6; + } +#endif + + HalUsbSetQueuePipeMapping8188EUsb(padapter, + pdvobjpriv->RtNumInPipes, pdvobjpriv->RtNumOutPipes); + +} + +static u32 _InitPowerOn_8188EU(_adapter *padapter) +{ + u16 value16; + /* HW Power on sequence */ + u8 bMacPwrCtrlOn = false; + + rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + if (bMacPwrCtrlOn == true) + return _SUCCESS; + + if (!HalPwrSeqCmdParsing(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, Rtl8188E_NIC_PWR_ON_FLOW)) { + RTW_ERR("%s: run power on flow fail\n", __func__); + return _FAIL; + } + + /* Enable MAC DMA/WMAC/SCHEDULE/SEC block */ + /* Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. */ + rtw_write16(padapter, REG_CR, 0x00); /* suggseted by zhouzhou, by page, 20111230 */ + + /* Enable MAC DMA/WMAC/SCHEDULE/SEC block */ + value16 = rtw_read16(padapter, REG_CR); + value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN + | PROTOCOL_EN | SCHEDULE_EN | ENSEC | CALTMR_EN); + /* for SDIO - Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. */ + + rtw_write16(padapter, REG_CR, value16); + + bMacPwrCtrlOn = true; + rtw_hal_set_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + + return _SUCCESS; + +} + +static void _dbg_dump_macreg(_adapter *padapter) +{ + u32 offset = 0; + u32 val32 = 0; + u32 index = 0 ; + for (index = 0; index < 64; index++) { + offset = index * 4; + val32 = rtw_read32(padapter, offset); + RTW_INFO("offset : 0x%02x ,val:0x%08x\n", offset, val32); + } +} + +static void _InitPABias(_adapter *padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + u8 pa_setting; + + /* FIXED PA current issue */ + /* efuse_one_byte_read(padapter, 0x1FA, &pa_setting); */ + efuse_OneByteRead(padapter, 0x1FA, &pa_setting, false); + + if (!(pa_setting & BIT0)) { + phy_set_rf_reg(padapter, RF_PATH_A, 0x15, 0x0FFFFF, 0x0F406); + phy_set_rf_reg(padapter, RF_PATH_A, 0x15, 0x0FFFFF, 0x4F406); + phy_set_rf_reg(padapter, RF_PATH_A, 0x15, 0x0FFFFF, 0x8F406); + phy_set_rf_reg(padapter, RF_PATH_A, 0x15, 0x0FFFFF, 0xCF406); + } + + if (!(pa_setting & BIT4)) { + pa_setting = rtw_read8(padapter, 0x16); + pa_setting &= 0x0F; + rtw_write8(padapter, 0x16, pa_setting | 0x80); + rtw_write8(padapter, 0x16, pa_setting | 0x90); + } +} +#ifdef CONFIG_BT_COEXIST +static void _InitBTCoexist(_adapter *padapter) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct btcoexist_priv *pbtpriv = &(pHalData->bt_coexist); + u8 u1Tmp; + + if (pbtpriv->BT_Coexist && pbtpriv->BT_CoexistType == BT_CSR_BC4) { + + /* #if MP_DRIVER != 1 */ + if (padapter->registrypriv.mp_mode == 0) { + if (pbtpriv->BT_Ant_isolation) { + rtw_write8(padapter, REG_GPIO_MUXCFG, 0xa0); + RTW_INFO("BT write 0x%x = 0x%x\n", REG_GPIO_MUXCFG, 0xa0); + } + } + /* #endif */ + + u1Tmp = rtw_read8(padapter, 0x4fd) & BIT0; + u1Tmp = u1Tmp | + ((pbtpriv->BT_Ant_isolation == 1) ? 0 : BIT1) | + ((pbtpriv->BT_Service == BT_SCO) ? 0 : BIT2); + rtw_write8(padapter, 0x4fd, u1Tmp); + RTW_INFO("BT write 0x%x = 0x%x for non-isolation\n", 0x4fd, u1Tmp); + + rtw_write32(padapter, REG_BT_COEX_TABLE + 4, 0xaaaa9aaa); + RTW_INFO("BT write 0x%x = 0x%x\n", REG_BT_COEX_TABLE + 4, 0xaaaa9aaa); + + rtw_write32(padapter, REG_BT_COEX_TABLE + 8, 0xffbd0040); + RTW_INFO("BT write 0x%x = 0x%x\n", REG_BT_COEX_TABLE + 8, 0xffbd0040); + + rtw_write32(padapter, REG_BT_COEX_TABLE + 0xc, 0x40000010); + RTW_INFO("BT write 0x%x = 0x%x\n", REG_BT_COEX_TABLE + 0xc, 0x40000010); + + /* Config to 1T1R */ + u1Tmp = rtw_read8(padapter, rOFDM0_TRxPathEnable); + u1Tmp &= ~(BIT1); + rtw_write8(padapter, rOFDM0_TRxPathEnable, u1Tmp); + RTW_INFO("BT write 0xC04 = 0x%x\n", u1Tmp); + + u1Tmp = rtw_read8(padapter, rOFDM1_TRxPathEnable); + u1Tmp &= ~(BIT1); + rtw_write8(padapter, rOFDM1_TRxPathEnable, u1Tmp); + RTW_INFO("BT write 0xD04 = 0x%x\n", u1Tmp); + + } +} +#endif + +/* --------------------------------------------------------------- + * + * MAC init functions + * + * --------------------------------------------------------------- */ + +/* Shall USB interface init this? */ +static void +_InitInterrupt( + PADAPTER Adapter +) +{ + u32 imr, imr_ex; + u8 usb_opt; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + +#ifdef CONFIG_USB_INTERRUPT_IN_PIPE + struct dvobj_priv *pdev = adapter_to_dvobj(Adapter); +#endif + + /* HISR write one to clear */ + rtw_write32(Adapter, REG_HISR_88E, 0xFFFFFFFF); + /* HIMR - */ + imr = IMR_PSTIMEOUT_88E | IMR_TBDER_88E | IMR_CPWM_88E | IMR_CPWM2_88E ; + rtw_write32(Adapter, REG_HIMR_88E, imr); + pHalData->IntrMask[0] = imr; + + imr_ex = IMR_TXERR_88E | IMR_RXERR_88E | IMR_TXFOVW_88E | IMR_RXFOVW_88E; + rtw_write32(Adapter, REG_HIMRE_88E, imr_ex); + pHalData->IntrMask[1] = imr_ex; + +#ifdef CONFIG_SUPPORT_USB_INT + /* REG_USB_SPECIAL_OPTION - BIT(4) */ + /* 0; Use interrupt endpoint to upload interrupt pkt */ + /* 1; Use bulk endpoint to upload interrupt pkt, */ + usb_opt = rtw_read8(Adapter, REG_USB_SPECIAL_OPTION); + + if ((IS_FULL_SPEED_USB(Adapter)) +#ifdef CONFIG_USB_INTERRUPT_IN_PIPE + || (pdev->RtInPipe[REALTEK_USB_IN_INT_EP_IDX] == 0x05) +#endif + ) + usb_opt = usb_opt & (~INT_BULK_SEL); + else + usb_opt = usb_opt | (INT_BULK_SEL); + + rtw_write8(Adapter, REG_USB_SPECIAL_OPTION, usb_opt); + +#endif/* CONFIG_SUPPORT_USB_INT */ + +} + +static void +_InitQueueReservedPage( + PADAPTER Adapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + struct registry_priv *pregistrypriv = &Adapter->registrypriv; + u32 outEPNum = (u32)pHalData->OutEpNumber; + u32 numHQ = 0; + u32 numLQ = 0; + u32 numNQ = 0; + u32 numPubQ = 0x00; + u32 value32; + u8 value8; + bool bWiFiConfig = pregistrypriv->wifi_spec; + + if (bWiFiConfig || pregistrypriv->qos_opt_enable) { + if (pHalData->OutEpQueueSel & TX_SELE_HQ) + numHQ = WMM_NORMAL_PAGE_NUM_HPQ_88E; + + if (pHalData->OutEpQueueSel & TX_SELE_LQ) + numLQ = WMM_NORMAL_PAGE_NUM_LPQ_88E; + + /* NOTE: This step shall be proceed before writting REG_RQPN. */ + if (pHalData->OutEpQueueSel & TX_SELE_NQ) + numNQ = WMM_NORMAL_PAGE_NUM_NPQ_88E; + } else { + if (pHalData->OutEpQueueSel & TX_SELE_HQ) + numHQ = NORMAL_PAGE_NUM_HPQ_88E; + + if (pHalData->OutEpQueueSel & TX_SELE_LQ) + numLQ = NORMAL_PAGE_NUM_LPQ_88E; + + /* NOTE: This step shall be proceed before writting REG_RQPN. */ + if (pHalData->OutEpQueueSel & TX_SELE_NQ) + numNQ = NORMAL_PAGE_NUM_NPQ_88E; + } + + value8 = (u8)_NPQ(numNQ); + rtw_write8(Adapter, REG_RQPN_NPQ, value8); + + numPubQ = TX_TOTAL_PAGE_NUMBER_88E(Adapter) - numHQ - numLQ - numNQ; + + /* TX DMA */ + value32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN; + rtw_write32(Adapter, REG_RQPN, value32); +} + +static void +_InitTxBufferBoundary( + PADAPTER Adapter, + u8 txpktbuf_bndy +) +{ + struct registry_priv *pregistrypriv = &Adapter->registrypriv; + /* HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); */ + + /* u16 txdmactrl; */ + + rtw_write8(Adapter, REG_BCNQ_BDNY, txpktbuf_bndy); + rtw_write8(Adapter, REG_MGQ_BDNY, txpktbuf_bndy); + rtw_write8(Adapter, REG_WMAC_LBK_BF_HD, txpktbuf_bndy); + rtw_write8(Adapter, REG_TRXFF_BNDY, txpktbuf_bndy); + rtw_write8(Adapter, REG_TDECTRL + 1, txpktbuf_bndy); + +} + +static void +_InitPageBoundary( + PADAPTER Adapter +) +{ + /* RX Page Boundary */ + u16 rxff_bndy = 0; + + rxff_bndy = MAX_RX_DMA_BUFFER_SIZE_88E(Adapter) - 1; + + rtw_write16(Adapter, (REG_TRXFF_BNDY + 2), rxff_bndy); +} + +static void +_InitNormalChipRegPriority( + PADAPTER Adapter, + u16 beQ, + u16 bkQ, + u16 viQ, + u16 voQ, + u16 mgtQ, + u16 hiQ +) +{ + u16 value16 = (rtw_read16(Adapter, REG_TRXDMA_CTRL) & 0x7); + + value16 |= _TXDMA_BEQ_MAP(beQ) | _TXDMA_BKQ_MAP(bkQ) | + _TXDMA_VIQ_MAP(viQ) | _TXDMA_VOQ_MAP(voQ) | + _TXDMA_MGQ_MAP(mgtQ) | _TXDMA_HIQ_MAP(hiQ); + + rtw_write16(Adapter, REG_TRXDMA_CTRL, value16); +} + +static void +_InitNormalChipOneOutEpPriority( + PADAPTER Adapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + u16 value = 0; + switch (pHalData->OutEpQueueSel) { + case TX_SELE_HQ: + value = QUEUE_HIGH; + break; + case TX_SELE_LQ: + value = QUEUE_LOW; + break; + case TX_SELE_NQ: + value = QUEUE_NORMAL; + break; + default: + /* RT_ASSERT(false,("Shall not reach here!\n")); */ + break; + } + + _InitNormalChipRegPriority(Adapter, + value, + value, + value, + value, + value, + value + ); + +} + +static void +_InitNormalChipTwoOutEpPriority( + PADAPTER Adapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + struct registry_priv *pregistrypriv = &Adapter->registrypriv; + u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ; + + u16 valueHi = 0; + u16 valueLow = 0; + + switch (pHalData->OutEpQueueSel) { + case (TX_SELE_HQ | TX_SELE_LQ): + valueHi = QUEUE_HIGH; + valueLow = QUEUE_LOW; + break; + case (TX_SELE_NQ | TX_SELE_LQ): + valueHi = QUEUE_NORMAL; + valueLow = QUEUE_LOW; + break; + case (TX_SELE_HQ | TX_SELE_NQ): + valueHi = QUEUE_HIGH; + valueLow = QUEUE_NORMAL; + break; + default: + /* RT_ASSERT(false,("Shall not reach here!\n")); */ + break; + } + + if (!pregistrypriv->wifi_spec) { + beQ = valueLow; + bkQ = valueLow; + viQ = valueHi; + voQ = valueHi; + mgtQ = valueHi; + hiQ = valueHi; + } else { /* for WMM ,CONFIG_OUT_EP_WIFI_MODE */ + beQ = valueLow; + bkQ = valueHi; + viQ = valueHi; + voQ = valueLow; + mgtQ = valueHi; + hiQ = valueHi; + } + + _InitNormalChipRegPriority(Adapter, beQ, bkQ, viQ, voQ, mgtQ, hiQ); + +} + +static void +_InitNormalChipThreeOutEpPriority( + PADAPTER Adapter +) +{ + struct registry_priv *pregistrypriv = &Adapter->registrypriv; + u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ; + + if (!pregistrypriv->wifi_spec) { /* typical setting */ + beQ = QUEUE_LOW; + bkQ = QUEUE_LOW; + viQ = QUEUE_NORMAL; + voQ = QUEUE_HIGH; + mgtQ = QUEUE_HIGH; + hiQ = QUEUE_HIGH; + } else { /* for WMM */ + beQ = QUEUE_LOW; + bkQ = QUEUE_NORMAL; + viQ = QUEUE_NORMAL; + voQ = QUEUE_HIGH; + mgtQ = QUEUE_HIGH; + hiQ = QUEUE_HIGH; + } + _InitNormalChipRegPriority(Adapter, beQ, bkQ, viQ, voQ, mgtQ, hiQ); +} + +static void +_InitQueuePriority( + PADAPTER Adapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + switch (pHalData->OutEpNumber) { + case 1: + _InitNormalChipOneOutEpPriority(Adapter); + break; + case 2: + _InitNormalChipTwoOutEpPriority(Adapter); + break; + case 3: + _InitNormalChipThreeOutEpPriority(Adapter); + break; + default: + /* RT_ASSERT(false,("Shall not reach here!\n")); */ + break; + } + +} + +static void +_InitHardwareDropIncorrectBulkOut( + PADAPTER Adapter +) +{ +#ifdef ENABLE_USB_DROP_INCORRECT_OUT + u32 value32 = rtw_read32(Adapter, REG_TXDMA_OFFSET_CHK); + value32 |= DROP_DATA_EN; + rtw_write32(Adapter, REG_TXDMA_OFFSET_CHK, value32); +#endif +} + +static void +_InitNetworkType( + PADAPTER Adapter +) +{ + u32 value32; + + value32 = rtw_read32(Adapter, REG_CR); + /* TODO: use the other function to set network type */ + value32 = (value32 & ~MASK_NETTYPE) | _NETTYPE(NT_LINK_AP); + + rtw_write32(Adapter, REG_CR, value32); + /* RASSERT(pIoBase->rtw_read8(REG_CR + 2) == 0x2); */ +} + +static void +_InitDriverInfoSize( + PADAPTER Adapter, + u8 drvInfoSize +) +{ + rtw_write8(Adapter, REG_RX_DRVINFO_SZ, drvInfoSize); +} + +static void +_InitWMACSetting( + PADAPTER Adapter +) +{ + /* u32 value32; */ + /* u16 value16; */ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + /* pHalData->ReceiveConfig = AAP | APM | AM | AB | APP_ICV | ADF | AMF | APP_FCS | HTC_LOC_CTRL | APP_MIC | APP_PHYSTS; */ + /* pHalData->ReceiveConfig = */ + /* RCR_AAP | RCR_APM | RCR_AM | RCR_AB |RCR_CBSSID_DATA| RCR_CBSSID_BCN| RCR_APP_ICV | RCR_AMF | RCR_HTC_LOC_CTRL | RCR_APP_MIC | RCR_APP_PHYSTS; */ + /* don't turn on AAP, it will allow all packets to driver */ + pHalData->ReceiveConfig = RCR_APM | RCR_AM | RCR_AB | RCR_CBSSID_DATA | RCR_CBSSID_BCN | RCR_APP_ICV | RCR_AMF | RCR_HTC_LOC_CTRL | RCR_APP_MIC | RCR_APP_PHYST_RXFF; + +#if (1 == RTL8188E_RX_PACKET_INCLUDE_CRC) + pHalData->ReceiveConfig |= ACRC32; +#endif + + /* some REG_RCR will be modified later by phy_ConfigMACWithHeaderFile() */ + rtw_write32(Adapter, REG_RCR, pHalData->ReceiveConfig); + + /* Accept all multicast address */ + rtw_write32(Adapter, REG_MAR, 0xFFFFFFFF); + rtw_write32(Adapter, REG_MAR + 4, 0xFFFFFFFF); + + /* Accept all data frames */ + /* value16 = 0xFFFF; */ + /* rtw_write16(Adapter, REG_RXFLTMAP2, value16); */ + + /* 2010.09.08 hpfan */ + /* Since ADF is removed from RCR, ps-poll will not be indicate to driver, */ + /* RxFilterMap should mask ps-poll to gurantee AP mode can rx ps-poll. */ + /* value16 = 0x400; */ + /* rtw_write16(Adapter, REG_RXFLTMAP1, value16); */ + + /* Accept all management frames */ + /* value16 = 0xFFFF; */ + /* rtw_write16(Adapter, REG_RXFLTMAP0, value16); */ + + /* enable RX_SHIFT bits */ + /* rtw_write8(Adapter, REG_TRXDMA_CTRL, rtw_read8(Adapter, REG_TRXDMA_CTRL)|BIT(1)); */ + +} + +static void +_InitAdaptiveCtrl( + PADAPTER Adapter +) +{ + u16 value16; + u32 value32; + + /* Response Rate Set */ + value32 = rtw_read32(Adapter, REG_RRSR); + value32 &= ~RATE_BITMAP_ALL; + value32 |= RATE_RRSR_CCK_ONLY_1M; + rtw_write32(Adapter, REG_RRSR, value32); + + /* CF-END Threshold */ + /* m_spIoBase->rtw_write8(REG_CFEND_TH, 0x1); */ + + /* SIFS (used in NAV) */ + value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10); + rtw_write16(Adapter, REG_SPEC_SIFS, value16); + + /* Retry Limit */ + value16 = _LRL(0x30) | _SRL(0x30); + rtw_write16(Adapter, REG_RL, value16); + +} + +static void +_InitRateFallback( + PADAPTER Adapter +) +{ + /* Set Data Auto Rate Fallback Retry Count register. */ + rtw_write32(Adapter, REG_DARFRC, 0x00000000); + rtw_write32(Adapter, REG_DARFRC + 4, 0x10080404); + rtw_write32(Adapter, REG_RARFRC, 0x04030201); + rtw_write32(Adapter, REG_RARFRC + 4, 0x08070605); + +} + +static void +_InitEDCA( + PADAPTER Adapter +) +{ + /* Set Spec SIFS (used in NAV) */ + rtw_write16(Adapter, REG_SPEC_SIFS, 0x100a); + rtw_write16(Adapter, REG_MAC_SPEC_SIFS, 0x100a); + + /* Set SIFS for CCK */ + rtw_write16(Adapter, REG_SIFS_CTX, 0x100a); + + /* Set SIFS for OFDM */ + rtw_write16(Adapter, REG_SIFS_TRX, 0x100a); + + /* TXOP */ + rtw_write32(Adapter, REG_EDCA_BE_PARAM, 0x005EA42B); + rtw_write32(Adapter, REG_EDCA_BK_PARAM, 0x0000A44F); + rtw_write32(Adapter, REG_EDCA_VI_PARAM, 0x005EA324); + rtw_write32(Adapter, REG_EDCA_VO_PARAM, 0x002FA226); +} + +static void +_InitBeaconMaxError( + PADAPTER Adapter, + bool InfraMode +) +{ + +} + +#ifdef CONFIG_LED +static void _InitHWLed(PADAPTER Adapter) +{ + struct led_priv *pledpriv = &(Adapter->ledpriv); + + if (pledpriv->LedStrategy != HW_LED) + return; + + /* HW led control + * to do .... + * must consider cases of antenna diversity/ commbo card/solo card/mini card */ + +} +#endif /* CONFIG_LED */ + +static void +_InitRDGSetting( + PADAPTER Adapter +) +{ + rtw_write8(Adapter, REG_RD_CTRL, 0xFF); + rtw_write16(Adapter, REG_RD_NAV_NXT, 0x200); + rtw_write8(Adapter, REG_RD_RESP_PKT_TH, 0x05); +} + +static void +_InitRetryFunction( + PADAPTER Adapter +) +{ + u8 value8; + + value8 = rtw_read8(Adapter, REG_FWHW_TXQ_CTRL); + value8 |= EN_AMPDU_RTY_NEW; + rtw_write8(Adapter, REG_FWHW_TXQ_CTRL, value8); + + /* Set ACK timeout */ + rtw_write8(Adapter, REG_ACKTO, 0x40); +} + +/*----------------------------------------------------------------------------- + * Function: usb_AggSettingTxUpdate() + * + * Overview: Seperate TX/RX parameters update independent for TP detection and + * dynamic TX/RX aggreagtion parameters update. + * + * Input: PADAPTER + * + * Output/Return: NONE + * + * Revised History: + * When Who Remark + * 12/10/2010 MHC Seperate to smaller function. + * + *---------------------------------------------------------------------------*/ +static void +usb_AggSettingTxUpdate( + PADAPTER Adapter +) +{ +#ifdef CONFIG_USB_TX_AGGREGATION + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + /* PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo); */ + u32 value32; + + if (Adapter->registrypriv.wifi_spec) + pHalData->UsbTxAggMode = false; + + if (pHalData->UsbTxAggMode) { + value32 = rtw_read32(Adapter, REG_TDECTRL); + value32 = value32 & ~(BLK_DESC_NUM_MASK << BLK_DESC_NUM_SHIFT); + value32 |= ((pHalData->UsbTxAggDescNum & BLK_DESC_NUM_MASK) << BLK_DESC_NUM_SHIFT); + + rtw_write32(Adapter, REG_TDECTRL, value32); + } + +#endif +} /* usb_AggSettingTxUpdate */ + +/*----------------------------------------------------------------------------- + * Function: usb_AggSettingRxUpdate() + * + * Overview: Seperate TX/RX parameters update independent for TP detection and + * dynamic TX/RX aggreagtion parameters update. + * + * Input: PADAPTER + * + * Output/Return: NONE + * + * Revised History: + * When Who Remark + * 12/10/2010 MHC Seperate to smaller function. + * + *---------------------------------------------------------------------------*/ +static void +usb_AggSettingRxUpdate( + PADAPTER Adapter +) +{ +#ifdef CONFIG_USB_RX_AGGREGATION + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + /* PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo); */ + u8 valueDMA; + u8 valueUSB; + + valueDMA = rtw_read8(Adapter, REG_TRXDMA_CTRL); + valueUSB = rtw_read8(Adapter, REG_USB_SPECIAL_OPTION); + + switch (pHalData->rxagg_mode) { + case RX_AGG_DMA: + valueDMA |= RXDMA_AGG_EN; + valueUSB &= ~USB_AGG_EN; + break; + case RX_AGG_USB: + valueDMA &= ~RXDMA_AGG_EN; + valueUSB |= USB_AGG_EN; + break; + case RX_AGG_MIX: + valueDMA |= RXDMA_AGG_EN; + valueUSB |= USB_AGG_EN; + break; + case RX_AGG_DISABLE: + default: + valueDMA &= ~RXDMA_AGG_EN; + valueUSB &= ~USB_AGG_EN; + break; + } + + rtw_write8(Adapter, REG_TRXDMA_CTRL, valueDMA); + rtw_write8(Adapter, REG_USB_SPECIAL_OPTION, valueUSB); + + switch (pHalData->rxagg_mode) { + case RX_AGG_DMA: + rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH, pHalData->rxagg_dma_size); + rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH + 1, pHalData->rxagg_dma_timeout); + break; + case RX_AGG_USB: + rtw_write8(Adapter, REG_USB_AGG_TH, pHalData->rxagg_usb_size); + rtw_write8(Adapter, REG_USB_AGG_TO, pHalData->rxagg_usb_timeout); + break; + case RX_AGG_MIX: + rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH, pHalData->rxagg_dma_size); + rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH + 1, pHalData->rxagg_dma_timeout & 0x1F); /* 0x280[12:8] */ + + rtw_write8(Adapter, REG_USB_AGG_TH, pHalData->rxagg_usb_size); + rtw_write8(Adapter, REG_USB_AGG_TO, pHalData->rxagg_usb_timeout); + + break; + case RX_AGG_DISABLE: + default: + /* TODO: */ + break; + } + + switch (PBP_128) { + case PBP_128: + pHalData->HwRxPageSize = 128; + break; + case PBP_64: + pHalData->HwRxPageSize = 64; + break; + case PBP_256: + pHalData->HwRxPageSize = 256; + break; + case PBP_512: + pHalData->HwRxPageSize = 512; + break; + case PBP_1024: + pHalData->HwRxPageSize = 1024; + break; + default: + /* RT_ASSERT(false, ("RX_PAGE_SIZE_REG_VALUE definition is incorrect!\n")); */ + break; + } +#endif +} /* usb_AggSettingRxUpdate */ + +static void +InitUsbAggregationSetting( + PADAPTER Adapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + /* Tx aggregation setting */ + usb_AggSettingTxUpdate(Adapter); + + /* Rx aggregation setting */ + usb_AggSettingRxUpdate(Adapter); + + /* 201/12/10 MH Add for USB agg mode dynamic switch. */ + pHalData->UsbRxHighSpeedMode = false; +} + +static void +HalRxAggr8188EUsb( + PADAPTER Adapter, + bool Value +) +{ +} + +/*----------------------------------------------------------------------------- + * Function: USB_AggModeSwitch() + * + * Overview: When RX traffic is more than 40M, we need to adjust some parameters to increase + * RX speed by increasing batch indication size. This will decrease TCP ACK speed, we + * need to monitor the influence of FTP/network share. + * For TX mode, we are still ubder investigation. + * + * Input: PADAPTER + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 12/10/2010 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +static void +USB_AggModeSwitch( + PADAPTER Adapter +) +{ +} /* USB_AggModeSwitch */ + +static void +_InitOperationMode( + PADAPTER Adapter +) +{ +} + +static void +_InitBeaconParameters( + PADAPTER Adapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + rtw_write16(Adapter, REG_BCN_CTRL, 0x1010); + + /* TODO: Remove these magic number */ + /* TBTT setup time:128 us */ + rtw_write8(Adapter, REG_TBTT_PROHIBIT, 0x04); + + /*TBTT hold time :4ms 0x540[19:8]*/ + rtw_write8(Adapter, REG_TBTT_PROHIBIT + 1, + TBTT_PROBIHIT_HOLD_TIME & 0xFF); + rtw_write8(Adapter, REG_TBTT_PROHIBIT + 2, + (rtw_read8(Adapter, REG_TBTT_PROHIBIT + 2) & 0xF0) | (TBTT_PROBIHIT_HOLD_TIME >> 8)); + rtw_write8(Adapter, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME_8188E);/* 5ms */ + rtw_write8(Adapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME_8188E); /* 2ms */ + + /* Suggested by designer timchen. Change beacon AIFS to the largest number */ + /* beacause test chip does not contension before sending beacon. by tynli. 2009.11.03 */ + rtw_write16(Adapter, REG_BCNTCFG, 0x660F); + + pHalData->RegBcnCtrlVal = rtw_read8(Adapter, REG_BCN_CTRL); + pHalData->RegTxPause = rtw_read8(Adapter, REG_TXPAUSE); + pHalData->RegFwHwTxQCtrl = rtw_read8(Adapter, REG_FWHW_TXQ_CTRL + 2); + pHalData->RegReg542 = rtw_read8(Adapter, REG_TBTT_PROHIBIT + 2); + pHalData->RegCR_1 = rtw_read8(Adapter, REG_CR + 1); +} + +static void +_InitRFType( + PADAPTER Adapter +) +{ + struct registry_priv *pregpriv = &Adapter->registrypriv; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + +#if DISABLE_BB_RF + pHalData->rf_chip = RF_PSEUDO_11N; + return; +#endif + pHalData->rf_chip = RF_6052; + + /* TODO: Consider that EEPROM set 92CU to 1T1R later. */ + /* Force to overwrite setting according to chip version. Ignore EEPROM setting. */ + /* pHalData->RF_Type = is92CU ? RF_2T2R : RF_1T1R; */ + RTW_INFO("Set RF Chip ID to RF_6052 and RF type to %d.\n", pHalData->rf_type); + +} + +static void +_BeaconFunctionEnable( + PADAPTER Adapter, + bool Enable, + bool Linked +) +{ + rtw_write8(Adapter, REG_BCN_CTRL, (BIT4 | BIT3 | BIT1)); + /* SetBcnCtrlReg(Adapter, (BIT4 | BIT3 | BIT1), 0x00); */ + + rtw_write8(Adapter, REG_RD_CTRL + 1, 0x6F); +} + +/* Set CCK and OFDM Block "ON" */ +static void _BBTurnOnBlock( + PADAPTER Adapter +) +{ +#if (DISABLE_BB_RF) + return; +#endif + + phy_set_bb_reg(Adapter, rFPGA0_RFMOD, bCCKEn, 0x1); + phy_set_bb_reg(Adapter, rFPGA0_RFMOD, bOFDMEn, 0x1); +} + +static void _RfPowerSave( + PADAPTER Adapter +) +{ +} + +enum { + Antenna_Lfet = 1, + Antenna_Right = 2, +}; + +static void +_InitAntenna_Selection(PADAPTER Adapter) +{ +#ifdef CONFIG_ANTENNA_DIVERSITY + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + if (pHalData->AntDivCfg == 0) + return; + RTW_INFO("==> %s ....\n", __func__); + + rtw_write32(Adapter, REG_LEDCFG0, rtw_read32(Adapter, REG_LEDCFG0) | BIT23); + phy_set_bb_reg(Adapter, rFPGA0_XAB_RFParameter, BIT13, 0x01); +#endif +} + +/* + * 2010/08/26 MH Add for selective suspend mode check. + * If Efuse 0x0e bit1 is not enabled, we can not support selective suspend for Minicard and + * slim card. + * */ +static void +HalDetectSelectiveSuspendMode( + PADAPTER Adapter +) +{ +} /* HalDetectSelectiveSuspendMode */ + +rt_rf_power_state RfOnOffDetect(PADAPTER pAdapter) +{ + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(pAdapter); + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + u8 val8; + rt_rf_power_state rfpowerstate = rf_off; + + if (pwrctl->bHWPowerdown) { + val8 = rtw_read8(pAdapter, REG_HSISR); + RTW_INFO("pwrdown, 0x5c(BIT7)=%02x\n", val8); + rfpowerstate = (val8 & BIT7) ? rf_off : rf_on; + } else { /* rf on/off */ + rtw_write8(pAdapter, REG_MAC_PINMUX_CFG, rtw_read8(pAdapter, REG_MAC_PINMUX_CFG) & ~(BIT3)); + val8 = rtw_read8(pAdapter, REG_GPIO_IO_SEL); + RTW_INFO("GPIO_IN=%02x\n", val8); + rfpowerstate = (val8 & BIT3) ? rf_on : rf_off; + } + return rfpowerstate; +} /* HalDetectPwrDownMode */ + +void _ps_open_RF(_adapter *padapter); + +static u32 rtl8188eu_hal_init(PADAPTER Adapter) +{ + u8 value8 = 0; + u16 value16; + u8 txpktbuf_bndy; + u32 status = _SUCCESS; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(Adapter); + struct registry_priv *pregistrypriv = &Adapter->registrypriv; + + rt_rf_power_state eRfPowerStateToSet; +#ifdef CONFIG_BT_COEXIST + struct btcoexist_priv *pbtpriv = &(pHalData->bt_coexist); +#endif + + u32 init_start_time = jiffies; + +#ifdef DBG_HAL_INIT_PROFILING + + enum HAL_INIT_STAGES { + HAL_INIT_STAGES_BEGIN = 0, + HAL_INIT_STAGES_INIT_PW_ON, + HAL_INIT_STAGES_MISC01, + HAL_INIT_STAGES_DOWNLOAD_FW, + HAL_INIT_STAGES_MAC, + HAL_INIT_STAGES_BB, + HAL_INIT_STAGES_RF, + HAL_INIT_STAGES_EFUSE_PATCH, + HAL_INIT_STAGES_INIT_LLTT, + + HAL_INIT_STAGES_MISC02, + HAL_INIT_STAGES_TURN_ON_BLOCK, + HAL_INIT_STAGES_INIT_SECURITY, + HAL_INIT_STAGES_MISC11, + HAL_INIT_STAGES_INIT_HAL_DM, + /* HAL_INIT_STAGES_RF_PS, */ + HAL_INIT_STAGES_IQK, + HAL_INIT_STAGES_PW_TRACK, + HAL_INIT_STAGES_LCK, + /* HAL_INIT_STAGES_MISC21, */ + /* HAL_INIT_STAGES_INIT_PABIAS, */ +#ifdef CONFIG_BT_COEXIST + HAL_INIT_STAGES_BT_COEXIST, +#endif + /* HAL_INIT_STAGES_ANTENNA_SEL, */ + /* HAL_INIT_STAGES_MISC31, */ + HAL_INIT_STAGES_END, + HAL_INIT_STAGES_NUM + }; + + char *hal_init_stages_str[] = { + "HAL_INIT_STAGES_BEGIN", + "HAL_INIT_STAGES_INIT_PW_ON", + "HAL_INIT_STAGES_MISC01", + "HAL_INIT_STAGES_DOWNLOAD_FW", + "HAL_INIT_STAGES_MAC", + "HAL_INIT_STAGES_BB", + "HAL_INIT_STAGES_RF", + "HAL_INIT_STAGES_EFUSE_PATCH", + "HAL_INIT_STAGES_INIT_LLTT", + "HAL_INIT_STAGES_MISC02", + "HAL_INIT_STAGES_TURN_ON_BLOCK", + "HAL_INIT_STAGES_INIT_SECURITY", + "HAL_INIT_STAGES_MISC11", + "HAL_INIT_STAGES_INIT_HAL_DM", + /* "HAL_INIT_STAGES_RF_PS", */ + "HAL_INIT_STAGES_IQK", + "HAL_INIT_STAGES_PW_TRACK", + "HAL_INIT_STAGES_LCK", + /* "HAL_INIT_STAGES_MISC21", */ +#ifdef CONFIG_BT_COEXIST + "HAL_INIT_STAGES_BT_COEXIST", +#endif + /* "HAL_INIT_STAGES_ANTENNA_SEL", */ + /* "HAL_INIT_STAGES_MISC31", */ + "HAL_INIT_STAGES_END", + }; + + int hal_init_profiling_i; + u32 hal_init_stages_timestamp[HAL_INIT_STAGES_NUM]; /* used to record the time of each stage's starting point */ + + for (hal_init_profiling_i = 0; hal_init_profiling_i < HAL_INIT_STAGES_NUM; hal_init_profiling_i++) + hal_init_stages_timestamp[hal_init_profiling_i] = 0; + +#define HAL_INIT_PROFILE_TAG(stage) do { hal_init_stages_timestamp[(stage)] = jiffies; } while (0) +#else +#define HAL_INIT_PROFILE_TAG(stage) do {} while (0) +#endif /* DBG_HAL_INIT_PROFILING */ + + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_BEGIN); + + if (pwrctrlpriv->bkeepfwalive) { + _ps_open_RF(Adapter); + + if (pHalData->bIQKInitialized) { + /* PHY_IQCalibrate(padapter, true); */ + phy_iq_calibrate_8188e(Adapter, true); + } else { + /* PHY_IQCalibrate(padapter, false); */ + phy_iq_calibrate_8188e(Adapter, false); + pHalData->bIQKInitialized = true; + } + + /* dm_check_txpowertracking(padapter); + * phy_lc_calibrate(padapter); */ + odm_txpowertracking_check(&pHalData->odmpriv); + phy_lc_calibrate_8188e(&pHalData->odmpriv); + + goto exit; + } + + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PW_ON); + status = rtw_hal_power_on(Adapter); + if (status == _FAIL) { + goto exit; + } + + /* Set RF type for BB/RF configuration */ + _InitRFType(Adapter);/* ->_ReadRFType() */ + + /* Save target channel */ + /* Current Channel will be updated again later. */ + pHalData->current_channel = 6;/* default set to 6 */ + if (pwrctrlpriv->reg_rfoff == true) + pwrctrlpriv->rf_pwrstate = rf_off; + + /* 2010/08/09 MH We need to check if we need to turnon or off RF after detecting */ + /* HW GPIO pin. Before PHY_RFConfig8192C. */ + /* HalDetectPwrDownMode(Adapter); */ + /* 2010/08/26 MH If Efuse does not support sective suspend then disable the function. */ + /*HalDetectSelectiveSuspendMode(Adapter);*/ + + if (!pregistrypriv->wifi_spec) + txpktbuf_bndy = TX_PAGE_BOUNDARY_88E(Adapter); + else { + /* for WMM */ + txpktbuf_bndy = WMM_NORMAL_TX_PAGE_BOUNDARY_88E(Adapter); + } + + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC01); + _InitQueueReservedPage(Adapter); + _InitQueuePriority(Adapter); + _InitPageBoundary(Adapter); + _InitTransferPageSize(Adapter); + +#ifdef CONFIG_IOL_IOREG_CFG + _InitTxBufferBoundary(Adapter, 0); +#endif + + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_DOWNLOAD_FW); + if (Adapter->registrypriv.mp_mode == 0) { + status = rtl8188e_FirmwareDownload(Adapter, false); + if (status != _SUCCESS) { + RTW_INFO("%s: Download Firmware failed!!\n", __func__); + Adapter->bFWReady = false; + pHalData->fw_ractrl = false; + return status; + } else { + Adapter->bFWReady = true; +#ifdef CONFIG_SFW_SUPPORTED + pHalData->fw_ractrl = IS_VENDOR_8188E_I_CUT_SERIES(Adapter) ? true : false; +#else + pHalData->fw_ractrl = false; +#endif + } + } + + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MAC); +#if (HAL_MAC_ENABLE == 1) + status = PHY_MACConfig8188E(Adapter); + if (status == _FAIL) { + RTW_INFO(" ### Failed to init MAC ......\n "); + goto exit; + } +#endif + + /* */ + /* d. Initialize BB related configurations. */ + /* */ + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_BB); +#if (HAL_BB_ENABLE == 1) + status = PHY_BBConfig8188E(Adapter); + if (status == _FAIL) { + RTW_INFO(" ### Failed to init BB ......\n "); + goto exit; + } +#endif + + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_RF); +#if (HAL_RF_ENABLE == 1) + status = PHY_RFConfig8188E(Adapter); + if (status == _FAIL) { + RTW_INFO(" ### Failed to init RF ......\n "); + goto exit; + } +#endif + + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_EFUSE_PATCH); +#if defined(CONFIG_IOL_EFUSE_PATCH) + status = rtl8188e_iol_efuse_patch(Adapter); + if (status == _FAIL) { + RTW_INFO("%s rtl8188e_iol_efuse_patch failed\n", __func__); + goto exit; + } +#endif + + _InitTxBufferBoundary(Adapter, txpktbuf_bndy); + + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_LLTT); + status = InitLLTTable(Adapter, txpktbuf_bndy); + if (status == _FAIL) { + goto exit; + } + + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC02); + /* Get Rx PHY status in order to report RSSI and others. */ + _InitDriverInfoSize(Adapter, DRVINFO_SZ); + + _InitInterrupt(Adapter); + _InitNetworkType(Adapter);/* set msr */ + _InitWMACSetting(Adapter); + _InitAdaptiveCtrl(Adapter); + _InitEDCA(Adapter); + /* _InitRateFallback(Adapter); */ /* just follow MP Team ???Georgia */ + _InitRetryFunction(Adapter); + InitUsbAggregationSetting(Adapter); + _InitOperationMode(Adapter);/* todo */ + _InitBeaconParameters(Adapter); + _InitBeaconMaxError(Adapter, true); + + /* */ + /* Init CR MACTXEN, MACRXEN after setting RxFF boundary REG_TRXFF_BNDY to patch */ + /* Hw bug which Hw initials RxFF boundry size to a value which is larger than the real Rx buffer size in 88E. */ + /* */ + /* Enable MACTXEN/MACRXEN block */ + value16 = rtw_read16(Adapter, REG_CR); + value16 |= (MACTXEN | MACRXEN); + rtw_write8(Adapter, REG_CR, value16); + + _InitHardwareDropIncorrectBulkOut(Adapter); + + if (pHalData->bRDGEnable) + _InitRDGSetting(Adapter); + + /* Enable TX Report & Tx Report Timer */ + value8 = rtw_read8(Adapter, REG_TX_RPT_CTRL); + rtw_write8(Adapter, REG_TX_RPT_CTRL, (value8 | BIT1 | BIT0)); + +#if (RATE_ADAPTIVE_SUPPORT == 1) + if (!pHalData->fw_ractrl) { + /* Set MAX RPT MACID */ + rtw_write8(Adapter, REG_TX_RPT_CTRL + 1, 2); /* FOR sta mode ,0: bc/mc ,1:AP */ + /* Tx RPT Timer. Unit: 32us */ + rtw_write16(Adapter, REG_TX_RPT_TIME, 0xCdf0); + } else +#endif + { + /* disable tx rpt */ + rtw_write8(Adapter, REG_TX_RPT_CTRL + 1, 0); /* FOR sta mode ,0: bc/mc ,1:AP */ + } + +#ifdef CONFIG_TX_EARLY_MODE + if (pHalData->bEarlyModeEnable) { + + value8 = rtw_read8(Adapter, REG_EARLY_MODE_CONTROL); +#if RTL8188E_EARLY_MODE_PKT_NUM_10 == 1 + value8 = value8 | 0x1f; +#else + value8 = value8 | 0xf; +#endif + rtw_write8(Adapter, REG_EARLY_MODE_CONTROL, value8); + + rtw_write8(Adapter, REG_EARLY_MODE_CONTROL + 3, 0x80); + + value8 = rtw_read8(Adapter, REG_TCR + 1); + value8 = value8 | 0x40; + rtw_write8(Adapter, REG_TCR + 1, value8); + } else +#endif + { + rtw_write8(Adapter, REG_EARLY_MODE_CONTROL, 0); + } + + rtw_write32(Adapter, REG_MACID_NO_LINK_0, 0xFFFFFFFF); + rtw_write32(Adapter, REG_MACID_NO_LINK_1, 0xFFFFFFFF); + +#if defined(CONFIG_CONCURRENT_MODE) || defined(CONFIG_TX_MCAST2UNI) + +#ifdef CONFIG_CHECK_AC_LIFETIME + /* Enable lifetime check for the four ACs */ + rtw_write8(Adapter, REG_LIFETIME_CTRL, rtw_read8(Adapter, REG_LIFETIME_CTRL) | 0x0f); +#endif /* CONFIG_CHECK_AC_LIFETIME */ + +#ifdef CONFIG_TX_MCAST2UNI + rtw_write16(Adapter, REG_PKT_VO_VI_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */ + rtw_write16(Adapter, REG_PKT_BE_BK_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */ +#else /* CONFIG_TX_MCAST2UNI */ + rtw_write16(Adapter, REG_PKT_VO_VI_LIFE_TIME, 0x3000); /* unit: 256us. 3s */ + rtw_write16(Adapter, REG_PKT_BE_BK_LIFE_TIME, 0x3000); /* unit: 256us. 3s */ +#endif /* CONFIG_TX_MCAST2UNI */ +#endif /* CONFIG_CONCURRENT_MODE || CONFIG_TX_MCAST2UNI */ + +#ifdef CONFIG_LED + _InitHWLed(Adapter); +#endif /* CONFIG_LED */ + + /* */ + /* Joseph Note: Keep RfRegChnlVal for later use. */ + /* */ + pHalData->RfRegChnlVal[0] = phy_query_rf_reg(Adapter, 0, RF_CHNLBW, bRFRegOffsetMask); + pHalData->RfRegChnlVal[1] = phy_query_rf_reg(Adapter, 1, RF_CHNLBW, bRFRegOffsetMask); + + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_TURN_ON_BLOCK); + _BBTurnOnBlock(Adapter); + /* NicIFSetMacAddress(padapter, padapter->PermanentAddress); */ + + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_SECURITY); + invalidate_cam_all(Adapter); + + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC11); + /* 2010/12/17 MH We need to set TX power according to EFUSE content at first. */ + PHY_SetTxPowerLevel8188E(Adapter, pHalData->current_channel); + + /* Move by Neo for USB SS to below setp + * _RfPowerSave(Adapter); */ + + _InitAntenna_Selection(Adapter); + + /* */ + /* Disable BAR, suggested by Scott */ + /* 2010.04.09 add by hpfan */ + /* */ + rtw_write32(Adapter, REG_BAR_MODE_CTRL, 0x0201ffff); + + /* HW SEQ CTRL */ + /* set 0x0 to 0xFF by tynli. Default enable HW SEQ NUM. */ + rtw_write8(Adapter, REG_HWSEQ_CTRL, 0xFF); + + PHY_SetRFEReg_8188E(Adapter); + + if (pregistrypriv->wifi_spec) { + rtw_write16(Adapter, REG_FAST_EDCA_CTRL , 0); + /* Nav limit , suggest by scott */ + rtw_write8(Adapter, REG_NAV_UPPER, 0x0); + } + + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_HAL_DM); + rtl8188e_InitHalDm(Adapter); + +#if (MP_DRIVER == 1) + if (Adapter->registrypriv.mp_mode == 1) { + Adapter->mppriv.channel = pHalData->current_channel; + MPT_InitializeAdapter(Adapter, Adapter->mppriv.channel); + } else +#endif /* #if (MP_DRIVER == 1) */ + { + /* */ + /* 2010/08/11 MH Merge from 8192SE for Minicard init. We need to confirm current radio status */ + /* and then decide to enable RF or not.!!!??? For Selective suspend mode. We may not */ + /* call init_adapter. May cause some problem?? */ + /* */ + /* Fix the bug that Hw/Sw radio off before S3/S4, the RF off action will not be executed */ + /* in MgntActSet_RF_State() after wake up, because the value of pHalData->eRFPowerState */ + /* is the same as eRfOff, we should change it to eRfOn after we config RF parameters. */ + /* Added by tynli. 2010.03.30. */ + pwrctrlpriv->rf_pwrstate = rf_on; + + if (!pHalData->fw_ractrl) { + /* enable Tx report. */ + rtw_write8(Adapter, REG_FWHW_TXQ_CTRL + 1, 0x0F); + /* tynli_test_tx_report. */ + rtw_write16(Adapter, REG_TX_RPT_TIME, 0x3DF0); + } + + /* Suggested by SD1 pisa. Added by tynli. 2011.10.21. */ + rtw_write8(Adapter, REG_EARLY_MODE_CONTROL + 3, 0x01); /* Pretx_en, for WEP/TKIP SEC */ + + /* enable tx DMA to drop the redundate data of packet */ + rtw_write16(Adapter, REG_TXDMA_OFFSET_CHK, (rtw_read16(Adapter, REG_TXDMA_OFFSET_CHK) | DROP_DATA_EN)); + + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_IQK); + /* 2010/08/26 MH Merge from 8192CE. */ + if (pwrctrlpriv->rf_pwrstate == rf_on) { + if (pHalData->bIQKInitialized) + phy_iq_calibrate_8188e(Adapter, true); + else { + phy_iq_calibrate_8188e(Adapter, false); + pHalData->bIQKInitialized = true; + } + + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_PW_TRACK); + + odm_txpowertracking_check(&pHalData->odmpriv); + + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_LCK); + phy_lc_calibrate_8188e(&pHalData->odmpriv); + } + } + + /* HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PABIAS); + * _InitPABias(Adapter); */ + rtw_write8(Adapter, REG_USB_HRPWM, 0); + +#ifdef CONFIG_XMIT_ACK + /* ack for xmit mgmt frames. */ + rtw_write32(Adapter, REG_FWHW_TXQ_CTRL, rtw_read32(Adapter, REG_FWHW_TXQ_CTRL) | BIT(12)); +#endif /* CONFIG_XMIT_ACK */ + +exit: + HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_END); + + RTW_INFO("%s in %dms\n", __func__, rtw_get_passing_time_ms(init_start_time)); + +#ifdef DBG_HAL_INIT_PROFILING + hal_init_stages_timestamp[HAL_INIT_STAGES_END] = jiffies; + + for (hal_init_profiling_i = 0; hal_init_profiling_i < HAL_INIT_STAGES_NUM - 1; hal_init_profiling_i++) { + RTW_INFO("DBG_HAL_INIT_PROFILING: %35s, %u, %5u, %5u\n" + , hal_init_stages_str[hal_init_profiling_i] + , hal_init_stages_timestamp[hal_init_profiling_i] + , (hal_init_stages_timestamp[hal_init_profiling_i + 1] - hal_init_stages_timestamp[hal_init_profiling_i]) + , rtw_get_time_interval_ms(hal_init_stages_timestamp[hal_init_profiling_i], hal_init_stages_timestamp[hal_init_profiling_i + 1]) + ); + } +#endif + + return status; +} + +void _ps_open_RF(_adapter *padapter) +{ + /* here call with bRegSSPwrLvl 1, bRegSSPwrLvl 2 needs to be verified */ + /* phy_SsPwrSwitch92CU(padapter, rf_on, 1); */ +} + +static void _ps_close_RF(_adapter *padapter) +{ + /* here call with bRegSSPwrLvl 1, bRegSSPwrLvl 2 needs to be verified */ + /* phy_SsPwrSwitch92CU(padapter, rf_off, 1); */ +} + +static void +hal_poweroff_8188eu( + PADAPTER Adapter +) +{ + + u8 val8; + u16 val16; + u32 val32; + u8 bMacPwrCtrlOn = false; + + rtw_hal_get_hwreg(Adapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); + if (bMacPwrCtrlOn == false) + return ; + + /* Stop Tx Report Timer. 0x4EC[Bit1]=b'0 */ + val8 = rtw_read8(Adapter, REG_TX_RPT_CTRL); + rtw_write8(Adapter, REG_TX_RPT_CTRL, val8 & (~BIT1)); + + /* stop rx */ + rtw_write8(Adapter, REG_CR, 0x0); + + /* Run LPS WL RFOFF flow */ + HalPwrSeqCmdParsing(Adapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, Rtl8188E_NIC_LPS_ENTER_FLOW); + + /* 2. 0x1F[7:0] = 0 */ /* turn off RF */ + /* rtw_write8(Adapter, REG_RF_CTRL, 0x00); */ + + val8 = rtw_read8(Adapter, REG_MCUFWDL); + if ((val8 & RAM_DL_SEL) && Adapter->bFWReady) { /* 8051 RAM code */ + /* _8051Reset88E(padapter); */ + + /* Reset MCU 0x2[10]=0. */ + val8 = rtw_read8(Adapter, REG_SYS_FUNC_EN + 1); + val8 &= ~BIT(2); /* 0x2[10], FEN_CPUEN */ + rtw_write8(Adapter, REG_SYS_FUNC_EN + 1, val8); + } + + /* val8 = rtw_read8(Adapter, REG_SYS_FUNC_EN+1); */ + /* val8 &= ~BIT(2); */ /* 0x2[10], FEN_CPUEN */ + /* rtw_write8(Adapter, REG_SYS_FUNC_EN+1, val8); */ + + /* MCUFWDL 0x80[1:0]=0 */ + /* reset MCU ready status */ + rtw_write8(Adapter, REG_MCUFWDL, 0); + + /* YJ,add,111212 */ + /* Disable 32k */ + val8 = rtw_read8(Adapter, REG_32K_CTRL); + rtw_write8(Adapter, REG_32K_CTRL, val8 & (~BIT0)); + + /* Card disable power action flow */ + HalPwrSeqCmdParsing(Adapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, Rtl8188E_NIC_DISABLE_FLOW); + + /* Reset MCU IO Wrapper */ + val8 = rtw_read8(Adapter, REG_RSV_CTRL + 1); + rtw_write8(Adapter, REG_RSV_CTRL + 1, (val8 & (~BIT3))); + val8 = rtw_read8(Adapter, REG_RSV_CTRL + 1); + rtw_write8(Adapter, REG_RSV_CTRL + 1, val8 | BIT3); + + /* YJ,test add, 111207. For Power Consumption. */ + val8 = rtw_read8(Adapter, GPIO_IN); + rtw_write8(Adapter, GPIO_OUT, val8); + rtw_write8(Adapter, GPIO_IO_SEL, 0xFF);/* Reg0x46 */ + + val8 = rtw_read8(Adapter, REG_GPIO_IO_SEL); + /* rtw_write8(Adapter, REG_GPIO_IO_SEL, (val8<<4)|val8); */ + rtw_write8(Adapter, REG_GPIO_IO_SEL, (val8 << 4)); + val8 = rtw_read8(Adapter, REG_GPIO_IO_SEL + 1); + rtw_write8(Adapter, REG_GPIO_IO_SEL + 1, val8 | 0x0F); /* Reg0x43 */ + rtw_write32(Adapter, REG_BB_PAD_CTRL, 0x00080808);/* set LNA ,TRSW,EX_PA Pin to output mode */ + + Adapter->bFWReady = false; + + bMacPwrCtrlOn = false; + rtw_hal_set_hwreg(Adapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn); +} +static void rtl8188eu_hw_power_down(_adapter *padapter) +{ + /* 2010/-8/09 MH For power down module, we need to enable register block contrl reg at 0x1c. */ + /* Then enable power down control bit of register 0x04 BIT4 and BIT15 as 1. */ + + /* Enable register area 0x0-0xc. */ + rtw_write8(padapter, REG_RSV_CTRL, 0x0); + rtw_write16(padapter, REG_APS_FSMCO, 0x8812); +} + +static u32 rtl8188eu_hal_deinit(PADAPTER Adapter) +{ + struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(Adapter); + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + RTW_INFO("==> %s\n", __func__); + +#ifdef CONFIG_SUPPORT_USB_INT + rtw_write32(Adapter, REG_HIMR_88E, IMR_DISABLED_88E); + rtw_write32(Adapter, REG_HIMRE_88E, IMR_DISABLED_88E); +#endif + +#ifdef SUPPORT_HW_RFOFF_DETECTED + RTW_INFO("bkeepfwalive(%x)\n", pwrctl->bkeepfwalive); + if (pwrctl->bkeepfwalive) { + _ps_close_RF(Adapter); + if ((pwrctl->bHWPwrPindetect) && (pwrctl->bHWPowerdown)) + rtl8188eu_hw_power_down(Adapter); + } else +#endif + { + if (rtw_is_hw_init_completed(Adapter)) { + rtw_hal_power_off(Adapter); + + if ((pwrctl->bHWPwrPindetect) && (pwrctl->bHWPowerdown)) + rtl8188eu_hw_power_down(Adapter); + + } + } + return _SUCCESS; +} + +static unsigned int rtl8188eu_inirp_init(PADAPTER Adapter) +{ + u8 i; + struct recv_buf *precvbuf; + uint status; + struct dvobj_priv *pdev = adapter_to_dvobj(Adapter); + struct intf_hdl *pintfhdl = &Adapter->iopriv.intf; + struct recv_priv *precvpriv = &(Adapter->recvpriv); + u32(*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem); +#ifdef CONFIG_USB_INTERRUPT_IN_PIPE + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u32(*_read_interrupt)(struct intf_hdl *pintfhdl, u32 addr); +#endif + + _read_port = pintfhdl->io_ops._read_port; + + status = _SUCCESS; + + precvpriv->ff_hwaddr = RECV_BULK_IN_ADDR; + + /* issue Rx irp to receive data */ + precvbuf = (struct recv_buf *)precvpriv->precv_buf; + for (i = 0; i < NR_RECVBUFF; i++) { + if (_read_port(pintfhdl, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf) == false) { + status = _FAIL; + goto exit; + } + + precvbuf++; + precvpriv->free_recv_buf_queue_cnt--; + } + +#ifdef CONFIG_USB_INTERRUPT_IN_PIPE + if (pdev->RtInPipe[REALTEK_USB_IN_INT_EP_IDX] != 0x05) { + status = _FAIL; + RTW_INFO("%s =>Warning !! Have not USB Int-IN pipe, RtIntInPipe(%d)!!!\n", __func__, pdev->RtInPipe[REALTEK_USB_IN_INT_EP_IDX]); + goto exit; + } + _read_interrupt = pintfhdl->io_ops._read_interrupt; + if (_read_interrupt(pintfhdl, RECV_INT_IN_ADDR) == false) { + status = _FAIL; + } +#endif + +exit: + + return status; + +} + +static unsigned int rtl8188eu_inirp_deinit(PADAPTER Adapter) +{ + + rtw_read_port_cancel(Adapter); + + return _SUCCESS; +} + +/* ------------------------------------------------------------------------- + * + * EEPROM Power index mapping + * + * ------------------------------------------------------------------------- */ + +/* ------------------------------------------------------------------- + * + * EEPROM/EFUSE Content Parsing + * + * ------------------------------------------------------------------- */ + +static void +_ReadLEDSetting( + PADAPTER Adapter, + u8 *PROMContent, + bool AutoloadFail +) +{ + struct led_priv *pledpriv = &(Adapter->ledpriv); + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); +#ifdef CONFIG_SW_LED + pledpriv->bRegUseLed = true; + + switch (pHalData->CustomerID) { + default: + pledpriv->LedStrategy = SW_LED_MODE1; + break; + } + pHalData->bLedOpenDrain = true;/* Support Open-drain arrangement for controlling the LED. Added by Roger, 2009.10.16. */ +#else /* HW LED */ + pledpriv->LedStrategy = HW_LED; +#endif /* CONFIG_SW_LED */ +} + +static void +_ReadRFSetting( + PADAPTER Adapter, + u8 *PROMContent, + bool AutoloadFail +) +{ +} + +static void +hal_InitPGData( + PADAPTER pAdapter, + u8 *PROMContent +) +{ +} +static void +Hal_EfuseParsePIDVID_8188EU( + PADAPTER pAdapter, + u8 *hwinfo, + bool AutoLoadFail +) +{ + + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + + if (!AutoLoadFail) { + /* VID, PID */ + pHalData->EEPROMVID = ReadLE2Byte(&hwinfo[EEPROM_VID_88EU]); + pHalData->EEPROMPID = ReadLE2Byte(&hwinfo[EEPROM_PID_88EU]); + + /* Customer ID, 0x00 and 0xff are reserved for Realtek. */ + pHalData->EEPROMCustomerID = *(u8 *)&hwinfo[EEPROM_CustomID_88E]; + pHalData->EEPROMSubCustomerID = EEPROM_Default_SubCustomerID; + + } else { + pHalData->EEPROMVID = EEPROM_Default_VID; + pHalData->EEPROMPID = EEPROM_Default_PID; + + /* Customer ID, 0x00 and 0xff are reserved for Realtek. */ + pHalData->EEPROMCustomerID = EEPROM_Default_CustomerID; + pHalData->EEPROMSubCustomerID = EEPROM_Default_SubCustomerID; + + } + + RTW_INFO("VID = 0x%04X, PID = 0x%04X\n", pHalData->EEPROMVID, pHalData->EEPROMPID); + RTW_INFO("Customer ID: 0x%02X, SubCustomer ID: 0x%02X\n", pHalData->EEPROMCustomerID, pHalData->EEPROMSubCustomerID); +} + +static void +Hal_CustomizeByCustomerID_8188EU( + PADAPTER padapter +) +{ +} + +static void +readAdapterInfo_8188EU( + PADAPTER padapter +) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); + + /* parse the eeprom/efuse content */ + Hal_EfuseParseIDCode88E(padapter, pHalData->efuse_eeprom_data); + Hal_EfuseParsePIDVID_8188EU(padapter, pHalData->efuse_eeprom_data, pHalData->bautoload_fail_flag); + hal_config_macaddr(padapter, pHalData->bautoload_fail_flag); + Hal_ReadPowerSavingMode88E(padapter, pHalData->efuse_eeprom_data, pHalData->bautoload_fail_flag); + Hal_ReadTxPowerInfo88E(padapter, pHalData->efuse_eeprom_data, pHalData->bautoload_fail_flag); + Hal_EfuseParseEEPROMVer88E(padapter, pHalData->efuse_eeprom_data, pHalData->bautoload_fail_flag); + rtl8188e_EfuseParseChnlPlan(padapter, pHalData->efuse_eeprom_data, pHalData->bautoload_fail_flag); + Hal_EfuseParseXtal_8188E(padapter, pHalData->efuse_eeprom_data, pHalData->bautoload_fail_flag); + Hal_EfuseParseCustomerID88E(padapter, pHalData->efuse_eeprom_data, pHalData->bautoload_fail_flag); + Hal_ReadAntennaDiversity88E(padapter, pHalData->efuse_eeprom_data, pHalData->bautoload_fail_flag); + Hal_EfuseParseBoardType88E(padapter, pHalData->efuse_eeprom_data, pHalData->bautoload_fail_flag); + Hal_ReadThermalMeter_88E(padapter, pHalData->efuse_eeprom_data, pHalData->bautoload_fail_flag); + Hal_ReadPAType_8188E(padapter, pHalData->efuse_eeprom_data, pHalData->bautoload_fail_flag); + Hal_ReadAmplifierType_8188E(padapter, pHalData->efuse_eeprom_data, pHalData->bautoload_fail_flag); + Hal_ReadRFEType_8188E(padapter, pHalData->efuse_eeprom_data, pHalData->bautoload_fail_flag); +#ifdef CONFIG_RF_POWER_TRIM + Hal_ReadRFGainOffset(padapter, pHalData->efuse_eeprom_data, pHalData->bautoload_fail_flag); +#endif /*CONFIG_RF_POWER_TRIM*/ + + Hal_CustomizeByCustomerID_8188EU(padapter); + + _ReadLEDSetting(padapter, pHalData->efuse_eeprom_data, pHalData->bautoload_fail_flag); +} + +static void _ReadPROMContent( + PADAPTER Adapter +) +{ + PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter); + u8 eeValue; + + /* check system boot selection */ + eeValue = rtw_read8(Adapter, REG_9346CR); + pHalData->EepromOrEfuse = (eeValue & BOOT_FROM_EEPROM) ? true : false; + pHalData->bautoload_fail_flag = (eeValue & EEPROM_EN) ? false : true; + + RTW_INFO("Boot from %s, Autoload %s !\n", (pHalData->EepromOrEfuse ? "EEPROM" : "EFUSE"), + (pHalData->bautoload_fail_flag ? "Fail" : "OK")); + + /* pHalData->EEType = IS_BOOT_FROM_EEPROM(Adapter) ? EEPROM_93C46 : EEPROM_BOOT_EFUSE; */ + + Hal_InitPGData88E(Adapter); + readAdapterInfo_8188EU(Adapter); +} + +static void +_ReadRFType( + PADAPTER Adapter +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + +#if DISABLE_BB_RF + pHalData->rf_chip = RF_PSEUDO_11N; +#else + pHalData->rf_chip = RF_6052; +#endif +} + +static u8 ReadAdapterInfo8188EU(PADAPTER Adapter) +{ + /* Read EEPROM size before call any EEPROM function */ + Adapter->EepromAddressSize = GetEEPROMSize8188E(Adapter); + + /* Efuse_InitSomeVar(Adapter); */ + + _ReadRFType(Adapter);/* rf_chip->_InitRFType() */ + _ReadPROMContent(Adapter); + + return _SUCCESS; +} + +static void UpdateInterruptMask8188EU(PADAPTER padapter, u8 bHIMR0 , u32 AddMSR, u32 RemoveMSR) +{ + HAL_DATA_TYPE *pHalData; + + u32 *himr; + pHalData = GET_HAL_DATA(padapter); + + if (bHIMR0) + himr = &(pHalData->IntrMask[0]); + else + himr = &(pHalData->IntrMask[1]); + + if (AddMSR) + *himr |= AddMSR; + + if (RemoveMSR) + *himr &= (~RemoveMSR); + + if (bHIMR0) + rtw_write32(padapter, REG_HIMR_88E, *himr); + else + rtw_write32(padapter, REG_HIMRE_88E, *himr); + +} + +static void SetHwReg8188EU(PADAPTER Adapter, u8 variable, u8 *val) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + switch (variable) { + + case HW_VAR_RXDMA_AGG_PG_TH: +#ifdef CONFIG_USB_RX_AGGREGATION + { + u8 threshold = *((u8 *)val); + if (threshold == 0) + threshold = pHalData->rxagg_dma_size; + rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH, threshold); + } +#endif + break; + case HW_VAR_SET_RPWM: +#ifdef CONFIG_LPS_LCLK + { + u8 ps_state = *((u8 *)val); + /* rpwm value only use BIT0(clock bit) ,BIT6(Ack bit), and BIT7(Toggle bit) for 88e. */ + /* BIT0 value - 1: 32k, 0:40MHz. */ + /* BIT6 value - 1: report cpwm value after success set, 0:do not report. */ + /* BIT7 value - Toggle bit change. */ + /* modify by Thomas. 2012/4/2. */ + ps_state = ps_state & 0xC1; + /* RTW_INFO("##### Change RPWM value to = %x for switch clk #####\n",ps_state); */ + rtw_write8(Adapter, REG_USB_HRPWM, ps_state); + } +#endif + break; + default: + SetHwReg8188E(Adapter, variable, val); + break; + } + +} + +static void GetHwReg8188EU(PADAPTER Adapter, u8 variable, u8 *val) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + switch (variable) { + default: + GetHwReg8188E(Adapter, variable, val); + break; + } + +} + +/* + * Description: + * Query setting of specified variable. + * */ +static u8 +GetHalDefVar8188EUsb( + PADAPTER Adapter, + HAL_DEF_VARIABLE eVariable, + void * pValue +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u8 bResult = _SUCCESS; + + switch (eVariable) { + case HW_VAR_MAX_RX_AMPDU_FACTOR: + *((u32 *)pValue) = MAX_AMPDU_FACTOR_64K; + break; + + case HAL_DEF_TX_LDPC: + case HAL_DEF_RX_LDPC: + *((u8 *)pValue) = false; + break; + case HAL_DEF_TX_STBC: + *((u8 *)pValue) = 0; + break; + case HAL_DEF_RX_STBC: + *((u8 *)pValue) = 1; + break; + default: + bResult = GetHalDefVar8188E(Adapter, eVariable, pValue); + break; + } + + return bResult; +} + +/* + * Description: + * Change default setting of specified variable. + * */ +static u8 +SetHalDefVar8188EUsb( + PADAPTER Adapter, + HAL_DEF_VARIABLE eVariable, + void * pValue +) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + u8 bResult = _SUCCESS; + + switch (eVariable) { + default: + bResult = SetHalDefVar(Adapter, eVariable, pValue); + break; + } + + return bResult; +} + +static void _update_response_rate(_adapter *padapter, unsigned int mask) +{ + u8 RateIndex = 0; + /* Set RRSR rate table. */ + rtw_write8(padapter, REG_RRSR, mask & 0xff); + rtw_write8(padapter, REG_RRSR + 1, (mask >> 8) & 0xff); + + /* Set RTS initial rate */ + while (mask > 0x1) { + mask = (mask >> 1); + RateIndex++; + } + rtw_write8(padapter, REG_INIRTS_RATE_SEL, RateIndex); +} + +static void SetBeaconRelatedRegisters8188EUsb(PADAPTER padapter) +{ + u32 value32; + /* HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); */ + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + u32 bcn_ctrl_reg = REG_BCN_CTRL; + /* reset TSF, enable update TSF, correcting TSF On Beacon */ + + /* REG_BCN_INTERVAL */ + /* REG_BCNDMATIM */ + /* REG_ATIMWND */ + /* REG_TBTT_PROHIBIT */ + /* REG_DRVERLYINT */ + /* REG_BCN_MAX_ERR */ + /* REG_BCNTCFG */ /* (0x510) */ + /* REG_DUAL_TSF_RST */ + /* REG_BCN_CTRL */ /* (0x550) */ + + /* BCN interval */ +#ifdef CONFIG_CONCURRENT_MODE + if (padapter->hw_port == HW_PORT1) + bcn_ctrl_reg = REG_BCN_CTRL_1; +#endif + rtw_write16(padapter, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval); + rtw_write8(padapter, REG_ATIMWND, 0x02);/* 2ms */ + + _InitBeaconParameters(padapter); + + rtw_write8(padapter, REG_SLOT, 0x09); + + value32 = rtw_read32(padapter, REG_TCR); + value32 &= ~TSFRST; + rtw_write32(padapter, REG_TCR, value32); + + value32 |= TSFRST; + rtw_write32(padapter, REG_TCR, value32); + + /* NOTE: Fix test chip's bug (about contention windows's randomness) */ + rtw_write8(padapter, REG_RXTSF_OFFSET_CCK, 0x50); + rtw_write8(padapter, REG_RXTSF_OFFSET_OFDM, 0x50); + + _BeaconFunctionEnable(padapter, true, true); + + ResumeTxBeacon(padapter); + + /* rtw_write8(padapter, 0x422, rtw_read8(padapter, 0x422)|BIT(6)); */ + + /* rtw_write8(padapter, 0x541, 0xff); */ + + /* rtw_write8(padapter, 0x542, rtw_read8(padapter, 0x541)|BIT(0)); */ + + rtw_write8(padapter, bcn_ctrl_reg, rtw_read8(padapter, bcn_ctrl_reg) | BIT(1)); + +} + +static void rtl8188eu_init_default_value(_adapter *padapter) +{ + PHAL_DATA_TYPE pHalData; + struct pwrctrl_priv *pwrctrlpriv; + u8 i; + + pHalData = GET_HAL_DATA(padapter); + pwrctrlpriv = adapter_to_pwrctl(padapter); + + rtl8188e_init_default_value(padapter); + + /* init default value */ + pHalData->fw_ractrl = false; + if (!pwrctrlpriv->bkeepfwalive) + pHalData->LastHMEBoxNum = 0; + + /* init dm default value */ + pHalData->bIQKInitialized = false; + pHalData->odmpriv.rf_calibrate_info.tm_trigger = 0;/* for IQK */ + /* pdmpriv->binitialized = false; + * pdmpriv->prv_traffic_idx = 3; + * pdmpriv->initialize = 0; */ + pHalData->odmpriv.rf_calibrate_info.thermal_value_hp_index = 0; + for (i = 0; i < HP_THERMAL_NUM; i++) + pHalData->odmpriv.rf_calibrate_info.thermal_value_hp[i] = 0; + + pHalData->EfuseHal.fakeEfuseBank = 0; + pHalData->EfuseHal.fakeEfuseUsedBytes = 0; + memset(pHalData->EfuseHal.fakeEfuseContent, 0xFF, EFUSE_MAX_HW_SIZE); + memset(pHalData->EfuseHal.fakeEfuseInitMap, 0xFF, EFUSE_MAX_MAP_LEN); + memset(pHalData->EfuseHal.fakeEfuseModifiedMap, 0xFF, EFUSE_MAX_MAP_LEN); +} + +static u8 rtl8188eu_ps_func(PADAPTER Adapter, HAL_INTF_PS_FUNC efunc_id, u8 *val) +{ + u8 bResult = true; + switch (efunc_id) { + +#if defined(CONFIG_AUTOSUSPEND) && defined(SUPPORT_HW_RFOFF_DETECTED) + case HAL_USB_SELECT_SUSPEND: { + u8 bfwpoll = *((u8 *)val); + /* rtl8188e_set_FwSelectSuspend_cmd(Adapter,bfwpoll ,500); */ /* note fw to support hw power down ping detect */ + } + break; +#endif /* CONFIG_AUTOSUSPEND && SUPPORT_HW_RFOFF_DETECTED */ + + default: + break; + } + return bResult; +} + +void rtl8188eu_set_hal_ops(_adapter *padapter) +{ + struct hal_ops *pHalFunc = &padapter->hal_func; + + pHalFunc->hal_power_on = _InitPowerOn_8188EU; + pHalFunc->hal_power_off = hal_poweroff_8188eu; + + pHalFunc->hal_init = &rtl8188eu_hal_init; + pHalFunc->hal_deinit = &rtl8188eu_hal_deinit; + + pHalFunc->inirp_init = &rtl8188eu_inirp_init; + pHalFunc->inirp_deinit = &rtl8188eu_inirp_deinit; + + pHalFunc->init_xmit_priv = &rtl8188eu_init_xmit_priv; + pHalFunc->free_xmit_priv = &rtl8188eu_free_xmit_priv; + + pHalFunc->init_recv_priv = &rtl8188eu_init_recv_priv; + pHalFunc->free_recv_priv = &rtl8188eu_free_recv_priv; +#ifdef CONFIG_SW_LED + pHalFunc->InitSwLeds = &rtl8188eu_InitSwLeds; + pHalFunc->DeInitSwLeds = &rtl8188eu_DeInitSwLeds; +#else /* case of hw led or no led */ + pHalFunc->InitSwLeds = NULL; + pHalFunc->DeInitSwLeds = NULL; +#endif/* CONFIG_SW_LED */ + + pHalFunc->init_default_value = &rtl8188eu_init_default_value; + pHalFunc->intf_chip_configure = &rtl8188eu_interface_configure; + pHalFunc->read_adapter_info = &ReadAdapterInfo8188EU; + pHalFunc->set_hw_reg_handler = &SetHwReg8188EU; + pHalFunc->GetHwRegHandler = &GetHwReg8188EU; + pHalFunc->get_hal_def_var_handler = &GetHalDefVar8188EUsb; + pHalFunc->SetHalDefVarHandler = &SetHalDefVar8188EUsb; + + pHalFunc->SetBeaconRelatedRegistersHandler = &SetBeaconRelatedRegisters8188EUsb; + + pHalFunc->hal_xmit = &rtl8188eu_hal_xmit; + pHalFunc->mgnt_xmit = &rtl8188eu_mgnt_xmit; + pHalFunc->hal_xmitframe_enqueue = &rtl8188eu_hal_xmitframe_enqueue; + +#ifdef CONFIG_HOSTAPD_MLME + pHalFunc->hostap_mgnt_xmit_entry = &rtl8188eu_hostap_mgnt_xmit_entry; +#endif + pHalFunc->interface_ps_func = &rtl8188eu_ps_func; + +#ifdef CONFIG_XMIT_THREAD_MODE + pHalFunc->xmit_thread_handler = &rtl8188eu_xmit_buf_handler; +#endif +#ifdef CONFIG_SUPPORT_USB_INT + pHalFunc->interrupt_handler = interrupt_handler_8188eu; +#endif + rtl8188e_set_hal_ops(pHalFunc); + +} diff --git a/drivers/staging/rtl8188eu/hal/usb_ops_linux.c b/drivers/staging/rtl8188eu/hal/usb_ops_linux.c new file mode 100644 index 000000000000..021e73723b6b --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/usb_ops_linux.c @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved. */ + +#define _HCI_OPS_OS_C_ + +#include +#include + + +#ifdef CONFIG_SUPPORT_USB_INT +void interrupt_handler_8188eu(_adapter *padapter, u16 pkt_len, u8 *pbuf) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct reportpwrstate_parm pwr_rpt; + + if (pkt_len != INTERRUPT_MSG_FORMAT_LEN) { + RTW_INFO("%s Invalid interrupt content length (%d)!\n", __func__, pkt_len); + return ; + } + + /* HISR */ + memcpy(&(pHalData->IntArray[0]), &(pbuf[USB_INTR_CONTENT_HISR_OFFSET]), 4); + memcpy(&(pHalData->IntArray[1]), &(pbuf[USB_INTR_CONTENT_HISRE_OFFSET]), 4); + +#ifdef CONFIG_LPS_LCLK + if (pHalData->IntArray[0] & IMR_CPWM_88E) { + memcpy(&pwr_rpt.state, &(pbuf[USB_INTR_CONTENT_CPWM1_OFFSET]), 1); + /* memcpy(&pwr_rpt.state2, &(pbuf[USB_INTR_CONTENT_CPWM2_OFFSET]), 1); */ + + /* 88e's cpwm value only change BIT0, so driver need to add PS_STATE_S2 for LPS flow. */ + pwr_rpt.state |= PS_STATE_S2; + _set_workitem(&(adapter_to_pwrctl(padapter)->cpwm_event)); + } +#endif/* CONFIG_LPS_LCLK */ + +#ifdef CONFIG_INTERRUPT_BASED_TXBCN + +#ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + if (pHalData->IntArray[0] & IMR_BCNDMAINT0_88E) /*only for BCN_0*/ +#endif +#ifdef CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR + if (pHalData->IntArray[0] & (IMR_TBDER_88E | IMR_TBDOK_88E)) +#endif + { + rtw_mi_set_tx_beacon_cmd(padapter); + } +#endif /* CONFIG_INTERRUPT_BASED_TXBCN */ + + + + +#ifdef DBG_CONFIG_ERROR_DETECT_INT + if (pHalData->IntArray[1] & IMR_TXERR_88E) + RTW_INFO("===> %s Tx Error Flag Interrupt Status\n", __func__); + if (pHalData->IntArray[1] & IMR_RXERR_88E) + RTW_INFO("===> %s Rx Error Flag INT Status\n", __func__); + if (pHalData->IntArray[1] & IMR_TXFOVW_88E) + RTW_INFO("===> %s Transmit FIFO Overflow\n", __func__); + if (pHalData->IntArray[1] & IMR_RXFOVW_88E) + RTW_INFO("===> %s Receive FIFO Overflow\n", __func__); +#endif/* DBG_CONFIG_ERROR_DETECT_INT */ + + +#ifdef CONFIG_FW_C2H_REG + /* C2H Event */ + if (pbuf[0] != 0) + usb_c2h_hisr_hdl(padapter, pbuf); +#endif +} +#endif + + +int recvbuf2recvframe(PADAPTER padapter, void *ptr) +{ + u8 *pbuf; + u16 pkt_cnt; + u32 pkt_offset; + s32 transfer_len; + struct recv_stat *prxstat; + u8 *pphy_status = NULL; + union recv_frame *precvframe = NULL; + struct rx_pkt_attrib *pattrib = NULL; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); + struct recv_priv *precvpriv = &padapter->recvpriv; + _queue *pfree_recv_queue = &precvpriv->free_recv_queue; + _pkt *pskb; + +#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX + pskb = NULL; + transfer_len = (s32)((struct recv_buf *)ptr)->transfer_len; + pbuf = ((struct recv_buf *)ptr)->pbuf; +#else + pskb = (_pkt *)ptr; + transfer_len = (s32)pskb->len; + pbuf = pskb->data; +#endif + prxstat = (struct recv_stat *)pbuf; + pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff; + + do { + prxstat = (struct recv_stat *)pbuf; + + precvframe = rtw_alloc_recvframe(pfree_recv_queue); + if (precvframe == NULL) { + RTW_INFO("%s()-%d: rtw_alloc_recvframe() failed! RX Drop!\n", __func__, __LINE__); + goto _exit_recvbuf2recvframe; + } + + INIT_LIST_HEAD(&precvframe->u.hdr.list); + precvframe->u.hdr.precvbuf = NULL; /* can't access the precvbuf for new arch. */ + precvframe->u.hdr.len = 0; + + rtl8188e_query_rx_desc_status(precvframe, prxstat); + + pattrib = &precvframe->u.hdr.attrib; + + if ((padapter->registrypriv.mp_mode == 0) && ((pattrib->crc_err) || (pattrib->icv_err))) { + RTW_INFO("%s: RX Warning! crc_err=%d icv_err=%d, skip!\n", __func__, pattrib->crc_err, pattrib->icv_err); + rtw_free_recvframe(precvframe, pfree_recv_queue); + goto _exit_recvbuf2recvframe; + } + + + pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + + pattrib->shift_sz + le16_to_cpu(pattrib->pkt_len); + + if ((le16_to_cpu(pattrib->pkt_len) <= 0) || (pkt_offset > transfer_len)) { + RTW_INFO("%s()-%d: RX Warning!,pkt_len<=0 or pkt_offset> transfoer_len\n", __func__, __LINE__); + rtw_free_recvframe(precvframe, pfree_recv_queue); + goto _exit_recvbuf2recvframe; + } + +#ifdef CONFIG_RX_PACKET_APPEND_FCS + if (check_fwstate(&padapter->mlmepriv, WIFI_MONITOR_STATE) == false) + if ((pattrib->pkt_rpt_type == NORMAL_RX) && (pHalData->ReceiveConfig & RCR_APPFCS)) + pattrib->pkt_len -= IEEE80211_FCS_LEN; +#endif + + if (rtw_os_alloc_recvframe(padapter, precvframe, + (pbuf + pattrib->shift_sz + pattrib->drvinfo_sz + RXDESC_SIZE), pskb) == _FAIL) { + rtw_free_recvframe(precvframe, pfree_recv_queue); + + goto _exit_recvbuf2recvframe; + } + + recvframe_put(precvframe, pattrib->pkt_len); + /* recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE); */ + + if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */ + if (pattrib->physt) + pphy_status = pbuf + RXDESC_OFFSET; + +#ifdef CONFIG_CONCURRENT_MODE + pre_recv_entry(precvframe, pphy_status); +#endif /*CONFIG_CONCURRENT_MODE*/ + + + if (pattrib->physt && pphy_status) + rx_query_phy_status(precvframe, pphy_status); + + rtw_recv_entry(precvframe); + + } else { /* pkt_rpt_type == TX_REPORT1-CCX, TX_REPORT2-TX RTP,HIS_REPORT-USB HISR RTP */ + + /* enqueue recvframe to txrtp queue */ + if (pattrib->pkt_rpt_type == TX_REPORT1) { + /* RTW_INFO("rx CCX\n"); */ + /* CCX-TXRPT ack for xmit mgmt frames. */ + handle_txrpt_ccx_88e(padapter, precvframe->u.hdr.rx_data); + } else if (pattrib->pkt_rpt_type == TX_REPORT2) { + /* RTW_INFO("recv TX RPT\n"); */ + odm_ra_tx_rpt2_handle_8188e( + &pHalData->odmpriv, + precvframe->u.hdr.rx_data, + pattrib->pkt_len, + le32_to_cpu(pattrib->MacIDValidEntry[0]), + le32_to_cpu(pattrib->MacIDValidEntry[1])); + } else if (pattrib->pkt_rpt_type == HIS_REPORT) { + /* RTW_INFO("%s , rx USB HISR\n",__func__); */ +#ifdef CONFIG_SUPPORT_USB_INT + interrupt_handler_8188eu(padapter, le16_to_cpu(pattrib->pkt_len), precvframe->u.hdr.rx_data); +#endif + } + rtw_free_recvframe(precvframe, pfree_recv_queue); + + } + +#ifdef CONFIG_USB_RX_AGGREGATION + switch (pHalData->rxagg_mode) { + case RX_AGG_DMA: + case RX_AGG_MIX: + pkt_offset = (u16)_RND128(pkt_offset); + break; + case RX_AGG_USB: + pkt_offset = (u16)_RND4(pkt_offset); + break; + case RX_AGG_DISABLE: + default: + break; + } +#endif + pkt_cnt--; + transfer_len -= pkt_offset; + pbuf += pkt_offset; + precvframe = NULL; + + if (transfer_len > 0 && pkt_cnt == 0) + pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff; + + } while ((transfer_len > 0) && (pkt_cnt > 0)); + +_exit_recvbuf2recvframe: + + return _SUCCESS; +} + + + +void rtl8188eu_xmit_tasklet(void *priv) +{ + int ret = false; + _adapter *padapter = (_adapter *)priv; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + + while (1) { + if (RTW_CANNOT_TX(padapter)) { + RTW_INFO("xmit_tasklet => bDriverStopped or bSurpriseRemoved or bWritePortCancel\n"); + break; + } + + if (rtw_xmit_ac_blocked(padapter) == true) + break; + + ret = rtl8188eu_xmitframe_complete(padapter, pxmitpriv, NULL); + + if (ret == false) + break; + } + +} + +void rtl8188eu_set_hw_type(struct dvobj_priv *pdvobj) +{ + pdvobj->HardwareType = HARDWARE_TYPE_RTL8188EU; + RTW_INFO("CHIP TYPE: RTL8188E\n"); +} diff --git a/drivers/staging/rtl8188eu/hal/version_rtl8188e.h b/drivers/staging/rtl8188eu/hal/version_rtl8188e.h new file mode 100644 index 000000000000..0facf233a901 --- /dev/null +++ b/drivers/staging/rtl8188eu/hal/version_rtl8188e.h @@ -0,0 +1,10 @@ +/*RTL8188E PHY Parameters*/ +/* +[Caution] + Since 01/Aug/2015, the commit rules will be simplified. + You do not need to fill up the version.h anymore, + only the maintenance supervisor fills it before formal release. +*/ +#define RELEASE_DATE_8188E 20160517 +#define COMMIT_BY_8188E "RF_Eason" +#define RELEASE_VERSION_8188E 70 -- 2.31.1