Annotation of sys/dev/ic/ar5xxx.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ar5xxx.c,v 1.42 2007/06/26 10:53:01 tom Exp $ */
2:
3: /*
4: * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: /*
20: * HAL interface for Atheros Wireless LAN devices.
21: * (Please have a look at ar5xxx.h for further information)
22: */
23:
24: #include <dev/pci/pcidevs.h>
25: #include <dev/ic/ar5xxx.h>
26:
27: extern ar5k_attach_t ar5k_ar5210_attach;
28: extern ar5k_attach_t ar5k_ar5211_attach;
29: extern ar5k_attach_t ar5k_ar5212_attach;
30:
31: static const struct {
32: u_int16_t vendor;
33: u_int16_t device;
34: ar5k_attach_t (*attach);
35: } ar5k_known_products[] = {
36: /*
37: * From pcidevs_data.h
38: */
39: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210,
40: ar5k_ar5210_attach },
41: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210_AP,
42: ar5k_ar5210_attach },
43: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210_DEFAULT,
44: ar5k_ar5210_attach },
45: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211,
46: ar5k_ar5211_attach },
47: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211_DEFAULT,
48: ar5k_ar5211_attach },
49: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5311,
50: ar5k_ar5211_attach },
51: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211_FPGA11B,
52: ar5k_ar5211_attach },
53: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211_LEGACY,
54: ar5k_ar5211_attach },
55: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212,
56: ar5k_ar5212_attach },
57: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_DEFAULT,
58: ar5k_ar5212_attach },
59: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_FPGA,
60: ar5k_ar5212_attach },
61: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_IBM,
62: ar5k_ar5212_attach },
63: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR2413,
64: ar5k_ar5212_attach },
65: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5413,
66: ar5k_ar5212_attach },
67: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5424,
68: ar5k_ar5212_attach },
69: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CRDAG675,
70: ar5k_ar5212_attach },
71: { PCI_VENDOR_3COM2, PCI_PRODUCT_3COM2_3CRPAG175,
72: ar5k_ar5212_attach }
73: };
74:
75: static const HAL_RATE_TABLE ar5k_rt_11a = AR5K_RATES_11A;
76: static const HAL_RATE_TABLE ar5k_rt_11b = AR5K_RATES_11B;
77: static const HAL_RATE_TABLE ar5k_rt_11g = AR5K_RATES_11G;
78: static const HAL_RATE_TABLE ar5k_rt_turbo = AR5K_RATES_TURBO;
79: static const HAL_RATE_TABLE ar5k_rt_xr = AR5K_RATES_XR;
80:
81: int ar5k_eeprom_read_ants(struct ath_hal *, u_int32_t *, u_int);
82: int ar5k_eeprom_read_modes(struct ath_hal *, u_int32_t *, u_int);
83: u_int16_t ar5k_eeprom_bin2freq(struct ath_hal *, u_int16_t, u_int);
84:
85: HAL_BOOL ar5k_ar5110_channel(struct ath_hal *, HAL_CHANNEL *);
86: u_int32_t ar5k_ar5110_chan2athchan(HAL_CHANNEL *);
87: HAL_BOOL ar5k_ar5111_channel(struct ath_hal *, HAL_CHANNEL *);
88: HAL_BOOL ar5k_ar5111_chan2athchan(u_int, struct ar5k_athchan_2ghz *);
89: HAL_BOOL ar5k_ar5112_channel(struct ath_hal *, HAL_CHANNEL *);
90: HAL_BOOL ar5k_check_channel(struct ath_hal *, u_int16_t, u_int flags);
91:
92: HAL_BOOL ar5k_ar5111_rfregs(struct ath_hal *, HAL_CHANNEL *, u_int);
93: HAL_BOOL ar5k_ar5112_rfregs(struct ath_hal *, HAL_CHANNEL *, u_int);
94: u_int ar5k_rfregs_op(u_int32_t *, u_int32_t, u_int32_t, u_int32_t,
95: u_int32_t, u_int32_t, HAL_BOOL);
96:
97: /*
98: * Supported channels
99: */
100: static const struct
101: ieee80211_regchannel ar5k_5ghz_channels[] = IEEE80211_CHANNELS_5GHZ;
102: static const struct
103: ieee80211_regchannel ar5k_2ghz_channels[] = IEEE80211_CHANNELS_2GHZ;
104:
105: /*
106: * Initial gain optimization values
107: */
108: static const struct ar5k_gain_opt ar5111_gain_opt = AR5K_AR5111_GAIN_OPT;
109: static const struct ar5k_gain_opt ar5112_gain_opt = AR5K_AR5112_GAIN_OPT;
110:
111: /*
112: * Initial register for the radio chipsets
113: */
114: static const struct ar5k_ini_rf ar5111_rf[] = AR5K_AR5111_INI_RF;
115: static const struct ar5k_ini_rf ar5112_rf[] = AR5K_AR5112_INI_RF;
116: static const struct ar5k_ini_rf ar5112a_rf[] = AR5K_AR5112A_INI_RF;
117: static const struct ar5k_ini_rfgain ar5k_rfg[] = AR5K_INI_RFGAIN;
118:
119: /*
120: * Enable to overwrite the country code (use "00" for debug)
121: */
122: #if 0
123: #define COUNTRYCODE "00"
124: #endif
125:
126: /*
127: * Perform a lookup if the device is supported by the HAL
128: */
129: const char *
130: ath_hal_probe(u_int16_t vendor, u_int16_t device)
131: {
132: int i;
133:
134: /*
135: * Perform a linear search on the table of supported devices
136: */
137: for (i = 0; i < AR5K_ELEMENTS(ar5k_known_products); i++) {
138: if (vendor == ar5k_known_products[i].vendor &&
139: device == ar5k_known_products[i].device)
140: return ("");
141: }
142:
143: return (NULL);
144: }
145:
146: /*
147: * Fills in the HAL structure and initialises the device
148: */
149: struct ath_hal *
150: ath_hal_attach(u_int16_t device, void *arg, bus_space_tag_t st,
151: bus_space_handle_t sh, u_int is_64bit, int *status)
152: {
153: struct ath_softc *sc = (struct ath_softc *)arg;
154: struct ath_hal *hal = NULL;
155: ar5k_attach_t *attach = NULL;
156: u_int8_t mac[IEEE80211_ADDR_LEN];
157: int i;
158:
159: *status = EINVAL;
160:
161: /*
162: * Call the chipset-dependent attach routine by device id
163: */
164: for (i = 0; i < AR5K_ELEMENTS(ar5k_known_products); i++) {
165: if (device == ar5k_known_products[i].device &&
166: ar5k_known_products[i].attach != NULL)
167: attach = ar5k_known_products[i].attach;
168: }
169:
170: if (attach == NULL) {
171: *status = ENXIO;
172: AR5K_PRINTF("device not supported: 0x%04x\n", device);
173: return (NULL);
174: }
175:
176: if ((hal = malloc(sizeof(struct ath_hal),
177: M_DEVBUF, M_NOWAIT)) == NULL) {
178: *status = ENOMEM;
179: AR5K_PRINT("out of memory\n");
180: return (NULL);
181: }
182:
183: bzero(hal, sizeof(struct ath_hal));
184:
185: hal->ah_sc = sc;
186: hal->ah_st = st;
187: hal->ah_sh = sh;
188: hal->ah_device = device;
189: hal->ah_sub_vendor = 0; /* XXX unknown?! */
190:
191: /*
192: * HAL information
193: */
194: hal->ah_abi = HAL_ABI_VERSION;
195: hal->ah_op_mode = HAL_M_STA;
196: hal->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
197: hal->ah_turbo = AH_FALSE;
198: hal->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
199: hal->ah_imr = 0;
200: hal->ah_atim_window = 0;
201: hal->ah_aifs = AR5K_TUNE_AIFS;
202: hal->ah_cw_min = AR5K_TUNE_CWMIN;
203: hal->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
204: hal->ah_software_retry = AH_FALSE;
205: hal->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY;
206:
207: switch (device) {
208: case PCI_PRODUCT_ATHEROS_AR2413:
209: case PCI_PRODUCT_ATHEROS_AR5413:
210: case PCI_PRODUCT_ATHEROS_AR5424:
211: /*
212: * Known single chip solutions
213: */
214: hal->ah_single_chip = AH_TRUE;
215: break;
216: case PCI_PRODUCT_ATHEROS_AR5212_IBM:
217: /*
218: * IBM ThinkPads use the same device ID for different
219: * chipset versions. Ugh.
220: */
221: if (is_64bit) {
222: /*
223: * PCI Express "Mini Card" interface based on the
224: * AR5424 chipset
225: */
226: hal->ah_single_chip = AH_TRUE;
227: } else {
228: /* Classic Mini PCI interface based on AR5212 */
229: hal->ah_single_chip = AH_FALSE;
230: }
231: break;
232: default:
233: /*
234: * Multi chip solutions
235: */
236: hal->ah_single_chip = AH_FALSE;
237: break;
238: }
239:
240: if ((attach)(device, hal, st, sh, status) == NULL)
241: goto failed;
242:
243: #ifdef AR5K_DEBUG
244: hal->ah_dump_state(hal);
245: #endif
246:
247: /*
248: * Get card capabilities, values, ...
249: */
250:
251: if (ar5k_eeprom_init(hal) != 0) {
252: AR5K_PRINT("unable to init EEPROM\n");
253: goto failed;
254: }
255:
256: /* Get misc capabilities */
257: if (hal->ah_get_capabilities(hal) != AH_TRUE) {
258: AR5K_PRINTF("unable to get device capabilities: 0x%04x\n",
259: device);
260: goto failed;
261: }
262:
263: /* Get MAC address */
264: if ((*status = ar5k_eeprom_read_mac(hal, mac)) != 0) {
265: AR5K_PRINTF("unable to read address from EEPROM: 0x%04x\n",
266: device);
267: goto failed;
268: }
269:
270: hal->ah_set_lladdr(hal, mac);
271:
272: /* Get rate tables */
273: if (hal->ah_capabilities.cap_mode & HAL_MODE_11A)
274: ar5k_rt_copy(&hal->ah_rt_11a, &ar5k_rt_11a);
275: if (hal->ah_capabilities.cap_mode & HAL_MODE_11B)
276: ar5k_rt_copy(&hal->ah_rt_11b, &ar5k_rt_11b);
277: if (hal->ah_capabilities.cap_mode & HAL_MODE_11G)
278: ar5k_rt_copy(&hal->ah_rt_11g, &ar5k_rt_11g);
279: if (hal->ah_capabilities.cap_mode & HAL_MODE_TURBO)
280: ar5k_rt_copy(&hal->ah_rt_turbo, &ar5k_rt_turbo);
281: if (hal->ah_capabilities.cap_mode & HAL_MODE_XR)
282: ar5k_rt_copy(&hal->ah_rt_xr, &ar5k_rt_xr);
283:
284: /* Initialize the gain optimization values */
285: if (hal->ah_radio == AR5K_AR5111) {
286: hal->ah_gain.g_step_idx = ar5111_gain_opt.go_default;
287: hal->ah_gain.g_step =
288: &ar5111_gain_opt.go_step[hal->ah_gain.g_step_idx];
289: hal->ah_gain.g_low = 20;
290: hal->ah_gain.g_high = 35;
291: hal->ah_gain.g_active = 1;
292: } else if (hal->ah_radio == AR5K_AR5112) {
293: hal->ah_gain.g_step_idx = ar5112_gain_opt.go_default;
294: hal->ah_gain.g_step =
295: &ar5111_gain_opt.go_step[hal->ah_gain.g_step_idx];
296: hal->ah_gain.g_low = 20;
297: hal->ah_gain.g_high = 85;
298: hal->ah_gain.g_active = 1;
299: }
300:
301: *status = HAL_OK;
302:
303: return (hal);
304:
305: failed:
306: free(hal, M_DEVBUF);
307: return (NULL);
308: }
309:
310: u_int16_t
311: ath_hal_computetxtime(struct ath_hal *hal, const HAL_RATE_TABLE *rates,
312: u_int32_t frame_length, u_int16_t rate_index, HAL_BOOL short_preamble)
313: {
314: const HAL_RATE *rate;
315: u_int32_t value;
316:
317: AR5K_ASSERT_ENTRY(rate_index, rates->rateCount);
318:
319: /*
320: * Get rate by index
321: */
322: rate = &rates->info[rate_index];
323:
324: /*
325: * Calculate the transmission time by operation (PHY) mode
326: */
327: switch (rate->phy) {
328: case IEEE80211_T_CCK:
329: /*
330: * CCK / DS mode (802.11b)
331: */
332: value = AR5K_CCK_TX_TIME(rate->rateKbps, frame_length,
333: (short_preamble && rate->shortPreamble));
334: break;
335:
336: case IEEE80211_T_OFDM:
337: /*
338: * Orthogonal Frequency Division Multiplexing
339: */
340: if (AR5K_OFDM_NUM_BITS_PER_SYM(rate->rateKbps) == 0)
341: return (0);
342: value = AR5K_OFDM_TX_TIME(rate->rateKbps, frame_length);
343: break;
344:
345: case IEEE80211_T_TURBO:
346: /*
347: * Orthogonal Frequency Division Multiplexing
348: * Atheros "Turbo Mode" (doubled rates)
349: */
350: if (AR5K_TURBO_NUM_BITS_PER_SYM(rate->rateKbps) == 0)
351: return (0);
352: value = AR5K_TURBO_TX_TIME(rate->rateKbps, frame_length);
353: break;
354:
355: case IEEE80211_T_XR:
356: /*
357: * Orthogonal Frequency Division Multiplexing
358: * Atheros "eXtended Range" (XR)
359: */
360: if (AR5K_XR_NUM_BITS_PER_SYM(rate->rateKbps) == 0)
361: return (0);
362: value = AR5K_XR_TX_TIME(rate->rateKbps, frame_length);
363: break;
364:
365: default:
366: return (0);
367: }
368:
369: return (value);
370: }
371:
372: HAL_BOOL
373: ar5k_check_channel(struct ath_hal *hal, u_int16_t freq, u_int flags)
374: {
375: /* Check if the channel is in our supported range */
376: if (flags & IEEE80211_CHAN_2GHZ) {
377: if ((freq >= hal->ah_capabilities.cap_range.range_2ghz_min) &&
378: (freq <= hal->ah_capabilities.cap_range.range_2ghz_max))
379: return (AH_TRUE);
380: } else if (flags & IEEE80211_CHAN_5GHZ) {
381: if ((freq >= hal->ah_capabilities.cap_range.range_5ghz_min) &&
382: (freq <= hal->ah_capabilities.cap_range.range_5ghz_max))
383: return (AH_TRUE);
384: }
385:
386: return (AH_FALSE);
387: }
388:
389: HAL_BOOL
390: ath_hal_init_channels(struct ath_hal *hal, HAL_CHANNEL *channels,
391: u_int max_channels, u_int *channels_size, u_int16_t mode,
392: HAL_BOOL outdoor, HAL_BOOL extended)
393: {
394: u_int i, c;
395: u_int32_t domain_current;
396: u_int domain_5ghz, domain_2ghz;
397: HAL_CHANNEL *all_channels;
398:
399: if ((all_channels = malloc(sizeof(HAL_CHANNEL) * max_channels,
400: M_TEMP, M_NOWAIT)) == NULL)
401: return (AH_FALSE);
402:
403: i = c = 0;
404: domain_current = hal->ah_regdomain;
405:
406: /*
407: * In debugging mode, enable all channels supported by the chipset
408: */
409: if (domain_current == DMN_DEFAULT) {
410: int min, max, freq;
411: u_int flags;
412:
413: min = ieee80211_mhz2ieee(IEEE80211_CHANNELS_2GHZ_MIN,
414: IEEE80211_CHAN_2GHZ);
415: max = ieee80211_mhz2ieee(IEEE80211_CHANNELS_2GHZ_MAX,
416: IEEE80211_CHAN_2GHZ);
417: flags = CHANNEL_B | CHANNEL_TG |
418: (hal->ah_version == AR5K_AR5211 ?
419: CHANNEL_PUREG : CHANNEL_G);
420:
421: debugchan:
422: for (i = min; i <= max && c < max_channels; i++) {
423: freq = ieee80211_ieee2mhz(i, flags);
424: if (ar5k_check_channel(hal, freq, flags) == AH_FALSE)
425: continue;
426: all_channels[c].c_channel = freq;
427: all_channels[c++].c_channel_flags = flags;
428: }
429:
430: if (flags & IEEE80211_CHAN_2GHZ) {
431: min = ieee80211_mhz2ieee(IEEE80211_CHANNELS_5GHZ_MIN,
432: IEEE80211_CHAN_5GHZ);
433: max = ieee80211_mhz2ieee(IEEE80211_CHANNELS_5GHZ_MAX,
434: IEEE80211_CHAN_5GHZ);
435: flags = CHANNEL_A | CHANNEL_T | CHANNEL_XR;
436: goto debugchan;
437: }
438:
439: goto done;
440: }
441:
442: domain_5ghz = ieee80211_regdomain2flag(domain_current,
443: IEEE80211_CHANNELS_5GHZ_MIN);
444: domain_2ghz = ieee80211_regdomain2flag(domain_current,
445: IEEE80211_CHANNELS_2GHZ_MIN);
446:
447: /*
448: * Create channel list based on chipset capabilities, regulation domain
449: * and mode. 5GHz...
450: */
451: for (i = 0; (hal->ah_capabilities.cap_range.range_5ghz_max > 0) &&
452: (i < AR5K_ELEMENTS(ar5k_5ghz_channels)) &&
453: (c < max_channels); i++) {
454: /* Check if channel is supported by the chipset */
455: if (ar5k_check_channel(hal,
456: ar5k_5ghz_channels[i].rc_channel,
457: IEEE80211_CHAN_5GHZ) == AH_FALSE)
458: continue;
459:
460: /* Match regulation domain */
461: if ((IEEE80211_DMN(ar5k_5ghz_channels[i].rc_domain) &
462: IEEE80211_DMN(domain_5ghz)) == 0)
463: continue;
464:
465: /* Match modes */
466: if (ar5k_5ghz_channels[i].rc_mode & IEEE80211_CHAN_TURBO) {
467: all_channels[c].c_channel_flags = CHANNEL_T;
468: } else if (ar5k_5ghz_channels[i].rc_mode &
469: IEEE80211_CHAN_OFDM) {
470: all_channels[c].c_channel_flags = CHANNEL_A;
471: } else
472: continue;
473:
474: /* Write channel and increment counter */
475: all_channels[c++].channel = ar5k_5ghz_channels[i].rc_channel;
476: }
477:
478: /*
479: * ...and 2GHz.
480: */
481: for (i = 0; (hal->ah_capabilities.cap_range.range_2ghz_max > 0) &&
482: (i < AR5K_ELEMENTS(ar5k_2ghz_channels)) &&
483: (c < max_channels); i++) {
484: /* Check if channel is supported by the chipset */
485: if (ar5k_check_channel(hal,
486: ar5k_2ghz_channels[i].rc_channel,
487: IEEE80211_CHAN_2GHZ) == AH_FALSE)
488: continue;
489:
490: /* Match regulation domain */
491: if ((IEEE80211_DMN(ar5k_2ghz_channels[i].rc_domain) &
492: IEEE80211_DMN(domain_2ghz)) == 0)
493: continue;
494:
495: /* Match modes */
496: if ((hal->ah_capabilities.cap_mode & HAL_MODE_11B) &&
497: (ar5k_2ghz_channels[i].rc_mode & IEEE80211_CHAN_CCK))
498: all_channels[c].c_channel_flags = CHANNEL_B;
499:
500: if ((hal->ah_capabilities.cap_mode & HAL_MODE_11G) &&
501: (ar5k_2ghz_channels[i].rc_mode & IEEE80211_CHAN_OFDM)) {
502: all_channels[c].c_channel_flags |=
503: hal->ah_version == AR5K_AR5211 ?
504: CHANNEL_PUREG : CHANNEL_G;
505: if (ar5k_2ghz_channels[i].rc_mode &
506: IEEE80211_CHAN_TURBO)
507: all_channels[c].c_channel_flags |= CHANNEL_TG;
508: }
509:
510: /* Write channel and increment counter */
511: all_channels[c++].channel = ar5k_2ghz_channels[i].rc_channel;
512: }
513:
514: done:
515: bcopy(all_channels, channels, sizeof(HAL_CHANNEL) * max_channels);
516: *channels_size = c;
517: free(all_channels, M_TEMP);
518: return (AH_TRUE);
519: }
520:
521: /*
522: * Common internal functions
523: */
524:
525: const char *
526: ar5k_printver(enum ar5k_srev_type type, u_int32_t val)
527: {
528: struct ar5k_srev_name names[] = AR5K_SREV_NAME;
529: const char *name = "xxxx";
530: int i;
531:
532: for (i = 0; i < AR5K_ELEMENTS(names); i++) {
533: if (type == AR5K_VERSION_DEV) {
534: if (names[i].sr_type == type &&
535: names[i].sr_val == val) {
536: name = names[i].sr_name;
537: break;
538: }
539: continue;
540: }
541: if (names[i].sr_type != type ||
542: names[i].sr_val == AR5K_SREV_UNKNOWN)
543: continue;
544: if ((val & 0xff) < names[i + 1].sr_val) {
545: name = names[i].sr_name;
546: break;
547: }
548: }
549:
550: return (name);
551: }
552:
553: void
554: ar5k_radar_alert(struct ath_hal *hal)
555: {
556: /*
557: * Limit ~1/s
558: */
559: if (hal->ah_radar.r_last_channel.channel ==
560: hal->ah_current_channel.channel &&
561: tick < (hal->ah_radar.r_last_alert + hz))
562: return;
563:
564: hal->ah_radar.r_last_channel.channel =
565: hal->ah_current_channel.channel;
566: hal->ah_radar.r_last_channel.c_channel_flags =
567: hal->ah_current_channel.c_channel_flags;
568: hal->ah_radar.r_last_alert = tick;
569:
570: AR5K_PRINTF("Possible radar activity detected at %u MHz (tick %u)\n",
571: hal->ah_radar.r_last_alert, hal->ah_current_channel.channel);
572: }
573:
574: u_int16_t
575: ar5k_regdomain_from_ieee(ieee80211_regdomain_t ieee)
576: {
577: u_int32_t regdomain = (u_int32_t)ieee;
578:
579: /*
580: * Use the default regulation domain if the value is empty
581: * or not supported by the net80211 regulation code.
582: */
583: if (ieee80211_regdomain2flag(regdomain,
584: IEEE80211_CHANNELS_5GHZ_MIN) == DMN_DEBUG)
585: return ((u_int16_t)AR5K_TUNE_REGDOMAIN);
586:
587: /* It is supported, just return the value */
588: return (regdomain);
589: }
590:
591: ieee80211_regdomain_t
592: ar5k_regdomain_to_ieee(u_int16_t regdomain)
593: {
594: ieee80211_regdomain_t ieee = (ieee80211_regdomain_t)regdomain;
595:
596: return (ieee);
597: }
598:
599: u_int16_t
600: ar5k_get_regdomain(struct ath_hal *hal)
601: {
602: u_int16_t regdomain;
603: ieee80211_regdomain_t ieee_regdomain;
604: #ifdef COUNTRYCODE
605: u_int16_t code;
606: #endif
607:
608: ar5k_eeprom_regulation_domain(hal, AH_FALSE, &ieee_regdomain);
609: hal->ah_capabilities.cap_regdomain.reg_hw = ieee_regdomain;
610:
611: #ifdef COUNTRYCODE
612: /*
613: * Get the regulation domain by country code. This will ignore
614: * the settings found in the EEPROM.
615: */
616: code = ieee80211_name2countrycode(COUNTRYCODE);
617: ieee_regdomain = ieee80211_countrycode2regdomain(code);
618: #endif
619:
620: regdomain = ar5k_regdomain_from_ieee(ieee_regdomain);
621: hal->ah_capabilities.cap_regdomain.reg_current = regdomain;
622:
623: return (regdomain);
624: }
625:
626: u_int32_t
627: ar5k_bitswap(u_int32_t val, u_int bits)
628: {
629: if (bits == 8) {
630: val = ((val & 0xF0) >> 4) | ((val & 0x0F) << 4);
631: val = ((val & 0xCC) >> 2) | ((val & 0x33) << 2);
632: val = ((val & 0xAA) >> 1) | ((val & 0x55) << 1);
633:
634: return val;
635: } else {
636: u_int32_t retval = 0, bit, i;
637:
638: for (i = 0; i < bits; i++) {
639: bit = (val >> i) & 1;
640: retval = (retval << 1) | bit;
641: }
642:
643: return retval;
644: }
645: }
646:
647: u_int
648: ar5k_htoclock(u_int usec, HAL_BOOL turbo)
649: {
650: return (turbo == AH_TRUE ? (usec * 80) : (usec * 40));
651: }
652:
653: u_int
654: ar5k_clocktoh(u_int clock, HAL_BOOL turbo)
655: {
656: return (turbo == AH_TRUE ? (clock / 80) : (clock / 40));
657: }
658:
659: void
660: ar5k_rt_copy(HAL_RATE_TABLE *dst, const HAL_RATE_TABLE *src)
661: {
662: bzero(dst, sizeof(HAL_RATE_TABLE));
663: dst->rateCount = src->rateCount;
664: bcopy(src->info, dst->info, sizeof(dst->info));
665: }
666:
667: HAL_BOOL
668: ar5k_register_timeout(struct ath_hal *hal, u_int32_t reg, u_int32_t flag,
669: u_int32_t val, HAL_BOOL is_set)
670: {
671: int i;
672: u_int32_t data;
673:
674: for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
675: data = AR5K_REG_READ(reg);
676: if ((is_set == AH_TRUE) && (data & flag))
677: break;
678: else if ((data & flag) == val)
679: break;
680: AR5K_DELAY(15);
681: }
682:
683: if (i <= 0)
684: return (AH_FALSE);
685:
686: return (AH_TRUE);
687: }
688:
689: /*
690: * Common ar5xx EEPROM access functions
691: */
692:
693: u_int16_t
694: ar5k_eeprom_bin2freq(struct ath_hal *hal, u_int16_t bin, u_int mode)
695: {
696: u_int16_t val;
697:
698: if (bin == AR5K_EEPROM_CHANNEL_DIS)
699: return (bin);
700:
701: if (mode == AR5K_EEPROM_MODE_11A) {
702: if (hal->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
703: val = (5 * bin) + 4800;
704: else
705: val = bin > 62 ?
706: (10 * 62) + (5 * (bin - 62)) + 5100 :
707: (bin * 10) + 5100;
708: } else {
709: if (hal->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
710: val = bin + 2300;
711: else
712: val = bin + 2400;
713: }
714:
715: return (val);
716: }
717:
718: int
719: ar5k_eeprom_read_ants(struct ath_hal *hal, u_int32_t *offset, u_int mode)
720: {
721: struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
722: u_int32_t o = *offset;
723: u_int16_t val;
724: int ret, i = 0;
725:
726: AR5K_EEPROM_READ(o++, val);
727: ee->ee_switch_settling[mode] = (val >> 8) & 0x7f;
728: ee->ee_ant_tx_rx[mode] = (val >> 2) & 0x3f;
729: ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
730:
731: AR5K_EEPROM_READ(o++, val);
732: ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
733: ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
734: ee->ee_ant_control[mode][i++] = val & 0x3f;
735:
736: AR5K_EEPROM_READ(o++, val);
737: ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f;
738: ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f;
739: ee->ee_ant_control[mode][i] = (val << 2) & 0x3f;
740:
741: AR5K_EEPROM_READ(o++, val);
742: ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3;
743: ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f;
744: ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f;
745: ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
746:
747: AR5K_EEPROM_READ(o++, val);
748: ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
749: ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
750: ee->ee_ant_control[mode][i++] = val & 0x3f;
751:
752: /* Get antenna modes */
753: hal->ah_antenna[mode][0] =
754: (ee->ee_ant_control[mode][0] << 4) | 0x1;
755: hal->ah_antenna[mode][HAL_ANT_FIXED_A] =
756: ee->ee_ant_control[mode][1] |
757: (ee->ee_ant_control[mode][2] << 6) |
758: (ee->ee_ant_control[mode][3] << 12) |
759: (ee->ee_ant_control[mode][4] << 18) |
760: (ee->ee_ant_control[mode][5] << 24);
761: hal->ah_antenna[mode][HAL_ANT_FIXED_B] =
762: ee->ee_ant_control[mode][6] |
763: (ee->ee_ant_control[mode][7] << 6) |
764: (ee->ee_ant_control[mode][8] << 12) |
765: (ee->ee_ant_control[mode][9] << 18) |
766: (ee->ee_ant_control[mode][10] << 24);
767:
768: /* return new offset */
769: *offset = o;
770:
771: return (0);
772: }
773:
774: int
775: ar5k_eeprom_read_modes(struct ath_hal *hal, u_int32_t *offset, u_int mode)
776: {
777: struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
778: u_int32_t o = *offset;
779: u_int16_t val;
780: int ret;
781:
782: AR5K_EEPROM_READ(o++, val);
783: ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
784: ee->ee_thr_62[mode] = val & 0xff;
785:
786: if (hal->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
787: ee->ee_thr_62[mode] =
788: mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
789:
790: AR5K_EEPROM_READ(o++, val);
791: ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff;
792: ee->ee_tx_frm2xpa_enable[mode] = val & 0xff;
793:
794: AR5K_EEPROM_READ(o++, val);
795: ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff;
796:
797: if ((val & 0xff) & 0x80)
798: ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
799: else
800: ee->ee_noise_floor_thr[mode] = val & 0xff;
801:
802: if (hal->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
803: ee->ee_noise_floor_thr[mode] =
804: mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
805:
806: AR5K_EEPROM_READ(o++, val);
807: ee->ee_xlna_gain[mode] = (val >> 5) & 0xff;
808: ee->ee_x_gain[mode] = (val >> 1) & 0xf;
809: ee->ee_xpd[mode] = val & 0x1;
810:
811: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
812: ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
813:
814: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
815: AR5K_EEPROM_READ(o++, val);
816: ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
817:
818: if (mode == AR5K_EEPROM_MODE_11A)
819: ee->ee_xr_power[mode] = val & 0x3f;
820: else {
821: ee->ee_ob[mode][0] = val & 0x7;
822: ee->ee_db[mode][0] = (val >> 3) & 0x7;
823: }
824: }
825:
826: if (hal->ah_ee_version < AR5K_EEPROM_VERSION_3_4) {
827: ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
828: ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
829: } else {
830: ee->ee_i_gain[mode] = (val >> 13) & 0x7;
831:
832: AR5K_EEPROM_READ(o++, val);
833: ee->ee_i_gain[mode] |= (val << 3) & 0x38;
834:
835: if (mode == AR5K_EEPROM_MODE_11G)
836: ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
837: }
838:
839: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
840: mode == AR5K_EEPROM_MODE_11A) {
841: ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
842: ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
843: }
844:
845: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_6 &&
846: mode == AR5K_EEPROM_MODE_11G)
847: ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
848:
849: /* return new offset */
850: *offset = o;
851:
852: return (0);
853: }
854:
855: int
856: ar5k_eeprom_init(struct ath_hal *hal)
857: {
858: struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
859: u_int32_t offset;
860: u_int16_t val;
861: int ret, i;
862: u_int mode;
863:
864: /* Initial TX thermal adjustment values */
865: ee->ee_tx_clip = 4;
866: ee->ee_pwd_84 = ee->ee_pwd_90 = 1;
867: ee->ee_gain_select = 1;
868:
869: /*
870: * Read values from EEPROM and store them in the capability structure
871: */
872: AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
873: AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
874: AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
875: AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
876: AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
877:
878: /* Return if we have an old EEPROM */
879: if (hal->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
880: return (0);
881:
882: #ifdef notyet
883: /*
884: * Validate the checksum of the EEPROM date. There are some
885: * devices with invalid EEPROMs.
886: */
887: for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
888: AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
889: cksum ^= val;
890: }
891: if (cksum != AR5K_EEPROM_INFO_CKSUM) {
892: AR5K_PRINTF("Invalid EEPROM checksum 0x%04x\n", cksum);
893: return (EINVAL);
894: }
895: #endif
896:
897: AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(hal->ah_ee_version),
898: ee_ant_gain);
899:
900: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
901: AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
902: AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
903: }
904:
905: if (hal->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
906: AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
907: ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
908: ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
909:
910: AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
911: ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
912: ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
913: }
914:
915: /*
916: * Get conformance test limit values
917: */
918: offset = AR5K_EEPROM_CTL(hal->ah_ee_version);
919: ee->ee_ctls = AR5K_EEPROM_N_CTLS(hal->ah_ee_version);
920:
921: for (i = 0; i < ee->ee_ctls; i++) {
922: AR5K_EEPROM_READ(offset++, val);
923: ee->ee_ctl[i] = (val >> 8) & 0xff;
924: ee->ee_ctl[i + 1] = val & 0xff;
925: }
926:
927: /*
928: * Get values for 802.11a (5GHz)
929: */
930: mode = AR5K_EEPROM_MODE_11A;
931:
932: ee->ee_turbo_max_power[mode] =
933: AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
934:
935: offset = AR5K_EEPROM_MODES_11A(hal->ah_ee_version);
936:
937: if ((ret = ar5k_eeprom_read_ants(hal, &offset, mode)) != 0)
938: return (ret);
939:
940: AR5K_EEPROM_READ(offset++, val);
941: ee->ee_adc_desired_size[mode] = (int8_t)((val >> 8) & 0xff);
942: ee->ee_ob[mode][3] = (val >> 5) & 0x7;
943: ee->ee_db[mode][3] = (val >> 2) & 0x7;
944: ee->ee_ob[mode][2] = (val << 1) & 0x7;
945:
946: AR5K_EEPROM_READ(offset++, val);
947: ee->ee_ob[mode][2] |= (val >> 15) & 0x1;
948: ee->ee_db[mode][2] = (val >> 12) & 0x7;
949: ee->ee_ob[mode][1] = (val >> 9) & 0x7;
950: ee->ee_db[mode][1] = (val >> 6) & 0x7;
951: ee->ee_ob[mode][0] = (val >> 3) & 0x7;
952: ee->ee_db[mode][0] = val & 0x7;
953:
954: if ((ret = ar5k_eeprom_read_modes(hal, &offset, mode)) != 0)
955: return (ret);
956:
957: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
958: AR5K_EEPROM_READ(offset++, val);
959: ee->ee_margin_tx_rx[mode] = val & 0x3f;
960: }
961:
962: /*
963: * Get values for 802.11b (2.4GHz)
964: */
965: mode = AR5K_EEPROM_MODE_11B;
966: offset = AR5K_EEPROM_MODES_11B(hal->ah_ee_version);
967:
968: if ((ret = ar5k_eeprom_read_ants(hal, &offset, mode)) != 0)
969: return (ret);
970:
971: AR5K_EEPROM_READ(offset++, val);
972: ee->ee_adc_desired_size[mode] = (int8_t)((val >> 8) & 0xff);
973: ee->ee_ob[mode][1] = (val >> 4) & 0x7;
974: ee->ee_db[mode][1] = val & 0x7;
975:
976: if ((ret = ar5k_eeprom_read_modes(hal, &offset, mode)) != 0)
977: return (ret);
978:
979: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
980: AR5K_EEPROM_READ(offset++, val);
981: ee->ee_cal_pier[mode][0] =
982: ar5k_eeprom_bin2freq(hal, val & 0xff, mode);
983: ee->ee_cal_pier[mode][1] =
984: ar5k_eeprom_bin2freq(hal, (val >> 8) & 0xff, mode);
985:
986: AR5K_EEPROM_READ(offset++, val);
987: ee->ee_cal_pier[mode][2] =
988: ar5k_eeprom_bin2freq(hal, val & 0xff, mode);
989: }
990:
991: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
992: ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
993: }
994:
995: /*
996: * Get values for 802.11g (2.4GHz)
997: */
998: mode = AR5K_EEPROM_MODE_11G;
999: offset = AR5K_EEPROM_MODES_11G(hal->ah_ee_version);
1000:
1001: if ((ret = ar5k_eeprom_read_ants(hal, &offset, mode)) != 0)
1002: return (ret);
1003:
1004: AR5K_EEPROM_READ(offset++, val);
1005: ee->ee_adc_desired_size[mode] = (int8_t)((val >> 8) & 0xff);
1006: ee->ee_ob[mode][1] = (val >> 4) & 0x7;
1007: ee->ee_db[mode][1] = val & 0x7;
1008:
1009: if ((ret = ar5k_eeprom_read_modes(hal, &offset, mode)) != 0)
1010: return (ret);
1011:
1012: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
1013: AR5K_EEPROM_READ(offset++, val);
1014: ee->ee_cal_pier[mode][0] =
1015: ar5k_eeprom_bin2freq(hal, val & 0xff, mode);
1016: ee->ee_cal_pier[mode][1] =
1017: ar5k_eeprom_bin2freq(hal, (val >> 8) & 0xff, mode);
1018:
1019: AR5K_EEPROM_READ(offset++, val);
1020: ee->ee_turbo_max_power[mode] = val & 0x7f;
1021: ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
1022:
1023: AR5K_EEPROM_READ(offset++, val);
1024: ee->ee_cal_pier[mode][2] =
1025: ar5k_eeprom_bin2freq(hal, val & 0xff, mode);
1026:
1027: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
1028: ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
1029: }
1030:
1031: AR5K_EEPROM_READ(offset++, val);
1032: ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
1033: ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
1034:
1035: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
1036: AR5K_EEPROM_READ(offset++, val);
1037: ee->ee_cck_ofdm_gain_delta = val & 0xff;
1038: }
1039: }
1040:
1041: /*
1042: * Read 5GHz EEPROM channels
1043: */
1044:
1045: return (0);
1046: }
1047:
1048: int
1049: ar5k_eeprom_read_mac(struct ath_hal *hal, u_int8_t *mac)
1050: {
1051: u_int32_t total, offset;
1052: u_int16_t data;
1053: int octet;
1054: u_int8_t mac_d[IEEE80211_ADDR_LEN];
1055:
1056: bzero(mac, IEEE80211_ADDR_LEN);
1057: bzero(&mac_d, IEEE80211_ADDR_LEN);
1058:
1059: if (hal->ah_eeprom_read(hal, 0x20, &data) != 0)
1060: return (EIO);
1061:
1062: for (offset = 0x1f, octet = 0, total = 0;
1063: offset >= 0x1d; offset--) {
1064: if (hal->ah_eeprom_read(hal, offset, &data) != 0)
1065: return (EIO);
1066:
1067: total += data;
1068: mac_d[octet + 1] = data & 0xff;
1069: mac_d[octet] = data >> 8;
1070: octet += 2;
1071: }
1072:
1073: bcopy(mac_d, mac, IEEE80211_ADDR_LEN);
1074:
1075: if ((!total) || total == (3 * 0xffff))
1076: return (EINVAL);
1077:
1078: return (0);
1079: }
1080:
1081: HAL_BOOL
1082: ar5k_eeprom_regulation_domain(struct ath_hal *hal, HAL_BOOL write,
1083: ieee80211_regdomain_t *regdomain)
1084: {
1085: u_int16_t ee_regdomain;
1086:
1087: /* Read current value */
1088: if (write != AH_TRUE) {
1089: ee_regdomain = hal->ah_capabilities.cap_eeprom.ee_regdomain;
1090: *regdomain = ar5k_regdomain_to_ieee(ee_regdomain);
1091: return (AH_TRUE);
1092: }
1093:
1094: ee_regdomain = ar5k_regdomain_from_ieee(*regdomain);
1095:
1096: /* Try to write a new value */
1097: if (hal->ah_capabilities.cap_eeprom.ee_protect &
1098: AR5K_EEPROM_PROTECT_WR_128_191)
1099: return (AH_FALSE);
1100: if (hal->ah_eeprom_write(hal, AR5K_EEPROM_REG_DOMAIN,
1101: ee_regdomain) != 0)
1102: return (AH_FALSE);
1103:
1104: hal->ah_capabilities.cap_eeprom.ee_regdomain = ee_regdomain;
1105:
1106: return (AH_TRUE);
1107: }
1108:
1109: /*
1110: * PHY/RF access functions
1111: */
1112:
1113: HAL_BOOL
1114: ar5k_channel(struct ath_hal *hal, HAL_CHANNEL *channel)
1115: {
1116: HAL_BOOL ret;
1117:
1118: /*
1119: * Check bounds supported by the PHY
1120: * (don't care about regulation restrictions at this point)
1121: */
1122: if ((channel->channel < hal->ah_capabilities.cap_range.range_2ghz_min ||
1123: channel->channel > hal->ah_capabilities.cap_range.range_2ghz_max) &&
1124: (channel->channel < hal->ah_capabilities.cap_range.range_5ghz_min ||
1125: channel->channel > hal->ah_capabilities.cap_range.range_5ghz_max)) {
1126: AR5K_PRINTF("channel out of supported range (%u MHz)\n",
1127: channel->channel);
1128: return (AH_FALSE);
1129: }
1130:
1131: /*
1132: * Set the channel and wait
1133: */
1134: if (hal->ah_radio == AR5K_AR5110)
1135: ret = ar5k_ar5110_channel(hal, channel);
1136: else if (hal->ah_radio == AR5K_AR5111)
1137: ret = ar5k_ar5111_channel(hal, channel);
1138: else
1139: ret = ar5k_ar5112_channel(hal, channel);
1140:
1141: if (ret == AH_FALSE)
1142: return (ret);
1143:
1144: hal->ah_current_channel.c_channel = channel->c_channel;
1145: hal->ah_current_channel.c_channel_flags = channel->c_channel_flags;
1146: hal->ah_turbo = channel->c_channel_flags == CHANNEL_T ?
1147: AH_TRUE : AH_FALSE;
1148:
1149: return (AH_TRUE);
1150: }
1151:
1152: u_int32_t
1153: ar5k_ar5110_chan2athchan(HAL_CHANNEL *channel)
1154: {
1155: u_int32_t athchan;
1156:
1157: /*
1158: * Convert IEEE channel/MHz to an internal channel value used
1159: * by the AR5210 chipset. This has not been verified with
1160: * newer chipsets like the AR5212A who have a completely
1161: * different RF/PHY part.
1162: */
1163: athchan = (ar5k_bitswap((ieee80211_mhz2ieee(channel->c_channel,
1164: channel->c_channel_flags) - 24) / 2, 5) << 1) |
1165: (1 << 6) | 0x1;
1166:
1167: return (athchan);
1168: }
1169:
1170: HAL_BOOL
1171: ar5k_ar5110_channel(struct ath_hal *hal, HAL_CHANNEL *channel)
1172: {
1173: u_int32_t data;
1174:
1175: /*
1176: * Set the channel and wait
1177: */
1178: data = ar5k_ar5110_chan2athchan(channel);
1179: AR5K_PHY_WRITE(0x27, data);
1180: AR5K_PHY_WRITE(0x30, 0);
1181: AR5K_DELAY(1000);
1182:
1183: return (AH_TRUE);
1184: }
1185:
1186: HAL_BOOL
1187: ar5k_ar5111_chan2athchan(u_int ieee, struct ar5k_athchan_2ghz *athchan)
1188: {
1189: int channel;
1190:
1191: /* Cast this value to catch negative channel numbers (>= -19) */
1192: channel = (int)ieee;
1193:
1194: /*
1195: * Map 2GHz IEEE channel to 5GHz Atheros channel
1196: */
1197: if (channel <= 13) {
1198: athchan->a2_athchan = 115 + channel;
1199: athchan->a2_flags = 0x46;
1200: } else if (channel == 14) {
1201: athchan->a2_athchan = 124;
1202: athchan->a2_flags = 0x44;
1203: } else if (channel >= 15 && channel <= 26) {
1204: athchan->a2_athchan = ((channel - 14) * 4) + 132;
1205: athchan->a2_flags = 0x46;
1206: } else
1207: return (AH_FALSE);
1208:
1209: return (AH_TRUE);
1210: }
1211:
1212: HAL_BOOL
1213: ar5k_ar5111_channel(struct ath_hal *hal, HAL_CHANNEL *channel)
1214: {
1215: u_int ieee_channel, ath_channel;
1216: u_int32_t data0, data1, clock;
1217: struct ar5k_athchan_2ghz ath_channel_2ghz;
1218:
1219: /*
1220: * Set the channel on the AR5111 radio
1221: */
1222: data0 = data1 = 0;
1223: ath_channel = ieee_channel = ieee80211_mhz2ieee(channel->c_channel,
1224: channel->c_channel_flags);
1225:
1226: if (channel->c_channel_flags & IEEE80211_CHAN_2GHZ) {
1227: /* Map 2GHz channel to 5GHz Atheros channel ID */
1228: if (ar5k_ar5111_chan2athchan(ieee_channel,
1229: &ath_channel_2ghz) == AH_FALSE)
1230: return (AH_FALSE);
1231:
1232: ath_channel = ath_channel_2ghz.a2_athchan;
1233: data0 = ((ar5k_bitswap(ath_channel_2ghz.a2_flags, 8) & 0xff)
1234: << 5) | (1 << 4);
1235: }
1236:
1237: if (ath_channel < 145 || !(ath_channel & 1)) {
1238: clock = 1;
1239: data1 = ((ar5k_bitswap(ath_channel - 24, 8) & 0xff) << 2)
1240: | (clock << 1) | (1 << 10) | 1;
1241: } else {
1242: clock = 0;
1243: data1 = ((ar5k_bitswap((ath_channel - 24) / 2, 8) & 0xff) << 2)
1244: | (clock << 1) | (1 << 10) | 1;
1245: }
1246:
1247: AR5K_PHY_WRITE(0x27, (data1 & 0xff) | ((data0 & 0xff) << 8));
1248: AR5K_PHY_WRITE(0x34, ((data1 >> 8) & 0xff) | (data0 & 0xff00));
1249:
1250: return (AH_TRUE);
1251: }
1252:
1253: HAL_BOOL
1254: ar5k_ar5112_channel(struct ath_hal *hal, HAL_CHANNEL *channel)
1255: {
1256: u_int32_t data, data0, data1, data2;
1257: u_int16_t c;
1258:
1259: data = data0 = data1 = data2 = 0;
1260: c = channel->c_channel;
1261:
1262: /*
1263: * Set the channel on the AR5112 or newer
1264: */
1265: if (c < 4800) {
1266: if (!((c - 2224) % 5)) {
1267: data0 = ((2 * (c - 704)) - 3040) / 10;
1268: data1 = 1;
1269: } else if (!((c - 2192) % 5)) {
1270: data0 = ((2 * (c - 672)) - 3040) / 10;
1271: data1 = 0;
1272: } else
1273: return (AH_FALSE);
1274:
1275: data0 = ar5k_bitswap((data0 << 2) & 0xff, 8);
1276: } else {
1277: if (!(c % 20) && c >= 5120) {
1278: data0 = ar5k_bitswap(((c - 4800) / 20 << 2), 8);
1279: data2 = ar5k_bitswap(3, 2);
1280: } else if (!(c % 10)) {
1281: data0 = ar5k_bitswap(((c - 4800) / 10 << 1), 8);
1282: data2 = ar5k_bitswap(2, 2);
1283: } else if (!(c % 5)) {
1284: data0 = ar5k_bitswap((c - 4800) / 5, 8);
1285: data2 = ar5k_bitswap(1, 2);
1286: } else
1287: return (AH_FALSE);
1288: }
1289:
1290: data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001;
1291:
1292: AR5K_PHY_WRITE(0x27, data & 0xff);
1293: AR5K_PHY_WRITE(0x36, (data >> 8) & 0x7f);
1294:
1295: return (AH_TRUE);
1296: }
1297:
1298: u_int
1299: ar5k_rfregs_op(u_int32_t *rf, u_int32_t offset, u_int32_t reg, u_int32_t bits,
1300: u_int32_t first, u_int32_t col, HAL_BOOL set)
1301: {
1302: u_int32_t mask, entry, last, data, shift, position;
1303: int32_t left;
1304: int i;
1305:
1306: if (rf == NULL) {
1307: /* should not happen */
1308: return (0);
1309: }
1310:
1311: if (!(col <= 3 && bits <= 32 && first + bits <= 319)) {
1312: AR5K_PRINTF("invalid values at offset %u\n", offset);
1313: return (0);
1314: }
1315:
1316: entry = ((first - 1) / 8) + offset;
1317: position = (first - 1) % 8;
1318:
1319: if (set == AH_TRUE)
1320: data = ar5k_bitswap(reg, bits);
1321:
1322: for (i = shift = 0, left = bits; left > 0; position = 0, entry++, i++) {
1323: last = (position + left > 8) ? 8 : position + left;
1324: mask = (((1 << last) - 1) ^ ((1 << position) - 1)) <<
1325: (col * 8);
1326:
1327: if (set == AH_TRUE) {
1328: rf[entry] &= ~mask;
1329: rf[entry] |= ((data << position) << (col * 8)) & mask;
1330: data >>= (8 - position);
1331: } else {
1332: data = (((rf[entry] & mask) >> (col * 8)) >>
1333: position) << shift;
1334: shift += last - position;
1335: }
1336:
1337: left -= 8 - position;
1338: }
1339:
1340: data = set == AH_TRUE ? 1 : ar5k_bitswap(data, bits);
1341:
1342: return (data);
1343: }
1344:
1345: u_int32_t
1346: ar5k_rfregs_gainf_corr(struct ath_hal *hal)
1347: {
1348: u_int32_t mix, step;
1349: u_int32_t *rf;
1350:
1351: if (hal->ah_rf_banks == NULL)
1352: return (0);
1353:
1354: rf = hal->ah_rf_banks;
1355: hal->ah_gain.g_f_corr = 0;
1356:
1357: if (ar5k_rfregs_op(rf, hal->ah_offset[7], 0, 1, 36, 0, AH_FALSE) != 1)
1358: return (0);
1359:
1360: step = ar5k_rfregs_op(rf, hal->ah_offset[7], 0, 4, 32, 0, AH_FALSE);
1361: mix = hal->ah_gain.g_step->gos_param[0];
1362:
1363: switch (mix) {
1364: case 3:
1365: hal->ah_gain.g_f_corr = step * 2;
1366: break;
1367: case 2:
1368: hal->ah_gain.g_f_corr = (step - 5) * 2;
1369: break;
1370: case 1:
1371: hal->ah_gain.g_f_corr = step;
1372: break;
1373: default:
1374: hal->ah_gain.g_f_corr = 0;
1375: break;
1376: }
1377:
1378: return (hal->ah_gain.g_f_corr);
1379: }
1380:
1381: HAL_BOOL
1382: ar5k_rfregs_gain_readback(struct ath_hal *hal)
1383: {
1384: u_int32_t step, mix, level[4];
1385: u_int32_t *rf;
1386:
1387: if (hal->ah_rf_banks == NULL)
1388: return (0);
1389:
1390: rf = hal->ah_rf_banks;
1391:
1392: if (hal->ah_radio == AR5K_AR5111) {
1393: step = ar5k_rfregs_op(rf, hal->ah_offset[7],
1394: 0, 6, 37, 0, AH_FALSE);
1395: level[0] = 0;
1396: level[1] = (step == 0x3f) ? 0x32 : step + 4;
1397: level[2] = (step != 0x3f) ? 0x40 : level[0];
1398: level[3] = level[2] + 0x32;
1399:
1400: hal->ah_gain.g_high = level[3] -
1401: (step == 0x3f ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5);
1402: hal->ah_gain.g_low = level[0] +
1403: (step == 0x3f ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0);
1404: } else {
1405: mix = ar5k_rfregs_op(rf, hal->ah_offset[7],
1406: 0, 1, 36, 0, AH_FALSE);
1407: level[0] = level[2] = 0;
1408:
1409: if (mix == 1) {
1410: level[1] = level[3] = 83;
1411: } else {
1412: level[1] = level[3] = 107;
1413: hal->ah_gain.g_high = 55;
1414: }
1415: }
1416:
1417: return ((hal->ah_gain.g_current >= level[0] &&
1418: hal->ah_gain.g_current <= level[1]) ||
1419: (hal->ah_gain.g_current >= level[2] &&
1420: hal->ah_gain.g_current <= level[3]));
1421: }
1422:
1423: int32_t
1424: ar5k_rfregs_gain_adjust(struct ath_hal *hal)
1425: {
1426: int ret = 0;
1427: const struct ar5k_gain_opt *go;
1428:
1429: go = hal->ah_radio == AR5K_AR5111 ?
1430: &ar5111_gain_opt : &ar5112_gain_opt;
1431:
1432: hal->ah_gain.g_step = &go->go_step[hal->ah_gain.g_step_idx];
1433:
1434: if (hal->ah_gain.g_current >= hal->ah_gain.g_high) {
1435: if (hal->ah_gain.g_step_idx == 0)
1436: return (-1);
1437: for (hal->ah_gain.g_target = hal->ah_gain.g_current;
1438: hal->ah_gain.g_target >= hal->ah_gain.g_high &&
1439: hal->ah_gain.g_step_idx > 0;
1440: hal->ah_gain.g_step =
1441: &go->go_step[hal->ah_gain.g_step_idx]) {
1442: hal->ah_gain.g_target -= 2 *
1443: (go->go_step[--(hal->ah_gain.g_step_idx)].gos_gain -
1444: hal->ah_gain.g_step->gos_gain);
1445: }
1446:
1447: ret = 1;
1448: goto done;
1449: }
1450:
1451: if (hal->ah_gain.g_current <= hal->ah_gain.g_low) {
1452: if (hal->ah_gain.g_step_idx == (go->go_steps_count - 1))
1453: return (-2);
1454: for (hal->ah_gain.g_target = hal->ah_gain.g_current;
1455: hal->ah_gain.g_target <= hal->ah_gain.g_low &&
1456: hal->ah_gain.g_step_idx < (go->go_steps_count - 1);
1457: hal->ah_gain.g_step =
1458: &go->go_step[hal->ah_gain.g_step_idx]) {
1459: hal->ah_gain.g_target -= 2 *
1460: (go->go_step[++(hal->ah_gain.g_step_idx)].gos_gain -
1461: hal->ah_gain.g_step->gos_gain);
1462: }
1463:
1464: ret = 2;
1465: goto done;
1466: }
1467:
1468: done:
1469: #ifdef AR5K_DEBUG
1470: AR5K_PRINTF("ret %d, gain step %u, current gain %u, target gain %u\n",
1471: ret,
1472: hal->ah_gain.g_step_idx,
1473: hal->ah_gain.g_current,
1474: hal->ah_gain.g_target);
1475: #endif
1476:
1477: return (ret);
1478: }
1479:
1480: HAL_BOOL
1481: ar5k_rfregs(struct ath_hal *hal, HAL_CHANNEL *channel, u_int mode)
1482: {
1483: ar5k_rfgain_t *func = NULL;
1484: HAL_BOOL ret;
1485:
1486: if (hal->ah_radio == AR5K_AR5111) {
1487: hal->ah_rf_banks_size = sizeof(ar5111_rf);
1488: func = ar5k_ar5111_rfregs;
1489: } else if (hal->ah_radio == AR5K_AR5112) {
1490: if (hal->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A)
1491: hal->ah_rf_banks_size = sizeof(ar5112a_rf);
1492: else
1493: hal->ah_rf_banks_size = sizeof(ar5112_rf);
1494: func = ar5k_ar5112_rfregs;
1495: } else
1496: return (AH_FALSE);
1497:
1498: if (hal->ah_rf_banks == NULL) {
1499: /* XXX do extra checks? */
1500: if ((hal->ah_rf_banks = malloc(hal->ah_rf_banks_size,
1501: M_DEVBUF, M_NOWAIT)) == NULL) {
1502: AR5K_PRINT("out of memory\n");
1503: return (AH_FALSE);
1504: }
1505: }
1506:
1507: ret = (func)(hal, channel, mode);
1508:
1509: if (ret == AH_TRUE)
1510: hal->ah_rf_gain = HAL_RFGAIN_INACTIVE;
1511:
1512: return (ret);
1513: }
1514:
1515: HAL_BOOL
1516: ar5k_ar5111_rfregs(struct ath_hal *hal, HAL_CHANNEL *channel, u_int mode)
1517: {
1518: struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
1519: const u_int rf_size = AR5K_ELEMENTS(ar5111_rf);
1520: u_int32_t *rf;
1521: int i, obdb = -1, bank = -1;
1522: u_int32_t ee_mode;
1523:
1524: AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
1525:
1526: rf = hal->ah_rf_banks;
1527:
1528: /* Copy values to modify them */
1529: for (i = 0; i < rf_size; i++) {
1530: if (ar5111_rf[i].rf_bank >=
1531: AR5K_AR5111_INI_RF_MAX_BANKS) {
1532: AR5K_PRINT("invalid bank\n");
1533: return (AH_FALSE);
1534: }
1535:
1536: if (bank != ar5111_rf[i].rf_bank) {
1537: bank = ar5111_rf[i].rf_bank;
1538: hal->ah_offset[bank] = i;
1539: }
1540:
1541: rf[i] = ar5111_rf[i].rf_value[mode];
1542: }
1543:
1544: if (channel->c_channel_flags & IEEE80211_CHAN_2GHZ) {
1545: if (channel->c_channel_flags & IEEE80211_CHAN_B)
1546: ee_mode = AR5K_EEPROM_MODE_11B;
1547: else
1548: ee_mode = AR5K_EEPROM_MODE_11G;
1549: obdb = 0;
1550:
1551: if (!ar5k_rfregs_op(rf, hal->ah_offset[0],
1552: ee->ee_ob[ee_mode][obdb], 3, 119, 0, AH_TRUE))
1553: return (AH_FALSE);
1554:
1555: if (!ar5k_rfregs_op(rf, hal->ah_offset[0],
1556: ee->ee_ob[ee_mode][obdb], 3, 122, 0, AH_TRUE))
1557: return (AH_FALSE);
1558:
1559: obdb = 1;
1560: } else {
1561: /* For 11a, Turbo and XR */
1562: ee_mode = AR5K_EEPROM_MODE_11A;
1563: obdb = channel->c_channel >= 5725 ? 3 :
1564: (channel->c_channel >= 5500 ? 2 :
1565: (channel->c_channel >= 5260 ? 1 :
1566: (channel->c_channel > 4000 ? 0 : -1)));
1567:
1568: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
1569: ee->ee_pwd_84, 1, 51, 3, AH_TRUE))
1570: return (AH_FALSE);
1571:
1572: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
1573: ee->ee_pwd_90, 1, 45, 3, AH_TRUE))
1574: return (AH_FALSE);
1575: }
1576:
1577: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
1578: !ee->ee_xpd[ee_mode], 1, 95, 0, AH_TRUE))
1579: return (AH_FALSE);
1580:
1581: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
1582: ee->ee_x_gain[ee_mode], 4, 96, 0, AH_TRUE))
1583: return (AH_FALSE);
1584:
1585: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
1586: obdb >= 0 ? ee->ee_ob[ee_mode][obdb] : 0, 3, 104, 0, AH_TRUE))
1587: return (AH_FALSE);
1588:
1589: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
1590: obdb >= 0 ? ee->ee_db[ee_mode][obdb] : 0, 3, 107, 0, AH_TRUE))
1591: return (AH_FALSE);
1592:
1593: if (!ar5k_rfregs_op(rf, hal->ah_offset[7],
1594: ee->ee_i_gain[ee_mode], 6, 29, 0, AH_TRUE))
1595: return (AH_FALSE);
1596:
1597: if (!ar5k_rfregs_op(rf, hal->ah_offset[7],
1598: ee->ee_xpd[ee_mode], 1, 4, 0, AH_TRUE))
1599: return (AH_FALSE);
1600:
1601: /* Write RF values */
1602: for (i = 0; i < rf_size; i++) {
1603: AR5K_REG_WAIT(i);
1604: AR5K_REG_WRITE(ar5111_rf[i].rf_register, rf[i]);
1605: }
1606:
1607: return (AH_TRUE);
1608: }
1609:
1610: HAL_BOOL
1611: ar5k_ar5112_rfregs(struct ath_hal *hal, HAL_CHANNEL *channel, u_int mode)
1612: {
1613: struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
1614: u_int rf_size;
1615: u_int32_t *rf;
1616: int i, obdb = -1, bank = -1;
1617: u_int32_t ee_mode;
1618: const struct ar5k_ini_rf *rf_ini;
1619:
1620: AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
1621:
1622: rf = hal->ah_rf_banks;
1623:
1624: if (hal->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
1625: rf_ini = ar5112a_rf;
1626: rf_size = AR5K_ELEMENTS(ar5112a_rf);
1627: } else {
1628: rf_ini = ar5112_rf;
1629: rf_size = AR5K_ELEMENTS(ar5112_rf);
1630: }
1631:
1632: /* Copy values to modify them */
1633: for (i = 0; i < rf_size; i++) {
1634: if (rf_ini[i].rf_bank >=
1635: AR5K_AR5112_INI_RF_MAX_BANKS) {
1636: AR5K_PRINT("invalid bank\n");
1637: return (AH_FALSE);
1638: }
1639:
1640: if (bank != rf_ini[i].rf_bank) {
1641: bank = rf_ini[i].rf_bank;
1642: hal->ah_offset[bank] = i;
1643: }
1644:
1645: rf[i] = rf_ini[i].rf_value[mode];
1646: }
1647:
1648: if (channel->c_channel_flags & IEEE80211_CHAN_2GHZ) {
1649: if (channel->c_channel_flags & IEEE80211_CHAN_B)
1650: ee_mode = AR5K_EEPROM_MODE_11B;
1651: else
1652: ee_mode = AR5K_EEPROM_MODE_11G;
1653: obdb = 0;
1654:
1655: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
1656: ee->ee_ob[ee_mode][obdb], 3, 287, 0, AH_TRUE))
1657: return (AH_FALSE);
1658:
1659: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
1660: ee->ee_ob[ee_mode][obdb], 3, 290, 0, AH_TRUE))
1661: return (AH_FALSE);
1662: } else {
1663: /* For 11a, Turbo and XR */
1664: ee_mode = AR5K_EEPROM_MODE_11A;
1665: obdb = channel->c_channel >= 5725 ? 3 :
1666: (channel->c_channel >= 5500 ? 2 :
1667: (channel->c_channel >= 5260 ? 1 :
1668: (channel->c_channel > 4000 ? 0 : -1)));
1669:
1670: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
1671: ee->ee_ob[ee_mode][obdb], 3, 279, 0, AH_TRUE))
1672: return (AH_FALSE);
1673:
1674: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
1675: ee->ee_ob[ee_mode][obdb], 3, 282, 0, AH_TRUE))
1676: return (AH_FALSE);
1677: }
1678:
1679: #ifdef notyet
1680: ar5k_rfregs_op(rf, hal->ah_offset[6],
1681: ee->ee_x_gain[ee_mode], 2, 270, 0, AH_TRUE);
1682: ar5k_rfregs_op(rf, hal->ah_offset[6],
1683: ee->ee_x_gain[ee_mode], 2, 257, 0, AH_TRUE);
1684: #endif
1685:
1686: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
1687: ee->ee_xpd[ee_mode], 1, 302, 0, AH_TRUE))
1688: return (AH_FALSE);
1689:
1690: if (!ar5k_rfregs_op(rf, hal->ah_offset[7],
1691: ee->ee_i_gain[ee_mode], 6, 14, 0, AH_TRUE))
1692: return (AH_FALSE);
1693:
1694: /* Write RF values */
1695: for (i = 0; i < rf_size; i++)
1696: AR5K_REG_WRITE(ar5112_rf[i].rf_register, rf[i]);
1697:
1698: return (AH_TRUE);
1699: }
1700:
1701: HAL_BOOL
1702: ar5k_rfgain(struct ath_hal *hal, u_int phy, u_int freq)
1703: {
1704: int i;
1705:
1706: switch (phy) {
1707: case AR5K_INI_PHY_5111:
1708: case AR5K_INI_PHY_5112:
1709: break;
1710: default:
1711: return (AH_FALSE);
1712: }
1713:
1714: switch (freq) {
1715: case AR5K_INI_RFGAIN_2GHZ:
1716: case AR5K_INI_RFGAIN_5GHZ:
1717: break;
1718: default:
1719: return (AH_FALSE);
1720: }
1721:
1722: for (i = 0; i < AR5K_ELEMENTS(ar5k_rfg); i++) {
1723: AR5K_REG_WAIT(i);
1724: AR5K_REG_WRITE((u_int32_t)ar5k_rfg[i].rfg_register,
1725: ar5k_rfg[i].rfg_value[phy][freq]);
1726: }
1727:
1728: return (AH_TRUE);
1729: }
1730:
1731: /*
1732: * Common TX power setup
1733: */
1734: void
1735: ar5k_txpower_table(struct ath_hal *hal, HAL_CHANNEL *channel, int16_t max_power)
1736: {
1737: u_int16_t txpower, *rates;
1738: int i, min, max, n;
1739:
1740: rates = hal->ah_txpower.txp_rates;
1741:
1742: txpower = AR5K_TUNE_DEFAULT_TXPOWER * 2;
1743: if (max_power > txpower) {
1744: txpower = max_power > AR5K_TUNE_MAX_TXPOWER ?
1745: AR5K_TUNE_MAX_TXPOWER : max_power;
1746: }
1747:
1748: for (i = 0; i < AR5K_MAX_RATES; i++)
1749: rates[i] = txpower;
1750:
1751: /* XXX setup target powers by rate */
1752:
1753: hal->ah_txpower.txp_min = rates[7];
1754: hal->ah_txpower.txp_max = rates[0];
1755: hal->ah_txpower.txp_ofdm = rates[0];
1756:
1757: /* Calculate the power table */
1758: n = AR5K_ELEMENTS(hal->ah_txpower.txp_pcdac);
1759: min = AR5K_EEPROM_PCDAC_START;
1760: max = AR5K_EEPROM_PCDAC_STOP;
1761: for (i = 0; i < n; i += AR5K_EEPROM_PCDAC_STEP)
1762: hal->ah_txpower.txp_pcdac[i] =
1763: #ifdef notyet
1764: min + ((i * (max - min)) / n);
1765: #else
1766: min;
1767: #endif
1768: }
CVSweb