xref: /freebsd/sys/dev/ath/ath_hal/ah_eeprom_v3.c (revision 6b7b2d80ed4d728d3ffd12c422e57798c1b63a84)
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$
18  */
19 #include "opt_ah.h"
20 
21 #include "ah.h"
22 #include "ah_internal.h"
23 #include "ah_eeprom_v3.h"
24 
25 static void
26 getPcdacInterceptsFromPcdacMinMax(HAL_EEPROM *ee,
27 	uint16_t pcdacMin, uint16_t pcdacMax, uint16_t *vp)
28 {
29 	static const uint16_t intercepts3[] =
30 		{ 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
31 	static const uint16_t intercepts3_2[] =
32 		{ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
33 	const uint16_t *ip = ee->ee_version < AR_EEPROM_VER3_2 ?
34 		intercepts3 : intercepts3_2;
35 	int i;
36 
37 	/* loop for the percentages in steps or 5 */
38 	for (i = 0; i < NUM_INTERCEPTS; i++ )
39 		*vp++ = (ip[i] * pcdacMax + (100 - ip[i]) * pcdacMin) / 100;
40 }
41 
42 /*
43  * Get channel value from binary representation held in eeprom
44  */
45 static uint16_t
46 fbin2freq(HAL_EEPROM *ee, uint16_t fbin)
47 {
48 	if (fbin == CHANNEL_UNUSED)	/* reserved value, don't convert */
49 		return fbin;
50 	return ee->ee_version <= AR_EEPROM_VER3_2 ?
51 		(fbin > 62 ? 5100 + 10*62 + 5*(fbin-62) : 5100 + 10*fbin) :
52 		4800 + 5*fbin;
53 }
54 
55 static uint16_t
56 fbin2freq_2p4(HAL_EEPROM *ee, uint16_t fbin)
57 {
58 	if (fbin == CHANNEL_UNUSED)	/* reserved value, don't convert */
59 		return fbin;
60 	return ee->ee_version <= AR_EEPROM_VER3_2 ?
61 		2400 + fbin :
62 		2300 + fbin;
63 }
64 
65 /*
66  * Now copy EEPROM frequency pier contents into the allocated space
67  */
68 static HAL_BOOL
69 readEepromFreqPierInfo(struct ath_hal *ah, HAL_EEPROM *ee)
70 {
71 #define	EEREAD(_off) do {				\
72 	if (!ath_hal_eepromRead(ah, _off, &eeval))	\
73 		return AH_FALSE;			\
74 } while (0)
75 	uint16_t eeval, off;
76 	int i;
77 
78 	if (ee->ee_version >= AR_EEPROM_VER4_0 &&
79 	    ee->ee_eepMap && !ee->ee_Amode) {
80 		/*
81 		 * V4.0 EEPROMs with map type 1 have frequency pier
82 		 * data only when 11a mode is supported.
83 		 */
84 		return AH_TRUE;
85 	}
86 	if (ee->ee_version >= AR_EEPROM_VER3_3) {
87 		off = GROUPS_OFFSET3_3 + GROUP1_OFFSET;
88 		for (i = 0; i < ee->ee_numChannels11a; i += 2) {
89 			EEREAD(off++);
90 			ee->ee_channels11a[i]   = (eeval >> 8) & FREQ_MASK_3_3;
91 			ee->ee_channels11a[i+1] = eeval & FREQ_MASK_3_3;
92 		}
93 	} else {
94 		off = GROUPS_OFFSET3_2 + GROUP1_OFFSET;
95 
96 		EEREAD(off++);
97 		ee->ee_channels11a[0] = (eeval >> 9) & FREQ_MASK;
98 		ee->ee_channels11a[1] = (eeval >> 2) & FREQ_MASK;
99 		ee->ee_channels11a[2] = (eeval << 5) & FREQ_MASK;
100 
101 		EEREAD(off++);
102 		ee->ee_channels11a[2] |= (eeval >> 11) & 0x1f;
103 		ee->ee_channels11a[3]  = (eeval >>  4) & FREQ_MASK;
104 		ee->ee_channels11a[4]  = (eeval <<  3) & FREQ_MASK;
105 
106 		EEREAD(off++);
107 		ee->ee_channels11a[4] |= (eeval >> 13) & 0x7;
108 		ee->ee_channels11a[5]  = (eeval >>  6) & FREQ_MASK;
109 		ee->ee_channels11a[6]  = (eeval <<  1) & FREQ_MASK;
110 
111 		EEREAD(off++);
112 		ee->ee_channels11a[6] |= (eeval >> 15) & 0x1;
113 		ee->ee_channels11a[7]  = (eeval >>  8) & FREQ_MASK;
114 		ee->ee_channels11a[8]  = (eeval >>  1) & FREQ_MASK;
115 		ee->ee_channels11a[9]  = (eeval <<  6) & FREQ_MASK;
116 
117 		EEREAD(off++);
118 		ee->ee_channels11a[9] |= (eeval >> 10) & 0x3f;
119 	}
120 
121 	for (i = 0; i < ee->ee_numChannels11a; i++)
122 		ee->ee_channels11a[i] = fbin2freq(ee, ee->ee_channels11a[i]);
123 
124 	return AH_TRUE;
125 #undef EEREAD
126 }
127 
128 /*
129  * Rev 4 Eeprom 5112 Power Extract Functions
130  */
131 
132 /*
133  * Allocate the power information based on the number of channels
134  * recorded by the calibration.  These values are then initialized.
135  */
136 static HAL_BOOL
137 eepromAllocExpnPower5112(struct ath_hal *ah,
138 	const EEPROM_POWER_5112 *pCalDataset,
139 	EEPROM_POWER_EXPN_5112 *pPowerExpn)
140 {
141 	uint16_t numChannels = pCalDataset->numChannels;
142 	const uint16_t *pChanList = pCalDataset->pChannels;
143 	void *data;
144 	int i, j;
145 
146 	/* Allocate the channel and Power Data arrays together */
147 	data = ath_hal_malloc(
148 		roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t)) +
149 		sizeof(EXPN_DATA_PER_CHANNEL_5112) * numChannels);
150 	if (data == AH_NULL) {
151 		HALDEBUG(ah, HAL_DEBUG_ANY,
152 		    "%s unable to allocate raw data struct (gen3)\n", __func__);
153 		return AH_FALSE;
154 	}
155 	pPowerExpn->pChannels = data;
156 	pPowerExpn->pDataPerChannel = (void *)(((char *)data) +
157 		roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t)));
158 
159 	pPowerExpn->numChannels = numChannels;
160 	for (i = 0; i < numChannels; i++) {
161 		pPowerExpn->pChannels[i] =
162 			pPowerExpn->pDataPerChannel[i].channelValue =
163 				pChanList[i];
164 		for (j = 0; j < NUM_XPD_PER_CHANNEL; j++) {
165 			pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].xpd_gain = j;
166 			pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].numPcdacs = 0;
167 		}
168 		pPowerExpn->pDataPerChannel[i].pDataPerXPD[0].numPcdacs = 4;
169 		pPowerExpn->pDataPerChannel[i].pDataPerXPD[3].numPcdacs = 3;
170 	}
171 	return AH_TRUE;
172 }
173 
174 /*
175  * Expand the dataSet from the calibration information into the
176  * final power structure for 5112
177  */
178 static HAL_BOOL
179 eepromExpandPower5112(struct ath_hal *ah,
180 	const EEPROM_POWER_5112 *pCalDataset,
181 	EEPROM_POWER_EXPN_5112 *pPowerExpn)
182 {
183 	int ii, jj, kk;
184 	int16_t maxPower_t4;
185 	EXPN_DATA_PER_XPD_5112 *pExpnXPD;
186 	/* ptr to array of info held per channel */
187 	const EEPROM_DATA_PER_CHANNEL_5112 *pCalCh;
188 	uint16_t xgainList[2], xpdMask;
189 
190 	pPowerExpn->xpdMask = pCalDataset->xpdMask;
191 
192 	xgainList[0] = 0xDEAD;
193 	xgainList[1] = 0xDEAD;
194 
195 	kk = 0;
196 	xpdMask = pPowerExpn->xpdMask;
197 	for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) {
198 		if (((xpdMask >> jj) & 1) > 0) {
199 			if (kk > 1) {
200 				HALDEBUG(ah, HAL_DEBUG_ANY,
201 				    "%s: too many xpdGains in dataset: %u\n",
202 				    __func__, kk);
203 				return AH_FALSE;
204 			}
205 			xgainList[kk++] = jj;
206 		}
207 	}
208 
209 	pPowerExpn->numChannels = pCalDataset->numChannels;
210 	if (pPowerExpn->numChannels == 0) {
211 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no channels\n", __func__);
212 		return AH_FALSE;
213 	}
214 
215 	for (ii = 0; ii < pPowerExpn->numChannels; ii++) {
216 		pCalCh = &pCalDataset->pDataPerChannel[ii];
217 		pPowerExpn->pDataPerChannel[ii].channelValue =
218 			pCalCh->channelValue;
219 		pPowerExpn->pDataPerChannel[ii].maxPower_t4 =
220 			pCalCh->maxPower_t4;
221 		maxPower_t4 = pPowerExpn->pDataPerChannel[ii].maxPower_t4;
222 
223 		for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++)
224 			pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj].numPcdacs = 0;
225 		if (xgainList[1] == 0xDEAD) {
226 			jj = xgainList[0];
227 			pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj];
228 			pExpnXPD->numPcdacs = 4;
229 			pExpnXPD->pcdac[0] = pCalCh->pcd1_xg0;
230 			pExpnXPD->pcdac[1] = (uint16_t)
231 				(pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0);
232 			pExpnXPD->pcdac[2] = (uint16_t)
233 				(pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0);
234 			pExpnXPD->pcdac[3] = (uint16_t)
235 				(pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0);
236 
237 			pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0;
238 			pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0;
239 			pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0;
240 			pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0;
241 
242 		} else {
243 			pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[0]].pcdac[0] = pCalCh->pcd1_xg0;
244 			pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[0] = 20;
245 			pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[1] = 35;
246 			pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[2] = 63;
247 
248 			jj = xgainList[0];
249 			pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj];
250 			pExpnXPD->numPcdacs = 4;
251 			pExpnXPD->pcdac[1] = (uint16_t)
252 				(pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0);
253 			pExpnXPD->pcdac[2] = (uint16_t)
254 				(pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0);
255 			pExpnXPD->pcdac[3] = (uint16_t)
256 				(pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0);
257 			pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0;
258 			pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0;
259 			pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0;
260 			pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0;
261 
262 			jj = xgainList[1];
263 			pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj];
264 			pExpnXPD->numPcdacs = 3;
265 
266 			pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg3;
267 			pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg3;
268 			pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg3;
269 		}
270 	}
271 	return AH_TRUE;
272 }
273 
274 static HAL_BOOL
275 readEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee)
276 {
277 #define	EEREAD(_off) do {				\
278 	if (!ath_hal_eepromRead(ah, _off, &eeval))	\
279 		return AH_FALSE;			\
280 } while (0)
281 	const uint16_t dbmmask		 = 0xff;
282 	const uint16_t pcdac_delta_mask = 0x1f;
283 	const uint16_t pcdac_mask	 = 0x3f;
284 	const uint16_t freqmask	 = 0xff;
285 
286 	int i, mode, numPiers;
287 	uint32_t off;
288 	uint16_t eeval;
289 	uint16_t freq[NUM_11A_EEPROM_CHANNELS];
290         EEPROM_POWER_5112 eePower;
291 
292 	HALASSERT(ee->ee_version >= AR_EEPROM_VER4_0);
293 	off = GROUPS_OFFSET3_3;
294 	for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
295 		numPiers = 0;
296 		switch (mode) {
297 		case headerInfo11A:
298 			if (!ee->ee_Amode)	/* no 11a calibration data */
299 				continue;
300 			while (numPiers < NUM_11A_EEPROM_CHANNELS) {
301 				EEREAD(off++);
302 				if ((eeval & freqmask) == 0)
303 					break;
304 				freq[numPiers++] = fbin2freq(ee,
305 					eeval & freqmask);
306 
307 				if (((eeval >> 8) & freqmask) == 0)
308 					break;
309 				freq[numPiers++] = fbin2freq(ee,
310 					(eeval>>8) & freqmask);
311 			}
312 			break;
313 		case headerInfo11B:
314 			if (!ee->ee_Bmode)	/* no 11b calibration data */
315 				continue;
316 			for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++)
317 				if (ee->ee_calPier11b[i] != CHANNEL_UNUSED)
318 					freq[numPiers++] = ee->ee_calPier11b[i];
319 			break;
320 		case headerInfo11G:
321 			if (!ee->ee_Gmode)	/* no 11g calibration data */
322 				continue;
323 			for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++)
324 				if (ee->ee_calPier11g[i] != CHANNEL_UNUSED)
325 					freq[numPiers++] = ee->ee_calPier11g[i];
326 			break;
327 		default:
328 			HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
329 			    __func__, mode);
330 			return AH_FALSE;
331 		}
332 
333 		OS_MEMZERO(&eePower, sizeof(eePower));
334 		eePower.numChannels = numPiers;
335 
336 		for (i = 0; i < numPiers; i++) {
337 			eePower.pChannels[i] = freq[i];
338 			eePower.pDataPerChannel[i].channelValue = freq[i];
339 
340 			EEREAD(off++);
341 			eePower.pDataPerChannel[i].pwr1_xg0 = (int16_t)
342 				((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256);
343 			eePower.pDataPerChannel[i].pwr2_xg0 = (int16_t)
344 				(((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256);
345 
346 			EEREAD(off++);
347 			eePower.pDataPerChannel[i].pwr3_xg0 = (int16_t)
348 				((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256);
349 			eePower.pDataPerChannel[i].pwr4_xg0 = (int16_t)
350 				(((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256);
351 
352 			EEREAD(off++);
353 			eePower.pDataPerChannel[i].pcd2_delta_xg0 = (uint16_t)
354 				(eeval & pcdac_delta_mask);
355 			eePower.pDataPerChannel[i].pcd3_delta_xg0 = (uint16_t)
356 				((eeval >> 5) & pcdac_delta_mask);
357 			eePower.pDataPerChannel[i].pcd4_delta_xg0 = (uint16_t)
358 				((eeval >> 10) & pcdac_delta_mask);
359 
360 			EEREAD(off++);
361 			eePower.pDataPerChannel[i].pwr1_xg3 = (int16_t)
362 				((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256);
363 			eePower.pDataPerChannel[i].pwr2_xg3 = (int16_t)
364 				(((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256);
365 
366 			EEREAD(off++);
367 			eePower.pDataPerChannel[i].pwr3_xg3 = (int16_t)
368 				((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256);
369 			if (ee->ee_version >= AR_EEPROM_VER4_3) {
370 				eePower.pDataPerChannel[i].maxPower_t4 =
371 					eePower.pDataPerChannel[i].pwr4_xg0;
372 				eePower.pDataPerChannel[i].pcd1_xg0 = (uint16_t)
373 					((eeval >> 8) & pcdac_mask);
374 			} else {
375 				eePower.pDataPerChannel[i].maxPower_t4 = (int16_t)
376 					(((eeval >> 8) & dbmmask) -
377 					 ((eeval >> 15) & 0x1)*256);
378 				eePower.pDataPerChannel[i].pcd1_xg0 = 1;
379 			}
380 		}
381 		eePower.xpdMask = ee->ee_xgain[mode];
382 
383 		if (!eepromAllocExpnPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) {
384 			HALDEBUG(ah, HAL_DEBUG_ANY,
385 			    "%s: did not allocate power struct\n", __func__);
386 			return AH_FALSE;
387                 }
388                 if (!eepromExpandPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) {
389 			HALDEBUG(ah, HAL_DEBUG_ANY,
390 			    "%s: did not expand power struct\n", __func__);
391 			return AH_FALSE;
392 		}
393 	}
394 	return AH_TRUE;
395 #undef EEREAD
396 }
397 
398 static void
399 freeEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee)
400 {
401 	int mode;
402 	void *data;
403 
404 	for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
405 		EEPROM_POWER_EXPN_5112 *pPowerExpn =
406 			&ee->ee_modePowerArray5112[mode];
407 		data = pPowerExpn->pChannels;
408 		if (data != AH_NULL) {
409 			pPowerExpn->pChannels = AH_NULL;
410 			ath_hal_free(data);
411 		}
412 	}
413 }
414 
415 static void
416 ar2413SetupEEPROMDataset(EEPROM_DATA_STRUCT_2413 *pEEPROMDataset2413,
417 	uint16_t myNumRawChannels, uint16_t *pMyRawChanList)
418 {
419 	uint16_t i, channelValue;
420 	uint32_t xpd_mask;
421 	uint16_t numPdGainsUsed;
422 
423 	pEEPROMDataset2413->numChannels = myNumRawChannels;
424 
425 	xpd_mask = pEEPROMDataset2413->xpd_mask;
426 	numPdGainsUsed = 0;
427 	if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++;
428 	if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++;
429 	if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++;
430 	if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++;
431 
432 	for (i = 0; i < myNumRawChannels; i++) {
433 		channelValue = pMyRawChanList[i];
434 		pEEPROMDataset2413->pChannels[i] = channelValue;
435 		pEEPROMDataset2413->pDataPerChannel[i].channelValue = channelValue;
436 		pEEPROMDataset2413->pDataPerChannel[i].numPdGains = numPdGainsUsed;
437 	}
438 }
439 
440 static HAL_BOOL
441 ar2413ReadCalDataset(struct ath_hal *ah, HAL_EEPROM *ee,
442 	EEPROM_DATA_STRUCT_2413 *pCalDataset,
443 	uint32_t start_offset, uint32_t maxPiers, uint8_t mode)
444 {
445 #define	EEREAD(_off) do {				\
446 	if (!ath_hal_eepromRead(ah, _off, &eeval))	\
447 		return AH_FALSE;			\
448 } while (0)
449 	const uint16_t dbm_I_mask = 0x1F;	/* 5-bits. 1dB step. */
450 	const uint16_t dbm_delta_mask = 0xF;	/* 4-bits. 0.5dB step. */
451 	const uint16_t Vpd_I_mask = 0x7F;	/* 7-bits. 0-128 */
452 	const uint16_t Vpd_delta_mask = 0x3F;	/* 6-bits. 0-63 */
453 	const uint16_t freqmask = 0xff;
454 
455 	uint16_t ii, eeval;
456 	uint16_t idx, numPiers;
457 	uint16_t freq[NUM_11A_EEPROM_CHANNELS];
458 
459 	idx = start_offset;
460     for (numPiers = 0; numPiers < maxPiers;) {
461         EEREAD(idx++);
462         if ((eeval & freqmask) == 0)
463             break;
464         if (mode == headerInfo11A)
465             freq[numPiers++] = fbin2freq(ee, (eeval & freqmask));
466         else
467             freq[numPiers++] = fbin2freq_2p4(ee, (eeval & freqmask));
468 
469         if (((eeval >> 8) & freqmask) == 0)
470             break;
471         if (mode == headerInfo11A)
472             freq[numPiers++] = fbin2freq(ee, (eeval >> 8) & freqmask);
473         else
474             freq[numPiers++] = fbin2freq_2p4(ee, (eeval >> 8) & freqmask);
475     }
476 	ar2413SetupEEPROMDataset(pCalDataset, numPiers, &freq[0]);
477 
478 	idx = start_offset + (maxPiers / 2);
479 	for (ii = 0; ii < pCalDataset->numChannels; ii++) {
480 		EEPROM_DATA_PER_CHANNEL_2413 *currCh =
481 			&(pCalDataset->pDataPerChannel[ii]);
482 
483 		if (currCh->numPdGains > 0) {
484 			/*
485 			 * Read the first NUM_POINTS_OTHER_PDGAINS pwr
486 			 * and Vpd values for pdgain_0
487 			 */
488 			EEREAD(idx++);
489 			currCh->pwr_I[0] = eeval & dbm_I_mask;
490 			currCh->Vpd_I[0] = (eeval >> 5) & Vpd_I_mask;
491 			currCh->pwr_delta_t2[0][0] =
492 				(eeval >> 12) & dbm_delta_mask;
493 
494 			EEREAD(idx++);
495 			currCh->Vpd_delta[0][0] = eeval & Vpd_delta_mask;
496 			currCh->pwr_delta_t2[1][0] =
497 				(eeval >> 6) & dbm_delta_mask;
498 			currCh->Vpd_delta[1][0] =
499 				(eeval >> 10) & Vpd_delta_mask;
500 
501 			EEREAD(idx++);
502 			currCh->pwr_delta_t2[2][0] = eeval & dbm_delta_mask;
503 			currCh->Vpd_delta[2][0] = (eeval >> 4) & Vpd_delta_mask;
504 		}
505 
506 		if (currCh->numPdGains > 1) {
507 			/*
508 			 * Read the first NUM_POINTS_OTHER_PDGAINS pwr
509 			 * and Vpd values for pdgain_1
510 			 */
511 			currCh->pwr_I[1] = (eeval >> 10) & dbm_I_mask;
512 			currCh->Vpd_I[1] = (eeval >> 15) & 0x1;
513 
514 			EEREAD(idx++);
515 			/* upper 6 bits */
516 			currCh->Vpd_I[1] |= (eeval & 0x3F) << 1;
517 			currCh->pwr_delta_t2[0][1] =
518 				(eeval >> 6) & dbm_delta_mask;
519 			currCh->Vpd_delta[0][1] =
520 				(eeval >> 10) & Vpd_delta_mask;
521 
522 			EEREAD(idx++);
523 			currCh->pwr_delta_t2[1][1] = eeval & dbm_delta_mask;
524 			currCh->Vpd_delta[1][1] = (eeval >> 4) & Vpd_delta_mask;
525 			currCh->pwr_delta_t2[2][1] =
526 				(eeval >> 10) & dbm_delta_mask;
527 			currCh->Vpd_delta[2][1] = (eeval >> 14) & 0x3;
528 
529 			EEREAD(idx++);
530 			/* upper 4 bits */
531 			currCh->Vpd_delta[2][1] |= (eeval & 0xF) << 2;
532 		} else if (currCh->numPdGains == 1) {
533 			/*
534 			 * Read the last pwr and Vpd values for pdgain_0
535 			 */
536 			currCh->pwr_delta_t2[3][0] =
537 				(eeval >> 10) & dbm_delta_mask;
538 			currCh->Vpd_delta[3][0] = (eeval >> 14) & 0x3;
539 
540 			EEREAD(idx++);
541 			/* upper 4 bits */
542 			currCh->Vpd_delta[3][0] |= (eeval & 0xF) << 2;
543 
544 			/* 4 words if numPdGains == 1 */
545 		}
546 
547 		if (currCh->numPdGains > 2) {
548 			/*
549 			 * Read the first NUM_POINTS_OTHER_PDGAINS pwr
550 			 * and Vpd values for pdgain_2
551 			 */
552 			currCh->pwr_I[2] = (eeval >> 4) & dbm_I_mask;
553 			currCh->Vpd_I[2] = (eeval >> 9) & Vpd_I_mask;
554 
555 			EEREAD(idx++);
556 			currCh->pwr_delta_t2[0][2] =
557 				(eeval >> 0) & dbm_delta_mask;
558 			currCh->Vpd_delta[0][2] = (eeval >> 4) & Vpd_delta_mask;
559 			currCh->pwr_delta_t2[1][2] =
560 				(eeval >> 10) & dbm_delta_mask;
561 			currCh->Vpd_delta[1][2] = (eeval >> 14) & 0x3;
562 
563 			EEREAD(idx++);
564 			/* upper 4 bits */
565 			currCh->Vpd_delta[1][2] |= (eeval & 0xF) << 2;
566 			currCh->pwr_delta_t2[2][2] =
567 				(eeval >> 4) & dbm_delta_mask;
568 			currCh->Vpd_delta[2][2] = (eeval >> 8) & Vpd_delta_mask;
569 		} else if (currCh->numPdGains == 2) {
570 			/*
571 			 * Read the last pwr and Vpd values for pdgain_1
572 			 */
573 			currCh->pwr_delta_t2[3][1] =
574 				(eeval >> 4) & dbm_delta_mask;
575 			currCh->Vpd_delta[3][1] = (eeval >> 8) & Vpd_delta_mask;
576 
577 			/* 6 words if numPdGains == 2 */
578 		}
579 
580 		if (currCh->numPdGains > 3) {
581 			/*
582 			 * Read the first NUM_POINTS_OTHER_PDGAINS pwr
583 			 * and Vpd values for pdgain_3
584 			 */
585 			currCh->pwr_I[3] = (eeval >> 14) & 0x3;
586 
587 			EEREAD(idx++);
588 			/* upper 3 bits */
589 			currCh->pwr_I[3] |= ((eeval >> 0) & 0x7) << 2;
590 			currCh->Vpd_I[3] = (eeval >> 3) & Vpd_I_mask;
591 			currCh->pwr_delta_t2[0][3] =
592 				(eeval >> 10) & dbm_delta_mask;
593 			currCh->Vpd_delta[0][3] = (eeval >> 14) & 0x3;
594 
595 			EEREAD(idx++);
596 			/* upper 4 bits */
597 			currCh->Vpd_delta[0][3] |= (eeval & 0xF) << 2;
598 			currCh->pwr_delta_t2[1][3] =
599 				(eeval >> 4) & dbm_delta_mask;
600 			currCh->Vpd_delta[1][3] = (eeval >> 8) & Vpd_delta_mask;
601 			currCh->pwr_delta_t2[2][3] = (eeval >> 14) & 0x3;
602 
603 			EEREAD(idx++);
604 			/* upper 2 bits */
605 			currCh->pwr_delta_t2[2][3] |= ((eeval >> 0) & 0x3) << 2;
606 			currCh->Vpd_delta[2][3] = (eeval >> 2) & Vpd_delta_mask;
607 			currCh->pwr_delta_t2[3][3] =
608 				(eeval >> 8) & dbm_delta_mask;
609 			currCh->Vpd_delta[3][3] = (eeval >> 12) & 0xF;
610 
611 			EEREAD(idx++);
612 			/* upper 2 bits */
613 			currCh->Vpd_delta[3][3] |= ((eeval >> 0) & 0x3) << 4;
614 
615 			/* 12 words if numPdGains == 4 */
616 		} else if (currCh->numPdGains == 3) {
617 			/* read the last pwr and Vpd values for pdgain_2 */
618 			currCh->pwr_delta_t2[3][2] = (eeval >> 14) & 0x3;
619 
620 			EEREAD(idx++);
621 			/* upper 2 bits */
622 			currCh->pwr_delta_t2[3][2] |= ((eeval >> 0) & 0x3) << 2;
623 			currCh->Vpd_delta[3][2] = (eeval >> 2) & Vpd_delta_mask;
624 
625 			/* 9 words if numPdGains == 3 */
626 		}
627 	}
628 	return AH_TRUE;
629 #undef EEREAD
630 }
631 
632 static void
633 ar2413SetupRawDataset(RAW_DATA_STRUCT_2413 *pRaw, EEPROM_DATA_STRUCT_2413 *pCal)
634 {
635 	uint16_t i, j, kk, channelValue;
636 	uint16_t xpd_mask;
637 	uint16_t numPdGainsUsed;
638 
639 	pRaw->numChannels = pCal->numChannels;
640 
641 	xpd_mask = pRaw->xpd_mask;
642 	numPdGainsUsed = 0;
643 	if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++;
644 	if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++;
645 	if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++;
646 	if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++;
647 
648 	for (i = 0; i < pCal->numChannels; i++) {
649 		channelValue = pCal->pChannels[i];
650 
651 		pRaw->pChannels[i] = channelValue;
652 
653 		pRaw->pDataPerChannel[i].channelValue = channelValue;
654 		pRaw->pDataPerChannel[i].numPdGains = numPdGainsUsed;
655 
656 		kk = 0;
657 		for (j = 0; j < MAX_NUM_PDGAINS_PER_CHANNEL; j++) {
658 			pRaw->pDataPerChannel[i].pDataPerPDGain[j].pd_gain = j;
659 			if ((xpd_mask >> j) & 0x1) {
660 				pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_OTHER_PDGAINS;
661 				kk++;
662 				if (kk == 1) {
663 					/*
664 					 * lowest pd_gain corresponds
665 					 *  to highest power and thus,
666 					 *  has one more point
667 					 */
668 					pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = NUM_POINTS_LAST_PDGAIN;
669 				}
670 			} else {
671 				pRaw->pDataPerChannel[i].pDataPerPDGain[j].numVpd = 0;
672 			}
673 		}
674 	}
675 }
676 
677 static HAL_BOOL
678 ar2413EepromToRawDataset(struct ath_hal *ah,
679 	EEPROM_DATA_STRUCT_2413 *pCal, RAW_DATA_STRUCT_2413 *pRaw)
680 {
681 	uint16_t ii, jj, kk, ss;
682 	RAW_DATA_PER_PDGAIN_2413 *pRawXPD;
683 	/* ptr to array of info held per channel */
684 	EEPROM_DATA_PER_CHANNEL_2413 *pCalCh;
685 	uint16_t xgain_list[MAX_NUM_PDGAINS_PER_CHANNEL];
686 	uint16_t xpd_mask;
687 	uint32_t numPdGainsUsed;
688 
689 	HALASSERT(pRaw->xpd_mask == pCal->xpd_mask);
690 
691 	xgain_list[0] = 0xDEAD;
692 	xgain_list[1] = 0xDEAD;
693 	xgain_list[2] = 0xDEAD;
694 	xgain_list[3] = 0xDEAD;
695 
696 	numPdGainsUsed = 0;
697 	xpd_mask = pRaw->xpd_mask;
698 	for (jj = 0; jj < MAX_NUM_PDGAINS_PER_CHANNEL; jj++) {
699 		if ((xpd_mask >> (MAX_NUM_PDGAINS_PER_CHANNEL-jj-1)) & 1)
700 			xgain_list[numPdGainsUsed++] = MAX_NUM_PDGAINS_PER_CHANNEL-jj-1;
701 	}
702 
703 	pRaw->numChannels = pCal->numChannels;
704 	for (ii = 0; ii < pRaw->numChannels; ii++) {
705 		pCalCh = &(pCal->pDataPerChannel[ii]);
706 		pRaw->pDataPerChannel[ii].channelValue = pCalCh->channelValue;
707 
708 		/* numVpd has already been setup appropriately for the relevant pdGains */
709 		for (jj = 0; jj < numPdGainsUsed; jj++) {
710 			/* use jj for calDataset and ss for rawDataset */
711 			ss = xgain_list[jj];
712 			pRawXPD = &(pRaw->pDataPerChannel[ii].pDataPerPDGain[ss]);
713 			HALASSERT(pRawXPD->numVpd >= 1);
714 
715 			pRawXPD->pwr_t4[0] = (uint16_t)(4*pCalCh->pwr_I[jj]);
716 			pRawXPD->Vpd[0]    = pCalCh->Vpd_I[jj];
717 
718 			for (kk = 1; kk < pRawXPD->numVpd; kk++) {
719 				pRawXPD->pwr_t4[kk] = (int16_t)(pRawXPD->pwr_t4[kk-1] + 2*pCalCh->pwr_delta_t2[kk-1][jj]);
720 				pRawXPD->Vpd[kk] = (uint16_t)(pRawXPD->Vpd[kk-1] + pCalCh->Vpd_delta[kk-1][jj]);
721 			}
722 			/* loop over Vpds */
723 		}
724 		/* loop over pd_gains */
725 	}
726 	/* loop over channels */
727 	return AH_TRUE;
728 }
729 
730 static HAL_BOOL
731 readEepromRawPowerCalInfo2413(struct ath_hal *ah, HAL_EEPROM *ee)
732 {
733 	/* NB: index is 1 less than numPdgains */
734 	static const uint16_t wordsForPdgains[] = { 4, 6, 9, 12 };
735 	EEPROM_DATA_STRUCT_2413 *pCal = AH_NULL;
736 	RAW_DATA_STRUCT_2413 *pRaw;
737 	int numEEPROMWordsPerChannel;
738 	uint32_t off;
739 	HAL_BOOL ret = AH_FALSE;
740 
741 	HALASSERT(ee->ee_version >= AR_EEPROM_VER5_0);
742 	HALASSERT(ee->ee_eepMap == 2);
743 
744 	pCal = ath_hal_malloc(sizeof(EEPROM_DATA_STRUCT_2413));
745 	if (pCal == AH_NULL)
746 		goto exit;
747 
748 	off = ee->ee_eepMap2PowerCalStart;
749 	if (ee->ee_Amode) {
750 		OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413));
751 		pCal->xpd_mask = ee->ee_xgain[headerInfo11A];
752 		if (!ar2413ReadCalDataset(ah, ee, pCal, off,
753 			NUM_11A_EEPROM_CHANNELS_2413, headerInfo11A)) {
754 			goto exit;
755 		}
756 		pRaw = &ee->ee_rawDataset2413[headerInfo11A];
757 		pRaw->xpd_mask = ee->ee_xgain[headerInfo11A];
758 		ar2413SetupRawDataset(pRaw, pCal);
759 		if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) {
760 			goto exit;
761 		}
762 		/* setup offsets for mode_11a next */
763 		numEEPROMWordsPerChannel = wordsForPdgains[
764 			pCal->pDataPerChannel[0].numPdGains - 1];
765 		off += pCal->numChannels * numEEPROMWordsPerChannel + 5;
766 	}
767 	if (ee->ee_Bmode) {
768 		OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413));
769 		pCal->xpd_mask = ee->ee_xgain[headerInfo11B];
770 		if (!ar2413ReadCalDataset(ah, ee, pCal, off,
771 			NUM_2_4_EEPROM_CHANNELS_2413 , headerInfo11B)) {
772 			goto exit;
773 		}
774 		pRaw = &ee->ee_rawDataset2413[headerInfo11B];
775 		pRaw->xpd_mask = ee->ee_xgain[headerInfo11B];
776 		ar2413SetupRawDataset(pRaw, pCal);
777 		if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) {
778 			goto exit;
779 		}
780 		/* setup offsets for mode_11g next */
781 		numEEPROMWordsPerChannel = wordsForPdgains[
782 			pCal->pDataPerChannel[0].numPdGains - 1];
783 		off += pCal->numChannels * numEEPROMWordsPerChannel + 2;
784 	}
785 	if (ee->ee_Gmode) {
786 		OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413));
787 		pCal->xpd_mask = ee->ee_xgain[headerInfo11G];
788 		if (!ar2413ReadCalDataset(ah, ee, pCal, off,
789 			NUM_2_4_EEPROM_CHANNELS_2413, headerInfo11G)) {
790 			goto exit;
791 		}
792 		pRaw = &ee->ee_rawDataset2413[headerInfo11G];
793 		pRaw->xpd_mask = ee->ee_xgain[headerInfo11G];
794 		ar2413SetupRawDataset(pRaw, pCal);
795 		if (!ar2413EepromToRawDataset(ah, pCal, pRaw)) {
796 			goto exit;
797 		}
798 	}
799 	ret = AH_TRUE;
800  exit:
801 	if (pCal != AH_NULL)
802 		ath_hal_free(pCal);
803 	return ret;
804 }
805 
806 /*
807  * Now copy EEPROM Raw Power Calibration per frequency contents
808  * into the allocated space
809  */
810 static HAL_BOOL
811 readEepromRawPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee)
812 {
813 #define	EEREAD(_off) do {				\
814 	if (!ath_hal_eepromRead(ah, _off, &eeval))	\
815 		return AH_FALSE;			\
816 } while (0)
817 	uint16_t eeval, nchan;
818 	uint32_t off;
819 	int i, j, mode;
820 
821         if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1)
822 		return readEepromRawPowerCalInfo5112(ah, ee);
823 	if (ee->ee_version >= AR_EEPROM_VER5_0 && ee->ee_eepMap == 2)
824 		return readEepromRawPowerCalInfo2413(ah, ee);
825 
826 	/*
827 	 * Group 2:  read raw power data for all frequency piers
828 	 *
829 	 * NOTE: Group 2 contains the raw power calibration
830 	 *	 information for each of the channels that
831 	 *	 we recorded above.
832 	 */
833 	for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
834 		uint16_t *pChannels = AH_NULL;
835 		DATA_PER_CHANNEL *pChannelData = AH_NULL;
836 
837 		off = ee->ee_version >= AR_EEPROM_VER3_3 ?
838 			GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2;
839 		switch (mode) {
840 		case headerInfo11A:
841 			off      	+= GROUP2_OFFSET;
842 			nchan		= ee->ee_numChannels11a;
843 			pChannelData	= ee->ee_dataPerChannel11a;
844 			pChannels	= ee->ee_channels11a;
845 			break;
846 		case headerInfo11B:
847 			if (!ee->ee_Bmode)
848 				continue;
849 			off		+= GROUP3_OFFSET;
850 			nchan		= ee->ee_numChannels2_4;
851 			pChannelData	= ee->ee_dataPerChannel11b;
852 			pChannels	= ee->ee_channels11b;
853 			break;
854 		case headerInfo11G:
855 			if (!ee->ee_Gmode)
856 				continue;
857 			off		+= GROUP4_OFFSET;
858 			nchan		= ee->ee_numChannels2_4;
859 			pChannelData	= ee->ee_dataPerChannel11g;
860 			pChannels	= ee->ee_channels11g;
861 			break;
862 		default:
863 			HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
864 			    __func__, mode);
865 			return AH_FALSE;
866 		}
867 		for (i = 0; i < nchan; i++) {
868 			pChannelData->channelValue = pChannels[i];
869 
870 			EEREAD(off++);
871 			pChannelData->pcdacMax     = (uint16_t)((eeval >> 10) & PCDAC_MASK);
872 			pChannelData->pcdacMin     = (uint16_t)((eeval >> 4) & PCDAC_MASK);
873 			pChannelData->PwrValues[0] = (uint16_t)((eeval << 2) & POWER_MASK);
874 
875 			EEREAD(off++);
876 			pChannelData->PwrValues[0] |= (uint16_t)((eeval >> 14) & 0x3);
877 			pChannelData->PwrValues[1] = (uint16_t)((eeval >> 8) & POWER_MASK);
878 			pChannelData->PwrValues[2] = (uint16_t)((eeval >> 2) & POWER_MASK);
879 			pChannelData->PwrValues[3] = (uint16_t)((eeval << 4) & POWER_MASK);
880 
881 			EEREAD(off++);
882 			pChannelData->PwrValues[3] |= (uint16_t)((eeval >> 12) & 0xf);
883 			pChannelData->PwrValues[4] = (uint16_t)((eeval >> 6) & POWER_MASK);
884 			pChannelData->PwrValues[5] = (uint16_t)(eeval  & POWER_MASK);
885 
886 			EEREAD(off++);
887 			pChannelData->PwrValues[6] = (uint16_t)((eeval >> 10) & POWER_MASK);
888 			pChannelData->PwrValues[7] = (uint16_t)((eeval >> 4) & POWER_MASK);
889 			pChannelData->PwrValues[8] = (uint16_t)((eeval << 2) & POWER_MASK);
890 
891 			EEREAD(off++);
892 			pChannelData->PwrValues[8] |= (uint16_t)((eeval >> 14) & 0x3);
893 			pChannelData->PwrValues[9] = (uint16_t)((eeval >> 8) & POWER_MASK);
894 			pChannelData->PwrValues[10] = (uint16_t)((eeval >> 2) & POWER_MASK);
895 
896 			getPcdacInterceptsFromPcdacMinMax(ee,
897 				pChannelData->pcdacMin, pChannelData->pcdacMax,
898 				pChannelData->PcdacValues) ;
899 
900 			for (j = 0; j < pChannelData->numPcdacValues; j++) {
901 				pChannelData->PwrValues[j] = (uint16_t)(
902 					PWR_STEP * pChannelData->PwrValues[j]);
903 				/* Note these values are scaled up. */
904 			}
905 			pChannelData++;
906 		}
907 	}
908 	return AH_TRUE;
909 #undef EEREAD
910 }
911 
912 /*
913  * Copy EEPROM Target Power Calbration per rate contents
914  * into the allocated space
915  */
916 static HAL_BOOL
917 readEepromTargetPowerCalInfo(struct ath_hal *ah, HAL_EEPROM *ee)
918 {
919 #define	EEREAD(_off) do {				\
920 	if (!ath_hal_eepromRead(ah, _off, &eeval))	\
921 		return AH_FALSE;			\
922 } while (0)
923 	uint16_t eeval, enable24;
924 	uint32_t off;
925 	int i, mode, nchan;
926 
927 	enable24 = ee->ee_Bmode || ee->ee_Gmode;
928 	for (mode = headerInfo11A; mode <= headerInfo11G; mode++) {
929 		TRGT_POWER_INFO *pPowerInfo;
930 		uint16_t *pNumTrgtChannels;
931 
932 		off = ee->ee_version >= AR_EEPROM_VER4_0 ?
933 				ee->ee_targetPowersStart - GROUP5_OFFSET :
934 		      ee->ee_version >= AR_EEPROM_VER3_3 ?
935 				GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2;
936 		switch (mode) {
937 		case headerInfo11A:
938 			off += GROUP5_OFFSET;
939 			nchan = NUM_TEST_FREQUENCIES;
940 			pPowerInfo = ee->ee_trgtPwr_11a;
941 			pNumTrgtChannels = &ee->ee_numTargetPwr_11a;
942 			break;
943 		case headerInfo11B:
944 			if (!enable24)
945 				continue;
946 			off += GROUP6_OFFSET;
947 			nchan = 2;
948 			pPowerInfo = ee->ee_trgtPwr_11b;
949 			pNumTrgtChannels = &ee->ee_numTargetPwr_11b;
950 			break;
951 		case headerInfo11G:
952 			if (!enable24)
953 				continue;
954 			off += GROUP7_OFFSET;
955 			nchan = 3;
956 			pPowerInfo = ee->ee_trgtPwr_11g;
957 			pNumTrgtChannels = &ee->ee_numTargetPwr_11g;
958 			break;
959 		default:
960 			HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n",
961 			    __func__, mode);
962 			return AH_FALSE;
963 		}
964 		*pNumTrgtChannels = 0;
965 		for (i = 0; i < nchan; i++) {
966 			EEREAD(off++);
967 			if (ee->ee_version >= AR_EEPROM_VER3_3) {
968 				pPowerInfo->testChannel = (eeval >> 8) & 0xff;
969 			} else {
970 				pPowerInfo->testChannel = (eeval >> 9) & 0x7f;
971 			}
972 
973 			if (pPowerInfo->testChannel != 0) {
974 				/* get the channel value and read rest of info */
975 				if (mode == headerInfo11A) {
976 					pPowerInfo->testChannel = fbin2freq(ee, pPowerInfo->testChannel);
977 				} else {
978 					pPowerInfo->testChannel = fbin2freq_2p4(ee, pPowerInfo->testChannel);
979 				}
980 
981 				if (ee->ee_version >= AR_EEPROM_VER3_3) {
982 					pPowerInfo->twicePwr6_24 = (eeval >> 2) & POWER_MASK;
983 					pPowerInfo->twicePwr36   = (eeval << 4) & POWER_MASK;
984 				} else {
985 					pPowerInfo->twicePwr6_24 = (eeval >> 3) & POWER_MASK;
986 					pPowerInfo->twicePwr36   = (eeval << 3) & POWER_MASK;
987 				}
988 
989 				EEREAD(off++);
990 				if (ee->ee_version >= AR_EEPROM_VER3_3) {
991 					pPowerInfo->twicePwr36 |= (eeval >> 12) & 0xf;
992 					pPowerInfo->twicePwr48 = (eeval >> 6) & POWER_MASK;
993 					pPowerInfo->twicePwr54 =  eeval & POWER_MASK;
994 				} else {
995 					pPowerInfo->twicePwr36 |= (eeval >> 13) & 0x7;
996 					pPowerInfo->twicePwr48 = (eeval >> 7) & POWER_MASK;
997 					pPowerInfo->twicePwr54 = (eeval >> 1) & POWER_MASK;
998 				}
999 				(*pNumTrgtChannels)++;
1000 			}
1001 			pPowerInfo++;
1002 		}
1003 	}
1004 	return AH_TRUE;
1005 #undef EEREAD
1006 }
1007 
1008 /*
1009  * Now copy EEPROM Coformance Testing Limits contents
1010  * into the allocated space
1011  */
1012 static HAL_BOOL
1013 readEepromCTLInfo(struct ath_hal *ah, HAL_EEPROM *ee)
1014 {
1015 #define	EEREAD(_off) do {				\
1016 	if (!ath_hal_eepromRead(ah, _off, &eeval))	\
1017 		return AH_FALSE;			\
1018 } while (0)
1019 	RD_EDGES_POWER *rep;
1020 	uint16_t eeval;
1021 	uint32_t off;
1022 	int i, j;
1023 
1024 	rep = ee->ee_rdEdgesPower;
1025 
1026 	off = GROUP8_OFFSET +
1027 		(ee->ee_version >= AR_EEPROM_VER4_0 ?
1028 			ee->ee_targetPowersStart - GROUP5_OFFSET :
1029 	         ee->ee_version >= AR_EEPROM_VER3_3 ?
1030 			GROUPS_OFFSET3_3 : GROUPS_OFFSET3_2);
1031 	for (i = 0; i < ee->ee_numCtls; i++) {
1032 		if (ee->ee_ctl[i] == 0) {
1033 			/* Move offset and edges */
1034 			off += (ee->ee_version >= AR_EEPROM_VER3_3 ? 8 : 7);
1035 			rep += NUM_EDGES;
1036 			continue;
1037 		}
1038 		if (ee->ee_version >= AR_EEPROM_VER3_3) {
1039 			for (j = 0; j < NUM_EDGES; j += 2) {
1040 				EEREAD(off++);
1041 				rep[j].rdEdge = (eeval >> 8) & FREQ_MASK_3_3;
1042 				rep[j+1].rdEdge = eeval & FREQ_MASK_3_3;
1043 			}
1044 			for (j = 0; j < NUM_EDGES; j += 2) {
1045 				EEREAD(off++);
1046 				rep[j].twice_rdEdgePower =
1047 					(eeval >> 8) & POWER_MASK;
1048 				rep[j].flag = (eeval >> 14) & 1;
1049 				rep[j+1].twice_rdEdgePower = eeval & POWER_MASK;
1050 				rep[j+1].flag = (eeval >> 6) & 1;
1051 			}
1052 		} else {
1053 			EEREAD(off++);
1054 			rep[0].rdEdge = (eeval >> 9) & FREQ_MASK;
1055 			rep[1].rdEdge = (eeval >> 2) & FREQ_MASK;
1056 			rep[2].rdEdge = (eeval << 5) & FREQ_MASK;
1057 
1058 			EEREAD(off++);
1059 			rep[2].rdEdge |= (eeval >> 11) & 0x1f;
1060 			rep[3].rdEdge = (eeval >> 4) & FREQ_MASK;
1061 			rep[4].rdEdge = (eeval << 3) & FREQ_MASK;
1062 
1063 			EEREAD(off++);
1064 			rep[4].rdEdge |= (eeval >> 13) & 0x7;
1065 			rep[5].rdEdge = (eeval >> 6) & FREQ_MASK;
1066 			rep[6].rdEdge = (eeval << 1) & FREQ_MASK;
1067 
1068 			EEREAD(off++);
1069 			rep[6].rdEdge |= (eeval >> 15) & 0x1;
1070 			rep[7].rdEdge = (eeval >> 8) & FREQ_MASK;
1071 
1072 			rep[0].twice_rdEdgePower = (eeval >> 2) & POWER_MASK;
1073 			rep[1].twice_rdEdgePower = (eeval << 4) & POWER_MASK;
1074 
1075 			EEREAD(off++);
1076 			rep[1].twice_rdEdgePower |= (eeval >> 12) & 0xf;
1077 			rep[2].twice_rdEdgePower = (eeval >> 6) & POWER_MASK;
1078 			rep[3].twice_rdEdgePower = eeval & POWER_MASK;
1079 
1080 			EEREAD(off++);
1081 			rep[4].twice_rdEdgePower = (eeval >> 10) & POWER_MASK;
1082 			rep[5].twice_rdEdgePower = (eeval >> 4) & POWER_MASK;
1083 			rep[6].twice_rdEdgePower = (eeval << 2) & POWER_MASK;
1084 
1085 			EEREAD(off++);
1086 			rep[6].twice_rdEdgePower |= (eeval >> 14) & 0x3;
1087 			rep[7].twice_rdEdgePower = (eeval >> 8) & POWER_MASK;
1088 		}
1089 
1090 		for (j = 0; j < NUM_EDGES; j++ ) {
1091 			if (rep[j].rdEdge != 0 || rep[j].twice_rdEdgePower != 0) {
1092 				if ((ee->ee_ctl[i] & CTL_MODE_M) == CTL_11A ||
1093 				    (ee->ee_ctl[i] & CTL_MODE_M) == CTL_TURBO) {
1094 					rep[j].rdEdge = fbin2freq(ee, rep[j].rdEdge);
1095 				} else {
1096 					rep[j].rdEdge = fbin2freq_2p4(ee, rep[j].rdEdge);
1097 				}
1098 			}
1099 		}
1100 		rep += NUM_EDGES;
1101 	}
1102 	return AH_TRUE;
1103 #undef EEREAD
1104 }
1105 
1106 /*
1107  * Read the individual header fields for a Rev 3 EEPROM
1108  */
1109 static HAL_BOOL
1110 readHeaderInfo(struct ath_hal *ah, HAL_EEPROM *ee)
1111 {
1112 #define	EEREAD(_off) do {				\
1113 	if (!ath_hal_eepromRead(ah, _off, &eeval))	\
1114 		return AH_FALSE;			\
1115 } while (0)
1116 	static const uint32_t headerOffset3_0[] = {
1117 		0x00C2, /* 0 - Mode bits, device type, max turbo power */
1118 		0x00C4, /* 1 - 2.4 and 5 antenna gain */
1119 		0x00C5, /* 2 - Begin 11A modal section */
1120 		0x00D0, /* 3 - Begin 11B modal section */
1121 		0x00DA, /* 4 - Begin 11G modal section */
1122 		0x00E4  /* 5 - Begin CTL section */
1123 	};
1124 	static const uint32_t headerOffset3_3[] = {
1125 		0x00C2, /* 0 - Mode bits, device type, max turbo power */
1126 		0x00C3, /* 1 - 2.4 and 5 antenna gain */
1127 		0x00D4, /* 2 - Begin 11A modal section */
1128 		0x00F2, /* 3 - Begin 11B modal section */
1129 		0x010D, /* 4 - Begin 11G modal section */
1130 		0x0128  /* 5 - Begin CTL section */
1131 	};
1132 
1133 	static const uint32_t regCapOffsetPre4_0 = 0x00CF;
1134 	static const uint32_t regCapOffsetPost4_0 = 0x00CA;
1135 
1136 	const uint32_t *header;
1137 	uint32_t off;
1138 	uint16_t eeval;
1139 	int i;
1140 
1141 	/* initialize cckOfdmGainDelta for < 4.2 eeprom */
1142 	ee->ee_cckOfdmGainDelta = CCK_OFDM_GAIN_DELTA;
1143 	ee->ee_scaledCh14FilterCckDelta = TENX_CH14_FILTER_CCK_DELTA_INIT;
1144 
1145 	if (ee->ee_version >= AR_EEPROM_VER3_3) {
1146 		header = headerOffset3_3;
1147 		ee->ee_numCtls = NUM_CTLS_3_3;
1148 	} else {
1149 		header = headerOffset3_0;
1150 		ee->ee_numCtls = NUM_CTLS;
1151 	}
1152 	HALASSERT(ee->ee_numCtls <= NUM_CTLS_MAX);
1153 
1154 	EEREAD(header[0]);
1155 	ee->ee_turbo5Disable	= (eeval >> 15) & 0x01;
1156 	ee->ee_rfKill		= (eeval >> 14) & 0x01;
1157 	ee->ee_deviceType	= (eeval >> 11) & 0x07;
1158 	ee->ee_turbo2WMaxPower5	= (eeval >> 4) & 0x7F;
1159 	if (ee->ee_version >= AR_EEPROM_VER4_0)
1160 		ee->ee_turbo2Disable	= (eeval >> 3) & 0x01;
1161 	else
1162 		ee->ee_turbo2Disable	= 1;
1163 	ee->ee_Gmode		= (eeval >> 2) & 0x01;
1164 	ee->ee_Bmode		= (eeval >> 1) & 0x01;
1165 	ee->ee_Amode		= (eeval & 0x01);
1166 
1167 	off = header[1];
1168 	EEREAD(off++);
1169 	ee->ee_antennaGainMax[0] = (int8_t)((eeval >> 8) & 0xFF);
1170 	ee->ee_antennaGainMax[1] = (int8_t)(eeval & 0xFF);
1171 	if (ee->ee_version >= AR_EEPROM_VER4_0) {
1172 		EEREAD(off++);
1173 		ee->ee_eepMap		 = (eeval>>14) & 0x3;
1174 		ee->ee_disableXr5	 = (eeval>>13) & 0x1;
1175 		ee->ee_disableXr2	 = (eeval>>12) & 0x1;
1176 		ee->ee_earStart		 = eeval & 0xfff;
1177 
1178 		EEREAD(off++);
1179 		ee->ee_targetPowersStart = eeval & 0xfff;
1180 		ee->ee_exist32kHzCrystal = (eeval>>14) & 0x1;
1181 
1182 		if (ee->ee_version >= AR_EEPROM_VER5_0) {
1183 			off += 2;
1184 			EEREAD(off);
1185 			ee->ee_eepMap2PowerCalStart = (eeval >> 4) & 0xfff;
1186 			/* Properly cal'ed 5.0 devices should be non-zero */
1187 		}
1188 	}
1189 
1190 	/* Read the moded sections of the EEPROM header in the order A, B, G */
1191 	for (i = headerInfo11A; i <= headerInfo11G; i++) {
1192 		/* Set the offset via the index */
1193 		off = header[2 + i];
1194 
1195 		EEREAD(off++);
1196 		ee->ee_switchSettling[i] = (eeval >> 8) & 0x7f;
1197 		ee->ee_txrxAtten[i] = (eeval >> 2) & 0x3f;
1198 		ee->ee_antennaControl[0][i] = (eeval << 4) & 0x3f;
1199 
1200 		EEREAD(off++);
1201 		ee->ee_antennaControl[0][i] |= (eeval >> 12) & 0x0f;
1202 		ee->ee_antennaControl[1][i] = (eeval >> 6) & 0x3f;
1203 		ee->ee_antennaControl[2][i] = eeval & 0x3f;
1204 
1205 		EEREAD(off++);
1206 		ee->ee_antennaControl[3][i] = (eeval >> 10)  & 0x3f;
1207 		ee->ee_antennaControl[4][i] = (eeval >> 4)  & 0x3f;
1208 		ee->ee_antennaControl[5][i] = (eeval << 2)  & 0x3f;
1209 
1210 		EEREAD(off++);
1211 		ee->ee_antennaControl[5][i] |= (eeval >> 14)  & 0x03;
1212 		ee->ee_antennaControl[6][i] = (eeval >> 8)  & 0x3f;
1213 		ee->ee_antennaControl[7][i] = (eeval >> 2)  & 0x3f;
1214 		ee->ee_antennaControl[8][i] = (eeval << 4)  & 0x3f;
1215 
1216 		EEREAD(off++);
1217 		ee->ee_antennaControl[8][i] |= (eeval >> 12)  & 0x0f;
1218 		ee->ee_antennaControl[9][i] = (eeval >> 6)  & 0x3f;
1219 		ee->ee_antennaControl[10][i] = eeval & 0x3f;
1220 
1221 		EEREAD(off++);
1222 		ee->ee_adcDesiredSize[i] = (int8_t)((eeval >> 8)  & 0xff);
1223 		switch (i) {
1224 		case headerInfo11A:
1225 			ee->ee_ob4 = (eeval >> 5)  & 0x07;
1226 			ee->ee_db4 = (eeval >> 2)  & 0x07;
1227 			ee->ee_ob3 = (eeval << 1)  & 0x07;
1228 			break;
1229 		case headerInfo11B:
1230 			ee->ee_obFor24 = (eeval >> 4)  & 0x07;
1231 			ee->ee_dbFor24 = eeval & 0x07;
1232 			break;
1233 		case headerInfo11G:
1234 			ee->ee_obFor24g = (eeval >> 4)  & 0x07;
1235 			ee->ee_dbFor24g = eeval & 0x07;
1236 			break;
1237 		}
1238 
1239 		if (i == headerInfo11A) {
1240 			EEREAD(off++);
1241 			ee->ee_ob3 |= (eeval >> 15)  & 0x01;
1242 			ee->ee_db3 = (eeval >> 12)  & 0x07;
1243 			ee->ee_ob2 = (eeval >> 9)  & 0x07;
1244 			ee->ee_db2 = (eeval >> 6)  & 0x07;
1245 			ee->ee_ob1 = (eeval >> 3)  & 0x07;
1246 			ee->ee_db1 = eeval & 0x07;
1247 		}
1248 
1249 		EEREAD(off++);
1250 		ee->ee_txEndToXLNAOn[i] = (eeval >> 8)  & 0xff;
1251 		ee->ee_thresh62[i] = eeval & 0xff;
1252 
1253 		EEREAD(off++);
1254 		ee->ee_txEndToXPAOff[i] = (eeval >> 8)  & 0xff;
1255 		ee->ee_txFrameToXPAOn[i] = eeval  & 0xff;
1256 
1257 		EEREAD(off++);
1258 		ee->ee_pgaDesiredSize[i] = (int8_t)((eeval >> 8)  & 0xff);
1259 		ee->ee_noiseFloorThresh[i] = eeval  & 0xff;
1260 		if (ee->ee_noiseFloorThresh[i] & 0x80) {
1261 			ee->ee_noiseFloorThresh[i] = 0 -
1262 				((ee->ee_noiseFloorThresh[i] ^ 0xff) + 1);
1263 		}
1264 
1265 		EEREAD(off++);
1266 		ee->ee_xlnaGain[i] = (eeval >> 5)  & 0xff;
1267 		ee->ee_xgain[i] = (eeval >> 1)  & 0x0f;
1268 		ee->ee_xpd[i] = eeval  & 0x01;
1269 		if (ee->ee_version >= AR_EEPROM_VER4_0) {
1270 			switch (i) {
1271 			case headerInfo11A:
1272 				ee->ee_fixedBias5 = (eeval >> 13) & 0x1;
1273 				break;
1274 			case headerInfo11G:
1275 				ee->ee_fixedBias2 = (eeval >> 13) & 0x1;
1276 				break;
1277 			}
1278 		}
1279 
1280 		if (ee->ee_version >= AR_EEPROM_VER3_3) {
1281 			EEREAD(off++);
1282 			ee->ee_falseDetectBackoff[i] = (eeval >> 6) & 0x7F;
1283 			switch (i) {
1284 			case headerInfo11B:
1285 				ee->ee_ob2GHz[0] = eeval & 0x7;
1286 				ee->ee_db2GHz[0] = (eeval >> 3) & 0x7;
1287 				break;
1288 			case headerInfo11G:
1289 				ee->ee_ob2GHz[1] = eeval & 0x7;
1290 				ee->ee_db2GHz[1] = (eeval >> 3) & 0x7;
1291 				break;
1292 			case headerInfo11A:
1293 				ee->ee_xrTargetPower5 = eeval & 0x3f;
1294 				break;
1295 			}
1296 		}
1297 		if (ee->ee_version >= AR_EEPROM_VER3_4) {
1298 			ee->ee_gainI[i] = (eeval >> 13) & 0x07;
1299 
1300 			EEREAD(off++);
1301 			ee->ee_gainI[i] |= (eeval << 3) & 0x38;
1302 			if (i == headerInfo11G) {
1303 				ee->ee_cckOfdmPwrDelta = (eeval >> 3) & 0xFF;
1304 				if (ee->ee_version >= AR_EEPROM_VER4_6)
1305 					ee->ee_scaledCh14FilterCckDelta =
1306 						(eeval >> 11) & 0x1f;
1307 			}
1308 			if (i == headerInfo11A &&
1309 			    ee->ee_version >= AR_EEPROM_VER4_0) {
1310 				ee->ee_iqCalI[0] = (eeval >> 8 ) & 0x3f;
1311 				ee->ee_iqCalQ[0] = (eeval >> 3 ) & 0x1f;
1312 			}
1313 		} else {
1314 			ee->ee_gainI[i] = 10;
1315 			ee->ee_cckOfdmPwrDelta = TENX_OFDM_CCK_DELTA_INIT;
1316 		}
1317 		if (ee->ee_version >= AR_EEPROM_VER4_0) {
1318 			switch (i) {
1319 			case headerInfo11B:
1320 				EEREAD(off++);
1321 				ee->ee_calPier11b[0] =
1322 					fbin2freq_2p4(ee, eeval&0xff);
1323 				ee->ee_calPier11b[1] =
1324 					fbin2freq_2p4(ee, (eeval >> 8)&0xff);
1325 				EEREAD(off++);
1326 				ee->ee_calPier11b[2] =
1327 					fbin2freq_2p4(ee, eeval&0xff);
1328 				if (ee->ee_version >= AR_EEPROM_VER4_1)
1329 					ee->ee_rxtxMargin[headerInfo11B] =
1330 						(eeval >> 8) & 0x3f;
1331 				break;
1332 			case headerInfo11G:
1333 				EEREAD(off++);
1334 				ee->ee_calPier11g[0] =
1335 					fbin2freq_2p4(ee, eeval & 0xff);
1336 				ee->ee_calPier11g[1] =
1337 					fbin2freq_2p4(ee, (eeval >> 8) & 0xff);
1338 
1339 				EEREAD(off++);
1340 				ee->ee_turbo2WMaxPower2 = eeval & 0x7F;
1341 				ee->ee_xrTargetPower2 = (eeval >> 7) & 0x3f;
1342 
1343 				EEREAD(off++);
1344 				ee->ee_calPier11g[2] =
1345 					fbin2freq_2p4(ee, eeval & 0xff);
1346 				if (ee->ee_version >= AR_EEPROM_VER4_1)
1347 					 ee->ee_rxtxMargin[headerInfo11G] =
1348 						(eeval >> 8) & 0x3f;
1349 
1350 				EEREAD(off++);
1351 				ee->ee_iqCalI[1] = (eeval >> 5) & 0x3F;
1352 				ee->ee_iqCalQ[1] = eeval & 0x1F;
1353 
1354 				if (ee->ee_version >= AR_EEPROM_VER4_2) {
1355 					EEREAD(off++);
1356 					ee->ee_cckOfdmGainDelta =
1357 						(uint8_t)(eeval & 0xFF);
1358 					if (ee->ee_version >= AR_EEPROM_VER5_0) {
1359 						ee->ee_switchSettlingTurbo[1] =
1360 							(eeval >> 8) & 0x7f;
1361 						ee->ee_txrxAttenTurbo[1] =
1362 							(eeval >> 15) & 0x1;
1363 						EEREAD(off++);
1364 						ee->ee_txrxAttenTurbo[1] |=
1365 							(eeval & 0x1F) << 1;
1366 						ee->ee_rxtxMarginTurbo[1] =
1367 							(eeval >> 5) & 0x3F;
1368 						ee->ee_adcDesiredSizeTurbo[1] =
1369 							(eeval >> 11) & 0x1F;
1370 						EEREAD(off++);
1371 						ee->ee_adcDesiredSizeTurbo[1] |=
1372 							(eeval & 0x7) << 5;
1373 						ee->ee_pgaDesiredSizeTurbo[1] =
1374 							(eeval >> 3) & 0xFF;
1375 					}
1376 				}
1377 				break;
1378 			case headerInfo11A:
1379 				if (ee->ee_version >= AR_EEPROM_VER4_1) {
1380 					EEREAD(off++);
1381 					ee->ee_rxtxMargin[headerInfo11A] =
1382 						eeval & 0x3f;
1383 					if (ee->ee_version >= AR_EEPROM_VER5_0) {
1384 						ee->ee_switchSettlingTurbo[0] =
1385 							(eeval >> 6) & 0x7f;
1386 						ee->ee_txrxAttenTurbo[0] =
1387 							(eeval >> 13) & 0x7;
1388 						EEREAD(off++);
1389 						ee->ee_txrxAttenTurbo[0] |=
1390 							(eeval & 0x7) << 3;
1391 						ee->ee_rxtxMarginTurbo[0] =
1392 							(eeval >> 3) & 0x3F;
1393 						ee->ee_adcDesiredSizeTurbo[0] =
1394 							(eeval >> 9) & 0x7F;
1395 						EEREAD(off++);
1396 						ee->ee_adcDesiredSizeTurbo[0] |=
1397 							(eeval & 0x1) << 7;
1398 						ee->ee_pgaDesiredSizeTurbo[0] =
1399 							(eeval >> 1) & 0xFF;
1400 					}
1401 				}
1402 				break;
1403 			}
1404 		}
1405 	}
1406 	if (ee->ee_version < AR_EEPROM_VER3_3) {
1407 		/* Version 3.1+ specific parameters */
1408 		EEREAD(0xec);
1409 		ee->ee_ob2GHz[0] = eeval & 0x7;
1410 		ee->ee_db2GHz[0] = (eeval >> 3) & 0x7;
1411 
1412 		EEREAD(0xed);
1413 		ee->ee_ob2GHz[1] = eeval & 0x7;
1414 		ee->ee_db2GHz[1] = (eeval >> 3) & 0x7;
1415 	}
1416 
1417 	/* Initialize corner cal (thermal tx gain adjust parameters) */
1418 	ee->ee_cornerCal.clip = 4;
1419 	ee->ee_cornerCal.pd90 = 1;
1420 	ee->ee_cornerCal.pd84 = 1;
1421 	ee->ee_cornerCal.gSel = 0;
1422 
1423 	/*
1424 	* Read the conformance test limit identifiers
1425 	* These are used to match regulatory domain testing needs with
1426 	* the RD-specific tests that have been calibrated in the EEPROM.
1427 	*/
1428 	off = header[5];
1429 	for (i = 0; i < ee->ee_numCtls; i += 2) {
1430 		EEREAD(off++);
1431 		ee->ee_ctl[i] = (eeval >> 8) & 0xff;
1432 		ee->ee_ctl[i+1] = eeval & 0xff;
1433 	}
1434 
1435 	if (ee->ee_version < AR_EEPROM_VER5_3) {
1436 		/* XXX only for 5413? */
1437 		ee->ee_spurChans[0][1] = AR_SPUR_5413_1;
1438 		ee->ee_spurChans[1][1] = AR_SPUR_5413_2;
1439 		ee->ee_spurChans[2][1] = AR_NO_SPUR;
1440 		ee->ee_spurChans[0][0] = AR_NO_SPUR;
1441 	} else {
1442 		/* Read spur mitigation data */
1443 		for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
1444 			EEREAD(off);
1445 			ee->ee_spurChans[i][0] = eeval;
1446 			EEREAD(off+AR_EEPROM_MODAL_SPURS);
1447 			ee->ee_spurChans[i][1] = eeval;
1448 			off++;
1449 		}
1450 	}
1451 
1452 	/* for recent changes to NF scale */
1453 	if (ee->ee_version <= AR_EEPROM_VER3_2) {
1454 		ee->ee_noiseFloorThresh[headerInfo11A] = -54;
1455 		ee->ee_noiseFloorThresh[headerInfo11B] = -1;
1456 		ee->ee_noiseFloorThresh[headerInfo11G] = -1;
1457 	}
1458 	/* to override thresh62 for better 2.4 and 5 operation */
1459 	if (ee->ee_version <= AR_EEPROM_VER3_2) {
1460 		ee->ee_thresh62[headerInfo11A] = 15;	/* 11A */
1461 		ee->ee_thresh62[headerInfo11B] = 28;	/* 11B */
1462 		ee->ee_thresh62[headerInfo11G] = 28;	/* 11G */
1463 	}
1464 
1465 	/* Check for regulatory capabilities */
1466 	if (ee->ee_version >= AR_EEPROM_VER4_0) {
1467 		EEREAD(regCapOffsetPost4_0);
1468 	} else {
1469 		EEREAD(regCapOffsetPre4_0);
1470 	}
1471 
1472 	ee->ee_regCap = eeval;
1473 
1474 	if (ee->ee_Amode == 0) {
1475 		/* Check for valid Amode in upgraded h/w */
1476 		if (ee->ee_version >= AR_EEPROM_VER4_0) {
1477 			ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A)?1:0;
1478 		} else {
1479 			ee->ee_Amode = (ee->ee_regCap & AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0)?1:0;
1480 		}
1481 	}
1482 
1483 	if (ee->ee_version >= AR_EEPROM_VER5_1)
1484 		EEREAD(AR_EEPROM_CAPABILITIES_OFFSET);
1485 	else
1486 		eeval = 0;
1487 	ee->ee_opCap = eeval;
1488 
1489 	EEREAD(AR_EEPROM_REG_DOMAIN);
1490 	ee->ee_regdomain = eeval;
1491 
1492 	return AH_TRUE;
1493 #undef EEREAD
1494 }
1495 
1496 /*
1497  * Now verify and copy EEPROM contents into the allocated space
1498  */
1499 static HAL_BOOL
1500 legacyEepromReadContents(struct ath_hal *ah, HAL_EEPROM *ee)
1501 {
1502 	/* Read the header information here */
1503 	if (!readHeaderInfo(ah, ee))
1504 		return AH_FALSE;
1505 #if 0
1506 	/* Require 5112 devices to have EEPROM 4.0 EEP_MAP set */
1507 	if (IS_5112(ah) && !ee->ee_eepMap) {
1508 		HALDEBUG(ah, HAL_DEBUG_ANY,
1509 		    "%s: 5112 devices must have EEPROM 4.0 with the "
1510 		    "EEP_MAP set\n", __func__);
1511 		return AH_FALSE;
1512 	}
1513 #endif
1514 	/*
1515 	 * Group 1: frequency pier locations readback
1516 	 * check that the structure has been populated
1517 	 * with enough space to hold the channels
1518 	 *
1519 	 * NOTE: Group 1 contains the 5 GHz channel numbers
1520 	 *	 that have dBm->pcdac calibrated information.
1521 	 */
1522 	if (!readEepromFreqPierInfo(ah, ee))
1523 		return AH_FALSE;
1524 
1525 	/*
1526 	 * Group 2:  readback data for all frequency piers
1527 	 *
1528 	 * NOTE: Group 2 contains the raw power calibration
1529 	 *	 information for each of the channels that we
1530 	 *	 recorded above.
1531 	 */
1532 	if (!readEepromRawPowerCalInfo(ah, ee))
1533 		return AH_FALSE;
1534 
1535 	/*
1536 	 * Group 5: target power values per rate
1537 	 *
1538 	 * NOTE: Group 5 contains the recorded maximum power
1539 	 *	 in dB that can be attained for the given rate.
1540 	 */
1541 	/* Read the power per rate info for test channels */
1542 	if (!readEepromTargetPowerCalInfo(ah, ee))
1543 		return AH_FALSE;
1544 
1545 	/*
1546 	 * Group 8: Conformance Test Limits information
1547 	 *
1548 	 * NOTE: Group 8 contains the values to limit the
1549 	 *	 maximum transmit power value based on any
1550 	 *	 band edge violations.
1551 	 */
1552 	/* Read the RD edge power limits */
1553 	return readEepromCTLInfo(ah, ee);
1554 }
1555 
1556 static HAL_STATUS
1557 legacyEepromGet(struct ath_hal *ah, int param, void *val)
1558 {
1559 	HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1560 	uint8_t *macaddr;
1561 	uint16_t eeval;
1562 	uint32_t sum;
1563 	int i;
1564 
1565 	switch (param) {
1566 	case AR_EEP_OPCAP:
1567 		*(uint16_t *) val = ee->ee_opCap;
1568 		return HAL_OK;
1569 	case AR_EEP_REGDMN_0:
1570 		*(uint16_t *) val = ee->ee_regdomain;
1571 		return HAL_OK;
1572 	case AR_EEP_RFSILENT:
1573 		if (!ath_hal_eepromRead(ah, AR_EEPROM_RFSILENT, &eeval))
1574 			return HAL_EEREAD;
1575 		*(uint16_t *) val = eeval;
1576 		return HAL_OK;
1577 	case AR_EEP_MACADDR:
1578 		sum = 0;
1579 		macaddr = val;
1580 		for (i = 0; i < 3; i++) {
1581 			if (!ath_hal_eepromRead(ah, AR_EEPROM_MAC(2-i), &eeval)) {
1582 				HALDEBUG(ah, HAL_DEBUG_ANY,
1583 				    "%s: cannot read EEPROM location %u\n",
1584 				    __func__, i);
1585 				return HAL_EEREAD;
1586 			}
1587 			sum += eeval;
1588 			macaddr[2*i] = eeval >> 8;
1589 			macaddr[2*i + 1] = eeval & 0xff;
1590 		}
1591 		if (sum == 0 || sum == 0xffff*3) {
1592 			HALDEBUG(ah, HAL_DEBUG_ANY,
1593 			    "%s: mac address read failed: %s\n", __func__,
1594 			    ath_hal_ether_sprintf(macaddr));
1595 			return HAL_EEBADMAC;
1596 		}
1597 		return HAL_OK;
1598 	case AR_EEP_RFKILL:
1599 		HALASSERT(val == AH_NULL);
1600 		return ee->ee_rfKill ? HAL_OK : HAL_EIO;
1601 	case AR_EEP_AMODE:
1602 		HALASSERT(val == AH_NULL);
1603 		return ee->ee_Amode ? HAL_OK : HAL_EIO;
1604 	case AR_EEP_BMODE:
1605 		HALASSERT(val == AH_NULL);
1606 		return ee->ee_Bmode ? HAL_OK : HAL_EIO;
1607 	case AR_EEP_GMODE:
1608 		HALASSERT(val == AH_NULL);
1609 		return ee->ee_Gmode ? HAL_OK : HAL_EIO;
1610 	case AR_EEP_TURBO5DISABLE:
1611 		HALASSERT(val == AH_NULL);
1612 		return ee->ee_turbo5Disable ? HAL_OK : HAL_EIO;
1613 	case AR_EEP_TURBO2DISABLE:
1614 		HALASSERT(val == AH_NULL);
1615 		return ee->ee_turbo2Disable ? HAL_OK : HAL_EIO;
1616 	case AR_EEP_ISTALON:		/* Talon detect */
1617 		HALASSERT(val == AH_NULL);
1618 		return (ee->ee_version >= AR_EEPROM_VER5_4 &&
1619 		    ath_hal_eepromRead(ah, 0x0b, &eeval) && eeval == 1) ?
1620 			HAL_OK : HAL_EIO;
1621 	case AR_EEP_32KHZCRYSTAL:
1622 		HALASSERT(val == AH_NULL);
1623 		return ee->ee_exist32kHzCrystal ? HAL_OK : HAL_EIO;
1624 	case AR_EEP_COMPRESS:
1625 		HALASSERT(val == AH_NULL);
1626 		return (ee->ee_opCap & AR_EEPROM_EEPCAP_COMPRESS_DIS) == 0 ?
1627 		    HAL_OK : HAL_EIO;
1628 	case AR_EEP_FASTFRAME:
1629 		HALASSERT(val == AH_NULL);
1630 		return (ee->ee_opCap & AR_EEPROM_EEPCAP_FASTFRAME_DIS) == 0 ?
1631 		    HAL_OK : HAL_EIO;
1632 	case AR_EEP_AES:
1633 		HALASSERT(val == AH_NULL);
1634 		return (ee->ee_opCap & AR_EEPROM_EEPCAP_AES_DIS) == 0 ?
1635 		    HAL_OK : HAL_EIO;
1636 	case AR_EEP_BURST:
1637 		HALASSERT(val == AH_NULL);
1638 		return (ee->ee_opCap & AR_EEPROM_EEPCAP_BURST_DIS) == 0 ?
1639 		    HAL_OK : HAL_EIO;
1640 	case AR_EEP_MAXQCU:
1641 		if (ee->ee_opCap & AR_EEPROM_EEPCAP_MAXQCU) {
1642 			*(uint16_t *) val =
1643 			    MS(ee->ee_opCap, AR_EEPROM_EEPCAP_MAXQCU);
1644 			return HAL_OK;
1645 		} else
1646 			return HAL_EIO;
1647 	case AR_EEP_KCENTRIES:
1648 		if (ee->ee_opCap & AR_EEPROM_EEPCAP_KC_ENTRIES) {
1649 			*(uint16_t *) val =
1650 			    1 << MS(ee->ee_opCap, AR_EEPROM_EEPCAP_KC_ENTRIES);
1651 			return HAL_OK;
1652 		} else
1653 			return HAL_EIO;
1654 	case AR_EEP_ANTGAINMAX_5:
1655 		*(int8_t *) val = ee->ee_antennaGainMax[0];
1656 		return HAL_OK;
1657 	case AR_EEP_ANTGAINMAX_2:
1658 		*(int8_t *) val = ee->ee_antennaGainMax[1];
1659 		return HAL_OK;
1660 	case AR_EEP_WRITEPROTECT:
1661 		HALASSERT(val == AH_NULL);
1662 		return (ee->ee_protect & AR_EEPROM_PROTECT_WP_128_191) ?
1663 		    HAL_OK : HAL_EIO;
1664 	}
1665 	return HAL_EINVAL;
1666 }
1667 
1668 static HAL_STATUS
1669 legacyEepromSet(struct ath_hal *ah, int param, int v)
1670 {
1671 	HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1672 
1673 	switch (param) {
1674 	case AR_EEP_AMODE:
1675 		ee->ee_Amode = v;
1676 		return HAL_OK;
1677 	case AR_EEP_BMODE:
1678 		ee->ee_Bmode = v;
1679 		return HAL_OK;
1680 	case AR_EEP_GMODE:
1681 		ee->ee_Gmode = v;
1682 		return HAL_OK;
1683 	case AR_EEP_TURBO5DISABLE:
1684 		ee->ee_turbo5Disable = v;
1685 		return HAL_OK;
1686 	case AR_EEP_TURBO2DISABLE:
1687 		ee->ee_turbo2Disable = v;
1688 		return HAL_OK;
1689 	case AR_EEP_COMPRESS:
1690 		if (v)
1691 			ee->ee_opCap &= ~AR_EEPROM_EEPCAP_COMPRESS_DIS;
1692 		else
1693 			ee->ee_opCap |= AR_EEPROM_EEPCAP_COMPRESS_DIS;
1694 		return HAL_OK;
1695 	case AR_EEP_FASTFRAME:
1696 		if (v)
1697 			ee->ee_opCap &= ~AR_EEPROM_EEPCAP_FASTFRAME_DIS;
1698 		else
1699 			ee->ee_opCap |= AR_EEPROM_EEPCAP_FASTFRAME_DIS;
1700 		return HAL_OK;
1701 	case AR_EEP_AES:
1702 		if (v)
1703 			ee->ee_opCap &= ~AR_EEPROM_EEPCAP_AES_DIS;
1704 		else
1705 			ee->ee_opCap |= AR_EEPROM_EEPCAP_AES_DIS;
1706 		return HAL_OK;
1707 	case AR_EEP_BURST:
1708 		if (v)
1709 			ee->ee_opCap &= ~AR_EEPROM_EEPCAP_BURST_DIS;
1710 		else
1711 			ee->ee_opCap |= AR_EEPROM_EEPCAP_BURST_DIS;
1712 		return HAL_OK;
1713 	}
1714 	return HAL_EINVAL;
1715 }
1716 
1717 static HAL_BOOL
1718 legacyEepromDiag(struct ath_hal *ah, int request,
1719      const void *args, uint32_t argsize, void **result, uint32_t *resultsize)
1720 {
1721 	HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1722 	const EEPROM_POWER_EXPN_5112 *pe;
1723 
1724 	switch (request) {
1725 	case HAL_DIAG_EEPROM:
1726 		*result = ee;
1727 		*resultsize = sizeof(*ee);
1728 		return AH_TRUE;
1729 	case HAL_DIAG_EEPROM_EXP_11A:
1730 	case HAL_DIAG_EEPROM_EXP_11B:
1731 	case HAL_DIAG_EEPROM_EXP_11G:
1732 		pe = &ee->ee_modePowerArray5112[
1733 		    request - HAL_DIAG_EEPROM_EXP_11A];
1734 		*result = pe->pChannels;
1735 		*resultsize = (*result == AH_NULL) ? 0 :
1736 			roundup(sizeof(uint16_t) * pe->numChannels,
1737 				sizeof(uint32_t)) +
1738 			sizeof(EXPN_DATA_PER_CHANNEL_5112) * pe->numChannels;
1739 		return AH_TRUE;
1740 	}
1741 	return AH_FALSE;
1742 }
1743 
1744 static uint16_t
1745 legacyEepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz)
1746 {
1747 	HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1748 
1749 	HALASSERT(0 <= ix && ix < AR_EEPROM_MODAL_SPURS);
1750 	return ee->ee_spurChans[ix][is2GHz];
1751 }
1752 
1753 /*
1754  * Reclaim any EEPROM-related storage.
1755  */
1756 static void
1757 legacyEepromDetach(struct ath_hal *ah)
1758 {
1759 	HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1760 
1761         if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1)
1762 		freeEepromRawPowerCalInfo5112(ah, ee);
1763 	ath_hal_free(ee);
1764 	AH_PRIVATE(ah)->ah_eeprom = AH_NULL;
1765 }
1766 
1767 /*
1768  * These are not valid 2.4 channels, either we change 'em
1769  * or we need to change the coding to accept them.
1770  */
1771 static const uint16_t channels11b[] = { 2412, 2447, 2484 };
1772 static const uint16_t channels11g[] = { 2312, 2412, 2484 };
1773 
1774 HAL_STATUS
1775 ath_hal_legacyEepromAttach(struct ath_hal *ah)
1776 {
1777 	HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1778 	uint32_t sum, eepMax;
1779 	uint16_t eeversion, eeprotect, eeval;
1780 	u_int i;
1781 
1782 	HALASSERT(ee == AH_NULL);
1783 
1784 	if (!ath_hal_eepromRead(ah, AR_EEPROM_VERSION, &eeversion)) {
1785 		HALDEBUG(ah, HAL_DEBUG_ANY,
1786 		    "%s: unable to read EEPROM version\n", __func__);
1787 		return HAL_EEREAD;
1788 	}
1789 	if (eeversion < AR_EEPROM_VER3) {
1790 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM version "
1791 		    "%u (0x%x) found\n", __func__, eeversion, eeversion);
1792 		return HAL_EEVERSION;
1793 	}
1794 
1795 	if (!ath_hal_eepromRead(ah, AR_EEPROM_PROTECT, &eeprotect)) {
1796 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cannot read EEPROM protection "
1797 		    "bits; read locked?\n", __func__);
1798 		return HAL_EEREAD;
1799 	}
1800 	HALDEBUG(ah, HAL_DEBUG_ATTACH, "EEPROM protect 0x%x\n", eeprotect);
1801 	/* XXX check proper access before continuing */
1802 
1803 	/*
1804 	 * Read the Atheros EEPROM entries and calculate the checksum.
1805 	 */
1806 	if (!ath_hal_eepromRead(ah, AR_EEPROM_SIZE_UPPER, &eeval)) {
1807 		HALDEBUG(ah, HAL_DEBUG_ANY,
1808 		    "%s: cannot read EEPROM upper size\n" , __func__);
1809 		return HAL_EEREAD;
1810 	}
1811 	if (eeval != 0)	{
1812 		eepMax = (eeval & AR_EEPROM_SIZE_UPPER_MASK) <<
1813 			AR_EEPROM_SIZE_ENDLOC_SHIFT;
1814 		if (!ath_hal_eepromRead(ah, AR_EEPROM_SIZE_LOWER, &eeval)) {
1815 			HALDEBUG(ah, HAL_DEBUG_ANY,
1816 			    "%s: cannot read EEPROM lower size\n" , __func__);
1817 			return HAL_EEREAD;
1818 		}
1819 		eepMax = (eepMax | eeval) - AR_EEPROM_ATHEROS_BASE;
1820 	} else
1821 		eepMax = AR_EEPROM_ATHEROS_MAX;
1822 	sum = 0;
1823 	for (i = 0; i < eepMax; i++) {
1824 		if (!ath_hal_eepromRead(ah, AR_EEPROM_ATHEROS(i), &eeval)) {
1825 			return HAL_EEREAD;
1826 		}
1827 		sum ^= eeval;
1828 	}
1829 	if (sum != 0xffff) {
1830 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad EEPROM checksum 0x%x\n",
1831 		    __func__, sum);
1832 		return HAL_EEBADSUM;
1833 	}
1834 
1835 	ee = ath_hal_malloc(sizeof(HAL_EEPROM));
1836 	if (ee == AH_NULL) {
1837 		/* XXX message */
1838 		return HAL_ENOMEM;
1839 	}
1840 
1841 	ee->ee_protect = eeprotect;
1842 	ee->ee_version = eeversion;
1843 
1844 	ee->ee_numChannels11a = NUM_11A_EEPROM_CHANNELS;
1845 	ee->ee_numChannels2_4 = NUM_2_4_EEPROM_CHANNELS;
1846 
1847 	for (i = 0; i < NUM_11A_EEPROM_CHANNELS; i ++)
1848 		ee->ee_dataPerChannel11a[i].numPcdacValues = NUM_PCDAC_VALUES;
1849 
1850 	/* the channel list for 2.4 is fixed, fill this in here */
1851 	for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) {
1852 		ee->ee_channels11b[i] = channels11b[i];
1853 		/* XXX 5211 requires a hack though we don't support 11g */
1854 		if (ah->ah_magic == 0x19570405)
1855 			ee->ee_channels11g[i] = channels11b[i];
1856 		else
1857 			ee->ee_channels11g[i] = channels11g[i];
1858 		ee->ee_dataPerChannel11b[i].numPcdacValues = NUM_PCDAC_VALUES;
1859 		ee->ee_dataPerChannel11g[i].numPcdacValues = NUM_PCDAC_VALUES;
1860 	}
1861 
1862 	if (!legacyEepromReadContents(ah, ee)) {
1863 		/* XXX message */
1864 		ath_hal_free(ee);
1865 		return HAL_EEREAD;	/* XXX */
1866 	}
1867 
1868 	AH_PRIVATE(ah)->ah_eeprom = ee;
1869 	AH_PRIVATE(ah)->ah_eeversion = eeversion;
1870 	AH_PRIVATE(ah)->ah_eepromDetach = legacyEepromDetach;
1871 	AH_PRIVATE(ah)->ah_eepromGet = legacyEepromGet;
1872 	AH_PRIVATE(ah)->ah_eepromSet = legacyEepromSet;
1873 	AH_PRIVATE(ah)->ah_getSpurChan = legacyEepromGetSpurChan;
1874 	AH_PRIVATE(ah)->ah_eepromDiag = legacyEepromDiag;
1875 	return HAL_OK;
1876 }
1877