Annotation of qemu/roms/ipxe/src/drivers/net/ath5k/ath5k.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
        !             3:  * Copyright (c) 2004-2005 Atheros Communications, Inc.
        !             4:  * Copyright (c) 2006 Devicescape Software, Inc.
        !             5:  * Copyright (c) 2007 Jiri Slaby <[email protected]>
        !             6:  * Copyright (c) 2007 Luis R. Rodriguez <[email protected]>
        !             7:  *
        !             8:  * Modified for iPXE, July 2009, by Joshua Oreman <[email protected]>
        !             9:  * Original from Linux kernel 2.6.30.
        !            10:  *
        !            11:  * All rights reserved.
        !            12:  *
        !            13:  * Redistribution and use in source and binary forms, with or without
        !            14:  * modification, are permitted provided that the following conditions
        !            15:  * are met:
        !            16:  * 1. Redistributions of source code must retain the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer,
        !            18:  *    without modification.
        !            19:  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
        !            20:  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
        !            21:  *    redistribution must be conditioned upon including a substantially
        !            22:  *    similar Disclaimer requirement for further binary redistribution.
        !            23:  * 3. Neither the names of the above-listed copyright holders nor the names
        !            24:  *    of any contributors may be used to endorse or promote products derived
        !            25:  *    from this software without specific prior written permission.
        !            26:  *
        !            27:  * Alternatively, this software may be distributed under the terms of the
        !            28:  * GNU General Public License ("GPL") version 2 as published by the Free
        !            29:  * Software Foundation.
        !            30:  *
        !            31:  * NO WARRANTY
        !            32:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
        !            33:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
        !            34:  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
        !            35:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
        !            36:  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
        !            37:  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            38:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            39:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
        !            40:  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            41:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
        !            42:  * THE POSSIBILITY OF SUCH DAMAGES.
        !            43:  *
        !            44:  */
        !            45: 
        !            46: FILE_LICENCE ( BSD3 );
        !            47: 
        !            48: #include <stdlib.h>
        !            49: #include <ipxe/malloc.h>
        !            50: #include <ipxe/timer.h>
        !            51: #include <ipxe/netdevice.h>
        !            52: #include <ipxe/pci.h>
        !            53: #include <ipxe/pci_io.h>
        !            54: 
        !            55: #include "base.h"
        !            56: #include "reg.h"
        !            57: 
        !            58: #define ATH5K_CALIB_INTERVAL   10 /* Calibrate PHY every 10 seconds */
        !            59: #define ATH5K_RETRIES          4  /* Number of times to retry packet sends */
        !            60: #define ATH5K_DESC_ALIGN       16 /* Alignment for TX/RX descriptors */
        !            61: 
        !            62: /******************\
        !            63: * Internal defines *
        !            64: \******************/
        !            65: 
        !            66: /* Known PCI ids */
        !            67: static struct pci_device_id ath5k_nics[] = {
        !            68:        PCI_ROM(0x168c, 0x0207, "ath5210e", "Atheros 5210 early", AR5K_AR5210),
        !            69:        PCI_ROM(0x168c, 0x0007, "ath5210", "Atheros 5210", AR5K_AR5210),
        !            70:        PCI_ROM(0x168c, 0x0011, "ath5311", "Atheros 5311 (AHB)", AR5K_AR5211),
        !            71:        PCI_ROM(0x168c, 0x0012, "ath5211", "Atheros 5211", AR5K_AR5211),
        !            72:        PCI_ROM(0x168c, 0x0013, "ath5212", "Atheros 5212", AR5K_AR5212),
        !            73:        PCI_ROM(0xa727, 0x0013, "ath5212c","3com Ath 5212", AR5K_AR5212),
        !            74:        PCI_ROM(0x10b7, 0x0013, "rdag675", "3com 3CRDAG675", AR5K_AR5212),
        !            75:        PCI_ROM(0x168c, 0x1014, "ath5212m", "Ath 5212 miniPCI", AR5K_AR5212),
        !            76:        PCI_ROM(0x168c, 0x0014, "ath5212x14", "Atheros 5212 x14", AR5K_AR5212),
        !            77:        PCI_ROM(0x168c, 0x0015, "ath5212x15", "Atheros 5212 x15", AR5K_AR5212),
        !            78:        PCI_ROM(0x168c, 0x0016, "ath5212x16", "Atheros 5212 x16", AR5K_AR5212),
        !            79:        PCI_ROM(0x168c, 0x0017, "ath5212x17", "Atheros 5212 x17", AR5K_AR5212),
        !            80:        PCI_ROM(0x168c, 0x0018, "ath5212x18", "Atheros 5212 x18", AR5K_AR5212),
        !            81:        PCI_ROM(0x168c, 0x0019, "ath5212x19", "Atheros 5212 x19", AR5K_AR5212),
        !            82:        PCI_ROM(0x168c, 0x001a, "ath2413", "Atheros 2413 Griffin", AR5K_AR5212),
        !            83:        PCI_ROM(0x168c, 0x001b, "ath5413", "Atheros 5413 Eagle", AR5K_AR5212),
        !            84:        PCI_ROM(0x168c, 0x001c, "ath5212e", "Atheros 5212 PCI-E", AR5K_AR5212),
        !            85:        PCI_ROM(0x168c, 0x001d, "ath2417", "Atheros 2417 Nala", AR5K_AR5212),
        !            86: };
        !            87: 
        !            88: /* Known SREVs */
        !            89: static const struct ath5k_srev_name srev_names[] = {
        !            90:        { "5210",       AR5K_VERSION_MAC,       AR5K_SREV_AR5210 },
        !            91:        { "5311",       AR5K_VERSION_MAC,       AR5K_SREV_AR5311 },
        !            92:        { "5311A",      AR5K_VERSION_MAC,       AR5K_SREV_AR5311A },
        !            93:        { "5311B",      AR5K_VERSION_MAC,       AR5K_SREV_AR5311B },
        !            94:        { "5211",       AR5K_VERSION_MAC,       AR5K_SREV_AR5211 },
        !            95:        { "5212",       AR5K_VERSION_MAC,       AR5K_SREV_AR5212 },
        !            96:        { "5213",       AR5K_VERSION_MAC,       AR5K_SREV_AR5213 },
        !            97:        { "5213A",      AR5K_VERSION_MAC,       AR5K_SREV_AR5213A },
        !            98:        { "2413",       AR5K_VERSION_MAC,       AR5K_SREV_AR2413 },
        !            99:        { "2414",       AR5K_VERSION_MAC,       AR5K_SREV_AR2414 },
        !           100:        { "5424",       AR5K_VERSION_MAC,       AR5K_SREV_AR5424 },
        !           101:        { "5413",       AR5K_VERSION_MAC,       AR5K_SREV_AR5413 },
        !           102:        { "5414",       AR5K_VERSION_MAC,       AR5K_SREV_AR5414 },
        !           103:        { "2415",       AR5K_VERSION_MAC,       AR5K_SREV_AR2415 },
        !           104:        { "5416",       AR5K_VERSION_MAC,       AR5K_SREV_AR5416 },
        !           105:        { "5418",       AR5K_VERSION_MAC,       AR5K_SREV_AR5418 },
        !           106:        { "2425",       AR5K_VERSION_MAC,       AR5K_SREV_AR2425 },
        !           107:        { "2417",       AR5K_VERSION_MAC,       AR5K_SREV_AR2417 },
        !           108:        { "xxxxx",      AR5K_VERSION_MAC,       AR5K_SREV_UNKNOWN },
        !           109:        { "5110",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5110 },
        !           110:        { "5111",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5111 },
        !           111:        { "5111A",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_5111A },
        !           112:        { "2111",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_2111 },
        !           113:        { "5112",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5112 },
        !           114:        { "5112A",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_5112A },
        !           115:        { "5112B",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_5112B },
        !           116:        { "2112",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_2112 },
        !           117:        { "2112A",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_2112A },
        !           118:        { "2112B",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_2112B },
        !           119:        { "2413",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_2413 },
        !           120:        { "5413",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5413 },
        !           121:        { "2316",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_2316 },
        !           122:        { "2317",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_2317 },
        !           123:        { "5424",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5424 },
        !           124:        { "5133",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5133 },
        !           125:        { "xxxxx",      AR5K_VERSION_RAD,       AR5K_SREV_UNKNOWN },
        !           126: };
        !           127: 
        !           128: #define ATH5K_SPMBL_NO   1
        !           129: #define ATH5K_SPMBL_YES  2
        !           130: #define ATH5K_SPMBL_BOTH 3
        !           131: 
        !           132: static const struct {
        !           133:        u16 bitrate;
        !           134:        u8 short_pmbl;
        !           135:        u8 hw_code;
        !           136: } ath5k_rates[] = {
        !           137:        { 10, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_1M },
        !           138:        { 20, ATH5K_SPMBL_NO, ATH5K_RATE_CODE_2M },
        !           139:        { 55, ATH5K_SPMBL_NO, ATH5K_RATE_CODE_5_5M },
        !           140:        { 110, ATH5K_SPMBL_NO, ATH5K_RATE_CODE_11M },
        !           141:        { 60, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_6M },
        !           142:        { 90, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_9M },
        !           143:        { 120, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_12M },
        !           144:        { 180, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_18M },
        !           145:        { 240, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_24M },
        !           146:        { 360, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_36M },
        !           147:        { 480, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_48M },
        !           148:        { 540, ATH5K_SPMBL_BOTH, ATH5K_RATE_CODE_54M },
        !           149:        { 20, ATH5K_SPMBL_YES, ATH5K_RATE_CODE_2M | AR5K_SET_SHORT_PREAMBLE },
        !           150:        { 55, ATH5K_SPMBL_YES, ATH5K_RATE_CODE_5_5M | AR5K_SET_SHORT_PREAMBLE },
        !           151:        { 110, ATH5K_SPMBL_YES, ATH5K_RATE_CODE_11M | AR5K_SET_SHORT_PREAMBLE },
        !           152:        { 0, 0, 0 },
        !           153: };
        !           154: 
        !           155: #define ATH5K_NR_RATES 15
        !           156: 
        !           157: /*
        !           158:  * Prototypes - PCI stack related functions
        !           159:  */
        !           160: static int             ath5k_probe(struct pci_device *pdev);
        !           161: static void            ath5k_remove(struct pci_device *pdev);
        !           162: 
        !           163: struct pci_driver ath5k_pci_driver __pci_driver = {
        !           164:        .ids            = ath5k_nics,
        !           165:        .id_count       = sizeof(ath5k_nics) / sizeof(ath5k_nics[0]),
        !           166:        .probe          = ath5k_probe,
        !           167:        .remove         = ath5k_remove,
        !           168: };
        !           169: 
        !           170: 
        !           171: 
        !           172: /*
        !           173:  * Prototypes - MAC 802.11 stack related functions
        !           174:  */
        !           175: static int ath5k_tx(struct net80211_device *dev, struct io_buffer *skb);
        !           176: static int ath5k_reset(struct ath5k_softc *sc, struct net80211_channel *chan);
        !           177: static int ath5k_reset_wake(struct ath5k_softc *sc);
        !           178: static int ath5k_start(struct net80211_device *dev);
        !           179: static void ath5k_stop(struct net80211_device *dev);
        !           180: static int ath5k_config(struct net80211_device *dev, int changed);
        !           181: static void ath5k_poll(struct net80211_device *dev);
        !           182: static void ath5k_irq(struct net80211_device *dev, int enable);
        !           183: 
        !           184: static struct net80211_device_operations ath5k_ops = {
        !           185:        .open           = ath5k_start,
        !           186:        .close          = ath5k_stop,
        !           187:        .transmit       = ath5k_tx,
        !           188:        .poll           = ath5k_poll,
        !           189:        .irq            = ath5k_irq,
        !           190:        .config         = ath5k_config,
        !           191: };
        !           192: 
        !           193: /*
        !           194:  * Prototypes - Internal functions
        !           195:  */
        !           196: /* Attach detach */
        !           197: static int     ath5k_attach(struct net80211_device *dev);
        !           198: static void    ath5k_detach(struct net80211_device *dev);
        !           199: /* Channel/mode setup */
        !           200: static unsigned int ath5k_copy_channels(struct ath5k_hw *ah,
        !           201:                                struct net80211_channel *channels,
        !           202:                                unsigned int mode,
        !           203:                                unsigned int max);
        !           204: static int     ath5k_setup_bands(struct net80211_device *dev);
        !           205: static int     ath5k_chan_set(struct ath5k_softc *sc,
        !           206:                                struct net80211_channel *chan);
        !           207: static void    ath5k_setcurmode(struct ath5k_softc *sc,
        !           208:                                unsigned int mode);
        !           209: static void    ath5k_mode_setup(struct ath5k_softc *sc);
        !           210: 
        !           211: /* Descriptor setup */
        !           212: static int     ath5k_desc_alloc(struct ath5k_softc *sc);
        !           213: static void    ath5k_desc_free(struct ath5k_softc *sc);
        !           214: /* Buffers setup */
        !           215: static int     ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf);
        !           216: static int     ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf);
        !           217: 
        !           218: static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
        !           219:                                    struct ath5k_buf *bf)
        !           220: {
        !           221:        if (!bf->iob)
        !           222:                return;
        !           223: 
        !           224:        net80211_tx_complete(sc->dev, bf->iob, 0, ECANCELED);
        !           225:        bf->iob = NULL;
        !           226: }
        !           227: 
        !           228: static inline void ath5k_rxbuf_free(struct ath5k_softc *sc __unused,
        !           229:                                    struct ath5k_buf *bf)
        !           230: {
        !           231:        free_iob(bf->iob);
        !           232:        bf->iob = NULL;
        !           233: }
        !           234: 
        !           235: /* Queues setup */
        !           236: static int     ath5k_txq_setup(struct ath5k_softc *sc,
        !           237:                                           int qtype, int subtype);
        !           238: static void    ath5k_txq_drainq(struct ath5k_softc *sc,
        !           239:                                 struct ath5k_txq *txq);
        !           240: static void    ath5k_txq_cleanup(struct ath5k_softc *sc);
        !           241: static void    ath5k_txq_release(struct ath5k_softc *sc);
        !           242: /* Rx handling */
        !           243: static int     ath5k_rx_start(struct ath5k_softc *sc);
        !           244: static void    ath5k_rx_stop(struct ath5k_softc *sc);
        !           245: /* Tx handling */
        !           246: static void    ath5k_tx_processq(struct ath5k_softc *sc,
        !           247:                                  struct ath5k_txq *txq);
        !           248: 
        !           249: /* Interrupt handling */
        !           250: static int     ath5k_init(struct ath5k_softc *sc);
        !           251: static int     ath5k_stop_hw(struct ath5k_softc *sc);
        !           252: 
        !           253: static void    ath5k_calibrate(struct ath5k_softc *sc);
        !           254: 
        !           255: /* Filter */
        !           256: static void    ath5k_configure_filter(struct ath5k_softc *sc);
        !           257: 
        !           258: /********************\
        !           259: * PCI Initialization *
        !           260: \********************/
        !           261: 
        !           262: #if DBGLVL_MAX
        !           263: static const char *
        !           264: ath5k_chip_name(enum ath5k_srev_type type, u16 val)
        !           265: {
        !           266:        const char *name = "xxxxx";
        !           267:        unsigned int i;
        !           268: 
        !           269:        for (i = 0; i < ARRAY_SIZE(srev_names); i++) {
        !           270:                if (srev_names[i].sr_type != type)
        !           271:                        continue;
        !           272: 
        !           273:                if ((val & 0xf0) == srev_names[i].sr_val)
        !           274:                        name = srev_names[i].sr_name;
        !           275: 
        !           276:                if ((val & 0xff) == srev_names[i].sr_val) {
        !           277:                        name = srev_names[i].sr_name;
        !           278:                        break;
        !           279:                }
        !           280:        }
        !           281: 
        !           282:        return name;
        !           283: }
        !           284: #endif
        !           285: 
        !           286: static int ath5k_probe(struct pci_device *pdev)
        !           287: {
        !           288:        void *mem;
        !           289:        struct ath5k_softc *sc;
        !           290:        struct net80211_device *dev;
        !           291:        int ret;
        !           292:        u8 csz;
        !           293: 
        !           294:        adjust_pci_device(pdev);
        !           295: 
        !           296:        /*
        !           297:         * Cache line size is used to size and align various
        !           298:         * structures used to communicate with the hardware.
        !           299:         */
        !           300:        pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
        !           301:        if (csz == 0) {
        !           302:                /*
        !           303:                 * We must have this setup properly for rx buffer
        !           304:                 * DMA to work so force a reasonable value here if it
        !           305:                 * comes up zero.
        !           306:                 */
        !           307:                csz = 16;
        !           308:                pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
        !           309:        }
        !           310:        /*
        !           311:         * The default setting of latency timer yields poor results,
        !           312:         * set it to the value used by other systems.  It may be worth
        !           313:         * tweaking this setting more.
        !           314:         */
        !           315:        pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
        !           316: 
        !           317:        /*
        !           318:         * Disable the RETRY_TIMEOUT register (0x41) to keep
        !           319:         * PCI Tx retries from interfering with C3 CPU state.
        !           320:         */
        !           321:        pci_write_config_byte(pdev, 0x41, 0);
        !           322: 
        !           323:        mem = ioremap(pdev->membase, 0x10000);
        !           324:        if (!mem) {
        !           325:                DBG("ath5k: cannot remap PCI memory region\n");
        !           326:                ret = -EIO;
        !           327:                goto err;
        !           328:        }
        !           329: 
        !           330:        /*
        !           331:         * Allocate dev (net80211 main struct)
        !           332:         * and dev->priv (driver private data)
        !           333:         */
        !           334:        dev = net80211_alloc(sizeof(*sc));
        !           335:        if (!dev) {
        !           336:                DBG("ath5k: cannot allocate 802.11 device\n");
        !           337:                ret = -ENOMEM;
        !           338:                goto err_map;
        !           339:        }
        !           340: 
        !           341:        /* Initialize driver private data */
        !           342:        sc = dev->priv;
        !           343:        sc->dev = dev;
        !           344:        sc->pdev = pdev;
        !           345: 
        !           346:        sc->hwinfo = zalloc(sizeof(*sc->hwinfo));
        !           347:        if (!sc->hwinfo) {
        !           348:                DBG("ath5k: cannot allocate 802.11 hardware info structure\n");
        !           349:                ret = -ENOMEM;
        !           350:                goto err_free;
        !           351:        }
        !           352: 
        !           353:        sc->hwinfo->flags = NET80211_HW_RX_HAS_FCS;
        !           354:        sc->hwinfo->signal_type = NET80211_SIGNAL_DB;
        !           355:        sc->hwinfo->signal_max = 40; /* 35dB should give perfect 54Mbps */
        !           356:        sc->hwinfo->channel_change_time = 5000;
        !           357: 
        !           358:        /* Avoid working with the device until setup is complete */
        !           359:        sc->status |= ATH_STAT_INVALID;
        !           360: 
        !           361:        sc->iobase = mem;
        !           362:        sc->cachelsz = csz * 4; /* convert to bytes */
        !           363: 
        !           364:        DBG("ath5k: register base at %p (%08lx)\n", sc->iobase, pdev->membase);
        !           365:        DBG("ath5k: cache line size %d\n", sc->cachelsz);
        !           366: 
        !           367:        /* Set private data */
        !           368:        pci_set_drvdata(pdev, dev);
        !           369:        dev->netdev->dev = (struct device *)pdev;
        !           370: 
        !           371:        /* Initialize device */
        !           372:        ret = ath5k_hw_attach(sc, pdev->id->driver_data, &sc->ah);
        !           373:        if (ret)
        !           374:                goto err_free_hwinfo;
        !           375: 
        !           376:        /* Finish private driver data initialization */
        !           377:        ret = ath5k_attach(dev);
        !           378:        if (ret)
        !           379:                goto err_ah;
        !           380: 
        !           381: #if DBGLVL_MAX
        !           382:        DBG("Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
        !           383:            ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
        !           384:            sc->ah->ah_mac_srev, sc->ah->ah_phy_revision);
        !           385: 
        !           386:        if (!sc->ah->ah_single_chip) {
        !           387:                /* Single chip radio (!RF5111) */
        !           388:                if (sc->ah->ah_radio_5ghz_revision &&
        !           389:                    !sc->ah->ah_radio_2ghz_revision) {
        !           390:                        /* No 5GHz support -> report 2GHz radio */
        !           391:                        if (!(sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11A)) {
        !           392:                                DBG("RF%s 2GHz radio found (0x%x)\n",
        !           393:                                    ath5k_chip_name(AR5K_VERSION_RAD,
        !           394:                                                    sc->ah->ah_radio_5ghz_revision),
        !           395:                                    sc->ah->ah_radio_5ghz_revision);
        !           396:                        /* No 2GHz support (5110 and some
        !           397:                         * 5Ghz only cards) -> report 5Ghz radio */
        !           398:                        } else if (!(sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11B)) {
        !           399:                                DBG("RF%s 5GHz radio found (0x%x)\n",
        !           400:                                    ath5k_chip_name(AR5K_VERSION_RAD,
        !           401:                                                    sc->ah->ah_radio_5ghz_revision),
        !           402:                                    sc->ah->ah_radio_5ghz_revision);
        !           403:                        /* Multiband radio */
        !           404:                        } else {
        !           405:                                DBG("RF%s multiband radio found (0x%x)\n",
        !           406:                                    ath5k_chip_name(AR5K_VERSION_RAD,
        !           407:                                                    sc->ah->ah_radio_5ghz_revision),
        !           408:                                    sc->ah->ah_radio_5ghz_revision);
        !           409:                        }
        !           410:                }
        !           411:                /* Multi chip radio (RF5111 - RF2111) ->
        !           412:                 * report both 2GHz/5GHz radios */
        !           413:                else if (sc->ah->ah_radio_5ghz_revision &&
        !           414:                         sc->ah->ah_radio_2ghz_revision) {
        !           415:                        DBG("RF%s 5GHz radio found (0x%x)\n",
        !           416:                            ath5k_chip_name(AR5K_VERSION_RAD,
        !           417:                                            sc->ah->ah_radio_5ghz_revision),
        !           418:                            sc->ah->ah_radio_5ghz_revision);
        !           419:                        DBG("RF%s 2GHz radio found (0x%x)\n",
        !           420:                            ath5k_chip_name(AR5K_VERSION_RAD,
        !           421:                                            sc->ah->ah_radio_2ghz_revision),
        !           422:                            sc->ah->ah_radio_2ghz_revision);
        !           423:                }
        !           424:        }
        !           425: #endif
        !           426: 
        !           427:        /* Ready to go */
        !           428:        sc->status &= ~ATH_STAT_INVALID;
        !           429: 
        !           430:        return 0;
        !           431: err_ah:
        !           432:        ath5k_hw_detach(sc->ah);
        !           433: err_free_hwinfo:
        !           434:        free(sc->hwinfo);
        !           435: err_free:
        !           436:        net80211_free(dev);
        !           437: err_map:
        !           438:        iounmap(mem);
        !           439: err:
        !           440:        return ret;
        !           441: }
        !           442: 
        !           443: static void ath5k_remove(struct pci_device *pdev)
        !           444: {
        !           445:        struct net80211_device *dev = pci_get_drvdata(pdev);
        !           446:        struct ath5k_softc *sc = dev->priv;
        !           447: 
        !           448:        ath5k_detach(dev);
        !           449:        ath5k_hw_detach(sc->ah);
        !           450:        iounmap(sc->iobase);
        !           451:        free(sc->hwinfo);
        !           452:        net80211_free(dev);
        !           453: }
        !           454: 
        !           455: 
        !           456: /***********************\
        !           457: * Driver Initialization *
        !           458: \***********************/
        !           459: 
        !           460: static int
        !           461: ath5k_attach(struct net80211_device *dev)
        !           462: {
        !           463:        struct ath5k_softc *sc = dev->priv;
        !           464:        struct ath5k_hw *ah = sc->ah;
        !           465:        int ret;
        !           466: 
        !           467:        /*
        !           468:         * Collect the channel list.  The 802.11 layer
        !           469:         * is resposible for filtering this list based
        !           470:         * on settings like the phy mode and regulatory
        !           471:         * domain restrictions.
        !           472:         */
        !           473:        ret = ath5k_setup_bands(dev);
        !           474:        if (ret) {
        !           475:                DBG("ath5k: can't get channels\n");
        !           476:                goto err;
        !           477:        }
        !           478: 
        !           479:        /* NB: setup here so ath5k_rate_update is happy */
        !           480:        if (ah->ah_modes & AR5K_MODE_BIT_11A)
        !           481:                ath5k_setcurmode(sc, AR5K_MODE_11A);
        !           482:        else
        !           483:                ath5k_setcurmode(sc, AR5K_MODE_11B);
        !           484: 
        !           485:        /*
        !           486:         * Allocate tx+rx descriptors and populate the lists.
        !           487:         */
        !           488:        ret = ath5k_desc_alloc(sc);
        !           489:        if (ret) {
        !           490:                DBG("ath5k: can't allocate descriptors\n");
        !           491:                goto err;
        !           492:        }
        !           493: 
        !           494:        /*
        !           495:         * Allocate hardware transmit queues. Note that hw functions
        !           496:         * handle reseting these queues at the needed time.
        !           497:         */
        !           498:        ret = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
        !           499:        if (ret) {
        !           500:                DBG("ath5k: can't setup xmit queue\n");
        !           501:                goto err_desc;
        !           502:        }
        !           503: 
        !           504:        sc->last_calib_ticks = currticks();
        !           505: 
        !           506:        ret = ath5k_eeprom_read_mac(ah, sc->hwinfo->hwaddr);
        !           507:        if (ret) {
        !           508:                DBG("ath5k: unable to read address from EEPROM: 0x%04x\n",
        !           509:                    sc->pdev->device);
        !           510:                goto err_queues;
        !           511:        }
        !           512: 
        !           513:        memset(sc->bssidmask, 0xff, ETH_ALEN);
        !           514:        ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
        !           515: 
        !           516:        ret = net80211_register(sc->dev, &ath5k_ops, sc->hwinfo);
        !           517:        if (ret) {
        !           518:                DBG("ath5k: can't register ieee80211 hw\n");
        !           519:                goto err_queues;
        !           520:        }
        !           521: 
        !           522:        return 0;
        !           523: err_queues:
        !           524:        ath5k_txq_release(sc);
        !           525: err_desc:
        !           526:        ath5k_desc_free(sc);
        !           527: err:
        !           528:        return ret;
        !           529: }
        !           530: 
        !           531: static void
        !           532: ath5k_detach(struct net80211_device *dev)
        !           533: {
        !           534:        struct ath5k_softc *sc = dev->priv;
        !           535: 
        !           536:        net80211_unregister(dev);
        !           537:        ath5k_desc_free(sc);
        !           538:        ath5k_txq_release(sc);
        !           539: }
        !           540: 
        !           541: 
        !           542: 
        !           543: 
        !           544: /********************\
        !           545: * Channel/mode setup *
        !           546: \********************/
        !           547: 
        !           548: /*
        !           549:  * Convert IEEE channel number to MHz frequency.
        !           550:  */
        !           551: static inline short
        !           552: ath5k_ieee2mhz(short chan)
        !           553: {
        !           554:        if (chan < 14)
        !           555:                return 2407 + 5 * chan;
        !           556:        if (chan == 14)
        !           557:                return 2484;
        !           558:        if (chan < 27)
        !           559:                return 2212 + 20 * chan;
        !           560:        return 5000 + 5 * chan;
        !           561: }
        !           562: 
        !           563: static unsigned int
        !           564: ath5k_copy_channels(struct ath5k_hw *ah,
        !           565:                    struct net80211_channel *channels,
        !           566:                    unsigned int mode, unsigned int max)
        !           567: {
        !           568:        unsigned int i, count, size, chfreq, freq, ch;
        !           569: 
        !           570:        if (!(ah->ah_modes & (1 << mode)))
        !           571:                return 0;
        !           572: 
        !           573:        switch (mode) {
        !           574:        case AR5K_MODE_11A:
        !           575:        case AR5K_MODE_11A_TURBO:
        !           576:                /* 1..220, but 2GHz frequencies are filtered by check_channel */
        !           577:                size = 220;
        !           578:                chfreq = CHANNEL_5GHZ;
        !           579:                break;
        !           580:        case AR5K_MODE_11B:
        !           581:        case AR5K_MODE_11G:
        !           582:        case AR5K_MODE_11G_TURBO:
        !           583:                size = 26;
        !           584:                chfreq = CHANNEL_2GHZ;
        !           585:                break;
        !           586:        default:
        !           587:                return 0;
        !           588:        }
        !           589: 
        !           590:        for (i = 0, count = 0; i < size && max > 0; i++) {
        !           591:                ch = i + 1 ;
        !           592:                freq = ath5k_ieee2mhz(ch);
        !           593: 
        !           594:                /* Check if channel is supported by the chipset */
        !           595:                if (!ath5k_channel_ok(ah, freq, chfreq))
        !           596:                        continue;
        !           597: 
        !           598:                /* Write channel info and increment counter */
        !           599:                channels[count].center_freq = freq;
        !           600:                channels[count].maxpower = 0; /* use regulatory */
        !           601:                channels[count].band = (chfreq == CHANNEL_2GHZ) ?
        !           602:                        NET80211_BAND_2GHZ : NET80211_BAND_5GHZ;
        !           603:                switch (mode) {
        !           604:                case AR5K_MODE_11A:
        !           605:                case AR5K_MODE_11G:
        !           606:                        channels[count].hw_value = chfreq | CHANNEL_OFDM;
        !           607:                        break;
        !           608:                case AR5K_MODE_11A_TURBO:
        !           609:                case AR5K_MODE_11G_TURBO:
        !           610:                        channels[count].hw_value = chfreq |
        !           611:                                CHANNEL_OFDM | CHANNEL_TURBO;
        !           612:                        break;
        !           613:                case AR5K_MODE_11B:
        !           614:                        channels[count].hw_value = CHANNEL_B;
        !           615:                }
        !           616: 
        !           617:                count++;
        !           618:                max--;
        !           619:        }
        !           620: 
        !           621:        return count;
        !           622: }
        !           623: 
        !           624: static int
        !           625: ath5k_setup_bands(struct net80211_device *dev)
        !           626: {
        !           627:        struct ath5k_softc *sc = dev->priv;
        !           628:        struct ath5k_hw *ah = sc->ah;
        !           629:        int max_c, count_c = 0;
        !           630:        int i;
        !           631:        int band;
        !           632: 
        !           633:        max_c = sizeof(sc->hwinfo->channels) / sizeof(sc->hwinfo->channels[0]);
        !           634: 
        !           635:        /* 2GHz band */
        !           636:        if (sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11G) {
        !           637:                /* G mode */
        !           638:                band = NET80211_BAND_2GHZ;
        !           639:                sc->hwinfo->bands = NET80211_BAND_BIT_2GHZ;
        !           640:                sc->hwinfo->modes = (NET80211_MODE_G | NET80211_MODE_B);
        !           641: 
        !           642:                for (i = 0; i < 12; i++)
        !           643:                        sc->hwinfo->rates[band][i] = ath5k_rates[i].bitrate;
        !           644:                sc->hwinfo->nr_rates[band] = 12;
        !           645: 
        !           646:                sc->hwinfo->nr_channels =
        !           647:                        ath5k_copy_channels(ah, sc->hwinfo->channels,
        !           648:                                            AR5K_MODE_11G, max_c);
        !           649:                count_c = sc->hwinfo->nr_channels;
        !           650:                max_c -= count_c;
        !           651:        } else if (sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11B) {
        !           652:                /* B mode */
        !           653:                band = NET80211_BAND_2GHZ;
        !           654:                sc->hwinfo->bands = NET80211_BAND_BIT_2GHZ;
        !           655:                sc->hwinfo->modes = NET80211_MODE_B;
        !           656: 
        !           657:                for (i = 0; i < 4; i++)
        !           658:                        sc->hwinfo->rates[band][i] = ath5k_rates[i].bitrate;
        !           659:                sc->hwinfo->nr_rates[band] = 4;
        !           660: 
        !           661:                sc->hwinfo->nr_channels =
        !           662:                        ath5k_copy_channels(ah, sc->hwinfo->channels,
        !           663:                                            AR5K_MODE_11B, max_c);
        !           664:                count_c = sc->hwinfo->nr_channels;
        !           665:                max_c -= count_c;
        !           666:        }
        !           667: 
        !           668:        /* 5GHz band, A mode */
        !           669:        if (sc->ah->ah_capabilities.cap_mode & AR5K_MODE_BIT_11A) {
        !           670:                band = NET80211_BAND_5GHZ;
        !           671:                sc->hwinfo->bands |= NET80211_BAND_BIT_5GHZ;
        !           672:                sc->hwinfo->modes |= NET80211_MODE_A;
        !           673: 
        !           674:                for (i = 0; i < 8; i++)
        !           675:                        sc->hwinfo->rates[band][i] = ath5k_rates[i+4].bitrate;
        !           676:                sc->hwinfo->nr_rates[band] = 8;
        !           677: 
        !           678:                sc->hwinfo->nr_channels =
        !           679:                        ath5k_copy_channels(ah, sc->hwinfo->channels,
        !           680:                                            AR5K_MODE_11B, max_c);
        !           681:                count_c = sc->hwinfo->nr_channels;
        !           682:                max_c -= count_c;
        !           683:        }
        !           684: 
        !           685:        return 0;
        !           686: }
        !           687: 
        !           688: /*
        !           689:  * Set/change channels.  If the channel is really being changed,
        !           690:  * it's done by reseting the chip.  To accomplish this we must
        !           691:  * first cleanup any pending DMA, then restart stuff after a la
        !           692:  * ath5k_init.
        !           693:  */
        !           694: static int
        !           695: ath5k_chan_set(struct ath5k_softc *sc, struct net80211_channel *chan)
        !           696: {
        !           697:        if (chan->center_freq != sc->curchan->center_freq ||
        !           698:            chan->hw_value != sc->curchan->hw_value) {
        !           699:                /*
        !           700:                 * To switch channels clear any pending DMA operations;
        !           701:                 * wait long enough for the RX fifo to drain, reset the
        !           702:                 * hardware at the new frequency, and then re-enable
        !           703:                 * the relevant bits of the h/w.
        !           704:                 */
        !           705:                DBG2("ath5k: resetting for channel change (%d -> %d MHz)\n",
        !           706:                     sc->curchan->center_freq, chan->center_freq);
        !           707:                return ath5k_reset(sc, chan);
        !           708:        }
        !           709: 
        !           710:        return 0;
        !           711: }
        !           712: 
        !           713: static void
        !           714: ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
        !           715: {
        !           716:        sc->curmode = mode;
        !           717: 
        !           718:        if (mode == AR5K_MODE_11A) {
        !           719:                sc->curband = NET80211_BAND_5GHZ;
        !           720:        } else {
        !           721:                sc->curband = NET80211_BAND_2GHZ;
        !           722:        }
        !           723: }
        !           724: 
        !           725: static void
        !           726: ath5k_mode_setup(struct ath5k_softc *sc)
        !           727: {
        !           728:        struct ath5k_hw *ah = sc->ah;
        !           729:        u32 rfilt;
        !           730: 
        !           731:        /* configure rx filter */
        !           732:        rfilt = sc->filter_flags;
        !           733:        ath5k_hw_set_rx_filter(ah, rfilt);
        !           734: 
        !           735:        if (ath5k_hw_hasbssidmask(ah))
        !           736:                ath5k_hw_set_bssid_mask(ah, sc->bssidmask);
        !           737: 
        !           738:        /* configure operational mode */
        !           739:        ath5k_hw_set_opmode(ah);
        !           740: 
        !           741:        ath5k_hw_set_mcast_filter(ah, 0, 0);
        !           742: }
        !           743: 
        !           744: static inline int
        !           745: ath5k_hw_rix_to_bitrate(int hw_rix)
        !           746: {
        !           747:        int i;
        !           748: 
        !           749:        for (i = 0; i < ATH5K_NR_RATES; i++) {
        !           750:                if (ath5k_rates[i].hw_code == hw_rix)
        !           751:                        return ath5k_rates[i].bitrate;
        !           752:        }
        !           753: 
        !           754:        DBG("ath5k: invalid rix %02x\n", hw_rix);
        !           755:        return 10;              /* use lowest rate */
        !           756: }
        !           757: 
        !           758: int ath5k_bitrate_to_hw_rix(int bitrate)
        !           759: {
        !           760:        int i;
        !           761: 
        !           762:        for (i = 0; i < ATH5K_NR_RATES; i++) {
        !           763:                if (ath5k_rates[i].bitrate == bitrate)
        !           764:                        return ath5k_rates[i].hw_code;
        !           765:        }
        !           766: 
        !           767:        DBG("ath5k: invalid bitrate %d\n", bitrate);
        !           768:        return ATH5K_RATE_CODE_1M; /* use lowest rate */
        !           769: }
        !           770: 
        !           771: /***************\
        !           772: * Buffers setup *
        !           773: \***************/
        !           774: 
        !           775: static struct io_buffer *
        !           776: ath5k_rx_iob_alloc(struct ath5k_softc *sc, u32 *iob_addr)
        !           777: {
        !           778:        struct io_buffer *iob;
        !           779:        unsigned int off;
        !           780: 
        !           781:        /*
        !           782:         * Allocate buffer with headroom_needed space for the
        !           783:         * fake physical layer header at the start.
        !           784:         */
        !           785:        iob = alloc_iob(sc->rxbufsize + sc->cachelsz - 1);
        !           786: 
        !           787:        if (!iob) {
        !           788:                DBG("ath5k: can't alloc iobuf of size %d\n",
        !           789:                    sc->rxbufsize + sc->cachelsz - 1);
        !           790:                return NULL;
        !           791:        }
        !           792: 
        !           793:        *iob_addr = virt_to_bus(iob->data);
        !           794: 
        !           795:        /*
        !           796:         * Cache-line-align.  This is important (for the
        !           797:         * 5210 at least) as not doing so causes bogus data
        !           798:         * in rx'd frames.
        !           799:         */
        !           800:        off = *iob_addr % sc->cachelsz;
        !           801:        if (off != 0) {
        !           802:                iob_reserve(iob, sc->cachelsz - off);
        !           803:                *iob_addr += sc->cachelsz - off;
        !           804:        }
        !           805: 
        !           806:        return iob;
        !           807: }
        !           808: 
        !           809: static int
        !           810: ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
        !           811: {
        !           812:        struct ath5k_hw *ah = sc->ah;
        !           813:        struct io_buffer *iob = bf->iob;
        !           814:        struct ath5k_desc *ds;
        !           815: 
        !           816:        if (!iob) {
        !           817:                iob = ath5k_rx_iob_alloc(sc, &bf->iobaddr);
        !           818:                if (!iob)
        !           819:                        return -ENOMEM;
        !           820:                bf->iob = iob;
        !           821:        }
        !           822: 
        !           823:        /*
        !           824:         * Setup descriptors.  For receive we always terminate
        !           825:         * the descriptor list with a self-linked entry so we'll
        !           826:         * not get overrun under high load (as can happen with a
        !           827:         * 5212 when ANI processing enables PHY error frames).
        !           828:         *
        !           829:         * To insure the last descriptor is self-linked we create
        !           830:         * each descriptor as self-linked and add it to the end.  As
        !           831:         * each additional descriptor is added the previous self-linked
        !           832:         * entry is ``fixed'' naturally.  This should be safe even
        !           833:         * if DMA is happening.  When processing RX interrupts we
        !           834:         * never remove/process the last, self-linked, entry on the
        !           835:         * descriptor list.  This insures the hardware always has
        !           836:         * someplace to write a new frame.
        !           837:         */
        !           838:        ds = bf->desc;
        !           839:        ds->ds_link = bf->daddr;        /* link to self */
        !           840:        ds->ds_data = bf->iobaddr;
        !           841:        if (ah->ah_setup_rx_desc(ah, ds,
        !           842:                                 iob_tailroom(iob),     /* buffer size */
        !           843:                                 0) != 0) {
        !           844:                DBG("ath5k: error setting up RX descriptor for %zd bytes\n", iob_tailroom(iob));
        !           845:                return -EINVAL;
        !           846:        }
        !           847: 
        !           848:        if (sc->rxlink != NULL)
        !           849:                *sc->rxlink = bf->daddr;
        !           850:        sc->rxlink = &ds->ds_link;
        !           851:        return 0;
        !           852: }
        !           853: 
        !           854: static int
        !           855: ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
        !           856: {
        !           857:        struct ath5k_hw *ah = sc->ah;
        !           858:        struct ath5k_txq *txq = &sc->txq;
        !           859:        struct ath5k_desc *ds = bf->desc;
        !           860:        struct io_buffer *iob = bf->iob;
        !           861:        unsigned int pktlen, flags;
        !           862:        int ret;
        !           863:        u16 duration = 0;
        !           864:        u16 cts_rate = 0;
        !           865: 
        !           866:        flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
        !           867:        bf->iobaddr = virt_to_bus(iob->data);
        !           868:        pktlen = iob_len(iob);
        !           869: 
        !           870:        /* FIXME: If we are in g mode and rate is a CCK rate
        !           871:         * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta
        !           872:         * from tx power (value is in dB units already) */
        !           873:        if (sc->dev->phy_flags & NET80211_PHY_USE_PROTECTION) {
        !           874:                struct net80211_device *dev = sc->dev;
        !           875: 
        !           876:                flags |= AR5K_TXDESC_CTSENA;
        !           877:                cts_rate = sc->hw_rtscts_rate;
        !           878:                duration = net80211_cts_duration(dev, pktlen);
        !           879:        }
        !           880:        ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
        !           881:                                   IEEE80211_TYP_FRAME_HEADER_LEN,
        !           882:                                   AR5K_PKT_TYPE_NORMAL, sc->power_level * 2,
        !           883:                                   sc->hw_rate, ATH5K_RETRIES,
        !           884:                                   AR5K_TXKEYIX_INVALID, 0, flags,
        !           885:                                   cts_rate, duration);
        !           886:        if (ret)
        !           887:                return ret;
        !           888: 
        !           889:        ds->ds_link = 0;
        !           890:        ds->ds_data = bf->iobaddr;
        !           891: 
        !           892:        list_add_tail(&bf->list, &txq->q);
        !           893:        if (txq->link == NULL) /* is this first packet? */
        !           894:                ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr);
        !           895:        else /* no, so only link it */
        !           896:                *txq->link = bf->daddr;
        !           897: 
        !           898:        txq->link = &ds->ds_link;
        !           899:        ath5k_hw_start_tx_dma(ah, txq->qnum);
        !           900:        mb();
        !           901: 
        !           902:        return 0;
        !           903: }
        !           904: 
        !           905: /*******************\
        !           906: * Descriptors setup *
        !           907: \*******************/
        !           908: 
        !           909: static int
        !           910: ath5k_desc_alloc(struct ath5k_softc *sc)
        !           911: {
        !           912:        struct ath5k_desc *ds;
        !           913:        struct ath5k_buf *bf;
        !           914:        u32 da;
        !           915:        unsigned int i;
        !           916:        int ret;
        !           917: 
        !           918:        /* allocate descriptors */
        !           919:        sc->desc_len = sizeof(struct ath5k_desc) * (ATH_TXBUF + ATH_RXBUF + 1);
        !           920:        sc->desc = malloc_dma(sc->desc_len, ATH5K_DESC_ALIGN);
        !           921:        if (sc->desc == NULL) {
        !           922:                DBG("ath5k: can't allocate descriptors\n");
        !           923:                ret = -ENOMEM;
        !           924:                goto err;
        !           925:        }
        !           926:        memset(sc->desc, 0, sc->desc_len);
        !           927:        sc->desc_daddr = virt_to_bus(sc->desc);
        !           928: 
        !           929:        ds = sc->desc;
        !           930:        da = sc->desc_daddr;
        !           931: 
        !           932:        bf = calloc(ATH_TXBUF + ATH_RXBUF + 1, sizeof(struct ath5k_buf));
        !           933:        if (bf == NULL) {
        !           934:                DBG("ath5k: can't allocate buffer pointers\n");
        !           935:                ret = -ENOMEM;
        !           936:                goto err_free;
        !           937:        }
        !           938:        sc->bufptr = bf;
        !           939: 
        !           940:        INIT_LIST_HEAD(&sc->rxbuf);
        !           941:        for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
        !           942:                bf->desc = ds;
        !           943:                bf->daddr = da;
        !           944:                list_add_tail(&bf->list, &sc->rxbuf);
        !           945:        }
        !           946: 
        !           947:        INIT_LIST_HEAD(&sc->txbuf);
        !           948:        sc->txbuf_len = ATH_TXBUF;
        !           949:        for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
        !           950:                bf->desc = ds;
        !           951:                bf->daddr = da;
        !           952:                list_add_tail(&bf->list, &sc->txbuf);
        !           953:        }
        !           954: 
        !           955:        return 0;
        !           956: 
        !           957: err_free:
        !           958:        free_dma(sc->desc, sc->desc_len);
        !           959: err:
        !           960:        sc->desc = NULL;
        !           961:        return ret;
        !           962: }
        !           963: 
        !           964: static void
        !           965: ath5k_desc_free(struct ath5k_softc *sc)
        !           966: {
        !           967:        struct ath5k_buf *bf;
        !           968: 
        !           969:        list_for_each_entry(bf, &sc->txbuf, list)
        !           970:                ath5k_txbuf_free(sc, bf);
        !           971:        list_for_each_entry(bf, &sc->rxbuf, list)
        !           972:                ath5k_rxbuf_free(sc, bf);
        !           973: 
        !           974:        /* Free memory associated with all descriptors */
        !           975:        free_dma(sc->desc, sc->desc_len);
        !           976: 
        !           977:        free(sc->bufptr);
        !           978:        sc->bufptr = NULL;
        !           979: }
        !           980: 
        !           981: 
        !           982: 
        !           983: 
        !           984: 
        !           985: /**************\
        !           986: * Queues setup *
        !           987: \**************/
        !           988: 
        !           989: static int
        !           990: ath5k_txq_setup(struct ath5k_softc *sc, int qtype, int subtype)
        !           991: {
        !           992:        struct ath5k_hw *ah = sc->ah;
        !           993:        struct ath5k_txq *txq;
        !           994:        struct ath5k_txq_info qi = {
        !           995:                .tqi_subtype = subtype,
        !           996:                .tqi_aifs = AR5K_TXQ_USEDEFAULT,
        !           997:                .tqi_cw_min = AR5K_TXQ_USEDEFAULT,
        !           998:                .tqi_cw_max = AR5K_TXQ_USEDEFAULT
        !           999:        };
        !          1000:        int qnum;
        !          1001: 
        !          1002:        /*
        !          1003:         * Enable interrupts only for EOL and DESC conditions.
        !          1004:         * We mark tx descriptors to receive a DESC interrupt
        !          1005:         * when a tx queue gets deep; otherwise waiting for the
        !          1006:         * EOL to reap descriptors.  Note that this is done to
        !          1007:         * reduce interrupt load and this only defers reaping
        !          1008:         * descriptors, never transmitting frames.  Aside from
        !          1009:         * reducing interrupts this also permits more concurrency.
        !          1010:         * The only potential downside is if the tx queue backs
        !          1011:         * up in which case the top half of the kernel may backup
        !          1012:         * due to a lack of tx descriptors.
        !          1013:         */
        !          1014:        qi.tqi_flags = AR5K_TXQ_FLAG_TXEOLINT_ENABLE |
        !          1015:                                AR5K_TXQ_FLAG_TXDESCINT_ENABLE;
        !          1016:        qnum = ath5k_hw_setup_tx_queue(ah, qtype, &qi);
        !          1017:        if (qnum < 0) {
        !          1018:                DBG("ath5k: can't set up a TX queue\n");
        !          1019:                return -EIO;
        !          1020:        }
        !          1021: 
        !          1022:        txq = &sc->txq;
        !          1023:        if (!txq->setup) {
        !          1024:                txq->qnum = qnum;
        !          1025:                txq->link = NULL;
        !          1026:                INIT_LIST_HEAD(&txq->q);
        !          1027:                txq->setup = 1;
        !          1028:        }
        !          1029:        return 0;
        !          1030: }
        !          1031: 
        !          1032: static void
        !          1033: ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
        !          1034: {
        !          1035:        struct ath5k_buf *bf, *bf0;
        !          1036: 
        !          1037:        list_for_each_entry_safe(bf, bf0, &txq->q, list) {
        !          1038:                ath5k_txbuf_free(sc, bf);
        !          1039: 
        !          1040:                list_del(&bf->list);
        !          1041:                list_add_tail(&bf->list, &sc->txbuf);
        !          1042:                sc->txbuf_len++;
        !          1043:        }
        !          1044:        txq->link = NULL;
        !          1045: }
        !          1046: 
        !          1047: /*
        !          1048:  * Drain the transmit queues and reclaim resources.
        !          1049:  */
        !          1050: static void
        !          1051: ath5k_txq_cleanup(struct ath5k_softc *sc)
        !          1052: {
        !          1053:        struct ath5k_hw *ah = sc->ah;
        !          1054: 
        !          1055:        if (!(sc->status & ATH_STAT_INVALID)) {
        !          1056:                /* don't touch the hardware if marked invalid */
        !          1057:                if (sc->txq.setup) {
        !          1058:                        ath5k_hw_stop_tx_dma(ah, sc->txq.qnum);
        !          1059:                        DBG("ath5k: txq [%d] %x, link %p\n",
        !          1060:                            sc->txq.qnum,
        !          1061:                            ath5k_hw_get_txdp(ah, sc->txq.qnum),
        !          1062:                            sc->txq.link);
        !          1063:                }
        !          1064:        }
        !          1065: 
        !          1066:        if (sc->txq.setup)
        !          1067:                ath5k_txq_drainq(sc, &sc->txq);
        !          1068: }
        !          1069: 
        !          1070: static void
        !          1071: ath5k_txq_release(struct ath5k_softc *sc)
        !          1072: {
        !          1073:        if (sc->txq.setup) {
        !          1074:                ath5k_hw_release_tx_queue(sc->ah);
        !          1075:                sc->txq.setup = 0;
        !          1076:        }
        !          1077: }
        !          1078: 
        !          1079: 
        !          1080: 
        !          1081: 
        !          1082: /*************\
        !          1083: * RX Handling *
        !          1084: \*************/
        !          1085: 
        !          1086: /*
        !          1087:  * Enable the receive h/w following a reset.
        !          1088:  */
        !          1089: static int
        !          1090: ath5k_rx_start(struct ath5k_softc *sc)
        !          1091: {
        !          1092:        struct ath5k_hw *ah = sc->ah;
        !          1093:        struct ath5k_buf *bf;
        !          1094:        int ret;
        !          1095: 
        !          1096:        sc->rxbufsize = IEEE80211_MAX_LEN;
        !          1097:        if (sc->rxbufsize % sc->cachelsz != 0)
        !          1098:                sc->rxbufsize += sc->cachelsz - (sc->rxbufsize % sc->cachelsz);
        !          1099: 
        !          1100:        sc->rxlink = NULL;
        !          1101: 
        !          1102:        list_for_each_entry(bf, &sc->rxbuf, list) {
        !          1103:                ret = ath5k_rxbuf_setup(sc, bf);
        !          1104:                if (ret != 0)
        !          1105:                        return ret;
        !          1106:        }
        !          1107: 
        !          1108:        bf = list_entry(sc->rxbuf.next, struct ath5k_buf, list);
        !          1109: 
        !          1110:        ath5k_hw_set_rxdp(ah, bf->daddr);
        !          1111:        ath5k_hw_start_rx_dma(ah);      /* enable recv descriptors */
        !          1112:        ath5k_mode_setup(sc);           /* set filters, etc. */
        !          1113:        ath5k_hw_start_rx_pcu(ah);      /* re-enable PCU/DMA engine */
        !          1114: 
        !          1115:        return 0;
        !          1116: }
        !          1117: 
        !          1118: /*
        !          1119:  * Disable the receive h/w in preparation for a reset.
        !          1120:  */
        !          1121: static void
        !          1122: ath5k_rx_stop(struct ath5k_softc *sc)
        !          1123: {
        !          1124:        struct ath5k_hw *ah = sc->ah;
        !          1125: 
        !          1126:        ath5k_hw_stop_rx_pcu(ah);       /* disable PCU */
        !          1127:        ath5k_hw_set_rx_filter(ah, 0);  /* clear recv filter */
        !          1128:        ath5k_hw_stop_rx_dma(ah);       /* disable DMA engine */
        !          1129: 
        !          1130:        sc->rxlink = NULL;              /* just in case */
        !          1131: }
        !          1132: 
        !          1133: static void
        !          1134: ath5k_handle_rx(struct ath5k_softc *sc)
        !          1135: {
        !          1136:        struct ath5k_rx_status rs;
        !          1137:        struct io_buffer *iob, *next_iob;
        !          1138:        u32 next_iob_addr;
        !          1139:        struct ath5k_buf *bf, *bf_last;
        !          1140:        struct ath5k_desc *ds;
        !          1141:        int ret;
        !          1142: 
        !          1143:        memset(&rs, 0, sizeof(rs));
        !          1144: 
        !          1145:        if (list_empty(&sc->rxbuf)) {
        !          1146:                DBG("ath5k: empty rx buf pool\n");
        !          1147:                return;
        !          1148:        }
        !          1149: 
        !          1150:        bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list);
        !          1151: 
        !          1152:        do {
        !          1153:                bf = list_entry(sc->rxbuf.next, struct ath5k_buf, list);
        !          1154:                assert(bf->iob != NULL);
        !          1155:                iob = bf->iob;
        !          1156:                ds = bf->desc;
        !          1157: 
        !          1158:                /*
        !          1159:                 * last buffer must not be freed to ensure proper hardware
        !          1160:                 * function. When the hardware finishes also a packet next to
        !          1161:                 * it, we are sure, it doesn't use it anymore and we can go on.
        !          1162:                 */
        !          1163:                if (bf_last == bf)
        !          1164:                        bf->flags |= 1;
        !          1165:                if (bf->flags) {
        !          1166:                        struct ath5k_buf *bf_next = list_entry(bf->list.next,
        !          1167:                                        struct ath5k_buf, list);
        !          1168:                        ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc,
        !          1169:                                        &rs);
        !          1170:                        if (ret)
        !          1171:                                break;
        !          1172:                        bf->flags &= ~1;
        !          1173:                        /* skip the overwritten one (even status is martian) */
        !          1174:                        goto next;
        !          1175:                }
        !          1176: 
        !          1177:                ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
        !          1178:                if (ret) {
        !          1179:                        if (ret != -EINPROGRESS) {
        !          1180:                                DBG("ath5k: error in processing rx desc: %s\n",
        !          1181:                                    strerror(ret));
        !          1182:                                net80211_rx_err(sc->dev, NULL, -ret);
        !          1183:                        } else {
        !          1184:                                /* normal return, reached end of
        !          1185:                                   available descriptors */
        !          1186:                        }
        !          1187:                        return;
        !          1188:                }
        !          1189: 
        !          1190:                if (rs.rs_more) {
        !          1191:                        DBG("ath5k: unsupported fragmented rx\n");
        !          1192:                        goto next;
        !          1193:                }
        !          1194: 
        !          1195:                if (rs.rs_status) {
        !          1196:                        if (rs.rs_status & AR5K_RXERR_PHY) {
        !          1197:                                /* These are uncommon, and may indicate a real problem. */
        !          1198:                                net80211_rx_err(sc->dev, NULL, EIO);
        !          1199:                                goto next;
        !          1200:                        }
        !          1201:                        if (rs.rs_status & AR5K_RXERR_CRC) {
        !          1202:                                /* These occur *all the time*. */
        !          1203:                                goto next;
        !          1204:                        }
        !          1205:                        if (rs.rs_status & AR5K_RXERR_DECRYPT) {
        !          1206:                                /*
        !          1207:                                 * Decrypt error.  If the error occurred
        !          1208:                                 * because there was no hardware key, then
        !          1209:                                 * let the frame through so the upper layers
        !          1210:                                 * can process it.  This is necessary for 5210
        !          1211:                                 * parts which have no way to setup a ``clear''
        !          1212:                                 * key cache entry.
        !          1213:                                 *
        !          1214:                                 * XXX do key cache faulting
        !          1215:                                 */
        !          1216:                                if (rs.rs_keyix == AR5K_RXKEYIX_INVALID &&
        !          1217:                                    !(rs.rs_status & AR5K_RXERR_CRC))
        !          1218:                                        goto accept;
        !          1219:                        }
        !          1220: 
        !          1221:                        /* any other error, unhandled */
        !          1222:                        DBG("ath5k: packet rx status %x\n", rs.rs_status);
        !          1223:                        goto next;
        !          1224:                }
        !          1225: accept:
        !          1226:                next_iob = ath5k_rx_iob_alloc(sc, &next_iob_addr);
        !          1227: 
        !          1228:                /*
        !          1229:                 * If we can't replace bf->iob with a new iob under memory
        !          1230:                 * pressure, just skip this packet
        !          1231:                 */
        !          1232:                if (!next_iob) {
        !          1233:                        DBG("ath5k: dropping packet under memory pressure\n");
        !          1234:                        goto next;
        !          1235:                }
        !          1236: 
        !          1237:                iob_put(iob, rs.rs_datalen);
        !          1238: 
        !          1239:                /* The MAC header is padded to have 32-bit boundary if the
        !          1240:                 * packet payload is non-zero. However, iPXE only
        !          1241:                 * supports standard 802.11 packets with 24-byte
        !          1242:                 * header, so no padding correction should be needed.
        !          1243:                 */
        !          1244: 
        !          1245:                DBG2("ath5k: rx %d bytes, signal %d\n", rs.rs_datalen,
        !          1246:                     rs.rs_rssi);
        !          1247: 
        !          1248:                net80211_rx(sc->dev, iob, rs.rs_rssi,
        !          1249:                            ath5k_hw_rix_to_bitrate(rs.rs_rate));
        !          1250: 
        !          1251:                bf->iob = next_iob;
        !          1252:                bf->iobaddr = next_iob_addr;
        !          1253: next:
        !          1254:                list_del(&bf->list);
        !          1255:                list_add_tail(&bf->list, &sc->rxbuf);
        !          1256:        } while (ath5k_rxbuf_setup(sc, bf) == 0);
        !          1257: }
        !          1258: 
        !          1259: 
        !          1260: 
        !          1261: 
        !          1262: /*************\
        !          1263: * TX Handling *
        !          1264: \*************/
        !          1265: 
        !          1266: static void
        !          1267: ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
        !          1268: {
        !          1269:        struct ath5k_tx_status ts;
        !          1270:        struct ath5k_buf *bf, *bf0;
        !          1271:        struct ath5k_desc *ds;
        !          1272:        struct io_buffer *iob;
        !          1273:        int ret;
        !          1274: 
        !          1275:        memset(&ts, 0, sizeof(ts));
        !          1276: 
        !          1277:        list_for_each_entry_safe(bf, bf0, &txq->q, list) {
        !          1278:                ds = bf->desc;
        !          1279: 
        !          1280:                ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
        !          1281:                if (ret) {
        !          1282:                        if (ret != -EINPROGRESS) {
        !          1283:                                DBG("ath5k: error in processing tx desc: %s\n",
        !          1284:                                    strerror(ret));
        !          1285:                        } else {
        !          1286:                                /* normal return, reached end of tx completions */
        !          1287:                        }
        !          1288:                        break;
        !          1289:                }
        !          1290: 
        !          1291:                iob = bf->iob;
        !          1292:                bf->iob = NULL;
        !          1293: 
        !          1294:                DBG2("ath5k: tx %zd bytes complete, %d retries\n",
        !          1295:                     iob_len(iob), ts.ts_retry[0]);
        !          1296: 
        !          1297:                net80211_tx_complete(sc->dev, iob, ts.ts_retry[0],
        !          1298:                                     ts.ts_status ? EIO : 0);
        !          1299: 
        !          1300:                list_del(&bf->list);
        !          1301:                list_add_tail(&bf->list, &sc->txbuf);
        !          1302:                sc->txbuf_len++;
        !          1303:        }
        !          1304: 
        !          1305:        if (list_empty(&txq->q))
        !          1306:                txq->link = NULL;
        !          1307: }
        !          1308: 
        !          1309: static void
        !          1310: ath5k_handle_tx(struct ath5k_softc *sc)
        !          1311: {
        !          1312:        ath5k_tx_processq(sc, &sc->txq);
        !          1313: }
        !          1314: 
        !          1315: 
        !          1316: /********************\
        !          1317: * Interrupt handling *
        !          1318: \********************/
        !          1319: 
        !          1320: static void
        !          1321: ath5k_irq(struct net80211_device *dev, int enable)
        !          1322: {
        !          1323:        struct ath5k_softc *sc = dev->priv;
        !          1324:        struct ath5k_hw *ah = sc->ah;
        !          1325: 
        !          1326:        sc->irq_ena = enable;
        !          1327:        ah->ah_ier = enable ? AR5K_IER_ENABLE : AR5K_IER_DISABLE;
        !          1328: 
        !          1329:        ath5k_hw_reg_write(ah, ah->ah_ier, AR5K_IER);
        !          1330:        ath5k_hw_set_imr(ah, sc->imask);
        !          1331: }
        !          1332: 
        !          1333: static int
        !          1334: ath5k_init(struct ath5k_softc *sc)
        !          1335: {
        !          1336:        struct ath5k_hw *ah = sc->ah;
        !          1337:        int ret, i;
        !          1338: 
        !          1339:        /*
        !          1340:         * Stop anything previously setup.  This is safe
        !          1341:         * no matter this is the first time through or not.
        !          1342:         */
        !          1343:        ath5k_stop_hw(sc);
        !          1344: 
        !          1345:        /*
        !          1346:         * The basic interface to setting the hardware in a good
        !          1347:         * state is ``reset''.  On return the hardware is known to
        !          1348:         * be powered up and with interrupts disabled.  This must
        !          1349:         * be followed by initialization of the appropriate bits
        !          1350:         * and then setup of the interrupt mask.
        !          1351:         */
        !          1352:        sc->curchan = sc->dev->channels + sc->dev->channel;
        !          1353:        sc->curband = sc->curchan->band;
        !          1354:        sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
        !          1355:                AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
        !          1356:                AR5K_INT_FATAL | AR5K_INT_GLOBAL;
        !          1357:        ret = ath5k_reset(sc, NULL);
        !          1358:        if (ret)
        !          1359:                goto done;
        !          1360: 
        !          1361:        ath5k_rfkill_hw_start(ah);
        !          1362: 
        !          1363:        /*
        !          1364:         * Reset the key cache since some parts do not reset the
        !          1365:         * contents on initial power up or resume from suspend.
        !          1366:         */
        !          1367:        for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
        !          1368:                ath5k_hw_reset_key(ah, i);
        !          1369: 
        !          1370:        /* Set ack to be sent at low bit-rates */
        !          1371:        ath5k_hw_set_ack_bitrate_high(ah, 0);
        !          1372: 
        !          1373:        ret = 0;
        !          1374: done:
        !          1375:        mb();
        !          1376:        return ret;
        !          1377: }
        !          1378: 
        !          1379: static int
        !          1380: ath5k_stop_hw(struct ath5k_softc *sc)
        !          1381: {
        !          1382:        struct ath5k_hw *ah = sc->ah;
        !          1383: 
        !          1384:        /*
        !          1385:         * Shutdown the hardware and driver:
        !          1386:         *    stop output from above
        !          1387:         *    disable interrupts
        !          1388:         *    turn off timers
        !          1389:         *    turn off the radio
        !          1390:         *    clear transmit machinery
        !          1391:         *    clear receive machinery
        !          1392:         *    drain and release tx queues
        !          1393:         *    reclaim beacon resources
        !          1394:         *    power down hardware
        !          1395:         *
        !          1396:         * Note that some of this work is not possible if the
        !          1397:         * hardware is gone (invalid).
        !          1398:         */
        !          1399: 
        !          1400:        if (!(sc->status & ATH_STAT_INVALID)) {
        !          1401:                ath5k_hw_set_imr(ah, 0);
        !          1402:        }
        !          1403:        ath5k_txq_cleanup(sc);
        !          1404:        if (!(sc->status & ATH_STAT_INVALID)) {
        !          1405:                ath5k_rx_stop(sc);
        !          1406:                ath5k_hw_phy_disable(ah);
        !          1407:        } else
        !          1408:                sc->rxlink = NULL;
        !          1409: 
        !          1410:        ath5k_rfkill_hw_stop(sc->ah);
        !          1411: 
        !          1412:        return 0;
        !          1413: }
        !          1414: 
        !          1415: static void
        !          1416: ath5k_poll(struct net80211_device *dev)
        !          1417: {
        !          1418:        struct ath5k_softc *sc = dev->priv;
        !          1419:        struct ath5k_hw *ah = sc->ah;
        !          1420:        enum ath5k_int status;
        !          1421:        unsigned int counter = 1000;
        !          1422: 
        !          1423:        if (currticks() - sc->last_calib_ticks >
        !          1424:            ATH5K_CALIB_INTERVAL * ticks_per_sec()) {
        !          1425:                ath5k_calibrate(sc);
        !          1426:                sc->last_calib_ticks = currticks();
        !          1427:        }
        !          1428: 
        !          1429:        if ((sc->status & ATH_STAT_INVALID) ||
        !          1430:            (sc->irq_ena && !ath5k_hw_is_intr_pending(ah)))
        !          1431:                return;
        !          1432: 
        !          1433:        do {
        !          1434:                ath5k_hw_get_isr(ah, &status);          /* NB: clears IRQ too */
        !          1435:                DBGP("ath5k: status %#x/%#x\n", status, sc->imask);
        !          1436:                if (status & AR5K_INT_FATAL) {
        !          1437:                        /*
        !          1438:                         * Fatal errors are unrecoverable.
        !          1439:                         * Typically these are caused by DMA errors.
        !          1440:                         */
        !          1441:                        DBG("ath5k: fatal error, resetting\n");
        !          1442:                        ath5k_reset_wake(sc);
        !          1443:                } else if (status & AR5K_INT_RXORN) {
        !          1444:                        DBG("ath5k: rx overrun, resetting\n");
        !          1445:                        ath5k_reset_wake(sc);
        !          1446:                } else {
        !          1447:                        if (status & AR5K_INT_RXEOL) {
        !          1448:                                /*
        !          1449:                                 * NB: the hardware should re-read the link when
        !          1450:                                 *     RXE bit is written, but it doesn't work at
        !          1451:                                 *     least on older hardware revs.
        !          1452:                                 */
        !          1453:                                DBG("ath5k: rx EOL\n");
        !          1454:                                sc->rxlink = NULL;
        !          1455:                        }
        !          1456:                        if (status & AR5K_INT_TXURN) {
        !          1457:                                /* bump tx trigger level */
        !          1458:                                DBG("ath5k: tx underrun\n");
        !          1459:                                ath5k_hw_update_tx_triglevel(ah, 1);
        !          1460:                        }
        !          1461:                        if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
        !          1462:                                ath5k_handle_rx(sc);
        !          1463:                        if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
        !          1464:                                      | AR5K_INT_TXERR | AR5K_INT_TXEOL))
        !          1465:                                ath5k_handle_tx(sc);
        !          1466:                }
        !          1467:        } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0);
        !          1468: 
        !          1469:        if (!counter)
        !          1470:                DBG("ath5k: too many interrupts, giving up for now\n");
        !          1471: }
        !          1472: 
        !          1473: /*
        !          1474:  * Periodically recalibrate the PHY to account
        !          1475:  * for temperature/environment changes.
        !          1476:  */
        !          1477: static void
        !          1478: ath5k_calibrate(struct ath5k_softc *sc)
        !          1479: {
        !          1480:        struct ath5k_hw *ah = sc->ah;
        !          1481: 
        !          1482:        if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) {
        !          1483:                /*
        !          1484:                 * Rfgain is out of bounds, reset the chip
        !          1485:                 * to load new gain values.
        !          1486:                 */
        !          1487:                DBG("ath5k: resetting for calibration\n");
        !          1488:                ath5k_reset_wake(sc);
        !          1489:        }
        !          1490:        if (ath5k_hw_phy_calibrate(ah, sc->curchan))
        !          1491:                DBG("ath5k: calibration of channel %d failed\n",
        !          1492:                    sc->curchan->channel_nr);
        !          1493: }
        !          1494: 
        !          1495: 
        !          1496: /********************\
        !          1497: * Net80211 functions *
        !          1498: \********************/
        !          1499: 
        !          1500: static int
        !          1501: ath5k_tx(struct net80211_device *dev, struct io_buffer *iob)
        !          1502: {
        !          1503:        struct ath5k_softc *sc = dev->priv;
        !          1504:        struct ath5k_buf *bf;
        !          1505:        int rc;
        !          1506: 
        !          1507:        /*
        !          1508:         * The hardware expects the header padded to 4 byte boundaries.
        !          1509:         * iPXE only ever sends 24-byte headers, so no action necessary.
        !          1510:         */
        !          1511: 
        !          1512:        if (list_empty(&sc->txbuf)) {
        !          1513:                DBG("ath5k: dropping packet because no tx bufs available\n");
        !          1514:                return -ENOBUFS;
        !          1515:        }
        !          1516: 
        !          1517:        bf = list_entry(sc->txbuf.next, struct ath5k_buf, list);
        !          1518:        list_del(&bf->list);
        !          1519:        sc->txbuf_len--;
        !          1520: 
        !          1521:        bf->iob = iob;
        !          1522: 
        !          1523:        if ((rc = ath5k_txbuf_setup(sc, bf)) != 0) {
        !          1524:                bf->iob = NULL;
        !          1525:                list_add_tail(&bf->list, &sc->txbuf);
        !          1526:                sc->txbuf_len++;
        !          1527:                return rc;
        !          1528:        }
        !          1529:        return 0;
        !          1530: }
        !          1531: 
        !          1532: /*
        !          1533:  * Reset the hardware.  If chan is not NULL, then also pause rx/tx
        !          1534:  * and change to the given channel.
        !          1535:  */
        !          1536: static int
        !          1537: ath5k_reset(struct ath5k_softc *sc, struct net80211_channel *chan)
        !          1538: {
        !          1539:        struct ath5k_hw *ah = sc->ah;
        !          1540:        int ret;
        !          1541: 
        !          1542:        if (chan) {
        !          1543:                ath5k_hw_set_imr(ah, 0);
        !          1544:                ath5k_txq_cleanup(sc);
        !          1545:                ath5k_rx_stop(sc);
        !          1546: 
        !          1547:                sc->curchan = chan;
        !          1548:                sc->curband = chan->band;
        !          1549:        }
        !          1550: 
        !          1551:        ret = ath5k_hw_reset(ah, sc->curchan, 1);
        !          1552:        if (ret) {
        !          1553:                DBG("ath5k: can't reset hardware: %s\n", strerror(ret));
        !          1554:                return ret;
        !          1555:        }
        !          1556: 
        !          1557:        ret = ath5k_rx_start(sc);
        !          1558:        if (ret) {
        !          1559:                DBG("ath5k: can't start rx logic: %s\n", strerror(ret));
        !          1560:                return ret;
        !          1561:        }
        !          1562: 
        !          1563:        /*
        !          1564:         * Change channels and update the h/w rate map if we're switching;
        !          1565:         * e.g. 11a to 11b/g.
        !          1566:         *
        !          1567:         * We may be doing a reset in response to an ioctl that changes the
        !          1568:         * channel so update any state that might change as a result.
        !          1569:         *
        !          1570:         * XXX needed?
        !          1571:         */
        !          1572: /*     ath5k_chan_change(sc, c); */
        !          1573: 
        !          1574:        /* Reenable interrupts if necessary */
        !          1575:        ath5k_irq(sc->dev, sc->irq_ena);
        !          1576: 
        !          1577:        return 0;
        !          1578: }
        !          1579: 
        !          1580: static int ath5k_reset_wake(struct ath5k_softc *sc)
        !          1581: {
        !          1582:        return ath5k_reset(sc, sc->curchan);
        !          1583: }
        !          1584: 
        !          1585: static int ath5k_start(struct net80211_device *dev)
        !          1586: {
        !          1587:        struct ath5k_softc *sc = dev->priv;
        !          1588:        int ret;
        !          1589: 
        !          1590:        if ((ret = ath5k_init(sc)) != 0)
        !          1591:                return ret;
        !          1592: 
        !          1593:        sc->assoc = 0;
        !          1594:        ath5k_configure_filter(sc);
        !          1595:        ath5k_hw_set_lladdr(sc->ah, dev->netdev->ll_addr);
        !          1596: 
        !          1597:        return 0;
        !          1598: }
        !          1599: 
        !          1600: static void ath5k_stop(struct net80211_device *dev)
        !          1601: {
        !          1602:        struct ath5k_softc *sc = dev->priv;
        !          1603:        u8 mac[ETH_ALEN] = {};
        !          1604: 
        !          1605:        ath5k_hw_set_lladdr(sc->ah, mac);
        !          1606: 
        !          1607:        ath5k_stop_hw(sc);
        !          1608: }
        !          1609: 
        !          1610: static int
        !          1611: ath5k_config(struct net80211_device *dev, int changed)
        !          1612: {
        !          1613:        struct ath5k_softc *sc = dev->priv;
        !          1614:        struct ath5k_hw *ah = sc->ah;
        !          1615:        struct net80211_channel *chan = &dev->channels[dev->channel];
        !          1616:        int ret;
        !          1617: 
        !          1618:        if (changed & NET80211_CFG_CHANNEL) {
        !          1619:                sc->power_level = chan->maxpower;
        !          1620:                if ((ret = ath5k_chan_set(sc, chan)) != 0)
        !          1621:                        return ret;
        !          1622:        }
        !          1623: 
        !          1624:        if ((changed & NET80211_CFG_RATE) ||
        !          1625:            (changed & NET80211_CFG_PHY_PARAMS)) {
        !          1626:                int spmbl = ATH5K_SPMBL_NO;
        !          1627:                u16 rate = dev->rates[dev->rate];
        !          1628:                u16 slowrate = dev->rates[dev->rtscts_rate];
        !          1629:                int i;
        !          1630: 
        !          1631:                if (dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE)
        !          1632:                        spmbl = ATH5K_SPMBL_YES;
        !          1633: 
        !          1634:                for (i = 0; i < ATH5K_NR_RATES; i++) {
        !          1635:                        if (ath5k_rates[i].bitrate == rate &&
        !          1636:                            (ath5k_rates[i].short_pmbl & spmbl))
        !          1637:                                sc->hw_rate = ath5k_rates[i].hw_code;
        !          1638: 
        !          1639:                        if (ath5k_rates[i].bitrate == slowrate &&
        !          1640:                            (ath5k_rates[i].short_pmbl & spmbl))
        !          1641:                                sc->hw_rtscts_rate = ath5k_rates[i].hw_code;
        !          1642:                }
        !          1643:        }
        !          1644: 
        !          1645:        if (changed & NET80211_CFG_ASSOC) {
        !          1646:                sc->assoc = !!(dev->state & NET80211_ASSOCIATED);
        !          1647:                if (sc->assoc) {
        !          1648:                        memcpy(ah->ah_bssid, dev->bssid, ETH_ALEN);
        !          1649:                } else {
        !          1650:                        memset(ah->ah_bssid, 0xff, ETH_ALEN);
        !          1651:                }
        !          1652:                ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
        !          1653:        }
        !          1654: 
        !          1655:        return 0;
        !          1656: }
        !          1657: 
        !          1658: /*
        !          1659:  * o always accept unicast, broadcast, and multicast traffic
        !          1660:  * o multicast traffic for all BSSIDs will be enabled if mac80211
        !          1661:  *   says it should be
        !          1662:  * o maintain current state of phy ofdm or phy cck error reception.
        !          1663:  *   If the hardware detects any of these type of errors then
        !          1664:  *   ath5k_hw_get_rx_filter() will pass to us the respective
        !          1665:  *   hardware filters to be able to receive these type of frames.
        !          1666:  * o probe request frames are accepted only when operating in
        !          1667:  *   hostap, adhoc, or monitor modes
        !          1668:  * o enable promiscuous mode according to the interface state
        !          1669:  * o accept beacons:
        !          1670:  *   - when operating in adhoc mode so the 802.11 layer creates
        !          1671:  *     node table entries for peers,
        !          1672:  *   - when operating in station mode for collecting rssi data when
        !          1673:  *     the station is otherwise quiet, or
        !          1674:  *   - when scanning
        !          1675:  */
        !          1676: static void ath5k_configure_filter(struct ath5k_softc *sc)
        !          1677: {
        !          1678:        struct ath5k_hw *ah = sc->ah;
        !          1679:        u32 mfilt[2], rfilt;
        !          1680: 
        !          1681:        /* Enable all multicast */
        !          1682:        mfilt[0] = ~0;
        !          1683:        mfilt[1] = ~0;
        !          1684: 
        !          1685:        /* Enable data frames and beacons */
        !          1686:        rfilt = (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST |
        !          1687:                 AR5K_RX_FILTER_MCAST | AR5K_RX_FILTER_BEACON);
        !          1688: 
        !          1689:        /* Set filters */
        !          1690:        ath5k_hw_set_rx_filter(ah, rfilt);
        !          1691: 
        !          1692:        /* Set multicast bits */
        !          1693:        ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
        !          1694: 
        !          1695:        /* Set the cached hw filter flags, this will alter actually
        !          1696:         * be set in HW */
        !          1697:        sc->filter_flags = rfilt;
        !          1698: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.