ah.c revision 1.2.4.2 1 1.2.4.2 skrll /*
2 1.2.4.2 skrll * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3 1.2.4.2 skrll * Copyright (c) 2002-2008 Atheros Communications, Inc.
4 1.2.4.2 skrll *
5 1.2.4.2 skrll * Permission to use, copy, modify, and/or distribute this software for any
6 1.2.4.2 skrll * purpose with or without fee is hereby granted, provided that the above
7 1.2.4.2 skrll * copyright notice and this permission notice appear in all copies.
8 1.2.4.2 skrll *
9 1.2.4.2 skrll * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 1.2.4.2 skrll * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 1.2.4.2 skrll * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 1.2.4.2 skrll * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 1.2.4.2 skrll * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 1.2.4.2 skrll * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 1.2.4.2 skrll * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 1.2.4.2 skrll *
17 1.2.4.2 skrll * $Id: ah.c,v 1.2.4.2 2009/01/19 13:19:19 skrll Exp $
18 1.2.4.2 skrll */
19 1.2.4.2 skrll #include "opt_ah.h"
20 1.2.4.2 skrll
21 1.2.4.2 skrll #include "ah.h"
22 1.2.4.2 skrll #include "ah_internal.h"
23 1.2.4.2 skrll #include "ah_devid.h"
24 1.2.4.2 skrll
25 1.2.4.2 skrll /* linker set of registered chips */
26 1.2.4.2 skrll OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
27 1.2.4.2 skrll
28 1.2.4.2 skrll /*
29 1.2.4.2 skrll * Check the set of registered chips to see if any recognize
30 1.2.4.2 skrll * the device as one they can support.
31 1.2.4.2 skrll */
32 1.2.4.2 skrll const char*
33 1.2.4.2 skrll ath_hal_probe(uint16_t vendorid, uint16_t devid)
34 1.2.4.2 skrll {
35 1.2.4.2 skrll struct ath_hal_chip * const *pchip;
36 1.2.4.2 skrll
37 1.2.4.2 skrll OS_SET_FOREACH(pchip, ah_chips) {
38 1.2.4.2 skrll const char *name = (*pchip)->probe(vendorid, devid);
39 1.2.4.2 skrll if (name != AH_NULL)
40 1.2.4.2 skrll return name;
41 1.2.4.2 skrll }
42 1.2.4.2 skrll return AH_NULL;
43 1.2.4.2 skrll }
44 1.2.4.2 skrll
45 1.2.4.2 skrll /*
46 1.2.4.2 skrll * Attach detects device chip revisions, initializes the hwLayer
47 1.2.4.2 skrll * function list, reads EEPROM information,
48 1.2.4.2 skrll * selects reset vectors, and performs a short self test.
49 1.2.4.2 skrll * Any failures will return an error that should cause a hardware
50 1.2.4.2 skrll * disable.
51 1.2.4.2 skrll */
52 1.2.4.2 skrll struct ath_hal*
53 1.2.4.2 skrll ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
54 1.2.4.2 skrll HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *error)
55 1.2.4.2 skrll {
56 1.2.4.2 skrll struct ath_hal_chip * const *pchip;
57 1.2.4.2 skrll
58 1.2.4.2 skrll OS_SET_FOREACH(pchip, ah_chips) {
59 1.2.4.2 skrll struct ath_hal_chip *chip = *pchip;
60 1.2.4.2 skrll struct ath_hal *ah;
61 1.2.4.2 skrll
62 1.2.4.2 skrll /* XXX don't have vendorid, assume atheros one works */
63 1.2.4.2 skrll if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
64 1.2.4.2 skrll continue;
65 1.2.4.2 skrll ah = chip->attach(devid, sc, st, sh, error);
66 1.2.4.2 skrll if (ah != AH_NULL) {
67 1.2.4.2 skrll /* copy back private state to public area */
68 1.2.4.2 skrll ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
69 1.2.4.2 skrll ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
70 1.2.4.2 skrll ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
71 1.2.4.2 skrll ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
72 1.2.4.2 skrll ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
73 1.2.4.2 skrll ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
74 1.2.4.2 skrll ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
75 1.2.4.2 skrll return ah;
76 1.2.4.2 skrll }
77 1.2.4.2 skrll }
78 1.2.4.2 skrll return AH_NULL;
79 1.2.4.2 skrll }
80 1.2.4.2 skrll
81 1.2.4.2 skrll /* linker set of registered RF backends */
82 1.2.4.2 skrll OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
83 1.2.4.2 skrll
84 1.2.4.2 skrll /*
85 1.2.4.2 skrll * Check the set of registered RF backends to see if
86 1.2.4.2 skrll * any recognize the device as one they can support.
87 1.2.4.2 skrll */
88 1.2.4.2 skrll struct ath_hal_rf *
89 1.2.4.2 skrll ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
90 1.2.4.2 skrll {
91 1.2.4.2 skrll #ifdef AH_HAS_RF
92 1.2.4.2 skrll struct ath_hal_rf * const *prf;
93 1.2.4.2 skrll
94 1.2.4.2 skrll OS_SET_FOREACH(prf, ah_rfs) {
95 1.2.4.2 skrll struct ath_hal_rf *rf = *prf;
96 1.2.4.2 skrll if (rf->probe(ah))
97 1.2.4.2 skrll return rf;
98 1.2.4.2 skrll }
99 1.2.4.2 skrll *ecode = HAL_ENOTSUPP;
100 1.2.4.2 skrll #endif
101 1.2.4.2 skrll return AH_NULL;
102 1.2.4.2 skrll }
103 1.2.4.2 skrll
104 1.2.4.2 skrll /*
105 1.2.4.2 skrll * Poll the register looking for a specific value.
106 1.2.4.2 skrll */
107 1.2.4.2 skrll HAL_BOOL
108 1.2.4.2 skrll ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
109 1.2.4.2 skrll {
110 1.2.4.2 skrll #define AH_TIMEOUT 1000
111 1.2.4.2 skrll int i;
112 1.2.4.2 skrll
113 1.2.4.2 skrll for (i = 0; i < AH_TIMEOUT; i++) {
114 1.2.4.2 skrll if ((OS_REG_READ(ah, reg) & mask) == val)
115 1.2.4.2 skrll return AH_TRUE;
116 1.2.4.2 skrll OS_DELAY(10);
117 1.2.4.2 skrll }
118 1.2.4.2 skrll HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
119 1.2.4.2 skrll "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
120 1.2.4.2 skrll __func__, reg, OS_REG_READ(ah, reg), mask, val);
121 1.2.4.2 skrll return AH_FALSE;
122 1.2.4.2 skrll #undef AH_TIMEOUT
123 1.2.4.2 skrll }
124 1.2.4.2 skrll
125 1.2.4.2 skrll /*
126 1.2.4.2 skrll * Reverse the bits starting at the low bit for a value of
127 1.2.4.2 skrll * bit_count in size
128 1.2.4.2 skrll */
129 1.2.4.2 skrll uint32_t
130 1.2.4.2 skrll ath_hal_reverseBits(uint32_t val, uint32_t n)
131 1.2.4.2 skrll {
132 1.2.4.2 skrll uint32_t retval;
133 1.2.4.2 skrll int i;
134 1.2.4.2 skrll
135 1.2.4.2 skrll for (i = 0, retval = 0; i < n; i++) {
136 1.2.4.2 skrll retval = (retval << 1) | (val & 1);
137 1.2.4.2 skrll val >>= 1;
138 1.2.4.2 skrll }
139 1.2.4.2 skrll return retval;
140 1.2.4.2 skrll }
141 1.2.4.2 skrll
142 1.2.4.2 skrll /*
143 1.2.4.2 skrll * Compute the time to transmit a frame of length frameLen bytes
144 1.2.4.2 skrll * using the specified rate, phy, and short preamble setting.
145 1.2.4.2 skrll */
146 1.2.4.2 skrll uint16_t
147 1.2.4.2 skrll ath_hal_computetxtime(struct ath_hal *ah,
148 1.2.4.2 skrll const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
149 1.2.4.2 skrll HAL_BOOL shortPreamble)
150 1.2.4.2 skrll {
151 1.2.4.2 skrll uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
152 1.2.4.2 skrll uint32_t kbps;
153 1.2.4.2 skrll
154 1.2.4.2 skrll kbps = rates->info[rateix].rateKbps;
155 1.2.4.2 skrll /*
156 1.2.4.2 skrll * index can be invalid duting dynamic Turbo transitions.
157 1.2.4.2 skrll */
158 1.2.4.2 skrll if(kbps == 0) return 0;
159 1.2.4.2 skrll switch (rates->info[rateix].phy) {
160 1.2.4.2 skrll
161 1.2.4.2 skrll case IEEE80211_T_CCK:
162 1.2.4.2 skrll #define CCK_SIFS_TIME 10
163 1.2.4.2 skrll #define CCK_PREAMBLE_BITS 144
164 1.2.4.2 skrll #define CCK_PLCP_BITS 48
165 1.2.4.2 skrll phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
166 1.2.4.2 skrll if (shortPreamble && rates->info[rateix].shortPreamble)
167 1.2.4.2 skrll phyTime >>= 1;
168 1.2.4.2 skrll numBits = frameLen << 3;
169 1.2.4.2 skrll txTime = CCK_SIFS_TIME + phyTime
170 1.2.4.2 skrll + ((numBits * 1000)/kbps);
171 1.2.4.2 skrll break;
172 1.2.4.2 skrll #undef CCK_SIFS_TIME
173 1.2.4.2 skrll #undef CCK_PREAMBLE_BITS
174 1.2.4.2 skrll #undef CCK_PLCP_BITS
175 1.2.4.2 skrll
176 1.2.4.2 skrll case IEEE80211_T_OFDM:
177 1.2.4.2 skrll #define OFDM_SIFS_TIME 16
178 1.2.4.2 skrll #define OFDM_PREAMBLE_TIME 20
179 1.2.4.2 skrll #define OFDM_PLCP_BITS 22
180 1.2.4.2 skrll #define OFDM_SYMBOL_TIME 4
181 1.2.4.2 skrll
182 1.2.4.2 skrll #define OFDM_SIFS_TIME_HALF 32
183 1.2.4.2 skrll #define OFDM_PREAMBLE_TIME_HALF 40
184 1.2.4.2 skrll #define OFDM_PLCP_BITS_HALF 22
185 1.2.4.2 skrll #define OFDM_SYMBOL_TIME_HALF 8
186 1.2.4.2 skrll
187 1.2.4.2 skrll #define OFDM_SIFS_TIME_QUARTER 64
188 1.2.4.2 skrll #define OFDM_PREAMBLE_TIME_QUARTER 80
189 1.2.4.2 skrll #define OFDM_PLCP_BITS_QUARTER 22
190 1.2.4.2 skrll #define OFDM_SYMBOL_TIME_QUARTER 16
191 1.2.4.2 skrll
192 1.2.4.2 skrll if (AH_PRIVATE(ah)->ah_curchan &&
193 1.2.4.2 skrll IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) {
194 1.2.4.2 skrll bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
195 1.2.4.2 skrll HALASSERT(bitsPerSymbol != 0);
196 1.2.4.2 skrll
197 1.2.4.2 skrll numBits = OFDM_PLCP_BITS + (frameLen << 3);
198 1.2.4.2 skrll numSymbols = howmany(numBits, bitsPerSymbol);
199 1.2.4.2 skrll txTime = OFDM_SIFS_TIME_QUARTER
200 1.2.4.2 skrll + OFDM_PREAMBLE_TIME_QUARTER
201 1.2.4.2 skrll + (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
202 1.2.4.2 skrll } else if (AH_PRIVATE(ah)->ah_curchan &&
203 1.2.4.2 skrll IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) {
204 1.2.4.2 skrll bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
205 1.2.4.2 skrll HALASSERT(bitsPerSymbol != 0);
206 1.2.4.2 skrll
207 1.2.4.2 skrll numBits = OFDM_PLCP_BITS + (frameLen << 3);
208 1.2.4.2 skrll numSymbols = howmany(numBits, bitsPerSymbol);
209 1.2.4.2 skrll txTime = OFDM_SIFS_TIME_HALF +
210 1.2.4.2 skrll OFDM_PREAMBLE_TIME_HALF
211 1.2.4.2 skrll + (numSymbols * OFDM_SYMBOL_TIME_HALF);
212 1.2.4.2 skrll } else { /* full rate channel */
213 1.2.4.2 skrll bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
214 1.2.4.2 skrll HALASSERT(bitsPerSymbol != 0);
215 1.2.4.2 skrll
216 1.2.4.2 skrll numBits = OFDM_PLCP_BITS + (frameLen << 3);
217 1.2.4.2 skrll numSymbols = howmany(numBits, bitsPerSymbol);
218 1.2.4.2 skrll txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
219 1.2.4.2 skrll + (numSymbols * OFDM_SYMBOL_TIME);
220 1.2.4.2 skrll }
221 1.2.4.2 skrll break;
222 1.2.4.2 skrll
223 1.2.4.2 skrll #undef OFDM_SIFS_TIME
224 1.2.4.2 skrll #undef OFDM_PREAMBLE_TIME
225 1.2.4.2 skrll #undef OFDM_PLCP_BITS
226 1.2.4.2 skrll #undef OFDM_SYMBOL_TIME
227 1.2.4.2 skrll
228 1.2.4.2 skrll case IEEE80211_T_TURBO:
229 1.2.4.2 skrll #define TURBO_SIFS_TIME 8
230 1.2.4.2 skrll #define TURBO_PREAMBLE_TIME 14
231 1.2.4.2 skrll #define TURBO_PLCP_BITS 22
232 1.2.4.2 skrll #define TURBO_SYMBOL_TIME 4
233 1.2.4.2 skrll /* we still save OFDM rates in kbps - so double them */
234 1.2.4.2 skrll bitsPerSymbol = ((kbps << 1) * TURBO_SYMBOL_TIME) / 1000;
235 1.2.4.2 skrll HALASSERT(bitsPerSymbol != 0);
236 1.2.4.2 skrll
237 1.2.4.2 skrll numBits = TURBO_PLCP_BITS + (frameLen << 3);
238 1.2.4.2 skrll numSymbols = howmany(numBits, bitsPerSymbol);
239 1.2.4.2 skrll txTime = TURBO_SIFS_TIME + TURBO_PREAMBLE_TIME
240 1.2.4.2 skrll + (numSymbols * TURBO_SYMBOL_TIME);
241 1.2.4.2 skrll break;
242 1.2.4.2 skrll #undef TURBO_SIFS_TIME
243 1.2.4.2 skrll #undef TURBO_PREAMBLE_TIME
244 1.2.4.2 skrll #undef TURBO_PLCP_BITS
245 1.2.4.2 skrll #undef TURBO_SYMBOL_TIME
246 1.2.4.2 skrll
247 1.2.4.2 skrll default:
248 1.2.4.2 skrll HALDEBUG(ah, HAL_DEBUG_PHYIO,
249 1.2.4.2 skrll "%s: unknown phy %u (rate ix %u)\n",
250 1.2.4.2 skrll __func__, rates->info[rateix].phy, rateix);
251 1.2.4.2 skrll txTime = 0;
252 1.2.4.2 skrll break;
253 1.2.4.2 skrll }
254 1.2.4.2 skrll return txTime;
255 1.2.4.2 skrll }
256 1.2.4.2 skrll
257 1.2.4.2 skrll static __inline int
258 1.2.4.2 skrll mapgsm(u_int freq, u_int flags)
259 1.2.4.2 skrll {
260 1.2.4.2 skrll freq *= 10;
261 1.2.4.2 skrll if (flags & CHANNEL_QUARTER)
262 1.2.4.2 skrll freq += 5;
263 1.2.4.2 skrll else if (flags & CHANNEL_HALF)
264 1.2.4.2 skrll freq += 10;
265 1.2.4.2 skrll else
266 1.2.4.2 skrll freq += 20;
267 1.2.4.2 skrll return (freq - 24220) / 5;
268 1.2.4.2 skrll }
269 1.2.4.2 skrll
270 1.2.4.2 skrll static __inline int
271 1.2.4.2 skrll mappsb(u_int freq, u_int flags)
272 1.2.4.2 skrll {
273 1.2.4.2 skrll return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
274 1.2.4.2 skrll }
275 1.2.4.2 skrll
276 1.2.4.2 skrll /*
277 1.2.4.2 skrll * Convert GHz frequency to IEEE channel number.
278 1.2.4.2 skrll */
279 1.2.4.2 skrll int
280 1.2.4.2 skrll ath_hal_mhz2ieee(struct ath_hal *ah, u_int freq, u_int flags)
281 1.2.4.2 skrll {
282 1.2.4.2 skrll if (flags & CHANNEL_2GHZ) { /* 2GHz band */
283 1.2.4.2 skrll if (freq == 2484)
284 1.2.4.2 skrll return 14;
285 1.2.4.2 skrll if (freq < 2484) {
286 1.2.4.2 skrll if (ath_hal_isgsmsku(ah))
287 1.2.4.2 skrll return mapgsm(freq, flags);
288 1.2.4.2 skrll return ((int)freq - 2407) / 5;
289 1.2.4.2 skrll } else
290 1.2.4.2 skrll return 15 + ((freq - 2512) / 20);
291 1.2.4.2 skrll } else if (flags & CHANNEL_5GHZ) {/* 5Ghz band */
292 1.2.4.2 skrll if (ath_hal_ispublicsafetysku(ah) &&
293 1.2.4.2 skrll IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
294 1.2.4.2 skrll return mappsb(freq, flags);
295 1.2.4.2 skrll } else if ((flags & CHANNEL_A) && (freq <= 5000)) {
296 1.2.4.2 skrll return (freq - 4000) / 5;
297 1.2.4.2 skrll } else {
298 1.2.4.2 skrll return (freq - 5000) / 5;
299 1.2.4.2 skrll }
300 1.2.4.2 skrll } else { /* either, guess */
301 1.2.4.2 skrll if (freq == 2484)
302 1.2.4.2 skrll return 14;
303 1.2.4.2 skrll if (freq < 2484) {
304 1.2.4.2 skrll if (ath_hal_isgsmsku(ah))
305 1.2.4.2 skrll return mapgsm(freq, flags);
306 1.2.4.2 skrll return ((int)freq - 2407) / 5;
307 1.2.4.2 skrll }
308 1.2.4.2 skrll if (freq < 5000) {
309 1.2.4.2 skrll if (ath_hal_ispublicsafetysku(ah) &&
310 1.2.4.2 skrll IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
311 1.2.4.2 skrll return mappsb(freq, flags);
312 1.2.4.2 skrll } else if (freq > 4900) {
313 1.2.4.2 skrll return (freq - 4000) / 5;
314 1.2.4.2 skrll } else {
315 1.2.4.2 skrll return 15 + ((freq - 2512) / 20);
316 1.2.4.2 skrll }
317 1.2.4.2 skrll }
318 1.2.4.2 skrll return (freq - 5000) / 5;
319 1.2.4.2 skrll }
320 1.2.4.2 skrll }
321 1.2.4.2 skrll
322 1.2.4.2 skrll typedef enum {
323 1.2.4.2 skrll WIRELESS_MODE_11a = 0,
324 1.2.4.2 skrll WIRELESS_MODE_TURBO = 1,
325 1.2.4.2 skrll WIRELESS_MODE_11b = 2,
326 1.2.4.2 skrll WIRELESS_MODE_11g = 3,
327 1.2.4.2 skrll WIRELESS_MODE_108g = 4,
328 1.2.4.2 skrll
329 1.2.4.2 skrll WIRELESS_MODE_MAX
330 1.2.4.2 skrll } WIRELESS_MODE;
331 1.2.4.2 skrll
332 1.2.4.2 skrll static WIRELESS_MODE
333 1.2.4.2 skrll ath_hal_chan2wmode(struct ath_hal *ah, const HAL_CHANNEL *chan)
334 1.2.4.2 skrll {
335 1.2.4.2 skrll if (IS_CHAN_CCK(chan))
336 1.2.4.2 skrll return WIRELESS_MODE_11b;
337 1.2.4.2 skrll if (IS_CHAN_G(chan))
338 1.2.4.2 skrll return WIRELESS_MODE_11g;
339 1.2.4.2 skrll if (IS_CHAN_108G(chan))
340 1.2.4.2 skrll return WIRELESS_MODE_108g;
341 1.2.4.2 skrll if (IS_CHAN_TURBO(chan))
342 1.2.4.2 skrll return WIRELESS_MODE_TURBO;
343 1.2.4.2 skrll return WIRELESS_MODE_11a;
344 1.2.4.2 skrll }
345 1.2.4.2 skrll
346 1.2.4.2 skrll /*
347 1.2.4.2 skrll * Convert between microseconds and core system clocks.
348 1.2.4.2 skrll */
349 1.2.4.2 skrll /* 11a Turbo 11b 11g 108g */
350 1.2.4.2 skrll static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 };
351 1.2.4.2 skrll
352 1.2.4.2 skrll u_int
353 1.2.4.2 skrll ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
354 1.2.4.2 skrll {
355 1.2.4.2 skrll const HAL_CHANNEL *c = (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan;
356 1.2.4.2 skrll u_int clks;
357 1.2.4.2 skrll
358 1.2.4.2 skrll /* NB: ah_curchan may be null when called attach time */
359 1.2.4.2 skrll if (c != AH_NULL) {
360 1.2.4.2 skrll clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
361 1.2.4.2 skrll if (IS_CHAN_HT40(c))
362 1.2.4.2 skrll clks <<= 1;
363 1.2.4.2 skrll else if (IS_CHAN_HALF_RATE(c))
364 1.2.4.2 skrll clks >>= 1;
365 1.2.4.2 skrll else if (IS_CHAN_QUARTER_RATE(c))
366 1.2.4.2 skrll clks >>= 2;
367 1.2.4.2 skrll } else
368 1.2.4.2 skrll clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
369 1.2.4.2 skrll return clks;
370 1.2.4.2 skrll }
371 1.2.4.2 skrll
372 1.2.4.2 skrll u_int
373 1.2.4.2 skrll ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
374 1.2.4.2 skrll {
375 1.2.4.2 skrll const HAL_CHANNEL *c = (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan;
376 1.2.4.2 skrll u_int usec;
377 1.2.4.2 skrll
378 1.2.4.2 skrll /* NB: ah_curchan may be null when called attach time */
379 1.2.4.2 skrll if (c != AH_NULL) {
380 1.2.4.2 skrll usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
381 1.2.4.2 skrll if (IS_CHAN_HT40(c))
382 1.2.4.2 skrll usec >>= 1;
383 1.2.4.2 skrll else if (IS_CHAN_HALF_RATE(c))
384 1.2.4.2 skrll usec <<= 1;
385 1.2.4.2 skrll else if (IS_CHAN_QUARTER_RATE(c))
386 1.2.4.2 skrll usec <<= 2;
387 1.2.4.2 skrll } else
388 1.2.4.2 skrll usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
389 1.2.4.2 skrll return usec;
390 1.2.4.2 skrll }
391 1.2.4.2 skrll
392 1.2.4.2 skrll /*
393 1.2.4.2 skrll * Setup a h/w rate table's reverse lookup table and
394 1.2.4.2 skrll * fill in ack durations. This routine is called for
395 1.2.4.2 skrll * each rate table returned through the ah_getRateTable
396 1.2.4.2 skrll * method. The reverse lookup tables are assumed to be
397 1.2.4.2 skrll * initialized to zero (or at least the first entry).
398 1.2.4.2 skrll * We use this as a key that indicates whether or not
399 1.2.4.2 skrll * we've previously setup the reverse lookup table.
400 1.2.4.2 skrll *
401 1.2.4.2 skrll * XXX not reentrant, but shouldn't matter
402 1.2.4.2 skrll */
403 1.2.4.2 skrll void
404 1.2.4.2 skrll ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
405 1.2.4.2 skrll {
406 1.2.4.2 skrll #define N(a) (sizeof(a)/sizeof(a[0]))
407 1.2.4.2 skrll int i;
408 1.2.4.2 skrll
409 1.2.4.2 skrll if (rt->rateCodeToIndex[0] != 0) /* already setup */
410 1.2.4.2 skrll return;
411 1.2.4.2 skrll for (i = 0; i < N(rt->rateCodeToIndex); i++)
412 1.2.4.2 skrll rt->rateCodeToIndex[i] = (uint8_t) -1;
413 1.2.4.2 skrll for (i = 0; i < rt->rateCount; i++) {
414 1.2.4.2 skrll uint8_t code = rt->info[i].rateCode;
415 1.2.4.2 skrll uint8_t cix = rt->info[i].controlRate;
416 1.2.4.2 skrll
417 1.2.4.2 skrll HALASSERT(code < N(rt->rateCodeToIndex));
418 1.2.4.2 skrll rt->rateCodeToIndex[code] = i;
419 1.2.4.2 skrll HALASSERT((code | rt->info[i].shortPreamble) <
420 1.2.4.2 skrll N(rt->rateCodeToIndex));
421 1.2.4.2 skrll rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
422 1.2.4.2 skrll /*
423 1.2.4.2 skrll * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
424 1.2.4.2 skrll * depends on whether they are marked as basic rates;
425 1.2.4.2 skrll * the static tables are setup with an 11b-compatible
426 1.2.4.2 skrll * 2Mb/s rate which will work but is suboptimal
427 1.2.4.2 skrll */
428 1.2.4.2 skrll rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
429 1.2.4.2 skrll WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
430 1.2.4.2 skrll rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
431 1.2.4.2 skrll WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
432 1.2.4.2 skrll }
433 1.2.4.2 skrll #undef N
434 1.2.4.2 skrll }
435 1.2.4.2 skrll
436 1.2.4.2 skrll HAL_STATUS
437 1.2.4.2 skrll ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
438 1.2.4.2 skrll uint32_t capability, uint32_t *result)
439 1.2.4.2 skrll {
440 1.2.4.2 skrll const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
441 1.2.4.2 skrll
442 1.2.4.2 skrll switch (type) {
443 1.2.4.2 skrll case HAL_CAP_REG_DMN: /* regulatory domain */
444 1.2.4.2 skrll *result = AH_PRIVATE(ah)->ah_currentRD;
445 1.2.4.2 skrll return HAL_OK;
446 1.2.4.2 skrll case HAL_CAP_CIPHER: /* cipher handled in hardware */
447 1.2.4.2 skrll case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
448 1.2.4.2 skrll return HAL_ENOTSUPP;
449 1.2.4.2 skrll case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
450 1.2.4.2 skrll return HAL_ENOTSUPP;
451 1.2.4.2 skrll case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */
452 1.2.4.2 skrll return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
453 1.2.4.2 skrll case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */
454 1.2.4.2 skrll return HAL_ENOTSUPP;
455 1.2.4.2 skrll case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */
456 1.2.4.2 skrll return HAL_ENOTSUPP;
457 1.2.4.2 skrll case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */
458 1.2.4.2 skrll *result = pCap->halKeyCacheSize;
459 1.2.4.2 skrll return HAL_OK;
460 1.2.4.2 skrll case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */
461 1.2.4.2 skrll *result = pCap->halTotalQueues;
462 1.2.4.2 skrll return HAL_OK;
463 1.2.4.2 skrll case HAL_CAP_VEOL: /* hardware supports virtual EOL */
464 1.2.4.2 skrll return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
465 1.2.4.2 skrll case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */
466 1.2.4.2 skrll return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
467 1.2.4.2 skrll case HAL_CAP_COMPRESSION:
468 1.2.4.2 skrll return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
469 1.2.4.2 skrll case HAL_CAP_BURST:
470 1.2.4.2 skrll return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
471 1.2.4.2 skrll case HAL_CAP_FASTFRAME:
472 1.2.4.2 skrll return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
473 1.2.4.2 skrll case HAL_CAP_DIAG: /* hardware diagnostic support */
474 1.2.4.2 skrll *result = AH_PRIVATE(ah)->ah_diagreg;
475 1.2.4.2 skrll return HAL_OK;
476 1.2.4.2 skrll case HAL_CAP_TXPOW: /* global tx power limit */
477 1.2.4.2 skrll switch (capability) {
478 1.2.4.2 skrll case 0: /* facility is supported */
479 1.2.4.2 skrll return HAL_OK;
480 1.2.4.2 skrll case 1: /* current limit */
481 1.2.4.2 skrll *result = AH_PRIVATE(ah)->ah_powerLimit;
482 1.2.4.2 skrll return HAL_OK;
483 1.2.4.2 skrll case 2: /* current max tx power */
484 1.2.4.2 skrll *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
485 1.2.4.2 skrll return HAL_OK;
486 1.2.4.2 skrll case 3: /* scale factor */
487 1.2.4.2 skrll *result = AH_PRIVATE(ah)->ah_tpScale;
488 1.2.4.2 skrll return HAL_OK;
489 1.2.4.2 skrll }
490 1.2.4.2 skrll return HAL_ENOTSUPP;
491 1.2.4.2 skrll case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */
492 1.2.4.2 skrll return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
493 1.2.4.2 skrll case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
494 1.2.4.2 skrll return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
495 1.2.4.2 skrll case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
496 1.2.4.2 skrll return HAL_ENOTSUPP;
497 1.2.4.2 skrll case HAL_CAP_RFSILENT: /* rfsilent support */
498 1.2.4.2 skrll switch (capability) {
499 1.2.4.2 skrll case 0: /* facility is supported */
500 1.2.4.2 skrll return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
501 1.2.4.2 skrll case 1: /* current setting */
502 1.2.4.2 skrll return AH_PRIVATE(ah)->ah_rfkillEnabled ?
503 1.2.4.2 skrll HAL_OK : HAL_ENOTSUPP;
504 1.2.4.2 skrll case 2: /* rfsilent config */
505 1.2.4.2 skrll *result = AH_PRIVATE(ah)->ah_rfsilent;
506 1.2.4.2 skrll return HAL_OK;
507 1.2.4.2 skrll }
508 1.2.4.2 skrll return HAL_ENOTSUPP;
509 1.2.4.2 skrll case HAL_CAP_11D:
510 1.2.4.2 skrll #ifdef AH_SUPPORT_11D
511 1.2.4.2 skrll return HAL_OK;
512 1.2.4.2 skrll #else
513 1.2.4.2 skrll return HAL_ENOTSUPP;
514 1.2.4.2 skrll #endif
515 1.2.4.2 skrll case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
516 1.2.4.2 skrll return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
517 1.2.4.2 skrll case HAL_CAP_HT:
518 1.2.4.2 skrll return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
519 1.2.4.2 skrll case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */
520 1.2.4.2 skrll *result = pCap->halTxChainMask;
521 1.2.4.2 skrll return HAL_OK;
522 1.2.4.2 skrll case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */
523 1.2.4.2 skrll *result = pCap->halRxChainMask;
524 1.2.4.2 skrll return HAL_OK;
525 1.2.4.2 skrll case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */
526 1.2.4.2 skrll *result = pCap->halTstampPrecision;
527 1.2.4.2 skrll return HAL_OK;
528 1.2.4.2 skrll default:
529 1.2.4.2 skrll return HAL_EINVAL;
530 1.2.4.2 skrll }
531 1.2.4.2 skrll }
532 1.2.4.2 skrll
533 1.2.4.2 skrll HAL_BOOL
534 1.2.4.2 skrll ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
535 1.2.4.2 skrll uint32_t capability, uint32_t setting, HAL_STATUS *status)
536 1.2.4.2 skrll {
537 1.2.4.2 skrll
538 1.2.4.2 skrll switch (type) {
539 1.2.4.2 skrll case HAL_CAP_TXPOW:
540 1.2.4.2 skrll switch (capability) {
541 1.2.4.2 skrll case 3:
542 1.2.4.2 skrll if (setting <= HAL_TP_SCALE_MIN) {
543 1.2.4.2 skrll AH_PRIVATE(ah)->ah_tpScale = setting;
544 1.2.4.2 skrll return AH_TRUE;
545 1.2.4.2 skrll }
546 1.2.4.2 skrll break;
547 1.2.4.2 skrll }
548 1.2.4.2 skrll break;
549 1.2.4.2 skrll case HAL_CAP_RFSILENT: /* rfsilent support */
550 1.2.4.2 skrll /*
551 1.2.4.2 skrll * NB: allow even if halRfSilentSupport is false
552 1.2.4.2 skrll * in case the EEPROM is misprogrammed.
553 1.2.4.2 skrll */
554 1.2.4.2 skrll switch (capability) {
555 1.2.4.2 skrll case 1: /* current setting */
556 1.2.4.2 skrll AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
557 1.2.4.2 skrll return AH_TRUE;
558 1.2.4.2 skrll case 2: /* rfsilent config */
559 1.2.4.2 skrll /* XXX better done per-chip for validation? */
560 1.2.4.2 skrll AH_PRIVATE(ah)->ah_rfsilent = setting;
561 1.2.4.2 skrll return AH_TRUE;
562 1.2.4.2 skrll }
563 1.2.4.2 skrll break;
564 1.2.4.2 skrll case HAL_CAP_REG_DMN: /* regulatory domain */
565 1.2.4.2 skrll AH_PRIVATE(ah)->ah_currentRD = setting;
566 1.2.4.2 skrll return AH_TRUE;
567 1.2.4.2 skrll case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
568 1.2.4.2 skrll AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
569 1.2.4.2 skrll return AH_TRUE;
570 1.2.4.2 skrll default:
571 1.2.4.2 skrll break;
572 1.2.4.2 skrll }
573 1.2.4.2 skrll if (status)
574 1.2.4.2 skrll *status = HAL_EINVAL;
575 1.2.4.2 skrll return AH_FALSE;
576 1.2.4.2 skrll }
577 1.2.4.2 skrll
578 1.2.4.2 skrll /*
579 1.2.4.2 skrll * Common support for getDiagState method.
580 1.2.4.2 skrll */
581 1.2.4.2 skrll
582 1.2.4.2 skrll static u_int
583 1.2.4.2 skrll ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
584 1.2.4.2 skrll void *dstbuf, int space)
585 1.2.4.2 skrll {
586 1.2.4.2 skrll uint32_t *dp = dstbuf;
587 1.2.4.2 skrll int i;
588 1.2.4.2 skrll
589 1.2.4.2 skrll for (i = 0; space >= 2*sizeof(uint32_t); i++) {
590 1.2.4.2 skrll u_int r = regs[i].start;
591 1.2.4.2 skrll u_int e = regs[i].end;
592 1.2.4.2 skrll *dp++ = (r<<16) | e;
593 1.2.4.2 skrll space -= sizeof(uint32_t);
594 1.2.4.2 skrll do {
595 1.2.4.2 skrll *dp++ = OS_REG_READ(ah, r);
596 1.2.4.2 skrll r += sizeof(uint32_t);
597 1.2.4.2 skrll space -= sizeof(uint32_t);
598 1.2.4.2 skrll } while (r <= e && space >= sizeof(uint32_t));
599 1.2.4.2 skrll }
600 1.2.4.2 skrll return (char *) dp - (char *) dstbuf;
601 1.2.4.2 skrll }
602 1.2.4.2 skrll
603 1.2.4.2 skrll HAL_BOOL
604 1.2.4.2 skrll ath_hal_getdiagstate(struct ath_hal *ah, int request,
605 1.2.4.2 skrll const void *args, uint32_t argsize,
606 1.2.4.2 skrll void **result, uint32_t *resultsize)
607 1.2.4.2 skrll {
608 1.2.4.2 skrll switch (request) {
609 1.2.4.2 skrll case HAL_DIAG_REVS:
610 1.2.4.2 skrll *result = &AH_PRIVATE(ah)->ah_devid;
611 1.2.4.2 skrll *resultsize = sizeof(HAL_REVS);
612 1.2.4.2 skrll return AH_TRUE;
613 1.2.4.2 skrll case HAL_DIAG_REGS:
614 1.2.4.2 skrll *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
615 1.2.4.2 skrll return AH_TRUE;
616 1.2.4.2 skrll case HAL_DIAG_FATALERR:
617 1.2.4.2 skrll *result = &AH_PRIVATE(ah)->ah_fatalState[0];
618 1.2.4.2 skrll *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
619 1.2.4.2 skrll return AH_TRUE;
620 1.2.4.2 skrll case HAL_DIAG_EEREAD:
621 1.2.4.2 skrll if (argsize != sizeof(uint16_t))
622 1.2.4.2 skrll return AH_FALSE;
623 1.2.4.2 skrll if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
624 1.2.4.2 skrll return AH_FALSE;
625 1.2.4.2 skrll *resultsize = sizeof(uint16_t);
626 1.2.4.2 skrll return AH_TRUE;
627 1.2.4.2 skrll #ifdef AH_PRIVATE_DIAG
628 1.2.4.2 skrll case HAL_DIAG_SETKEY: {
629 1.2.4.2 skrll const HAL_DIAG_KEYVAL *dk;
630 1.2.4.2 skrll
631 1.2.4.2 skrll if (argsize != sizeof(HAL_DIAG_KEYVAL))
632 1.2.4.2 skrll return AH_FALSE;
633 1.2.4.2 skrll dk = (const HAL_DIAG_KEYVAL *)args;
634 1.2.4.2 skrll return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
635 1.2.4.2 skrll &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
636 1.2.4.2 skrll }
637 1.2.4.2 skrll case HAL_DIAG_RESETKEY:
638 1.2.4.2 skrll if (argsize != sizeof(uint16_t))
639 1.2.4.2 skrll return AH_FALSE;
640 1.2.4.2 skrll return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
641 1.2.4.2 skrll #ifdef AH_SUPPORT_WRITE_EEPROM
642 1.2.4.2 skrll case HAL_DIAG_EEWRITE: {
643 1.2.4.2 skrll const HAL_DIAG_EEVAL *ee;
644 1.2.4.2 skrll if (argsize != sizeof(HAL_DIAG_EEVAL))
645 1.2.4.2 skrll return AH_FALSE;
646 1.2.4.2 skrll ee = (const HAL_DIAG_EEVAL *)args;
647 1.2.4.2 skrll return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
648 1.2.4.2 skrll }
649 1.2.4.2 skrll #endif /* AH_SUPPORT_WRITE_EEPROM */
650 1.2.4.2 skrll #endif /* AH_PRIVATE_DIAG */
651 1.2.4.2 skrll case HAL_DIAG_11NCOMPAT:
652 1.2.4.2 skrll if (argsize == 0) {
653 1.2.4.2 skrll *resultsize = sizeof(uint32_t);
654 1.2.4.2 skrll *((uint32_t *)(*result)) =
655 1.2.4.2 skrll AH_PRIVATE(ah)->ah_11nCompat;
656 1.2.4.2 skrll } else if (argsize == sizeof(uint32_t)) {
657 1.2.4.2 skrll AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
658 1.2.4.2 skrll } else
659 1.2.4.2 skrll return AH_FALSE;
660 1.2.4.2 skrll return AH_TRUE;
661 1.2.4.2 skrll }
662 1.2.4.2 skrll return AH_FALSE;
663 1.2.4.2 skrll }
664 1.2.4.2 skrll
665 1.2.4.2 skrll /*
666 1.2.4.2 skrll * Set the properties of the tx queue with the parameters
667 1.2.4.2 skrll * from qInfo.
668 1.2.4.2 skrll */
669 1.2.4.2 skrll HAL_BOOL
670 1.2.4.2 skrll ath_hal_setTxQProps(struct ath_hal *ah,
671 1.2.4.2 skrll HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
672 1.2.4.2 skrll {
673 1.2.4.2 skrll uint32_t cw;
674 1.2.4.2 skrll
675 1.2.4.2 skrll if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
676 1.2.4.2 skrll HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
677 1.2.4.2 skrll "%s: inactive queue\n", __func__);
678 1.2.4.2 skrll return AH_FALSE;
679 1.2.4.2 skrll }
680 1.2.4.2 skrll /* XXX validate parameters */
681 1.2.4.2 skrll qi->tqi_ver = qInfo->tqi_ver;
682 1.2.4.2 skrll qi->tqi_subtype = qInfo->tqi_subtype;
683 1.2.4.2 skrll qi->tqi_qflags = qInfo->tqi_qflags;
684 1.2.4.2 skrll qi->tqi_priority = qInfo->tqi_priority;
685 1.2.4.2 skrll if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
686 1.2.4.2 skrll qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
687 1.2.4.2 skrll else
688 1.2.4.2 skrll qi->tqi_aifs = INIT_AIFS;
689 1.2.4.2 skrll if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
690 1.2.4.2 skrll cw = AH_MIN(qInfo->tqi_cwmin, 1024);
691 1.2.4.2 skrll /* make sure that the CWmin is of the form (2^n - 1) */
692 1.2.4.2 skrll qi->tqi_cwmin = 1;
693 1.2.4.2 skrll while (qi->tqi_cwmin < cw)
694 1.2.4.2 skrll qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
695 1.2.4.2 skrll } else
696 1.2.4.2 skrll qi->tqi_cwmin = qInfo->tqi_cwmin;
697 1.2.4.2 skrll if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
698 1.2.4.2 skrll cw = AH_MIN(qInfo->tqi_cwmax, 1024);
699 1.2.4.2 skrll /* make sure that the CWmax is of the form (2^n - 1) */
700 1.2.4.2 skrll qi->tqi_cwmax = 1;
701 1.2.4.2 skrll while (qi->tqi_cwmax < cw)
702 1.2.4.2 skrll qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
703 1.2.4.2 skrll } else
704 1.2.4.2 skrll qi->tqi_cwmax = INIT_CWMAX;
705 1.2.4.2 skrll /* Set retry limit values */
706 1.2.4.2 skrll if (qInfo->tqi_shretry != 0)
707 1.2.4.2 skrll qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
708 1.2.4.2 skrll else
709 1.2.4.2 skrll qi->tqi_shretry = INIT_SH_RETRY;
710 1.2.4.2 skrll if (qInfo->tqi_lgretry != 0)
711 1.2.4.2 skrll qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
712 1.2.4.2 skrll else
713 1.2.4.2 skrll qi->tqi_lgretry = INIT_LG_RETRY;
714 1.2.4.2 skrll qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
715 1.2.4.2 skrll qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
716 1.2.4.2 skrll qi->tqi_burstTime = qInfo->tqi_burstTime;
717 1.2.4.2 skrll qi->tqi_readyTime = qInfo->tqi_readyTime;
718 1.2.4.2 skrll
719 1.2.4.2 skrll switch (qInfo->tqi_subtype) {
720 1.2.4.2 skrll case HAL_WME_UPSD:
721 1.2.4.2 skrll if (qi->tqi_type == HAL_TX_QUEUE_DATA)
722 1.2.4.2 skrll qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
723 1.2.4.2 skrll break;
724 1.2.4.2 skrll default:
725 1.2.4.2 skrll break; /* NB: silence compiler */
726 1.2.4.2 skrll }
727 1.2.4.2 skrll return AH_TRUE;
728 1.2.4.2 skrll }
729 1.2.4.2 skrll
730 1.2.4.2 skrll HAL_BOOL
731 1.2.4.2 skrll ath_hal_getTxQProps(struct ath_hal *ah,
732 1.2.4.2 skrll HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
733 1.2.4.2 skrll {
734 1.2.4.2 skrll if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
735 1.2.4.2 skrll HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
736 1.2.4.2 skrll "%s: inactive queue\n", __func__);
737 1.2.4.2 skrll return AH_FALSE;
738 1.2.4.2 skrll }
739 1.2.4.2 skrll
740 1.2.4.2 skrll qInfo->tqi_qflags = qi->tqi_qflags;
741 1.2.4.2 skrll qInfo->tqi_ver = qi->tqi_ver;
742 1.2.4.2 skrll qInfo->tqi_subtype = qi->tqi_subtype;
743 1.2.4.2 skrll qInfo->tqi_qflags = qi->tqi_qflags;
744 1.2.4.2 skrll qInfo->tqi_priority = qi->tqi_priority;
745 1.2.4.2 skrll qInfo->tqi_aifs = qi->tqi_aifs;
746 1.2.4.2 skrll qInfo->tqi_cwmin = qi->tqi_cwmin;
747 1.2.4.2 skrll qInfo->tqi_cwmax = qi->tqi_cwmax;
748 1.2.4.2 skrll qInfo->tqi_shretry = qi->tqi_shretry;
749 1.2.4.2 skrll qInfo->tqi_lgretry = qi->tqi_lgretry;
750 1.2.4.2 skrll qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
751 1.2.4.2 skrll qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
752 1.2.4.2 skrll qInfo->tqi_burstTime = qi->tqi_burstTime;
753 1.2.4.2 skrll qInfo->tqi_readyTime = qi->tqi_readyTime;
754 1.2.4.2 skrll return AH_TRUE;
755 1.2.4.2 skrll }
756 1.2.4.2 skrll
757 1.2.4.2 skrll /* 11a Turbo 11b 11g 108g */
758 1.2.4.2 skrll static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 };
759 1.2.4.2 skrll
760 1.2.4.2 skrll /*
761 1.2.4.2 skrll * Read the current channel noise floor and return.
762 1.2.4.2 skrll * If nf cal hasn't finished, channel noise floor should be 0
763 1.2.4.2 skrll * and we return a nominal value based on band and frequency.
764 1.2.4.2 skrll *
765 1.2.4.2 skrll * NB: This is a private routine used by per-chip code to
766 1.2.4.2 skrll * implement the ah_getChanNoise method.
767 1.2.4.2 skrll */
768 1.2.4.2 skrll int16_t
769 1.2.4.2 skrll ath_hal_getChanNoise(struct ath_hal *ah, HAL_CHANNEL *chan)
770 1.2.4.2 skrll {
771 1.2.4.2 skrll HAL_CHANNEL_INTERNAL *ichan;
772 1.2.4.2 skrll
773 1.2.4.2 skrll ichan = ath_hal_checkchannel(ah, chan);
774 1.2.4.2 skrll if (ichan == AH_NULL) {
775 1.2.4.2 skrll HALDEBUG(ah, HAL_DEBUG_NFCAL,
776 1.2.4.2 skrll "%s: invalid channel %u/0x%x; no mapping\n",
777 1.2.4.2 skrll __func__, chan->channel, chan->channelFlags);
778 1.2.4.2 skrll return 0;
779 1.2.4.2 skrll }
780 1.2.4.2 skrll if (ichan->rawNoiseFloor == 0) {
781 1.2.4.2 skrll WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
782 1.2.4.2 skrll
783 1.2.4.2 skrll HALASSERT(mode < WIRELESS_MODE_MAX);
784 1.2.4.2 skrll return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
785 1.2.4.2 skrll } else
786 1.2.4.2 skrll return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
787 1.2.4.2 skrll }
788 1.2.4.2 skrll
789 1.2.4.2 skrll /*
790 1.2.4.2 skrll * Process all valid raw noise floors into the dBm noise floor values.
791 1.2.4.2 skrll * Though our device has no reference for a dBm noise floor, we perform
792 1.2.4.2 skrll * a relative minimization of NF's based on the lowest NF found across a
793 1.2.4.2 skrll * channel scan.
794 1.2.4.2 skrll */
795 1.2.4.2 skrll void
796 1.2.4.2 skrll ath_hal_process_noisefloor(struct ath_hal *ah)
797 1.2.4.2 skrll {
798 1.2.4.2 skrll HAL_CHANNEL_INTERNAL *c;
799 1.2.4.2 skrll int16_t correct2, correct5;
800 1.2.4.2 skrll int16_t lowest2, lowest5;
801 1.2.4.2 skrll int i;
802 1.2.4.2 skrll
803 1.2.4.2 skrll /*
804 1.2.4.2 skrll * Find the lowest 2GHz and 5GHz noise floor values after adjusting
805 1.2.4.2 skrll * for statistically recorded NF/channel deviation.
806 1.2.4.2 skrll */
807 1.2.4.2 skrll correct2 = lowest2 = 0;
808 1.2.4.2 skrll correct5 = lowest5 = 0;
809 1.2.4.2 skrll for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
810 1.2.4.2 skrll WIRELESS_MODE mode;
811 1.2.4.2 skrll int16_t nf;
812 1.2.4.2 skrll
813 1.2.4.2 skrll c = &AH_PRIVATE(ah)->ah_channels[i];
814 1.2.4.2 skrll if (c->rawNoiseFloor >= 0)
815 1.2.4.2 skrll continue;
816 1.2.4.2 skrll mode = ath_hal_chan2wmode(ah, (HAL_CHANNEL *) c);
817 1.2.4.2 skrll HALASSERT(mode < WIRELESS_MODE_MAX);
818 1.2.4.2 skrll nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
819 1.2.4.2 skrll ath_hal_getNfAdjust(ah, c);
820 1.2.4.2 skrll if (IS_CHAN_5GHZ(c)) {
821 1.2.4.2 skrll if (nf < lowest5) {
822 1.2.4.2 skrll lowest5 = nf;
823 1.2.4.2 skrll correct5 = NOISE_FLOOR[mode] -
824 1.2.4.2 skrll (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
825 1.2.4.2 skrll }
826 1.2.4.2 skrll } else {
827 1.2.4.2 skrll if (nf < lowest2) {
828 1.2.4.2 skrll lowest2 = nf;
829 1.2.4.2 skrll correct2 = NOISE_FLOOR[mode] -
830 1.2.4.2 skrll (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
831 1.2.4.2 skrll }
832 1.2.4.2 skrll }
833 1.2.4.2 skrll }
834 1.2.4.2 skrll
835 1.2.4.2 skrll /* Correct the channels to reach the expected NF value */
836 1.2.4.2 skrll for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
837 1.2.4.2 skrll c = &AH_PRIVATE(ah)->ah_channels[i];
838 1.2.4.2 skrll if (c->rawNoiseFloor >= 0)
839 1.2.4.2 skrll continue;
840 1.2.4.2 skrll /* Apply correction factor */
841 1.2.4.2 skrll c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
842 1.2.4.2 skrll (IS_CHAN_5GHZ(c) ? correct5 : correct2);
843 1.2.4.2 skrll HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u/0x%x raw nf %d adjust %d\n",
844 1.2.4.2 skrll c->channel, c->channelFlags, c->rawNoiseFloor,
845 1.2.4.2 skrll c->noiseFloorAdjust);
846 1.2.4.2 skrll }
847 1.2.4.2 skrll }
848 1.2.4.2 skrll
849 1.2.4.2 skrll /*
850 1.2.4.2 skrll * INI support routines.
851 1.2.4.2 skrll */
852 1.2.4.2 skrll
853 1.2.4.2 skrll int
854 1.2.4.2 skrll ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
855 1.2.4.2 skrll int col, int regWr)
856 1.2.4.2 skrll {
857 1.2.4.2 skrll int r;
858 1.2.4.2 skrll
859 1.2.4.2 skrll for (r = 0; r < ia->rows; r++) {
860 1.2.4.2 skrll OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
861 1.2.4.2 skrll HAL_INI_VAL(ia, r, col));
862 1.2.4.2 skrll DMA_YIELD(regWr);
863 1.2.4.2 skrll }
864 1.2.4.2 skrll return regWr;
865 1.2.4.2 skrll }
866 1.2.4.2 skrll
867 1.2.4.2 skrll void
868 1.2.4.2 skrll ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
869 1.2.4.2 skrll {
870 1.2.4.2 skrll int r;
871 1.2.4.2 skrll
872 1.2.4.2 skrll for (r = 0; r < ia->rows; r++)
873 1.2.4.2 skrll data[r] = HAL_INI_VAL(ia, r, col);
874 1.2.4.2 skrll }
875 1.2.4.2 skrll
876 1.2.4.2 skrll int
877 1.2.4.2 skrll ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
878 1.2.4.2 skrll const uint32_t data[], int regWr)
879 1.2.4.2 skrll {
880 1.2.4.2 skrll int r;
881 1.2.4.2 skrll
882 1.2.4.2 skrll for (r = 0; r < ia->rows; r++) {
883 1.2.4.2 skrll OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
884 1.2.4.2 skrll DMA_YIELD(regWr);
885 1.2.4.2 skrll }
886 1.2.4.2 skrll return regWr;
887 1.2.4.2 skrll }
888