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