ar5416_misc.c (231864) | ar5416_misc.c (231927) |
---|---|
1/* 2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 * Copyright (c) 2002-2008 Atheros Communications, Inc. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * | 1/* 2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 * Copyright (c) 2002-2008 Atheros Communications, Inc. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * |
17 * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c 231864 2012-02-17 08:45:08Z adrian $ | 17 * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c 231927 2012-02-20 03:07:07Z adrian $ |
18 */ 19#include "opt_ah.h" 20 21#include "ah.h" 22#include "ah_internal.h" 23#include "ah_devid.h" 24#include "ah_desc.h" /* NB: for HAL_PHYERR* */ 25 --- 689 unchanged lines hidden (view full) --- 715 716 HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown BB hang signature! " 717 "<0x806c>=0x%x\n", __func__, hang_sig); 718 719 return 0; 720#undef N 721} 722#undef NUM_STATUS_READS | 18 */ 19#include "opt_ah.h" 20 21#include "ah.h" 22#include "ah_internal.h" 23#include "ah_devid.h" 24#include "ah_desc.h" /* NB: for HAL_PHYERR* */ 25 --- 689 unchanged lines hidden (view full) --- 715 716 HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown BB hang signature! " 717 "<0x806c>=0x%x\n", __func__, hang_sig); 718 719 return 0; 720#undef N 721} 722#undef NUM_STATUS_READS |
723 724/* 725 * Get the radar parameter values and return them in the pe 726 * structure 727 */ 728void 729ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) 730{ 731 uint32_t val, temp; 732 733 val = OS_REG_READ(ah, AR_PHY_RADAR_0); 734 735 temp = MS(val,AR_PHY_RADAR_0_FIRPWR); 736 temp |= 0xFFFFFF80; 737 pe->pe_firpwr = temp; 738 pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI); 739 pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT); 740 pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI); 741 pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND); 742 743 /* RADAR_1 values */ 744 val = OS_REG_READ(ah, AR_PHY_RADAR_1); 745 pe->pe_relpwr = MS(val, AR_PHY_RADAR_1_RELPWR_THRESH); 746 pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH); 747 pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN); 748 749 pe->pe_extchannel = !! (OS_REG_READ(ah, AR_PHY_RADAR_EXT) & 750 AR_PHY_RADAR_EXT_ENA); 751 752 pe->pe_usefir128 = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) & 753 AR_PHY_RADAR_1_USE_FIR128); 754 pe->pe_blockradar = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) & 755 AR_PHY_RADAR_1_BLOCK_CHECK); 756 pe->pe_enmaxrssi = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) & 757 AR_PHY_RADAR_1_MAX_RRSSI); 758 pe->pe_enabled = !! 759 (OS_REG_READ(ah, AR_PHY_RADAR_0) & AR_PHY_RADAR_0_ENA); 760 pe->pe_enrelpwr = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) & 761 AR_PHY_RADAR_1_RELPWR_ENA); 762 pe->pe_en_relstep_check = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) & 763 AR_PHY_RADAR_1_RELSTEP_CHECK); 764} 765 766/* 767 * Enable radar detection and set the radar parameters per the 768 * values in pe 769 */ 770void 771ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) 772{ 773 uint32_t val; 774 775 val = OS_REG_READ(ah, AR_PHY_RADAR_0); 776 777 if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) { 778 val &= ~AR_PHY_RADAR_0_FIRPWR; 779 val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR); 780 } 781 if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) { 782 val &= ~AR_PHY_RADAR_0_RRSSI; 783 val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI); 784 } 785 if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) { 786 val &= ~AR_PHY_RADAR_0_HEIGHT; 787 val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT); 788 } 789 if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) { 790 val &= ~AR_PHY_RADAR_0_PRSSI; 791 val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI); 792 } 793 if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) { 794 val &= ~AR_PHY_RADAR_0_INBAND; 795 val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND); 796 } 797 798 /*Enable FFT data*/ 799 val |= AR_PHY_RADAR_0_FFT_ENA; 800 OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); 801 802 /* Implicitly enable */ 803 if (pe->pe_enabled == 1) 804 OS_REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); 805 else if (pe->pe_enabled == 0) 806 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); 807 808 if (pe->pe_usefir128 == 1) 809 OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128); 810 else if (pe->pe_usefir128 == 0) 811 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128); 812 813 if (pe->pe_enmaxrssi == 1) 814 OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI); 815 else if (pe->pe_enmaxrssi == 0) 816 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI); 817 818 if (pe->pe_blockradar == 1) 819 OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK); 820 else if (pe->pe_blockradar == 0) 821 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK); 822 823 if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) { 824 val = OS_REG_READ(ah, AR_PHY_RADAR_1); 825 val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH; 826 val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH); 827 OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); 828 } 829 if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) { 830 val = OS_REG_READ(ah, AR_PHY_RADAR_1); 831 val &= ~AR_PHY_RADAR_1_RELPWR_THRESH; 832 val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH); 833 OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); 834 } 835 836 if (pe->pe_en_relstep_check == 1) 837 OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, 838 AR_PHY_RADAR_1_RELSTEP_CHECK); 839 else if (pe->pe_en_relstep_check == 0) 840 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, 841 AR_PHY_RADAR_1_RELSTEP_CHECK); 842 843 if (pe->pe_enrelpwr == 1) 844 OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, 845 AR_PHY_RADAR_1_RELPWR_ENA); 846 else if (pe->pe_enrelpwr == 0) 847 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, 848 AR_PHY_RADAR_1_RELPWR_ENA); 849 850 if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) { 851 val = OS_REG_READ(ah, AR_PHY_RADAR_1); 852 val &= ~AR_PHY_RADAR_1_MAXLEN; 853 val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN); 854 OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); 855 } 856 857 /* 858 * Enable HT/40 if the upper layer asks; 859 * it should check the channel is HT/40 and HAL_CAP_EXT_CHAN_DFS 860 * is available. 861 */ 862 if (pe->pe_extchannel == 1) 863 OS_REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); 864 else if (pe->pe_extchannel == 0) 865 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); 866} 867 868/* 869 * Extract the radar event information from the given phy error. 870 * 871 * Returns AH_TRUE if the phy error was actually a phy error, 872 * AH_FALSE if the phy error wasn't a phy error. 873 */ 874 875/* Flags for pulse_bw_info */ 876#define PRI_CH_RADAR_FOUND 0x01 877#define EXT_CH_RADAR_FOUND 0x02 878#define EXT_CH_RADAR_EARLY_FOUND 0x04 879 880HAL_BOOL 881ar5416ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs, 882 uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event) 883{ 884 HAL_BOOL doDfsExtCh; 885 HAL_BOOL doDfsEnhanced; 886 HAL_BOOL doDfsCombinedRssi; 887 888 uint8_t rssi = 0, ext_rssi = 0; 889 uint8_t pulse_bw_info = 0, pulse_length_ext = 0, pulse_length_pri = 0; 890 uint32_t dur = 0; 891 int pri_found = 1, ext_found = 0; 892 int early_ext = 0; 893 int is_dc = 0; 894 uint16_t datalen; /* length from the RX status field */ 895 896 /* Check whether the given phy error is a radar event */ 897 if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) && 898 (rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT)) { 899 return AH_FALSE; 900 } 901 902 /* Grab copies of the capabilities; just to make the code clearer */ 903 doDfsExtCh = AH_PRIVATE(ah)->ah_caps.halExtChanDfsSupport; 904 doDfsEnhanced = AH_PRIVATE(ah)->ah_caps.halEnhancedDfsSupport; 905 doDfsCombinedRssi = AH_PRIVATE(ah)->ah_caps.halUseCombinedRadarRssi; 906 907 datalen = rxs->rs_datalen; 908 909 /* If hardware supports it, use combined RSSI, else use chain 0 RSSI */ 910 if (doDfsCombinedRssi) 911 rssi = (uint8_t) rxs->rs_rssi; 912 else 913 rssi = (uint8_t) rxs->rs_rssi_ctl[0]; 914 915 /* Set this; but only use it if doDfsExtCh is set */ 916 ext_rssi = (uint8_t) rxs->rs_rssi_ext[0]; 917 918 /* Cap it at 0 if the RSSI is a negative number */ 919 if (rssi & 0x80) 920 rssi = 0; 921 922 if (ext_rssi & 0x80) 923 ext_rssi = 0; 924 925 /* 926 * Fetch the relevant data from the frame 927 */ 928 if (doDfsExtCh) { 929 if (datalen < 3) 930 return AH_FALSE; 931 932 /* Last three bytes of the frame are of interest */ 933 pulse_length_pri = *(buf + datalen - 3); 934 pulse_length_ext = *(buf + datalen - 2); 935 pulse_bw_info = *(buf + datalen - 1); 936 HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, ext_rssi=%d, pulse_length_pri=%d," 937 " pulse_length_ext=%d, pulse_bw_info=%x\n", 938 __func__, rssi, ext_rssi, pulse_length_pri, pulse_length_ext, 939 pulse_bw_info); 940 } else { 941 /* The pulse width is byte 0 of the data */ 942 if (datalen >= 1) 943 dur = ((uint8_t) buf[0]) & 0xff; 944 else 945 dur = 0; 946 947 if (dur == 0 && rssi == 0) { 948 HALDEBUG(ah, HAL_DEBUG_DFS, "%s: dur and rssi are 0\n", __func__); 949 return AH_FALSE; 950 } 951 952 HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n", __func__, rssi, dur); 953 954 /* Single-channel only */ 955 pri_found = 1; 956 ext_found = 0; 957 } 958 959 /* 960 * If doing extended channel data, pulse_bw_info must 961 * have one of the flags set. 962 */ 963 if (doDfsExtCh && pulse_bw_info == 0x0) 964 return AH_FALSE; 965 966 /* 967 * If the extended channel data is available, calculate 968 * which to pay attention to. 969 */ 970 if (doDfsExtCh) { 971 /* If pulse is on DC, take the larger duration of the two */ 972 if ((pulse_bw_info & EXT_CH_RADAR_FOUND) && 973 (pulse_bw_info & PRI_CH_RADAR_FOUND)) { 974 is_dc = 1; 975 if (pulse_length_ext > pulse_length_pri) { 976 dur = pulse_length_ext; 977 pri_found = 0; 978 ext_found = 1; 979 } else { 980 dur = pulse_length_pri; 981 pri_found = 1; 982 ext_found = 0; 983 } 984 } else if (pulse_bw_info & EXT_CH_RADAR_EARLY_FOUND) { 985 dur = pulse_length_ext; 986 pri_found = 0; 987 ext_found = 1; 988 early_ext = 1; 989 } else if (pulse_bw_info & PRI_CH_RADAR_FOUND) { 990 dur = pulse_length_pri; 991 pri_found = 1; 992 ext_found = 0; 993 } else if (pulse_bw_info & EXT_CH_RADAR_FOUND) { 994 dur = pulse_length_ext; 995 pri_found = 0; 996 ext_found = 1; 997 } 998 999 } 1000 1001 /* 1002 * For enhanced DFS (Merlin and later), pulse_bw_info has 1003 * implications for selecting the correct RSSI value. 1004 */ 1005 if (doDfsEnhanced) { 1006 switch (pulse_bw_info & 0x03) { 1007 case 0: 1008 /* No radar? */ 1009 rssi = 0; 1010 break; 1011 case PRI_CH_RADAR_FOUND: 1012 /* Radar in primary channel */ 1013 /* Cannot use ctrl channel RSSI if ext channel is stronger */ 1014 if (ext_rssi >= (rssi + 3)) { 1015 rssi = 0; 1016 }; 1017 break; 1018 case EXT_CH_RADAR_FOUND: 1019 /* Radar in extended channel */ 1020 /* Cannot use ext channel RSSI if ctrl channel is stronger */ 1021 if (rssi >= (ext_rssi + 12)) { 1022 rssi = 0; 1023 } else { 1024 rssi = ext_rssi; 1025 } 1026 break; 1027 case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND): 1028 /* When both are present, use stronger one */ 1029 if (rssi < ext_rssi) 1030 rssi = ext_rssi; 1031 break; 1032 } 1033 } 1034 1035 /* 1036 * If not doing enhanced DFS, choose the ext channel if 1037 * it is stronger than the main channel 1038 */ 1039 if (doDfsExtCh && !doDfsEnhanced) { 1040 if ((ext_rssi > rssi) && (ext_rssi < 128)) 1041 rssi = ext_rssi; 1042 } 1043 1044 /* 1045 * XXX what happens if the above code decides the RSSI 1046 * XXX wasn't valid, an sets it to 0? 1047 */ 1048 1049 /* 1050 * Fill out dfs_event structure. 1051 */ 1052 event->re_full_ts = fulltsf; 1053 event->re_ts = rxs->rs_tstamp; 1054 event->re_rssi = rssi; 1055 event->re_dur = dur; 1056 1057 event->re_flags = 0; 1058 if (pri_found) 1059 event->re_flags |= HAL_DFS_EVENT_PRICH; 1060 if (ext_found) 1061 event->re_flags |= HAL_DFS_EVENT_EXTCH; 1062 if (early_ext) 1063 event->re_flags |= HAL_DFS_EVENT_EXTEARLY; 1064 if (is_dc) 1065 event->re_flags |= HAL_DFS_EVENT_ISDC; 1066 1067 return AH_TRUE; 1068} 1069 1070/* 1071 * Return whether fast-clock is currently enabled for this 1072 * channel. 1073 */ 1074HAL_BOOL 1075ar5416IsFastClockEnabled(struct ath_hal *ah) 1076{ 1077 struct ath_hal_private *ahp = AH_PRIVATE(ah); 1078 1079 return IS_5GHZ_FAST_CLOCK_EN(ah, ahp->ah_curchan); 1080} | |