[BACK]Return to ar5xxx.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/ar5xxx.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: ar5xxx.c,v 1.42 2007/06/26 10:53:01 tom Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            17:  */
        !            18:
        !            19: /*
        !            20:  * HAL interface for Atheros Wireless LAN devices.
        !            21:  * (Please have a look at ar5xxx.h for further information)
        !            22:  */
        !            23:
        !            24: #include <dev/pci/pcidevs.h>
        !            25: #include <dev/ic/ar5xxx.h>
        !            26:
        !            27: extern ar5k_attach_t ar5k_ar5210_attach;
        !            28: extern ar5k_attach_t ar5k_ar5211_attach;
        !            29: extern ar5k_attach_t ar5k_ar5212_attach;
        !            30:
        !            31: static const struct {
        !            32:        u_int16_t       vendor;
        !            33:        u_int16_t       device;
        !            34:        ar5k_attach_t   (*attach);
        !            35: } ar5k_known_products[] = {
        !            36:        /*
        !            37:         * From pcidevs_data.h
        !            38:         */
        !            39:        { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210,
        !            40:            ar5k_ar5210_attach },
        !            41:        { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210_AP,
        !            42:            ar5k_ar5210_attach },
        !            43:        { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210_DEFAULT,
        !            44:            ar5k_ar5210_attach },
        !            45:        { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211,
        !            46:            ar5k_ar5211_attach },
        !            47:        { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211_DEFAULT,
        !            48:            ar5k_ar5211_attach },
        !            49:        { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5311,
        !            50:            ar5k_ar5211_attach },
        !            51:        { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211_FPGA11B,
        !            52:            ar5k_ar5211_attach },
        !            53:        { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211_LEGACY,
        !            54:            ar5k_ar5211_attach },
        !            55:        { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212,
        !            56:            ar5k_ar5212_attach },
        !            57:        { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_DEFAULT,
        !            58:            ar5k_ar5212_attach },
        !            59:        { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_FPGA,
        !            60:            ar5k_ar5212_attach },
        !            61:        { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_IBM,
        !            62:            ar5k_ar5212_attach },
        !            63:        { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR2413,
        !            64:            ar5k_ar5212_attach },
        !            65:        { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5413,
        !            66:            ar5k_ar5212_attach },
        !            67:        { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5424,
        !            68:            ar5k_ar5212_attach },
        !            69:        { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CRDAG675,
        !            70:            ar5k_ar5212_attach },
        !            71:        { PCI_VENDOR_3COM2, PCI_PRODUCT_3COM2_3CRPAG175,
        !            72:            ar5k_ar5212_attach }
        !            73: };
        !            74:
        !            75: static const HAL_RATE_TABLE ar5k_rt_11a = AR5K_RATES_11A;
        !            76: static const HAL_RATE_TABLE ar5k_rt_11b = AR5K_RATES_11B;
        !            77: static const HAL_RATE_TABLE ar5k_rt_11g = AR5K_RATES_11G;
        !            78: static const HAL_RATE_TABLE ar5k_rt_turbo = AR5K_RATES_TURBO;
        !            79: static const HAL_RATE_TABLE ar5k_rt_xr = AR5K_RATES_XR;
        !            80:
        !            81: int             ar5k_eeprom_read_ants(struct ath_hal *, u_int32_t *, u_int);
        !            82: int             ar5k_eeprom_read_modes(struct ath_hal *, u_int32_t *, u_int);
        !            83: u_int16_t       ar5k_eeprom_bin2freq(struct ath_hal *, u_int16_t, u_int);
        !            84:
        !            85: HAL_BOOL        ar5k_ar5110_channel(struct ath_hal *, HAL_CHANNEL *);
        !            86: u_int32_t       ar5k_ar5110_chan2athchan(HAL_CHANNEL *);
        !            87: HAL_BOOL        ar5k_ar5111_channel(struct ath_hal *, HAL_CHANNEL *);
        !            88: HAL_BOOL        ar5k_ar5111_chan2athchan(u_int, struct ar5k_athchan_2ghz *);
        !            89: HAL_BOOL        ar5k_ar5112_channel(struct ath_hal *, HAL_CHANNEL *);
        !            90: HAL_BOOL        ar5k_check_channel(struct ath_hal *, u_int16_t, u_int flags);
        !            91:
        !            92: HAL_BOOL        ar5k_ar5111_rfregs(struct ath_hal *, HAL_CHANNEL *, u_int);
        !            93: HAL_BOOL        ar5k_ar5112_rfregs(struct ath_hal *, HAL_CHANNEL *, u_int);
        !            94: u_int           ar5k_rfregs_op(u_int32_t *, u_int32_t, u_int32_t, u_int32_t,
        !            95:     u_int32_t, u_int32_t, HAL_BOOL);
        !            96:
        !            97: /*
        !            98:  * Supported channels
        !            99:  */
        !           100: static const struct
        !           101: ieee80211_regchannel ar5k_5ghz_channels[] = IEEE80211_CHANNELS_5GHZ;
        !           102: static const struct
        !           103: ieee80211_regchannel ar5k_2ghz_channels[] = IEEE80211_CHANNELS_2GHZ;
        !           104:
        !           105: /*
        !           106:  * Initial gain optimization values
        !           107:  */
        !           108: static const struct ar5k_gain_opt ar5111_gain_opt = AR5K_AR5111_GAIN_OPT;
        !           109: static const struct ar5k_gain_opt ar5112_gain_opt = AR5K_AR5112_GAIN_OPT;
        !           110:
        !           111: /*
        !           112:  * Initial register for the radio chipsets
        !           113:  */
        !           114: static const struct ar5k_ini_rf ar5111_rf[] = AR5K_AR5111_INI_RF;
        !           115: static const struct ar5k_ini_rf ar5112_rf[] = AR5K_AR5112_INI_RF;
        !           116: static const struct ar5k_ini_rf ar5112a_rf[] = AR5K_AR5112A_INI_RF;
        !           117: static const struct ar5k_ini_rfgain ar5k_rfg[] = AR5K_INI_RFGAIN;
        !           118:
        !           119: /*
        !           120:  * Enable to overwrite the country code (use "00" for debug)
        !           121:  */
        !           122: #if 0
        !           123: #define COUNTRYCODE "00"
        !           124: #endif
        !           125:
        !           126: /*
        !           127:  * Perform a lookup if the device is supported by the HAL
        !           128:  */
        !           129: const char *
        !           130: ath_hal_probe(u_int16_t vendor, u_int16_t device)
        !           131: {
        !           132:        int i;
        !           133:
        !           134:        /*
        !           135:         * Perform a linear search on the table of supported devices
        !           136:         */
        !           137:        for (i = 0; i < AR5K_ELEMENTS(ar5k_known_products); i++) {
        !           138:                if (vendor == ar5k_known_products[i].vendor &&
        !           139:                    device == ar5k_known_products[i].device)
        !           140:                        return ("");
        !           141:        }
        !           142:
        !           143:        return (NULL);
        !           144: }
        !           145:
        !           146: /*
        !           147:  * Fills in the HAL structure and initialises the device
        !           148:  */
        !           149: struct ath_hal *
        !           150: ath_hal_attach(u_int16_t device, void *arg, bus_space_tag_t st,
        !           151:     bus_space_handle_t sh, u_int is_64bit, int *status)
        !           152: {
        !           153:        struct ath_softc *sc = (struct ath_softc *)arg;
        !           154:        struct ath_hal *hal = NULL;
        !           155:        ar5k_attach_t *attach = NULL;
        !           156:        u_int8_t mac[IEEE80211_ADDR_LEN];
        !           157:        int i;
        !           158:
        !           159:        *status = EINVAL;
        !           160:
        !           161:        /*
        !           162:         * Call the chipset-dependent attach routine by device id
        !           163:         */
        !           164:        for (i = 0; i < AR5K_ELEMENTS(ar5k_known_products); i++) {
        !           165:                if (device == ar5k_known_products[i].device &&
        !           166:                    ar5k_known_products[i].attach != NULL)
        !           167:                        attach = ar5k_known_products[i].attach;
        !           168:        }
        !           169:
        !           170:        if (attach == NULL) {
        !           171:                *status = ENXIO;
        !           172:                AR5K_PRINTF("device not supported: 0x%04x\n", device);
        !           173:                return (NULL);
        !           174:        }
        !           175:
        !           176:        if ((hal = malloc(sizeof(struct ath_hal),
        !           177:                 M_DEVBUF, M_NOWAIT)) == NULL) {
        !           178:                *status = ENOMEM;
        !           179:                AR5K_PRINT("out of memory\n");
        !           180:                return (NULL);
        !           181:        }
        !           182:
        !           183:        bzero(hal, sizeof(struct ath_hal));
        !           184:
        !           185:        hal->ah_sc = sc;
        !           186:        hal->ah_st = st;
        !           187:        hal->ah_sh = sh;
        !           188:        hal->ah_device = device;
        !           189:        hal->ah_sub_vendor = 0; /* XXX unknown?! */
        !           190:
        !           191:        /*
        !           192:         * HAL information
        !           193:         */
        !           194:        hal->ah_abi = HAL_ABI_VERSION;
        !           195:        hal->ah_op_mode = HAL_M_STA;
        !           196:        hal->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
        !           197:        hal->ah_turbo = AH_FALSE;
        !           198:        hal->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
        !           199:        hal->ah_imr = 0;
        !           200:        hal->ah_atim_window = 0;
        !           201:        hal->ah_aifs = AR5K_TUNE_AIFS;
        !           202:        hal->ah_cw_min = AR5K_TUNE_CWMIN;
        !           203:        hal->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
        !           204:        hal->ah_software_retry = AH_FALSE;
        !           205:        hal->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY;
        !           206:
        !           207:        switch (device) {
        !           208:        case PCI_PRODUCT_ATHEROS_AR2413:
        !           209:        case PCI_PRODUCT_ATHEROS_AR5413:
        !           210:        case PCI_PRODUCT_ATHEROS_AR5424:
        !           211:                /*
        !           212:                 * Known single chip solutions
        !           213:                 */
        !           214:                hal->ah_single_chip = AH_TRUE;
        !           215:                break;
        !           216:        case PCI_PRODUCT_ATHEROS_AR5212_IBM:
        !           217:                /*
        !           218:                 * IBM ThinkPads use the same device ID for different
        !           219:                 * chipset versions. Ugh.
        !           220:                 */
        !           221:                if (is_64bit) {
        !           222:                        /*
        !           223:                         * PCI Express "Mini Card" interface based on the
        !           224:                         * AR5424 chipset
        !           225:                         */
        !           226:                        hal->ah_single_chip = AH_TRUE;
        !           227:                } else {
        !           228:                        /* Classic Mini PCI interface based on AR5212 */
        !           229:                        hal->ah_single_chip = AH_FALSE;
        !           230:                }
        !           231:                break;
        !           232:        default:
        !           233:                /*
        !           234:                 * Multi chip solutions
        !           235:                 */
        !           236:                hal->ah_single_chip = AH_FALSE;
        !           237:                break;
        !           238:        }
        !           239:
        !           240:        if ((attach)(device, hal, st, sh, status) == NULL)
        !           241:                goto failed;
        !           242:
        !           243: #ifdef AR5K_DEBUG
        !           244:        hal->ah_dump_state(hal);
        !           245: #endif
        !           246:
        !           247:        /*
        !           248:         * Get card capabilities, values, ...
        !           249:         */
        !           250:
        !           251:        if (ar5k_eeprom_init(hal) != 0) {
        !           252:                AR5K_PRINT("unable to init EEPROM\n");
        !           253:                goto failed;
        !           254:        }
        !           255:
        !           256:        /* Get misc capabilities */
        !           257:        if (hal->ah_get_capabilities(hal) != AH_TRUE) {
        !           258:                AR5K_PRINTF("unable to get device capabilities: 0x%04x\n",
        !           259:                    device);
        !           260:                goto failed;
        !           261:        }
        !           262:
        !           263:        /* Get MAC address */
        !           264:        if ((*status = ar5k_eeprom_read_mac(hal, mac)) != 0) {
        !           265:                AR5K_PRINTF("unable to read address from EEPROM: 0x%04x\n",
        !           266:                    device);
        !           267:                goto failed;
        !           268:        }
        !           269:
        !           270:        hal->ah_set_lladdr(hal, mac);
        !           271:
        !           272:        /* Get rate tables */
        !           273:        if (hal->ah_capabilities.cap_mode & HAL_MODE_11A)
        !           274:                ar5k_rt_copy(&hal->ah_rt_11a, &ar5k_rt_11a);
        !           275:        if (hal->ah_capabilities.cap_mode & HAL_MODE_11B)
        !           276:                ar5k_rt_copy(&hal->ah_rt_11b, &ar5k_rt_11b);
        !           277:        if (hal->ah_capabilities.cap_mode & HAL_MODE_11G)
        !           278:                ar5k_rt_copy(&hal->ah_rt_11g, &ar5k_rt_11g);
        !           279:        if (hal->ah_capabilities.cap_mode & HAL_MODE_TURBO)
        !           280:                ar5k_rt_copy(&hal->ah_rt_turbo, &ar5k_rt_turbo);
        !           281:        if (hal->ah_capabilities.cap_mode & HAL_MODE_XR)
        !           282:                ar5k_rt_copy(&hal->ah_rt_xr, &ar5k_rt_xr);
        !           283:
        !           284:        /* Initialize the gain optimization values */
        !           285:        if (hal->ah_radio == AR5K_AR5111) {
        !           286:                hal->ah_gain.g_step_idx = ar5111_gain_opt.go_default;
        !           287:                hal->ah_gain.g_step =
        !           288:                    &ar5111_gain_opt.go_step[hal->ah_gain.g_step_idx];
        !           289:                hal->ah_gain.g_low = 20;
        !           290:                hal->ah_gain.g_high = 35;
        !           291:                hal->ah_gain.g_active = 1;
        !           292:        } else if (hal->ah_radio == AR5K_AR5112) {
        !           293:                hal->ah_gain.g_step_idx = ar5112_gain_opt.go_default;
        !           294:                hal->ah_gain.g_step =
        !           295:                    &ar5111_gain_opt.go_step[hal->ah_gain.g_step_idx];
        !           296:                hal->ah_gain.g_low = 20;
        !           297:                hal->ah_gain.g_high = 85;
        !           298:                hal->ah_gain.g_active = 1;
        !           299:        }
        !           300:
        !           301:        *status = HAL_OK;
        !           302:
        !           303:        return (hal);
        !           304:
        !           305:  failed:
        !           306:        free(hal, M_DEVBUF);
        !           307:        return (NULL);
        !           308: }
        !           309:
        !           310: u_int16_t
        !           311: ath_hal_computetxtime(struct ath_hal *hal, const HAL_RATE_TABLE *rates,
        !           312:     u_int32_t frame_length, u_int16_t rate_index, HAL_BOOL short_preamble)
        !           313: {
        !           314:        const HAL_RATE *rate;
        !           315:        u_int32_t value;
        !           316:
        !           317:        AR5K_ASSERT_ENTRY(rate_index, rates->rateCount);
        !           318:
        !           319:        /*
        !           320:         * Get rate by index
        !           321:         */
        !           322:        rate = &rates->info[rate_index];
        !           323:
        !           324:        /*
        !           325:         * Calculate the transmission time by operation (PHY) mode
        !           326:         */
        !           327:        switch (rate->phy) {
        !           328:        case IEEE80211_T_CCK:
        !           329:                /*
        !           330:                 * CCK / DS mode (802.11b)
        !           331:                 */
        !           332:                value = AR5K_CCK_TX_TIME(rate->rateKbps, frame_length,
        !           333:                    (short_preamble && rate->shortPreamble));
        !           334:                break;
        !           335:
        !           336:        case IEEE80211_T_OFDM:
        !           337:                /*
        !           338:                 * Orthogonal Frequency Division Multiplexing
        !           339:                 */
        !           340:                if (AR5K_OFDM_NUM_BITS_PER_SYM(rate->rateKbps) == 0)
        !           341:                        return (0);
        !           342:                value = AR5K_OFDM_TX_TIME(rate->rateKbps, frame_length);
        !           343:                break;
        !           344:
        !           345:        case IEEE80211_T_TURBO:
        !           346:                /*
        !           347:                 * Orthogonal Frequency Division Multiplexing
        !           348:                 * Atheros "Turbo Mode" (doubled rates)
        !           349:                 */
        !           350:                if (AR5K_TURBO_NUM_BITS_PER_SYM(rate->rateKbps) == 0)
        !           351:                        return (0);
        !           352:                value = AR5K_TURBO_TX_TIME(rate->rateKbps, frame_length);
        !           353:                break;
        !           354:
        !           355:        case IEEE80211_T_XR:
        !           356:                /*
        !           357:                 * Orthogonal Frequency Division Multiplexing
        !           358:                 * Atheros "eXtended Range" (XR)
        !           359:                 */
        !           360:                if (AR5K_XR_NUM_BITS_PER_SYM(rate->rateKbps) == 0)
        !           361:                        return (0);
        !           362:                value = AR5K_XR_TX_TIME(rate->rateKbps, frame_length);
        !           363:                break;
        !           364:
        !           365:        default:
        !           366:                return (0);
        !           367:        }
        !           368:
        !           369:        return (value);
        !           370: }
        !           371:
        !           372: HAL_BOOL
        !           373: ar5k_check_channel(struct ath_hal *hal, u_int16_t freq, u_int flags)
        !           374: {
        !           375:        /* Check if the channel is in our supported range */
        !           376:        if (flags & IEEE80211_CHAN_2GHZ) {
        !           377:                if ((freq >= hal->ah_capabilities.cap_range.range_2ghz_min) &&
        !           378:                    (freq <= hal->ah_capabilities.cap_range.range_2ghz_max))
        !           379:                        return (AH_TRUE);
        !           380:        } else if (flags & IEEE80211_CHAN_5GHZ) {
        !           381:                if ((freq >= hal->ah_capabilities.cap_range.range_5ghz_min) &&
        !           382:                    (freq <= hal->ah_capabilities.cap_range.range_5ghz_max))
        !           383:                        return (AH_TRUE);
        !           384:        }
        !           385:
        !           386:        return (AH_FALSE);
        !           387: }
        !           388:
        !           389: HAL_BOOL
        !           390: ath_hal_init_channels(struct ath_hal *hal, HAL_CHANNEL *channels,
        !           391:     u_int max_channels, u_int *channels_size, u_int16_t mode,
        !           392:     HAL_BOOL outdoor, HAL_BOOL extended)
        !           393: {
        !           394:        u_int i, c;
        !           395:        u_int32_t domain_current;
        !           396:        u_int domain_5ghz, domain_2ghz;
        !           397:        HAL_CHANNEL *all_channels;
        !           398:
        !           399:        if ((all_channels = malloc(sizeof(HAL_CHANNEL) * max_channels,
        !           400:            M_TEMP, M_NOWAIT)) == NULL)
        !           401:                return (AH_FALSE);
        !           402:
        !           403:        i = c = 0;
        !           404:        domain_current = hal->ah_regdomain;
        !           405:
        !           406:        /*
        !           407:         * In debugging mode, enable all channels supported by the chipset
        !           408:         */
        !           409:        if (domain_current == DMN_DEFAULT) {
        !           410:                int min, max, freq;
        !           411:                u_int flags;
        !           412:
        !           413:                min = ieee80211_mhz2ieee(IEEE80211_CHANNELS_2GHZ_MIN,
        !           414:                    IEEE80211_CHAN_2GHZ);
        !           415:                max = ieee80211_mhz2ieee(IEEE80211_CHANNELS_2GHZ_MAX,
        !           416:                    IEEE80211_CHAN_2GHZ);
        !           417:                flags = CHANNEL_B | CHANNEL_TG |
        !           418:                    (hal->ah_version == AR5K_AR5211 ?
        !           419:                    CHANNEL_PUREG : CHANNEL_G);
        !           420:
        !           421:  debugchan:
        !           422:                for (i = min; i <= max && c < max_channels; i++) {
        !           423:                        freq = ieee80211_ieee2mhz(i, flags);
        !           424:                        if (ar5k_check_channel(hal, freq, flags) == AH_FALSE)
        !           425:                                continue;
        !           426:                        all_channels[c].c_channel = freq;
        !           427:                        all_channels[c++].c_channel_flags = flags;
        !           428:                }
        !           429:
        !           430:                if (flags & IEEE80211_CHAN_2GHZ) {
        !           431:                        min = ieee80211_mhz2ieee(IEEE80211_CHANNELS_5GHZ_MIN,
        !           432:                            IEEE80211_CHAN_5GHZ);
        !           433:                        max = ieee80211_mhz2ieee(IEEE80211_CHANNELS_5GHZ_MAX,
        !           434:                            IEEE80211_CHAN_5GHZ);
        !           435:                        flags = CHANNEL_A | CHANNEL_T | CHANNEL_XR;
        !           436:                        goto debugchan;
        !           437:                }
        !           438:
        !           439:                goto done;
        !           440:        }
        !           441:
        !           442:        domain_5ghz = ieee80211_regdomain2flag(domain_current,
        !           443:            IEEE80211_CHANNELS_5GHZ_MIN);
        !           444:        domain_2ghz = ieee80211_regdomain2flag(domain_current,
        !           445:            IEEE80211_CHANNELS_2GHZ_MIN);
        !           446:
        !           447:        /*
        !           448:         * Create channel list based on chipset capabilities, regulation domain
        !           449:         * and mode. 5GHz...
        !           450:         */
        !           451:        for (i = 0; (hal->ah_capabilities.cap_range.range_5ghz_max > 0) &&
        !           452:                 (i < AR5K_ELEMENTS(ar5k_5ghz_channels)) &&
        !           453:                 (c < max_channels); i++) {
        !           454:                /* Check if channel is supported by the chipset */
        !           455:                if (ar5k_check_channel(hal,
        !           456:                    ar5k_5ghz_channels[i].rc_channel,
        !           457:                    IEEE80211_CHAN_5GHZ) == AH_FALSE)
        !           458:                        continue;
        !           459:
        !           460:                /* Match regulation domain */
        !           461:                if ((IEEE80211_DMN(ar5k_5ghz_channels[i].rc_domain) &
        !           462:                        IEEE80211_DMN(domain_5ghz)) == 0)
        !           463:                        continue;
        !           464:
        !           465:                /* Match modes */
        !           466:                if (ar5k_5ghz_channels[i].rc_mode & IEEE80211_CHAN_TURBO) {
        !           467:                        all_channels[c].c_channel_flags = CHANNEL_T;
        !           468:                } else if (ar5k_5ghz_channels[i].rc_mode &
        !           469:                    IEEE80211_CHAN_OFDM) {
        !           470:                        all_channels[c].c_channel_flags = CHANNEL_A;
        !           471:                } else
        !           472:                        continue;
        !           473:
        !           474:                /* Write channel and increment counter */
        !           475:                all_channels[c++].channel = ar5k_5ghz_channels[i].rc_channel;
        !           476:        }
        !           477:
        !           478:        /*
        !           479:         * ...and 2GHz.
        !           480:         */
        !           481:        for (i = 0; (hal->ah_capabilities.cap_range.range_2ghz_max > 0) &&
        !           482:                 (i < AR5K_ELEMENTS(ar5k_2ghz_channels)) &&
        !           483:                 (c < max_channels); i++) {
        !           484:                /* Check if channel is supported by the chipset */
        !           485:                if (ar5k_check_channel(hal,
        !           486:                    ar5k_2ghz_channels[i].rc_channel,
        !           487:                    IEEE80211_CHAN_2GHZ) == AH_FALSE)
        !           488:                        continue;
        !           489:
        !           490:                /* Match regulation domain */
        !           491:                if ((IEEE80211_DMN(ar5k_2ghz_channels[i].rc_domain) &
        !           492:                        IEEE80211_DMN(domain_2ghz)) == 0)
        !           493:                        continue;
        !           494:
        !           495:                /* Match modes */
        !           496:                if ((hal->ah_capabilities.cap_mode & HAL_MODE_11B) &&
        !           497:                    (ar5k_2ghz_channels[i].rc_mode & IEEE80211_CHAN_CCK))
        !           498:                        all_channels[c].c_channel_flags = CHANNEL_B;
        !           499:
        !           500:                if ((hal->ah_capabilities.cap_mode & HAL_MODE_11G) &&
        !           501:                    (ar5k_2ghz_channels[i].rc_mode & IEEE80211_CHAN_OFDM)) {
        !           502:                        all_channels[c].c_channel_flags |=
        !           503:                            hal->ah_version == AR5K_AR5211 ?
        !           504:                            CHANNEL_PUREG : CHANNEL_G;
        !           505:                        if (ar5k_2ghz_channels[i].rc_mode &
        !           506:                            IEEE80211_CHAN_TURBO)
        !           507:                                all_channels[c].c_channel_flags |= CHANNEL_TG;
        !           508:                }
        !           509:
        !           510:                /* Write channel and increment counter */
        !           511:                all_channels[c++].channel = ar5k_2ghz_channels[i].rc_channel;
        !           512:        }
        !           513:
        !           514:  done:
        !           515:        bcopy(all_channels, channels, sizeof(HAL_CHANNEL) * max_channels);
        !           516:        *channels_size = c;
        !           517:        free(all_channels, M_TEMP);
        !           518:        return (AH_TRUE);
        !           519: }
        !           520:
        !           521: /*
        !           522:  * Common internal functions
        !           523:  */
        !           524:
        !           525: const char *
        !           526: ar5k_printver(enum ar5k_srev_type type, u_int32_t val)
        !           527: {
        !           528:        struct ar5k_srev_name names[] = AR5K_SREV_NAME;
        !           529:        const char *name = "xxxx";
        !           530:        int i;
        !           531:
        !           532:        for (i = 0; i < AR5K_ELEMENTS(names); i++) {
        !           533:                if (type == AR5K_VERSION_DEV) {
        !           534:                        if (names[i].sr_type == type &&
        !           535:                            names[i].sr_val == val) {
        !           536:                                name = names[i].sr_name;
        !           537:                                break;
        !           538:                        }
        !           539:                        continue;
        !           540:                }
        !           541:                if (names[i].sr_type != type ||
        !           542:                    names[i].sr_val == AR5K_SREV_UNKNOWN)
        !           543:                        continue;
        !           544:                if ((val & 0xff) < names[i + 1].sr_val) {
        !           545:                        name = names[i].sr_name;
        !           546:                        break;
        !           547:                }
        !           548:        }
        !           549:
        !           550:        return (name);
        !           551: }
        !           552:
        !           553: void
        !           554: ar5k_radar_alert(struct ath_hal *hal)
        !           555: {
        !           556:        /*
        !           557:         * Limit ~1/s
        !           558:         */
        !           559:        if (hal->ah_radar.r_last_channel.channel ==
        !           560:            hal->ah_current_channel.channel &&
        !           561:            tick < (hal->ah_radar.r_last_alert + hz))
        !           562:                return;
        !           563:
        !           564:        hal->ah_radar.r_last_channel.channel =
        !           565:            hal->ah_current_channel.channel;
        !           566:        hal->ah_radar.r_last_channel.c_channel_flags =
        !           567:            hal->ah_current_channel.c_channel_flags;
        !           568:        hal->ah_radar.r_last_alert = tick;
        !           569:
        !           570:        AR5K_PRINTF("Possible radar activity detected at %u MHz (tick %u)\n",
        !           571:            hal->ah_radar.r_last_alert, hal->ah_current_channel.channel);
        !           572: }
        !           573:
        !           574: u_int16_t
        !           575: ar5k_regdomain_from_ieee(ieee80211_regdomain_t ieee)
        !           576: {
        !           577:        u_int32_t regdomain = (u_int32_t)ieee;
        !           578:
        !           579:        /*
        !           580:         * Use the default regulation domain if the value is empty
        !           581:         * or not supported by the net80211 regulation code.
        !           582:         */
        !           583:        if (ieee80211_regdomain2flag(regdomain,
        !           584:            IEEE80211_CHANNELS_5GHZ_MIN) == DMN_DEBUG)
        !           585:                return ((u_int16_t)AR5K_TUNE_REGDOMAIN);
        !           586:
        !           587:        /* It is supported, just return the value */
        !           588:        return (regdomain);
        !           589: }
        !           590:
        !           591: ieee80211_regdomain_t
        !           592: ar5k_regdomain_to_ieee(u_int16_t regdomain)
        !           593: {
        !           594:        ieee80211_regdomain_t ieee = (ieee80211_regdomain_t)regdomain;
        !           595:
        !           596:        return (ieee);
        !           597: }
        !           598:
        !           599: u_int16_t
        !           600: ar5k_get_regdomain(struct ath_hal *hal)
        !           601: {
        !           602:        u_int16_t regdomain;
        !           603:        ieee80211_regdomain_t ieee_regdomain;
        !           604: #ifdef COUNTRYCODE
        !           605:        u_int16_t code;
        !           606: #endif
        !           607:
        !           608:        ar5k_eeprom_regulation_domain(hal, AH_FALSE, &ieee_regdomain);
        !           609:        hal->ah_capabilities.cap_regdomain.reg_hw = ieee_regdomain;
        !           610:
        !           611: #ifdef COUNTRYCODE
        !           612:        /*
        !           613:         * Get the regulation domain by country code. This will ignore
        !           614:         * the settings found in the EEPROM.
        !           615:         */
        !           616:        code = ieee80211_name2countrycode(COUNTRYCODE);
        !           617:        ieee_regdomain = ieee80211_countrycode2regdomain(code);
        !           618: #endif
        !           619:
        !           620:        regdomain = ar5k_regdomain_from_ieee(ieee_regdomain);
        !           621:        hal->ah_capabilities.cap_regdomain.reg_current = regdomain;
        !           622:
        !           623:        return (regdomain);
        !           624: }
        !           625:
        !           626: u_int32_t
        !           627: ar5k_bitswap(u_int32_t val, u_int bits)
        !           628: {
        !           629:        if (bits == 8) {
        !           630:                val = ((val & 0xF0) >>  4) | ((val & 0x0F) <<  4);
        !           631:                val = ((val & 0xCC) >>  2) | ((val & 0x33) <<  2);
        !           632:                val = ((val & 0xAA) >>  1) | ((val & 0x55) <<  1);
        !           633:
        !           634:                return val;
        !           635:        } else {
        !           636:                u_int32_t retval = 0, bit, i;
        !           637:
        !           638:                for (i = 0; i < bits; i++) {
        !           639:                        bit = (val >> i) & 1;
        !           640:                        retval = (retval << 1) | bit;
        !           641:                }
        !           642:
        !           643:                return retval;
        !           644:        }
        !           645: }
        !           646:
        !           647: u_int
        !           648: ar5k_htoclock(u_int usec, HAL_BOOL turbo)
        !           649: {
        !           650:        return (turbo == AH_TRUE ? (usec * 80) : (usec * 40));
        !           651: }
        !           652:
        !           653: u_int
        !           654: ar5k_clocktoh(u_int clock, HAL_BOOL turbo)
        !           655: {
        !           656:        return (turbo == AH_TRUE ? (clock / 80) : (clock / 40));
        !           657: }
        !           658:
        !           659: void
        !           660: ar5k_rt_copy(HAL_RATE_TABLE *dst, const HAL_RATE_TABLE *src)
        !           661: {
        !           662:        bzero(dst, sizeof(HAL_RATE_TABLE));
        !           663:        dst->rateCount = src->rateCount;
        !           664:        bcopy(src->info, dst->info, sizeof(dst->info));
        !           665: }
        !           666:
        !           667: HAL_BOOL
        !           668: ar5k_register_timeout(struct ath_hal *hal, u_int32_t reg, u_int32_t flag,
        !           669:     u_int32_t val, HAL_BOOL is_set)
        !           670: {
        !           671:        int i;
        !           672:        u_int32_t data;
        !           673:
        !           674:        for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
        !           675:                data = AR5K_REG_READ(reg);
        !           676:                if ((is_set == AH_TRUE) && (data & flag))
        !           677:                        break;
        !           678:                else if ((data & flag) == val)
        !           679:                        break;
        !           680:                AR5K_DELAY(15);
        !           681:        }
        !           682:
        !           683:        if (i <= 0)
        !           684:                return (AH_FALSE);
        !           685:
        !           686:        return (AH_TRUE);
        !           687: }
        !           688:
        !           689: /*
        !           690:  * Common ar5xx EEPROM access functions
        !           691:  */
        !           692:
        !           693: u_int16_t
        !           694: ar5k_eeprom_bin2freq(struct ath_hal *hal, u_int16_t bin, u_int mode)
        !           695: {
        !           696:        u_int16_t val;
        !           697:
        !           698:        if (bin == AR5K_EEPROM_CHANNEL_DIS)
        !           699:                return (bin);
        !           700:
        !           701:        if (mode == AR5K_EEPROM_MODE_11A) {
        !           702:                if (hal->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
        !           703:                        val = (5 * bin) + 4800;
        !           704:                else
        !           705:                        val = bin > 62 ?
        !           706:                            (10 * 62) + (5 * (bin - 62)) + 5100 :
        !           707:                            (bin * 10) + 5100;
        !           708:        } else {
        !           709:                if (hal->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
        !           710:                        val = bin + 2300;
        !           711:                else
        !           712:                        val = bin + 2400;
        !           713:        }
        !           714:
        !           715:        return (val);
        !           716: }
        !           717:
        !           718: int
        !           719: ar5k_eeprom_read_ants(struct ath_hal *hal, u_int32_t *offset, u_int mode)
        !           720: {
        !           721:        struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
        !           722:        u_int32_t o = *offset;
        !           723:        u_int16_t val;
        !           724:        int ret, i = 0;
        !           725:
        !           726:        AR5K_EEPROM_READ(o++, val);
        !           727:        ee->ee_switch_settling[mode]    = (val >> 8) & 0x7f;
        !           728:        ee->ee_ant_tx_rx[mode]          = (val >> 2) & 0x3f;
        !           729:        ee->ee_ant_control[mode][i]     = (val << 4) & 0x3f;
        !           730:
        !           731:        AR5K_EEPROM_READ(o++, val);
        !           732:        ee->ee_ant_control[mode][i++]   |= (val >> 12) & 0xf;
        !           733:        ee->ee_ant_control[mode][i++]   = (val >> 6) & 0x3f;
        !           734:        ee->ee_ant_control[mode][i++]   = val & 0x3f;
        !           735:
        !           736:        AR5K_EEPROM_READ(o++, val);
        !           737:        ee->ee_ant_control[mode][i++]   = (val >> 10) & 0x3f;
        !           738:        ee->ee_ant_control[mode][i++]   = (val >> 4) & 0x3f;
        !           739:        ee->ee_ant_control[mode][i]     = (val << 2) & 0x3f;
        !           740:
        !           741:        AR5K_EEPROM_READ(o++, val);
        !           742:        ee->ee_ant_control[mode][i++]   |= (val >> 14) & 0x3;
        !           743:        ee->ee_ant_control[mode][i++]   = (val >> 8) & 0x3f;
        !           744:        ee->ee_ant_control[mode][i++]   = (val >> 2) & 0x3f;
        !           745:        ee->ee_ant_control[mode][i]     = (val << 4) & 0x3f;
        !           746:
        !           747:        AR5K_EEPROM_READ(o++, val);
        !           748:        ee->ee_ant_control[mode][i++]   |= (val >> 12) & 0xf;
        !           749:        ee->ee_ant_control[mode][i++]   = (val >> 6) & 0x3f;
        !           750:        ee->ee_ant_control[mode][i++]   = val & 0x3f;
        !           751:
        !           752:        /* Get antenna modes */
        !           753:        hal->ah_antenna[mode][0] =
        !           754:            (ee->ee_ant_control[mode][0] << 4) | 0x1;
        !           755:        hal->ah_antenna[mode][HAL_ANT_FIXED_A] =
        !           756:            ee->ee_ant_control[mode][1] |
        !           757:            (ee->ee_ant_control[mode][2] << 6) |
        !           758:            (ee->ee_ant_control[mode][3] << 12) |
        !           759:            (ee->ee_ant_control[mode][4] << 18) |
        !           760:            (ee->ee_ant_control[mode][5] << 24);
        !           761:        hal->ah_antenna[mode][HAL_ANT_FIXED_B] =
        !           762:            ee->ee_ant_control[mode][6] |
        !           763:            (ee->ee_ant_control[mode][7] << 6) |
        !           764:            (ee->ee_ant_control[mode][8] << 12) |
        !           765:            (ee->ee_ant_control[mode][9] << 18) |
        !           766:            (ee->ee_ant_control[mode][10] << 24);
        !           767:
        !           768:        /* return new offset */
        !           769:        *offset = o;
        !           770:
        !           771:        return (0);
        !           772: }
        !           773:
        !           774: int
        !           775: ar5k_eeprom_read_modes(struct ath_hal *hal, u_int32_t *offset, u_int mode)
        !           776: {
        !           777:        struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
        !           778:        u_int32_t o = *offset;
        !           779:        u_int16_t val;
        !           780:        int ret;
        !           781:
        !           782:        AR5K_EEPROM_READ(o++, val);
        !           783:        ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
        !           784:        ee->ee_thr_62[mode]             = val & 0xff;
        !           785:
        !           786:        if (hal->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
        !           787:                ee->ee_thr_62[mode] =
        !           788:                    mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
        !           789:
        !           790:        AR5K_EEPROM_READ(o++, val);
        !           791:        ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff;
        !           792:        ee->ee_tx_frm2xpa_enable[mode]  = val & 0xff;
        !           793:
        !           794:        AR5K_EEPROM_READ(o++, val);
        !           795:        ee->ee_pga_desired_size[mode]   = (val >> 8) & 0xff;
        !           796:
        !           797:        if ((val & 0xff) & 0x80)
        !           798:                ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
        !           799:        else
        !           800:                ee->ee_noise_floor_thr[mode] = val & 0xff;
        !           801:
        !           802:        if (hal->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
        !           803:                ee->ee_noise_floor_thr[mode] =
        !           804:                    mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
        !           805:
        !           806:        AR5K_EEPROM_READ(o++, val);
        !           807:        ee->ee_xlna_gain[mode]          = (val >> 5) & 0xff;
        !           808:        ee->ee_x_gain[mode]             = (val >> 1) & 0xf;
        !           809:        ee->ee_xpd[mode]                = val & 0x1;
        !           810:
        !           811:        if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
        !           812:                ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
        !           813:
        !           814:        if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
        !           815:                AR5K_EEPROM_READ(o++, val);
        !           816:                ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
        !           817:
        !           818:                if (mode == AR5K_EEPROM_MODE_11A)
        !           819:                        ee->ee_xr_power[mode] = val & 0x3f;
        !           820:                else {
        !           821:                        ee->ee_ob[mode][0] = val & 0x7;
        !           822:                        ee->ee_db[mode][0] = (val >> 3) & 0x7;
        !           823:                }
        !           824:        }
        !           825:
        !           826:        if (hal->ah_ee_version < AR5K_EEPROM_VERSION_3_4) {
        !           827:                ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
        !           828:                ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
        !           829:        } else {
        !           830:                ee->ee_i_gain[mode] = (val >> 13) & 0x7;
        !           831:
        !           832:                AR5K_EEPROM_READ(o++, val);
        !           833:                ee->ee_i_gain[mode] |= (val << 3) & 0x38;
        !           834:
        !           835:                if (mode == AR5K_EEPROM_MODE_11G)
        !           836:                        ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
        !           837:        }
        !           838:
        !           839:        if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
        !           840:            mode == AR5K_EEPROM_MODE_11A) {
        !           841:                ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
        !           842:                ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
        !           843:        }
        !           844:
        !           845:        if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_6 &&
        !           846:            mode == AR5K_EEPROM_MODE_11G)
        !           847:                ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
        !           848:
        !           849:        /* return new offset */
        !           850:        *offset = o;
        !           851:
        !           852:        return (0);
        !           853: }
        !           854:
        !           855: int
        !           856: ar5k_eeprom_init(struct ath_hal *hal)
        !           857: {
        !           858:        struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
        !           859:        u_int32_t offset;
        !           860:        u_int16_t val;
        !           861:        int ret, i;
        !           862:        u_int mode;
        !           863:
        !           864:        /* Initial TX thermal adjustment values */
        !           865:        ee->ee_tx_clip = 4;
        !           866:        ee->ee_pwd_84 = ee->ee_pwd_90 = 1;
        !           867:        ee->ee_gain_select = 1;
        !           868:
        !           869:        /*
        !           870:         * Read values from EEPROM and store them in the capability structure
        !           871:         */
        !           872:        AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
        !           873:        AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
        !           874:        AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
        !           875:        AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
        !           876:        AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
        !           877:
        !           878:        /* Return if we have an old EEPROM */
        !           879:        if (hal->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
        !           880:                return (0);
        !           881:
        !           882: #ifdef notyet
        !           883:        /*
        !           884:         * Validate the checksum of the EEPROM date. There are some
        !           885:         * devices with invalid EEPROMs.
        !           886:         */
        !           887:        for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
        !           888:                AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
        !           889:                cksum ^= val;
        !           890:        }
        !           891:        if (cksum != AR5K_EEPROM_INFO_CKSUM) {
        !           892:                AR5K_PRINTF("Invalid EEPROM checksum 0x%04x\n", cksum);
        !           893:                return (EINVAL);
        !           894:        }
        !           895: #endif
        !           896:
        !           897:        AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(hal->ah_ee_version),
        !           898:            ee_ant_gain);
        !           899:
        !           900:        if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
        !           901:                AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
        !           902:                AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
        !           903:        }
        !           904:
        !           905:        if (hal->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
        !           906:                AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
        !           907:                ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
        !           908:                ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
        !           909:
        !           910:                AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
        !           911:                ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
        !           912:                ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
        !           913:        }
        !           914:
        !           915:        /*
        !           916:         * Get conformance test limit values
        !           917:         */
        !           918:        offset = AR5K_EEPROM_CTL(hal->ah_ee_version);
        !           919:        ee->ee_ctls = AR5K_EEPROM_N_CTLS(hal->ah_ee_version);
        !           920:
        !           921:        for (i = 0; i < ee->ee_ctls; i++) {
        !           922:                AR5K_EEPROM_READ(offset++, val);
        !           923:                ee->ee_ctl[i] = (val >> 8) & 0xff;
        !           924:                ee->ee_ctl[i + 1] = val & 0xff;
        !           925:        }
        !           926:
        !           927:        /*
        !           928:         * Get values for 802.11a (5GHz)
        !           929:         */
        !           930:        mode = AR5K_EEPROM_MODE_11A;
        !           931:
        !           932:        ee->ee_turbo_max_power[mode] =
        !           933:            AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
        !           934:
        !           935:        offset = AR5K_EEPROM_MODES_11A(hal->ah_ee_version);
        !           936:
        !           937:        if ((ret = ar5k_eeprom_read_ants(hal, &offset, mode)) != 0)
        !           938:                return (ret);
        !           939:
        !           940:        AR5K_EEPROM_READ(offset++, val);
        !           941:        ee->ee_adc_desired_size[mode]   = (int8_t)((val >> 8) & 0xff);
        !           942:        ee->ee_ob[mode][3]              = (val >> 5) & 0x7;
        !           943:        ee->ee_db[mode][3]              = (val >> 2) & 0x7;
        !           944:        ee->ee_ob[mode][2]              = (val << 1) & 0x7;
        !           945:
        !           946:        AR5K_EEPROM_READ(offset++, val);
        !           947:        ee->ee_ob[mode][2]              |= (val >> 15) & 0x1;
        !           948:        ee->ee_db[mode][2]              = (val >> 12) & 0x7;
        !           949:        ee->ee_ob[mode][1]              = (val >> 9) & 0x7;
        !           950:        ee->ee_db[mode][1]              = (val >> 6) & 0x7;
        !           951:        ee->ee_ob[mode][0]              = (val >> 3) & 0x7;
        !           952:        ee->ee_db[mode][0]              = val & 0x7;
        !           953:
        !           954:        if ((ret = ar5k_eeprom_read_modes(hal, &offset, mode)) != 0)
        !           955:                return (ret);
        !           956:
        !           957:        if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
        !           958:                AR5K_EEPROM_READ(offset++, val);
        !           959:                ee->ee_margin_tx_rx[mode] = val & 0x3f;
        !           960:        }
        !           961:
        !           962:        /*
        !           963:         * Get values for 802.11b (2.4GHz)
        !           964:         */
        !           965:        mode = AR5K_EEPROM_MODE_11B;
        !           966:        offset = AR5K_EEPROM_MODES_11B(hal->ah_ee_version);
        !           967:
        !           968:        if ((ret = ar5k_eeprom_read_ants(hal, &offset, mode)) != 0)
        !           969:                return (ret);
        !           970:
        !           971:        AR5K_EEPROM_READ(offset++, val);
        !           972:        ee->ee_adc_desired_size[mode]   = (int8_t)((val >> 8) & 0xff);
        !           973:        ee->ee_ob[mode][1]              = (val >> 4) & 0x7;
        !           974:        ee->ee_db[mode][1]              = val & 0x7;
        !           975:
        !           976:        if ((ret = ar5k_eeprom_read_modes(hal, &offset, mode)) != 0)
        !           977:                return (ret);
        !           978:
        !           979:        if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
        !           980:                AR5K_EEPROM_READ(offset++, val);
        !           981:                ee->ee_cal_pier[mode][0] =
        !           982:                    ar5k_eeprom_bin2freq(hal, val & 0xff, mode);
        !           983:                ee->ee_cal_pier[mode][1] =
        !           984:                    ar5k_eeprom_bin2freq(hal, (val >> 8) & 0xff, mode);
        !           985:
        !           986:                AR5K_EEPROM_READ(offset++, val);
        !           987:                ee->ee_cal_pier[mode][2] =
        !           988:                    ar5k_eeprom_bin2freq(hal, val & 0xff, mode);
        !           989:        }
        !           990:
        !           991:        if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
        !           992:                ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
        !           993:        }
        !           994:
        !           995:        /*
        !           996:         * Get values for 802.11g (2.4GHz)
        !           997:         */
        !           998:        mode = AR5K_EEPROM_MODE_11G;
        !           999:        offset = AR5K_EEPROM_MODES_11G(hal->ah_ee_version);
        !          1000:
        !          1001:        if ((ret = ar5k_eeprom_read_ants(hal, &offset, mode)) != 0)
        !          1002:                return (ret);
        !          1003:
        !          1004:        AR5K_EEPROM_READ(offset++, val);
        !          1005:        ee->ee_adc_desired_size[mode]   = (int8_t)((val >> 8) & 0xff);
        !          1006:        ee->ee_ob[mode][1]              = (val >> 4) & 0x7;
        !          1007:        ee->ee_db[mode][1]              = val & 0x7;
        !          1008:
        !          1009:        if ((ret = ar5k_eeprom_read_modes(hal, &offset, mode)) != 0)
        !          1010:                return (ret);
        !          1011:
        !          1012:        if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
        !          1013:                AR5K_EEPROM_READ(offset++, val);
        !          1014:                ee->ee_cal_pier[mode][0] =
        !          1015:                    ar5k_eeprom_bin2freq(hal, val & 0xff, mode);
        !          1016:                ee->ee_cal_pier[mode][1] =
        !          1017:                    ar5k_eeprom_bin2freq(hal, (val >> 8) & 0xff, mode);
        !          1018:
        !          1019:                AR5K_EEPROM_READ(offset++, val);
        !          1020:                ee->ee_turbo_max_power[mode] = val & 0x7f;
        !          1021:                ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
        !          1022:
        !          1023:                AR5K_EEPROM_READ(offset++, val);
        !          1024:                ee->ee_cal_pier[mode][2] =
        !          1025:                    ar5k_eeprom_bin2freq(hal, val & 0xff, mode);
        !          1026:
        !          1027:                if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
        !          1028:                        ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
        !          1029:                }
        !          1030:
        !          1031:                AR5K_EEPROM_READ(offset++, val);
        !          1032:                ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
        !          1033:                ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
        !          1034:
        !          1035:                if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
        !          1036:                        AR5K_EEPROM_READ(offset++, val);
        !          1037:                        ee->ee_cck_ofdm_gain_delta = val & 0xff;
        !          1038:                }
        !          1039:        }
        !          1040:
        !          1041:        /*
        !          1042:         * Read 5GHz EEPROM channels
        !          1043:         */
        !          1044:
        !          1045:        return (0);
        !          1046: }
        !          1047:
        !          1048: int
        !          1049: ar5k_eeprom_read_mac(struct ath_hal *hal, u_int8_t *mac)
        !          1050: {
        !          1051:        u_int32_t total, offset;
        !          1052:        u_int16_t data;
        !          1053:        int octet;
        !          1054:        u_int8_t mac_d[IEEE80211_ADDR_LEN];
        !          1055:
        !          1056:        bzero(mac, IEEE80211_ADDR_LEN);
        !          1057:        bzero(&mac_d, IEEE80211_ADDR_LEN);
        !          1058:
        !          1059:        if (hal->ah_eeprom_read(hal, 0x20, &data) != 0)
        !          1060:                return (EIO);
        !          1061:
        !          1062:        for (offset = 0x1f, octet = 0, total = 0;
        !          1063:             offset >= 0x1d; offset--) {
        !          1064:                if (hal->ah_eeprom_read(hal, offset, &data) != 0)
        !          1065:                        return (EIO);
        !          1066:
        !          1067:                total += data;
        !          1068:                mac_d[octet + 1] = data & 0xff;
        !          1069:                mac_d[octet] = data >> 8;
        !          1070:                octet += 2;
        !          1071:        }
        !          1072:
        !          1073:        bcopy(mac_d, mac, IEEE80211_ADDR_LEN);
        !          1074:
        !          1075:        if ((!total) || total == (3 * 0xffff))
        !          1076:                return (EINVAL);
        !          1077:
        !          1078:        return (0);
        !          1079: }
        !          1080:
        !          1081: HAL_BOOL
        !          1082: ar5k_eeprom_regulation_domain(struct ath_hal *hal, HAL_BOOL write,
        !          1083:     ieee80211_regdomain_t *regdomain)
        !          1084: {
        !          1085:        u_int16_t ee_regdomain;
        !          1086:
        !          1087:        /* Read current value */
        !          1088:        if (write != AH_TRUE) {
        !          1089:                ee_regdomain = hal->ah_capabilities.cap_eeprom.ee_regdomain;
        !          1090:                *regdomain = ar5k_regdomain_to_ieee(ee_regdomain);
        !          1091:                return (AH_TRUE);
        !          1092:        }
        !          1093:
        !          1094:        ee_regdomain = ar5k_regdomain_from_ieee(*regdomain);
        !          1095:
        !          1096:        /* Try to write a new value */
        !          1097:        if (hal->ah_capabilities.cap_eeprom.ee_protect &
        !          1098:            AR5K_EEPROM_PROTECT_WR_128_191)
        !          1099:                return (AH_FALSE);
        !          1100:        if (hal->ah_eeprom_write(hal, AR5K_EEPROM_REG_DOMAIN,
        !          1101:            ee_regdomain) != 0)
        !          1102:                return (AH_FALSE);
        !          1103:
        !          1104:        hal->ah_capabilities.cap_eeprom.ee_regdomain = ee_regdomain;
        !          1105:
        !          1106:        return (AH_TRUE);
        !          1107: }
        !          1108:
        !          1109: /*
        !          1110:  * PHY/RF access functions
        !          1111:  */
        !          1112:
        !          1113: HAL_BOOL
        !          1114: ar5k_channel(struct ath_hal *hal, HAL_CHANNEL *channel)
        !          1115: {
        !          1116:        HAL_BOOL ret;
        !          1117:
        !          1118:        /*
        !          1119:         * Check bounds supported by the PHY
        !          1120:         * (don't care about regulation restrictions at this point)
        !          1121:         */
        !          1122:        if ((channel->channel < hal->ah_capabilities.cap_range.range_2ghz_min ||
        !          1123:            channel->channel > hal->ah_capabilities.cap_range.range_2ghz_max) &&
        !          1124:            (channel->channel < hal->ah_capabilities.cap_range.range_5ghz_min ||
        !          1125:            channel->channel > hal->ah_capabilities.cap_range.range_5ghz_max)) {
        !          1126:                AR5K_PRINTF("channel out of supported range (%u MHz)\n",
        !          1127:                    channel->channel);
        !          1128:                return (AH_FALSE);
        !          1129:        }
        !          1130:
        !          1131:        /*
        !          1132:         * Set the channel and wait
        !          1133:         */
        !          1134:        if (hal->ah_radio == AR5K_AR5110)
        !          1135:                ret = ar5k_ar5110_channel(hal, channel);
        !          1136:        else if (hal->ah_radio == AR5K_AR5111)
        !          1137:                ret = ar5k_ar5111_channel(hal, channel);
        !          1138:        else
        !          1139:                ret = ar5k_ar5112_channel(hal, channel);
        !          1140:
        !          1141:        if (ret == AH_FALSE)
        !          1142:                return (ret);
        !          1143:
        !          1144:        hal->ah_current_channel.c_channel = channel->c_channel;
        !          1145:        hal->ah_current_channel.c_channel_flags = channel->c_channel_flags;
        !          1146:        hal->ah_turbo = channel->c_channel_flags == CHANNEL_T ?
        !          1147:            AH_TRUE : AH_FALSE;
        !          1148:
        !          1149:        return (AH_TRUE);
        !          1150: }
        !          1151:
        !          1152: u_int32_t
        !          1153: ar5k_ar5110_chan2athchan(HAL_CHANNEL *channel)
        !          1154: {
        !          1155:        u_int32_t athchan;
        !          1156:
        !          1157:        /*
        !          1158:         * Convert IEEE channel/MHz to an internal channel value used
        !          1159:         * by the AR5210 chipset. This has not been verified with
        !          1160:         * newer chipsets like the AR5212A who have a completely
        !          1161:         * different RF/PHY part.
        !          1162:         */
        !          1163:        athchan = (ar5k_bitswap((ieee80211_mhz2ieee(channel->c_channel,
        !          1164:            channel->c_channel_flags) - 24) / 2, 5) << 1) |
        !          1165:            (1 << 6) | 0x1;
        !          1166:
        !          1167:        return (athchan);
        !          1168: }
        !          1169:
        !          1170: HAL_BOOL
        !          1171: ar5k_ar5110_channel(struct ath_hal *hal, HAL_CHANNEL *channel)
        !          1172: {
        !          1173:        u_int32_t data;
        !          1174:
        !          1175:        /*
        !          1176:         * Set the channel and wait
        !          1177:         */
        !          1178:        data = ar5k_ar5110_chan2athchan(channel);
        !          1179:        AR5K_PHY_WRITE(0x27, data);
        !          1180:        AR5K_PHY_WRITE(0x30, 0);
        !          1181:        AR5K_DELAY(1000);
        !          1182:
        !          1183:        return (AH_TRUE);
        !          1184: }
        !          1185:
        !          1186: HAL_BOOL
        !          1187: ar5k_ar5111_chan2athchan(u_int ieee, struct ar5k_athchan_2ghz *athchan)
        !          1188: {
        !          1189:        int channel;
        !          1190:
        !          1191:        /* Cast this value to catch negative channel numbers (>= -19) */
        !          1192:        channel = (int)ieee;
        !          1193:
        !          1194:        /*
        !          1195:         * Map 2GHz IEEE channel to 5GHz Atheros channel
        !          1196:         */
        !          1197:        if (channel <= 13) {
        !          1198:                athchan->a2_athchan = 115 + channel;
        !          1199:                athchan->a2_flags = 0x46;
        !          1200:        } else if (channel == 14) {
        !          1201:                athchan->a2_athchan = 124;
        !          1202:                athchan->a2_flags = 0x44;
        !          1203:        } else if (channel >= 15 && channel <= 26) {
        !          1204:                athchan->a2_athchan = ((channel - 14) * 4) + 132;
        !          1205:                athchan->a2_flags = 0x46;
        !          1206:        } else
        !          1207:                return (AH_FALSE);
        !          1208:
        !          1209:        return (AH_TRUE);
        !          1210: }
        !          1211:
        !          1212: HAL_BOOL
        !          1213: ar5k_ar5111_channel(struct ath_hal *hal, HAL_CHANNEL *channel)
        !          1214: {
        !          1215:        u_int ieee_channel, ath_channel;
        !          1216:        u_int32_t data0, data1, clock;
        !          1217:        struct ar5k_athchan_2ghz ath_channel_2ghz;
        !          1218:
        !          1219:        /*
        !          1220:         * Set the channel on the AR5111 radio
        !          1221:         */
        !          1222:        data0 = data1 = 0;
        !          1223:        ath_channel = ieee_channel = ieee80211_mhz2ieee(channel->c_channel,
        !          1224:            channel->c_channel_flags);
        !          1225:
        !          1226:        if (channel->c_channel_flags & IEEE80211_CHAN_2GHZ) {
        !          1227:                /* Map 2GHz channel to 5GHz Atheros channel ID */
        !          1228:                if (ar5k_ar5111_chan2athchan(ieee_channel,
        !          1229:                        &ath_channel_2ghz) == AH_FALSE)
        !          1230:                        return (AH_FALSE);
        !          1231:
        !          1232:                ath_channel = ath_channel_2ghz.a2_athchan;
        !          1233:                data0 = ((ar5k_bitswap(ath_channel_2ghz.a2_flags, 8) & 0xff)
        !          1234:                    << 5) | (1 << 4);
        !          1235:        }
        !          1236:
        !          1237:        if (ath_channel < 145 || !(ath_channel & 1)) {
        !          1238:                clock = 1;
        !          1239:                data1 = ((ar5k_bitswap(ath_channel - 24, 8) & 0xff) << 2)
        !          1240:                    | (clock << 1) | (1 << 10) | 1;
        !          1241:        } else {
        !          1242:                clock = 0;
        !          1243:                data1 = ((ar5k_bitswap((ath_channel - 24) / 2, 8) & 0xff) << 2)
        !          1244:                    | (clock << 1) | (1 << 10) | 1;
        !          1245:        }
        !          1246:
        !          1247:        AR5K_PHY_WRITE(0x27, (data1 & 0xff) | ((data0 & 0xff) << 8));
        !          1248:        AR5K_PHY_WRITE(0x34, ((data1 >> 8) & 0xff) | (data0 & 0xff00));
        !          1249:
        !          1250:        return (AH_TRUE);
        !          1251: }
        !          1252:
        !          1253: HAL_BOOL
        !          1254: ar5k_ar5112_channel(struct ath_hal *hal, HAL_CHANNEL *channel)
        !          1255: {
        !          1256:        u_int32_t data, data0, data1, data2;
        !          1257:        u_int16_t c;
        !          1258:
        !          1259:        data = data0 = data1 = data2 = 0;
        !          1260:        c = channel->c_channel;
        !          1261:
        !          1262:        /*
        !          1263:         * Set the channel on the AR5112 or newer
        !          1264:         */
        !          1265:        if (c < 4800) {
        !          1266:                if (!((c - 2224) % 5)) {
        !          1267:                        data0 = ((2 * (c - 704)) - 3040) / 10;
        !          1268:                        data1 = 1;
        !          1269:                } else if (!((c - 2192) % 5)) {
        !          1270:                        data0 = ((2 * (c - 672)) - 3040) / 10;
        !          1271:                        data1 = 0;
        !          1272:                } else
        !          1273:                        return (AH_FALSE);
        !          1274:
        !          1275:                data0 = ar5k_bitswap((data0 << 2) & 0xff, 8);
        !          1276:        } else {
        !          1277:                if (!(c % 20) && c >= 5120) {
        !          1278:                        data0 = ar5k_bitswap(((c - 4800) / 20 << 2), 8);
        !          1279:                        data2 = ar5k_bitswap(3, 2);
        !          1280:                } else if (!(c % 10)) {
        !          1281:                        data0 = ar5k_bitswap(((c - 4800) / 10 << 1), 8);
        !          1282:                        data2 = ar5k_bitswap(2, 2);
        !          1283:                } else if (!(c % 5)) {
        !          1284:                        data0 = ar5k_bitswap((c - 4800) / 5, 8);
        !          1285:                        data2 = ar5k_bitswap(1, 2);
        !          1286:                } else
        !          1287:                        return (AH_FALSE);
        !          1288:        }
        !          1289:
        !          1290:        data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001;
        !          1291:
        !          1292:        AR5K_PHY_WRITE(0x27, data & 0xff);
        !          1293:        AR5K_PHY_WRITE(0x36, (data >> 8) & 0x7f);
        !          1294:
        !          1295:        return (AH_TRUE);
        !          1296: }
        !          1297:
        !          1298: u_int
        !          1299: ar5k_rfregs_op(u_int32_t *rf, u_int32_t offset, u_int32_t reg, u_int32_t bits,
        !          1300:     u_int32_t first, u_int32_t col, HAL_BOOL set)
        !          1301: {
        !          1302:        u_int32_t mask, entry, last, data, shift, position;
        !          1303:        int32_t left;
        !          1304:        int i;
        !          1305:
        !          1306:        if (rf == NULL) {
        !          1307:                /* should not happen */
        !          1308:                return (0);
        !          1309:        }
        !          1310:
        !          1311:        if (!(col <= 3 && bits <= 32 && first + bits <= 319)) {
        !          1312:                AR5K_PRINTF("invalid values at offset %u\n", offset);
        !          1313:                return (0);
        !          1314:        }
        !          1315:
        !          1316:        entry = ((first - 1) / 8) + offset;
        !          1317:        position = (first - 1) % 8;
        !          1318:
        !          1319:        if (set == AH_TRUE)
        !          1320:                data = ar5k_bitswap(reg, bits);
        !          1321:
        !          1322:        for (i = shift = 0, left = bits; left > 0; position = 0, entry++, i++) {
        !          1323:                last = (position + left > 8) ? 8 : position + left;
        !          1324:                mask = (((1 << last) - 1) ^ ((1 << position) - 1)) <<
        !          1325:                    (col * 8);
        !          1326:
        !          1327:                if (set == AH_TRUE) {
        !          1328:                        rf[entry] &= ~mask;
        !          1329:                        rf[entry] |= ((data << position) << (col * 8)) & mask;
        !          1330:                        data >>= (8 - position);
        !          1331:                } else {
        !          1332:                        data = (((rf[entry] & mask) >> (col * 8)) >>
        !          1333:                            position) << shift;
        !          1334:                        shift += last - position;
        !          1335:                }
        !          1336:
        !          1337:                left -= 8 - position;
        !          1338:        }
        !          1339:
        !          1340:        data = set == AH_TRUE ? 1 : ar5k_bitswap(data, bits);
        !          1341:
        !          1342:        return (data);
        !          1343: }
        !          1344:
        !          1345: u_int32_t
        !          1346: ar5k_rfregs_gainf_corr(struct ath_hal *hal)
        !          1347: {
        !          1348:        u_int32_t mix, step;
        !          1349:        u_int32_t *rf;
        !          1350:
        !          1351:        if (hal->ah_rf_banks == NULL)
        !          1352:                return (0);
        !          1353:
        !          1354:        rf = hal->ah_rf_banks;
        !          1355:        hal->ah_gain.g_f_corr = 0;
        !          1356:
        !          1357:        if (ar5k_rfregs_op(rf, hal->ah_offset[7], 0, 1, 36, 0, AH_FALSE) != 1)
        !          1358:                return (0);
        !          1359:
        !          1360:        step = ar5k_rfregs_op(rf, hal->ah_offset[7], 0, 4, 32, 0, AH_FALSE);
        !          1361:        mix = hal->ah_gain.g_step->gos_param[0];
        !          1362:
        !          1363:        switch (mix) {
        !          1364:        case 3:
        !          1365:                hal->ah_gain.g_f_corr = step * 2;
        !          1366:                break;
        !          1367:        case 2:
        !          1368:                hal->ah_gain.g_f_corr = (step - 5) * 2;
        !          1369:                break;
        !          1370:        case 1:
        !          1371:                hal->ah_gain.g_f_corr = step;
        !          1372:                break;
        !          1373:        default:
        !          1374:                hal->ah_gain.g_f_corr = 0;
        !          1375:                break;
        !          1376:        }
        !          1377:
        !          1378:        return (hal->ah_gain.g_f_corr);
        !          1379: }
        !          1380:
        !          1381: HAL_BOOL
        !          1382: ar5k_rfregs_gain_readback(struct ath_hal *hal)
        !          1383: {
        !          1384:        u_int32_t step, mix, level[4];
        !          1385:        u_int32_t *rf;
        !          1386:
        !          1387:        if (hal->ah_rf_banks == NULL)
        !          1388:                return (0);
        !          1389:
        !          1390:        rf = hal->ah_rf_banks;
        !          1391:
        !          1392:        if (hal->ah_radio == AR5K_AR5111) {
        !          1393:                step = ar5k_rfregs_op(rf, hal->ah_offset[7],
        !          1394:                    0, 6, 37, 0, AH_FALSE);
        !          1395:                level[0] = 0;
        !          1396:                level[1] = (step == 0x3f) ? 0x32 : step + 4;
        !          1397:                level[2] = (step != 0x3f) ? 0x40 : level[0];
        !          1398:                level[3] = level[2] + 0x32;
        !          1399:
        !          1400:                hal->ah_gain.g_high = level[3] -
        !          1401:                    (step == 0x3f ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5);
        !          1402:                hal->ah_gain.g_low = level[0] +
        !          1403:                    (step == 0x3f ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0);
        !          1404:        } else {
        !          1405:                mix = ar5k_rfregs_op(rf, hal->ah_offset[7],
        !          1406:                    0, 1, 36, 0, AH_FALSE);
        !          1407:                level[0] = level[2] = 0;
        !          1408:
        !          1409:                if (mix == 1) {
        !          1410:                        level[1] = level[3] = 83;
        !          1411:                } else {
        !          1412:                        level[1] = level[3] = 107;
        !          1413:                        hal->ah_gain.g_high = 55;
        !          1414:                }
        !          1415:        }
        !          1416:
        !          1417:        return ((hal->ah_gain.g_current >= level[0] &&
        !          1418:            hal->ah_gain.g_current <= level[1]) ||
        !          1419:            (hal->ah_gain.g_current >= level[2] &&
        !          1420:            hal->ah_gain.g_current <= level[3]));
        !          1421: }
        !          1422:
        !          1423: int32_t
        !          1424: ar5k_rfregs_gain_adjust(struct ath_hal *hal)
        !          1425: {
        !          1426:        int ret = 0;
        !          1427:        const struct ar5k_gain_opt *go;
        !          1428:
        !          1429:        go = hal->ah_radio == AR5K_AR5111 ?
        !          1430:            &ar5111_gain_opt : &ar5112_gain_opt;
        !          1431:
        !          1432:        hal->ah_gain.g_step = &go->go_step[hal->ah_gain.g_step_idx];
        !          1433:
        !          1434:        if (hal->ah_gain.g_current >= hal->ah_gain.g_high) {
        !          1435:                if (hal->ah_gain.g_step_idx == 0)
        !          1436:                        return (-1);
        !          1437:                for (hal->ah_gain.g_target = hal->ah_gain.g_current;
        !          1438:                    hal->ah_gain.g_target >=  hal->ah_gain.g_high &&
        !          1439:                    hal->ah_gain.g_step_idx > 0;
        !          1440:                    hal->ah_gain.g_step =
        !          1441:                    &go->go_step[hal->ah_gain.g_step_idx]) {
        !          1442:                        hal->ah_gain.g_target -= 2 *
        !          1443:                            (go->go_step[--(hal->ah_gain.g_step_idx)].gos_gain -
        !          1444:                            hal->ah_gain.g_step->gos_gain);
        !          1445:                }
        !          1446:
        !          1447:                ret = 1;
        !          1448:                goto done;
        !          1449:        }
        !          1450:
        !          1451:        if (hal->ah_gain.g_current <= hal->ah_gain.g_low) {
        !          1452:                if (hal->ah_gain.g_step_idx == (go->go_steps_count - 1))
        !          1453:                        return (-2);
        !          1454:                for (hal->ah_gain.g_target = hal->ah_gain.g_current;
        !          1455:                    hal->ah_gain.g_target <=  hal->ah_gain.g_low &&
        !          1456:                    hal->ah_gain.g_step_idx < (go->go_steps_count - 1);
        !          1457:                    hal->ah_gain.g_step =
        !          1458:                    &go->go_step[hal->ah_gain.g_step_idx]) {
        !          1459:                        hal->ah_gain.g_target -= 2 *
        !          1460:                            (go->go_step[++(hal->ah_gain.g_step_idx)].gos_gain -
        !          1461:                            hal->ah_gain.g_step->gos_gain);
        !          1462:                }
        !          1463:
        !          1464:                ret = 2;
        !          1465:                goto done;
        !          1466:        }
        !          1467:
        !          1468:  done:
        !          1469: #ifdef AR5K_DEBUG
        !          1470:        AR5K_PRINTF("ret %d, gain step %u, current gain %u, target gain %u\n",
        !          1471:            ret,
        !          1472:            hal->ah_gain.g_step_idx,
        !          1473:            hal->ah_gain.g_current,
        !          1474:            hal->ah_gain.g_target);
        !          1475: #endif
        !          1476:
        !          1477:        return (ret);
        !          1478: }
        !          1479:
        !          1480: HAL_BOOL
        !          1481: ar5k_rfregs(struct ath_hal *hal, HAL_CHANNEL *channel, u_int mode)
        !          1482: {
        !          1483:        ar5k_rfgain_t *func = NULL;
        !          1484:        HAL_BOOL ret;
        !          1485:
        !          1486:        if (hal->ah_radio == AR5K_AR5111) {
        !          1487:                hal->ah_rf_banks_size = sizeof(ar5111_rf);
        !          1488:                func = ar5k_ar5111_rfregs;
        !          1489:        } else if (hal->ah_radio == AR5K_AR5112) {
        !          1490:                if (hal->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A)
        !          1491:                        hal->ah_rf_banks_size = sizeof(ar5112a_rf);
        !          1492:                else
        !          1493:                        hal->ah_rf_banks_size = sizeof(ar5112_rf);
        !          1494:                func = ar5k_ar5112_rfregs;
        !          1495:        } else
        !          1496:                return (AH_FALSE);
        !          1497:
        !          1498:        if (hal->ah_rf_banks == NULL) {
        !          1499:                /* XXX do extra checks? */
        !          1500:                if ((hal->ah_rf_banks = malloc(hal->ah_rf_banks_size,
        !          1501:                    M_DEVBUF, M_NOWAIT)) == NULL) {
        !          1502:                        AR5K_PRINT("out of memory\n");
        !          1503:                        return (AH_FALSE);
        !          1504:                }
        !          1505:        }
        !          1506:
        !          1507:        ret = (func)(hal, channel, mode);
        !          1508:
        !          1509:        if (ret == AH_TRUE)
        !          1510:                hal->ah_rf_gain = HAL_RFGAIN_INACTIVE;
        !          1511:
        !          1512:        return (ret);
        !          1513: }
        !          1514:
        !          1515: HAL_BOOL
        !          1516: ar5k_ar5111_rfregs(struct ath_hal *hal, HAL_CHANNEL *channel, u_int mode)
        !          1517: {
        !          1518:        struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
        !          1519:        const u_int rf_size = AR5K_ELEMENTS(ar5111_rf);
        !          1520:        u_int32_t *rf;
        !          1521:        int i, obdb = -1, bank = -1;
        !          1522:        u_int32_t ee_mode;
        !          1523:
        !          1524:        AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
        !          1525:
        !          1526:        rf = hal->ah_rf_banks;
        !          1527:
        !          1528:        /* Copy values to modify them */
        !          1529:        for (i = 0; i < rf_size; i++) {
        !          1530:                if (ar5111_rf[i].rf_bank >=
        !          1531:                    AR5K_AR5111_INI_RF_MAX_BANKS) {
        !          1532:                        AR5K_PRINT("invalid bank\n");
        !          1533:                        return (AH_FALSE);
        !          1534:                }
        !          1535:
        !          1536:                if (bank != ar5111_rf[i].rf_bank) {
        !          1537:                        bank = ar5111_rf[i].rf_bank;
        !          1538:                        hal->ah_offset[bank] = i;
        !          1539:                }
        !          1540:
        !          1541:                rf[i] = ar5111_rf[i].rf_value[mode];
        !          1542:        }
        !          1543:
        !          1544:        if (channel->c_channel_flags & IEEE80211_CHAN_2GHZ) {
        !          1545:                if (channel->c_channel_flags & IEEE80211_CHAN_B)
        !          1546:                        ee_mode = AR5K_EEPROM_MODE_11B;
        !          1547:                else
        !          1548:                        ee_mode = AR5K_EEPROM_MODE_11G;
        !          1549:                obdb = 0;
        !          1550:
        !          1551:                if (!ar5k_rfregs_op(rf, hal->ah_offset[0],
        !          1552:                        ee->ee_ob[ee_mode][obdb], 3, 119, 0, AH_TRUE))
        !          1553:                        return (AH_FALSE);
        !          1554:
        !          1555:                if (!ar5k_rfregs_op(rf, hal->ah_offset[0],
        !          1556:                        ee->ee_ob[ee_mode][obdb], 3, 122, 0, AH_TRUE))
        !          1557:                        return (AH_FALSE);
        !          1558:
        !          1559:                obdb = 1;
        !          1560:        } else {
        !          1561:                /* For 11a, Turbo and XR */
        !          1562:                ee_mode = AR5K_EEPROM_MODE_11A;
        !          1563:                obdb = channel->c_channel >= 5725 ? 3 :
        !          1564:                    (channel->c_channel >= 5500 ? 2 :
        !          1565:                        (channel->c_channel >= 5260 ? 1 :
        !          1566:                            (channel->c_channel > 4000 ? 0 : -1)));
        !          1567:
        !          1568:                if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
        !          1569:                        ee->ee_pwd_84, 1, 51, 3, AH_TRUE))
        !          1570:                        return (AH_FALSE);
        !          1571:
        !          1572:                if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
        !          1573:                        ee->ee_pwd_90, 1, 45, 3, AH_TRUE))
        !          1574:                        return (AH_FALSE);
        !          1575:        }
        !          1576:
        !          1577:        if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
        !          1578:                !ee->ee_xpd[ee_mode], 1, 95, 0, AH_TRUE))
        !          1579:                return (AH_FALSE);
        !          1580:
        !          1581:        if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
        !          1582:                ee->ee_x_gain[ee_mode], 4, 96, 0, AH_TRUE))
        !          1583:                return (AH_FALSE);
        !          1584:
        !          1585:        if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
        !          1586:                obdb >= 0 ? ee->ee_ob[ee_mode][obdb] : 0, 3, 104, 0, AH_TRUE))
        !          1587:                return (AH_FALSE);
        !          1588:
        !          1589:        if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
        !          1590:                obdb >= 0 ? ee->ee_db[ee_mode][obdb] : 0, 3, 107, 0, AH_TRUE))
        !          1591:                return (AH_FALSE);
        !          1592:
        !          1593:        if (!ar5k_rfregs_op(rf, hal->ah_offset[7],
        !          1594:                ee->ee_i_gain[ee_mode], 6, 29, 0, AH_TRUE))
        !          1595:                return (AH_FALSE);
        !          1596:
        !          1597:        if (!ar5k_rfregs_op(rf, hal->ah_offset[7],
        !          1598:                ee->ee_xpd[ee_mode], 1, 4, 0, AH_TRUE))
        !          1599:                return (AH_FALSE);
        !          1600:
        !          1601:        /* Write RF values */
        !          1602:        for (i = 0; i < rf_size; i++) {
        !          1603:                AR5K_REG_WAIT(i);
        !          1604:                AR5K_REG_WRITE(ar5111_rf[i].rf_register, rf[i]);
        !          1605:        }
        !          1606:
        !          1607:        return (AH_TRUE);
        !          1608: }
        !          1609:
        !          1610: HAL_BOOL
        !          1611: ar5k_ar5112_rfregs(struct ath_hal *hal, HAL_CHANNEL *channel, u_int mode)
        !          1612: {
        !          1613:        struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
        !          1614:        u_int rf_size;
        !          1615:        u_int32_t *rf;
        !          1616:        int i, obdb = -1, bank = -1;
        !          1617:        u_int32_t ee_mode;
        !          1618:        const struct ar5k_ini_rf *rf_ini;
        !          1619:
        !          1620:        AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
        !          1621:
        !          1622:        rf = hal->ah_rf_banks;
        !          1623:
        !          1624:        if (hal->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
        !          1625:                rf_ini = ar5112a_rf;
        !          1626:                rf_size = AR5K_ELEMENTS(ar5112a_rf);
        !          1627:        } else {
        !          1628:                rf_ini = ar5112_rf;
        !          1629:                rf_size = AR5K_ELEMENTS(ar5112_rf);
        !          1630:        }
        !          1631:
        !          1632:        /* Copy values to modify them */
        !          1633:        for (i = 0; i < rf_size; i++) {
        !          1634:                if (rf_ini[i].rf_bank >=
        !          1635:                    AR5K_AR5112_INI_RF_MAX_BANKS) {
        !          1636:                        AR5K_PRINT("invalid bank\n");
        !          1637:                        return (AH_FALSE);
        !          1638:                }
        !          1639:
        !          1640:                if (bank != rf_ini[i].rf_bank) {
        !          1641:                        bank = rf_ini[i].rf_bank;
        !          1642:                        hal->ah_offset[bank] = i;
        !          1643:                }
        !          1644:
        !          1645:                rf[i] = rf_ini[i].rf_value[mode];
        !          1646:        }
        !          1647:
        !          1648:        if (channel->c_channel_flags & IEEE80211_CHAN_2GHZ) {
        !          1649:                if (channel->c_channel_flags & IEEE80211_CHAN_B)
        !          1650:                        ee_mode = AR5K_EEPROM_MODE_11B;
        !          1651:                else
        !          1652:                        ee_mode = AR5K_EEPROM_MODE_11G;
        !          1653:                obdb = 0;
        !          1654:
        !          1655:                if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
        !          1656:                        ee->ee_ob[ee_mode][obdb], 3, 287, 0, AH_TRUE))
        !          1657:                        return (AH_FALSE);
        !          1658:
        !          1659:                if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
        !          1660:                        ee->ee_ob[ee_mode][obdb], 3, 290, 0, AH_TRUE))
        !          1661:                        return (AH_FALSE);
        !          1662:        } else {
        !          1663:                /* For 11a, Turbo and XR */
        !          1664:                ee_mode = AR5K_EEPROM_MODE_11A;
        !          1665:                obdb = channel->c_channel >= 5725 ? 3 :
        !          1666:                    (channel->c_channel >= 5500 ? 2 :
        !          1667:                        (channel->c_channel >= 5260 ? 1 :
        !          1668:                            (channel->c_channel > 4000 ? 0 : -1)));
        !          1669:
        !          1670:                if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
        !          1671:                        ee->ee_ob[ee_mode][obdb], 3, 279, 0, AH_TRUE))
        !          1672:                        return (AH_FALSE);
        !          1673:
        !          1674:                if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
        !          1675:                        ee->ee_ob[ee_mode][obdb], 3, 282, 0, AH_TRUE))
        !          1676:                        return (AH_FALSE);
        !          1677:        }
        !          1678:
        !          1679: #ifdef notyet
        !          1680:        ar5k_rfregs_op(rf, hal->ah_offset[6],
        !          1681:            ee->ee_x_gain[ee_mode], 2, 270, 0, AH_TRUE);
        !          1682:        ar5k_rfregs_op(rf, hal->ah_offset[6],
        !          1683:            ee->ee_x_gain[ee_mode], 2, 257, 0, AH_TRUE);
        !          1684: #endif
        !          1685:
        !          1686:        if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
        !          1687:                ee->ee_xpd[ee_mode], 1, 302, 0, AH_TRUE))
        !          1688:                return (AH_FALSE);
        !          1689:
        !          1690:        if (!ar5k_rfregs_op(rf, hal->ah_offset[7],
        !          1691:                ee->ee_i_gain[ee_mode], 6, 14, 0, AH_TRUE))
        !          1692:                return (AH_FALSE);
        !          1693:
        !          1694:        /* Write RF values */
        !          1695:        for (i = 0; i < rf_size; i++)
        !          1696:                AR5K_REG_WRITE(ar5112_rf[i].rf_register, rf[i]);
        !          1697:
        !          1698:        return (AH_TRUE);
        !          1699: }
        !          1700:
        !          1701: HAL_BOOL
        !          1702: ar5k_rfgain(struct ath_hal *hal, u_int phy, u_int freq)
        !          1703: {
        !          1704:        int i;
        !          1705:
        !          1706:        switch (phy) {
        !          1707:        case AR5K_INI_PHY_5111:
        !          1708:        case AR5K_INI_PHY_5112:
        !          1709:                break;
        !          1710:        default:
        !          1711:                return (AH_FALSE);
        !          1712:        }
        !          1713:
        !          1714:        switch (freq) {
        !          1715:        case AR5K_INI_RFGAIN_2GHZ:
        !          1716:        case AR5K_INI_RFGAIN_5GHZ:
        !          1717:                break;
        !          1718:        default:
        !          1719:                return (AH_FALSE);
        !          1720:        }
        !          1721:
        !          1722:        for (i = 0; i < AR5K_ELEMENTS(ar5k_rfg); i++) {
        !          1723:                AR5K_REG_WAIT(i);
        !          1724:                AR5K_REG_WRITE((u_int32_t)ar5k_rfg[i].rfg_register,
        !          1725:                    ar5k_rfg[i].rfg_value[phy][freq]);
        !          1726:        }
        !          1727:
        !          1728:        return (AH_TRUE);
        !          1729: }
        !          1730:
        !          1731: /*
        !          1732:  * Common TX power setup
        !          1733:  */
        !          1734: void
        !          1735: ar5k_txpower_table(struct ath_hal *hal, HAL_CHANNEL *channel, int16_t max_power)
        !          1736: {
        !          1737:        u_int16_t txpower, *rates;
        !          1738:        int i, min, max, n;
        !          1739:
        !          1740:        rates = hal->ah_txpower.txp_rates;
        !          1741:
        !          1742:        txpower = AR5K_TUNE_DEFAULT_TXPOWER * 2;
        !          1743:        if (max_power > txpower) {
        !          1744:                txpower = max_power > AR5K_TUNE_MAX_TXPOWER ?
        !          1745:                    AR5K_TUNE_MAX_TXPOWER : max_power;
        !          1746:        }
        !          1747:
        !          1748:        for (i = 0; i < AR5K_MAX_RATES; i++)
        !          1749:                rates[i] = txpower;
        !          1750:
        !          1751:        /* XXX setup target powers by rate */
        !          1752:
        !          1753:        hal->ah_txpower.txp_min = rates[7];
        !          1754:        hal->ah_txpower.txp_max = rates[0];
        !          1755:        hal->ah_txpower.txp_ofdm = rates[0];
        !          1756:
        !          1757:        /* Calculate the power table */
        !          1758:        n = AR5K_ELEMENTS(hal->ah_txpower.txp_pcdac);
        !          1759:        min = AR5K_EEPROM_PCDAC_START;
        !          1760:        max = AR5K_EEPROM_PCDAC_STOP;
        !          1761:        for (i = 0; i < n; i += AR5K_EEPROM_PCDAC_STEP)
        !          1762:                hal->ah_txpower.txp_pcdac[i] =
        !          1763: #ifdef notyet
        !          1764:                    min + ((i * (max - min)) / n);
        !          1765: #else
        !          1766:                    min;
        !          1767: #endif
        !          1768: }

CVSweb