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