]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ath/ath_hal/ah_eeprom_v3.c
MFV r347989:
[FreeBSD/FreeBSD.git] / sys / dev / ath / ath_hal / ah_eeprom_v3.c
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 }