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