From 0fb8aa363f2972009439cee7351d1e2289652cdb Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 16 Jul 2008 16:30:03 +0000 Subject: [PATCH] add some madwifi fixes and enhancements by Sven-Ola, refresh patches SVN-Revision: 11848 --- package/madwifi/Makefile | 2 +- .../madwifi/patches/202-debug_variables.patch | 204 ++ .../madwifi/patches/300-napi_polling.patch | 38 +- package/madwifi/patches/305-pureg_fix.patch | 2 +- .../madwifi/patches/309-micfail_detect.patch | 10 +- package/madwifi/patches/310-noise_get.patch | 8 +- package/madwifi/patches/317-bmask.patch | 2 +- .../madwifi/patches/323-dfs_optional.patch | 4 +- .../madwifi/patches/325-channel_spam.patch | 6 +- package/madwifi/patches/327-queue.patch | 6 +- package/madwifi/patches/330-beaconcal.patch | 22 +- .../madwifi/patches/331-memory_alloc.patch | 4 +- .../madwifi/patches/332-reset_beacons.patch | 2 +- package/madwifi/patches/333-apscan_mode.patch | 2 +- package/madwifi/patches/342-performance.patch | 6 +- .../madwifi/patches/343-txqueue_races.patch | 2 +- .../patches/345-minstrel_sampling.patch | 2 +- package/madwifi/patches/347-tuning.patch | 2 +- package/madwifi/patches/348-ackcts.patch | 4 +- package/madwifi/patches/349-reset.patch | 2 +- package/madwifi/patches/351-scanlist.patch | 2 +- package/madwifi/patches/352-ani_fix.patch | 24 +- .../patches/355-eap_auth_disassoc.patch | 2 +- package/madwifi/patches/363-fix_turbo.patch | 11 + .../madwifi/patches/364-memory_alloc.patch | 13 + .../patches/365-turbo_channelsearch.patch | 10 + .../madwifi/patches/366-bstuck_thresh.patch | 52 + .../madwifi/patches/406-monitor_r3711.patch | 20 + package/madwifi/patches/407-new_athinfo.patch | 2352 +++++++++++++++++ 29 files changed, 2739 insertions(+), 77 deletions(-) create mode 100644 package/madwifi/patches/202-debug_variables.patch create mode 100644 package/madwifi/patches/363-fix_turbo.patch create mode 100644 package/madwifi/patches/364-memory_alloc.patch create mode 100644 package/madwifi/patches/365-turbo_channelsearch.patch create mode 100644 package/madwifi/patches/366-bstuck_thresh.patch create mode 100644 package/madwifi/patches/406-monitor_r3711.patch create mode 100644 package/madwifi/patches/407-new_athinfo.patch diff --git a/package/madwifi/Makefile b/package/madwifi/Makefile index 874438b296..ac15b2c67c 100644 --- a/package/madwifi/Makefile +++ b/package/madwifi/Makefile @@ -118,7 +118,7 @@ ifeq ($(findstring PCI,$(BUS)),PCI) MADWIFI_AUTOLOAD+= ath_pci endif -MADWIFI_APPLETS:=80211stats,athchans,athctrl,athkey,athstats,wlanconfig +MADWIFI_APPLETS:=80211stats,athchans,athctrl,athkey,athstats,wlanconfig,ath_info ifdef CONFIG_MADWIFI_DEBUG MADWIFI_APPLETS:=$(strip $(MADWIFI_APPLETS)),athdebug,80211debug endif diff --git a/package/madwifi/patches/202-debug_variables.patch b/package/madwifi/patches/202-debug_variables.patch new file mode 100644 index 0000000000..83556ee7df --- /dev/null +++ b/package/madwifi/patches/202-debug_variables.patch @@ -0,0 +1,204 @@ +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -453,8 +453,8 @@ + MODULE_PARM_DESC(ratectl, "Rate control algorithm [amrr|minstrel|onoe|sample], " + "defaults to '" DEF_RATE_CTL "'"); + +-static int ath_debug = 0; + #ifdef AR_DEBUG ++static int ath_debug = 0; + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52)) + MODULE_PARM(ath_debug, "i"); + #else +@@ -465,8 +465,8 @@ + static void ath_printtxbuf(const struct ath_buf *, int); + #endif /* defined(AR_DEBUG) */ + +-static int ieee80211_debug = 0; + #ifdef AR_DEBUG ++static int ieee80211_debug = 0; + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52)) + MODULE_PARM(ieee80211_debug, "i"); + #else +@@ -1565,7 +1565,9 @@ + void + ath_suspend(struct net_device *dev) + { ++#ifdef AR_DEBUG + struct ath_softc *sc = dev->priv; ++#endif + + DPRINTF(sc, ATH_DEBUG_ANY, "flags=%x\n", dev->flags); + ath_stop(dev); +@@ -1574,7 +1576,9 @@ + void + ath_resume(struct net_device *dev) + { ++#ifdef AR_DEBUG + struct ath_softc *sc = dev->priv; ++#endif + + DPRINTF(sc, ATH_DEBUG_ANY, "flags=%x\n", dev->flags); + ath_init(dev); +@@ -4019,7 +4023,9 @@ + ath_key_update_begin(struct ieee80211vap *vap) + { + struct net_device *dev = vap->iv_ic->ic_dev; ++#ifdef AR_DEBUG + struct ath_softc *sc = dev->priv; ++#endif + + DPRINTF(sc, ATH_DEBUG_KEYCACHE, "Begin\n"); + /* +@@ -4040,7 +4046,9 @@ + ath_key_update_end(struct ieee80211vap *vap) + { + struct net_device *dev = vap->iv_ic->ic_dev; ++#ifdef AR_DEBUG + struct ath_softc *sc = dev->priv; ++#endif + + DPRINTF(sc, ATH_DEBUG_KEYCACHE, "End\n"); + netif_wake_queue(dev); +@@ -6218,7 +6226,9 @@ + struct sk_buff *skb, int subtype, int rssi, u_int64_t rtsf) + { + struct ath_softc *sc = vap->iv_ic->ic_dev->priv; ++#ifdef AR_DEBUG + struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data; ++#endif + struct ieee80211_node * ni = ni_or_null; + u_int64_t hw_tsf, beacon_tsf; + u_int32_t hw_tu, beacon_tu, intval; +@@ -8382,7 +8392,9 @@ + static void + ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq) + { ++#ifdef AR_DEBUG + struct ath_hal *ah = sc->sc_ah; ++#endif + struct ath_buf *bf; + /* + * NB: this assumes output has been stopped and +@@ -11002,6 +11014,7 @@ + strncat(m, b, MLEN); + } + strncat(m, "\n", MLEN); ++#ifdef AR_DEBUG + if (1 /* bootverbose */) { + unsigned int i; + for (i = 0; i <= WME_AC_VO; i++) { +@@ -11014,6 +11027,7 @@ + sc->sc_cabq->axq_qnum); + IPRINTF(sc, "Use hw queue %u for beacons\n", sc->sc_bhalq); + } ++#endif + #undef HAL_MODE_DUALBAND + } + +--- a/ath/if_ath_radar.c ++++ b/ath/if_ath_radar.c +@@ -156,7 +156,9 @@ + #endif + }; + ++#ifdef AR_DEBUG + static u_int32_t interval_to_frequency(u_int32_t pri); ++#endif + + /* Returns true if radar detection is enabled. */ + int ath_radar_is_enabled(struct ath_softc *sc) +@@ -229,7 +231,9 @@ + { + + struct ath_hal *ah = sc->sc_ah; ++#ifdef AR_DEBUG + struct net_device *dev = sc->sc_dev; ++#endif + struct ieee80211com *ic = &sc->sc_ic; + int required = 0; + +@@ -366,6 +370,7 @@ + #define MR_FAIL_MIN_PERIOD 4 + #define MR_FAIL_MAX_PERIOD 5 + ++#ifdef AR_DEBUG + static const char* get_match_result_desc(u_int32_t code) { + switch (code) { + case MR_MATCH: +@@ -384,6 +389,7 @@ + return "unknown"; + } + } ++#endif + + static int32_t match_radar( + u_int32_t matched, +@@ -775,7 +781,10 @@ + struct ath_softc *sc, struct ath_rp *last_pulse, + u_int32_t *index, u_int32_t *pri, u_int32_t *matching_pulses, + u_int32_t *missed_pulses, u_int32_t *noise_pulses) +-{ struct net_device *dev = sc->sc_dev; ++{ ++#ifdef AR_DEBUG ++ struct net_device *dev = sc->sc_dev; ++#endif + int i; + int best_index = -1; + unsigned int best_matched = 0; +@@ -1217,6 +1226,7 @@ + return (-1 != best_index) ? AH_TRUE : AH_FALSE; + } + ++#ifdef AR_DEBUG + static u_int32_t interval_to_frequency(u_int32_t interval) + { + /* Calculate BRI from PRI */ +@@ -1224,6 +1234,7 @@ + /* Round to nearest multiple of 50 */ + return frequency + ((frequency % 50) >= 25 ? 50 : 0) - (frequency % 50); + } ++#endif + + #ifdef ATH_RADAR_LONG_PULSE + static const char* get_longpulse_desc(int lp) { +@@ -1580,7 +1591,9 @@ + void ath_rp_record(struct ath_softc *sc, u_int64_t tsf, u_int8_t rssi, + u_int8_t width, HAL_BOOL is_simulated) + { ++#ifdef AR_DEBUG + struct net_device *dev = sc->sc_dev; ++#endif + struct ath_rp *pulse; + + DPRINTF(sc, ATH_DEBUG_DOTHPULSES, "%s: ath_rp_record: " +--- a/ath_rate/minstrel/minstrel.c ++++ b/ath_rate/minstrel/minstrel.c +@@ -931,7 +931,9 @@ + (struct ieee80211_node_table *) &vap->iv_ic->ic_sta; + unsigned int x = 0; + unsigned int this_tp, this_prob, this_eprob; ++#ifdef AR_DEBUG + struct ath_softc *sc = vap->iv_ic->ic_dev->priv;; ++#endif + + IEEE80211_NODE_TABLE_LOCK_IRQ(nt); + TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { +--- a/net80211/ieee80211_scan_ap.c ++++ b/net80211/ieee80211_scan_ap.c +@@ -731,6 +731,7 @@ + + sort(chans, ss_last, sizeof(*chans), pc_cmp, pc_swap); + ++#ifdef IEEE80211_DEBUG + for (i = 0; i < ss_last; i++) { + int chan = ieee80211_chan2ieee(ic, chans[i].chan); + +@@ -742,6 +743,7 @@ + !!IEEE80211_ARE_CHANS_SAME_MODE(chans[i].chan, + ic->ic_bsschan)); + } ++#endif + + best = NULL; + best_rssi = 0xff; /* If signal is bigger than 0xff, we'd be melting. */ diff --git a/package/madwifi/patches/300-napi_polling.patch b/package/madwifi/patches/300-napi_polling.patch index ba72329f6d..6b472caacd 100644 --- a/package/madwifi/patches/300-napi_polling.patch +++ b/package/madwifi/patches/300-napi_polling.patch @@ -44,7 +44,7 @@ #ifdef USE_HEADERLEN_RESV dev->hard_header_len += sizeof(struct ieee80211_qosframe) + sizeof(struct llc) + -@@ -2216,6 +2228,7 @@ +@@ -2220,6 +2232,7 @@ (status & HAL_INT_GLOBAL) ? " HAL_INT_GLOBAL" : "" ); @@ -52,7 +52,7 @@ status &= sc->sc_imask; /* discard unasked for bits */ /* As soon as we know we have a real interrupt we intend to service, * we will check to see if we need an initial hardware TSF reading. -@@ -2273,7 +2286,23 @@ +@@ -2277,7 +2290,23 @@ } if (status & (HAL_INT_RX | HAL_INT_RXPHY)) { ath_uapsd_processtriggers(sc, hw_tsf); @@ -77,7 +77,7 @@ } if (status & HAL_INT_TX) { #ifdef ATH_SUPERG_DYNTURBO -@@ -2299,6 +2328,11 @@ +@@ -2303,6 +2332,11 @@ } } #endif @@ -89,7 +89,7 @@ ATH_SCHEDULE_TQUEUE(&sc->sc_txtq, &needmark); } if (status & HAL_INT_BMISS) { -@@ -2511,6 +2545,7 @@ +@@ -2515,6 +2549,7 @@ if (sc->sc_tx99 != NULL) sc->sc_tx99->start(sc->sc_tx99); #endif @@ -97,7 +97,7 @@ done: ATH_UNLOCK(sc); -@@ -2551,6 +2586,9 @@ +@@ -2555,6 +2590,9 @@ if (sc->sc_tx99 != NULL) sc->sc_tx99->stop(sc->sc_tx99); #endif @@ -107,7 +107,7 @@ netif_stop_queue(dev); /* XXX re-enabled by ath_newstate */ dev->flags &= ~IFF_RUNNING; /* NB: avoid recursion */ ieee80211_stop_running(ic); /* stop all VAPs */ -@@ -4009,6 +4047,39 @@ +@@ -4013,6 +4051,39 @@ return ath_keyset(sc, k, mac, vap->iv_bss); } @@ -147,7 +147,7 @@ /* * Block/unblock tx+rx processing while a key change is done. * We assume the caller serializes key management operations -@@ -4026,13 +4097,7 @@ +@@ -4032,13 +4103,7 @@ * When called from the rx tasklet we cannot use * tasklet_disable because it will block waiting * for us to complete execution. @@ -161,8 +161,8 @@ netif_stop_queue(dev); } -@@ -4043,9 +4108,9 @@ - struct ath_softc *sc = dev->priv; +@@ -4051,9 +4116,9 @@ + #endif DPRINTF(sc, ATH_DEBUG_KEYCACHE, "End\n"); - netif_wake_queue(dev); @@ -174,7 +174,7 @@ } /* -@@ -6350,15 +6415,25 @@ +@@ -6360,15 +6425,25 @@ sc->sc_rxotherant = 0; } @@ -204,7 +204,7 @@ struct ieee80211com *ic = &sc->sc_ic; struct ath_hal *ah = sc ? sc->sc_ah : NULL; struct ath_desc *ds; -@@ -6368,8 +6443,10 @@ +@@ -6378,8 +6453,10 @@ unsigned int len; int type; u_int phyerr; @@ -215,7 +215,7 @@ do { bf = STAILQ_FIRST(&sc->sc_rxbuf); if (bf == NULL) { /* XXX ??? can this happen */ -@@ -6393,6 +6470,15 @@ +@@ -6403,6 +6480,15 @@ /* NB: never process the self-linked entry at the end */ break; } @@ -231,7 +231,7 @@ skb = bf->bf_skb; if (skb == NULL) { EPRINTF(sc, "Dropping; buffer contains NULL skbuff.\n"); -@@ -6440,6 +6526,7 @@ +@@ -6450,6 +6536,7 @@ sc->sc_stats.ast_rx_phyerr++; phyerr = rs->rs_phyerr & 0x1f; sc->sc_stats.ast_rx_phy[phyerr]++; @@ -239,7 +239,7 @@ } if (rs->rs_status & HAL_RXERR_DECRYPT) { /* -@@ -6635,9 +6722,43 @@ +@@ -6645,9 +6732,43 @@ STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); ATH_RXBUF_UNLOCK_IRQ(sc); } while (ath_rxbuf_init(sc, bf) == 0); @@ -283,7 +283,7 @@ #undef PA2DESC } -@@ -8288,12 +8409,24 @@ +@@ -8298,12 +8419,24 @@ { struct net_device *dev = (struct net_device *)data; struct ath_softc *sc = dev->priv; @@ -308,7 +308,7 @@ netif_wake_queue(dev); if (sc->sc_softled) -@@ -8309,7 +8442,9 @@ +@@ -8319,7 +8452,9 @@ { struct net_device *dev = (struct net_device *)data; struct ath_softc *sc = dev->priv; @@ -318,7 +318,7 @@ /* * Process each active queue. */ -@@ -8330,6 +8465,16 @@ +@@ -8340,6 +8475,16 @@ if (sc->sc_uapsdq && txqactive(sc->sc_ah, sc->sc_uapsdq->axq_qnum)) ath_tx_processq(sc, sc->sc_uapsdq); @@ -335,7 +335,7 @@ netif_wake_queue(dev); if (sc->sc_softled) -@@ -8345,13 +8490,25 @@ +@@ -8355,13 +8500,25 @@ struct net_device *dev = (struct net_device *)data; struct ath_softc *sc = dev->priv; unsigned int i; @@ -361,7 +361,7 @@ netif_wake_queue(dev); if (sc->sc_softled) -@@ -10284,9 +10441,9 @@ +@@ -10296,9 +10453,9 @@ dev->mtu = mtu; if ((dev->flags & IFF_RUNNING) && !sc->sc_invalid) { /* NB: the rx buffers may need to be reallocated */ diff --git a/package/madwifi/patches/305-pureg_fix.patch b/package/madwifi/patches/305-pureg_fix.patch index 196ac743cf..ba7e62ed8f 100644 --- a/package/madwifi/patches/305-pureg_fix.patch +++ b/package/madwifi/patches/305-pureg_fix.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -4149,7 +4149,9 @@ +@@ -4157,7 +4157,9 @@ rfilt |= HAL_RX_FILTER_PROM; if (ic->ic_opmode == IEEE80211_M_STA || sc->sc_opmode == HAL_M_IBSS || /* NB: AHDEMO too */ diff --git a/package/madwifi/patches/309-micfail_detect.patch b/package/madwifi/patches/309-micfail_detect.patch index 91986cd624..23da333786 100644 --- a/package/madwifi/patches/309-micfail_detect.patch +++ b/package/madwifi/patches/309-micfail_detect.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -6446,6 +6446,7 @@ +@@ -6456,6 +6456,7 @@ int type; u_int phyerr; u_int processed = 0, early_stop = 0; @@ -8,7 +8,7 @@ DPRINTF(sc, ATH_DEBUG_RX_PROC, "invoked\n"); process_rx_again: -@@ -6547,24 +6548,8 @@ +@@ -6557,24 +6558,8 @@ } if (rs->rs_status & HAL_RXERR_MIC) { sc->sc_stats.ast_rx_badmic++; @@ -35,7 +35,7 @@ } /* * Reject error frames if we have no vaps that -@@ -6603,8 +6588,9 @@ +@@ -6613,8 +6598,9 @@ /* * Finished monitor mode handling, now reject * error frames before passing to other vaps @@ -46,7 +46,7 @@ ieee80211_dev_kfree_skb(&skb); goto rx_next; } -@@ -6612,6 +6598,26 @@ +@@ -6622,6 +6608,26 @@ /* remove the CRC */ skb_trim(skb, skb->len - IEEE80211_CRC_LEN); @@ -73,7 +73,7 @@ /* * From this point on we assume the frame is at least * as large as ieee80211_frame_min; verify that. -@@ -6624,6 +6630,7 @@ +@@ -6634,6 +6640,7 @@ goto rx_next; } diff --git a/package/madwifi/patches/310-noise_get.patch b/package/madwifi/patches/310-noise_get.patch index b37ff52922..8b24b2110c 100644 --- a/package/madwifi/patches/310-noise_get.patch +++ b/package/madwifi/patches/310-noise_get.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -1695,8 +1695,6 @@ +@@ -1699,8 +1699,6 @@ * get to reality. This value is used in monitor mode and by tools like * Wireshark and Kismet. */ @@ -9,7 +9,7 @@ ATH_RXBUF_LOCK_IRQ(sc); if (sc->sc_rxbufcur == NULL) sc->sc_rxbufcur = STAILQ_FIRST(&sc->sc_rxbuf); -@@ -8966,6 +8964,7 @@ +@@ -8978,6 +8976,7 @@ sc->sc_curchan.channel); sc->sc_stats.ast_per_calfail++; } @@ -17,7 +17,7 @@ ath_hal_process_noisefloor(ah); if (isIQdone == AH_TRUE) { -@@ -9034,6 +9033,7 @@ +@@ -9046,6 +9045,7 @@ struct ath_softc *sc = dev->priv; (void) ath_chan_set(sc, ic->ic_curchan); @@ -25,7 +25,7 @@ /* * If we are returning to our bss channel then mark state * so the next recv'd beacon's TSF will be used to sync the -@@ -9302,6 +9302,7 @@ +@@ -9314,6 +9314,7 @@ } ath_hal_process_noisefloor(ah); diff --git a/package/madwifi/patches/317-bmask.patch b/package/madwifi/patches/317-bmask.patch index 4654b818c0..24d2f9f22c 100644 --- a/package/madwifi/patches/317-bmask.patch +++ b/package/madwifi/patches/317-bmask.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -8680,6 +8680,10 @@ +@@ -8692,6 +8692,10 @@ sc->sc_rxbufcur = NULL; diff --git a/package/madwifi/patches/323-dfs_optional.patch b/package/madwifi/patches/323-dfs_optional.patch index 46c480aac2..d1f3b6258e 100644 --- a/package/madwifi/patches/323-dfs_optional.patch +++ b/package/madwifi/patches/323-dfs_optional.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -1774,17 +1774,14 @@ +@@ -1778,17 +1778,14 @@ * may have occurred in the intervening timeframe. */ bf->bf_channoise = ic->ic_channoise; @@ -27,7 +27,7 @@ bus_dma_sync_single(sc->sc_bdev, bf->bf_skbaddr, --- a/ath/if_ath_radar.c +++ b/ath/if_ath_radar.c -@@ -261,7 +261,7 @@ +@@ -265,7 +265,7 @@ unsigned int new_rxfilt = old_rxfilt; ath_hal_intrset(ah, old_ier & ~HAL_INT_GLOBAL); diff --git a/package/madwifi/patches/325-channel_spam.patch b/package/madwifi/patches/325-channel_spam.patch index 0059ba6546..5c18c11849 100644 --- a/package/madwifi/patches/325-channel_spam.patch +++ b/package/madwifi/patches/325-channel_spam.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -9783,7 +9783,9 @@ +@@ -9795,7 +9795,9 @@ /* * Convert HAL channels to ieee80211 ones. */ @@ -10,7 +10,7 @@ for (i = 0; i < nchan; i++) { HAL_CHANNEL *c = &chans[i]; struct ieee80211_channel *ichan = &ic->ic_channels[i]; -@@ -9810,6 +9812,7 @@ +@@ -9822,6 +9824,7 @@ ic->ic_chan_non_occupy[i].tv_sec = 0; ic->ic_chan_non_occupy[i].tv_usec = 0; @@ -18,7 +18,7 @@ IPRINTF(sc, "Channel %3d (%4d MHz) Max Tx Power %d dBm%s " "[%d hw %d reg] Flags%s%s%s%s%s%s%s%s%s%s%s%s%" "s%s%s%s%s%s%s%s%s%s%s%s\n", -@@ -9898,6 +9901,7 @@ +@@ -9910,6 +9913,7 @@ (c->privFlags & 0x0080 ? " PF & (1 << 7)" : "") ); diff --git a/package/madwifi/patches/327-queue.patch b/package/madwifi/patches/327-queue.patch index 53a80f6e6f..ca42da386a 100644 --- a/package/madwifi/patches/327-queue.patch +++ b/package/madwifi/patches/327-queue.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -8431,8 +8431,6 @@ +@@ -8441,8 +8441,6 @@ ath_hal_intrset(sc->sc_ah, sc->sc_imask); local_irq_restore(flags); @@ -9,7 +9,7 @@ if (sc->sc_softled) ath_led_event(sc, ATH_LED_TX); } -@@ -8479,8 +8477,6 @@ +@@ -8489,8 +8487,6 @@ ath_hal_intrset(sc->sc_ah, sc->sc_imask); local_irq_restore(flags); @@ -18,7 +18,7 @@ if (sc->sc_softled) ath_led_event(sc, ATH_LED_TX); } -@@ -8513,8 +8509,6 @@ +@@ -8523,8 +8519,6 @@ ath_hal_intrset(sc->sc_ah, sc->sc_imask); local_irq_restore(flags); diff --git a/package/madwifi/patches/330-beaconcal.patch b/package/madwifi/patches/330-beaconcal.patch index 46b8b76a0f..174e566bf2 100644 --- a/package/madwifi/patches/330-beaconcal.patch +++ b/package/madwifi/patches/330-beaconcal.patch @@ -24,7 +24,7 @@ module_param(countrycode, int, 0600); module_param(maxvaps, int, 0600); module_param(outdoor, int, 0600); -@@ -2598,7 +2601,8 @@ +@@ -2602,7 +2605,8 @@ } if (!sc->sc_invalid) { del_timer_sync(&sc->sc_dfs_cac_timer); @@ -34,7 +34,7 @@ } ath_draintxq(sc); if (!sc->sc_invalid) { -@@ -2615,6 +2619,20 @@ +@@ -2619,6 +2623,20 @@ return 0; } @@ -55,7 +55,7 @@ /* * Stop the device, grabbing the top-level lock to protect * against concurrent entry through ath_init (which can happen -@@ -2740,6 +2758,12 @@ +@@ -2744,6 +2762,12 @@ HAL_STATUS status; /* @@ -68,7 +68,7 @@ * Convert to a HAL channel description with the flags * constrained to reflect the current operating mode. */ -@@ -5145,6 +5169,8 @@ +@@ -5153,6 +5177,8 @@ "Invoking ath_hal_txstart with sc_bhalq: %d\n", sc->sc_bhalq); ath_hal_txstart(ah, sc->sc_bhalq); @@ -77,7 +77,7 @@ sc->sc_stats.ast_be_xmit++; /* XXX per-VAP? */ } -@@ -5394,6 +5420,7 @@ +@@ -5402,6 +5428,7 @@ ath_hal_beacontimers(ah, &bs); sc->sc_imask |= HAL_INT_BMISS; ath_hal_intrset(ah, sc->sc_imask); @@ -85,7 +85,7 @@ } else { ath_hal_intrset(ah, 0); if (reset_tsf) -@@ -5405,8 +5432,11 @@ +@@ -5413,8 +5440,11 @@ */ intval |= HAL_BEACON_ENA; sc->sc_imask |= HAL_INT_SWBA; @@ -98,7 +98,7 @@ #ifdef ATH_SUPERG_DYNTURBO ath_beacon_dturbo_config(vap, intval & ~(HAL_BEACON_RESET_TSF | HAL_BEACON_ENA)); -@@ -8870,6 +8900,9 @@ +@@ -8882,6 +8912,9 @@ /* Enter DFS wait period */ mod_timer(&sc->sc_dfs_cac_timer, jiffies + (sc->sc_dfs_cac_period * HZ)); @@ -108,7 +108,7 @@ } /* * re configure beacons when it is a turbo mode switch. -@@ -8979,8 +9012,11 @@ +@@ -8991,8 +9024,11 @@ sc->sc_curchan.channel, sc->sc_curchan.channelFlags, isIQdone ? "done" : "not done"); @@ -122,7 +122,7 @@ } static void -@@ -9087,7 +9123,8 @@ +@@ -9099,7 +9135,8 @@ ieee80211_state_name[vap->iv_state], ieee80211_state_name[nstate]); @@ -132,7 +132,7 @@ ath_hal_setledstate(ah, leds[nstate]); /* set LED */ netif_stop_queue(dev); /* before we do anything else */ -@@ -9312,7 +9349,8 @@ +@@ -9324,7 +9361,8 @@ "VAP -> DFSWAIT_PENDING \n"); /* start calibration timer with a really small value * 1/10 sec */ @@ -142,7 +142,7 @@ /* wake the receiver */ netif_wake_queue(dev); /* don't do the other usual stuff... */ -@@ -9355,7 +9393,7 @@ +@@ -9367,7 +9405,7 @@ error = avp->av_newstate(vap, nstate, arg); /* Finally, start any timers. */ diff --git a/package/madwifi/patches/331-memory_alloc.patch b/package/madwifi/patches/331-memory_alloc.patch index eae4a55368..c18f6b4fd2 100644 --- a/package/madwifi/patches/331-memory_alloc.patch +++ b/package/madwifi/patches/331-memory_alloc.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -3318,17 +3318,18 @@ +@@ -3322,17 +3322,18 @@ * without affecting any other bridge ports. */ if (skb_cloned(skb)) { /* Remember the original SKB so we can free up our references */ @@ -25,7 +25,7 @@ eh = (struct ether_header *)skb->data; #ifdef ATH_SUPERG_FF -@@ -3599,6 +3600,8 @@ +@@ -3603,6 +3604,8 @@ sc->sc_stats.ast_tx_mgmt++; return 0; bad: diff --git a/package/madwifi/patches/332-reset_beacons.patch b/package/madwifi/patches/332-reset_beacons.patch index 8d4cdabcf0..b01ea7cba5 100644 --- a/package/madwifi/patches/332-reset_beacons.patch +++ b/package/madwifi/patches/332-reset_beacons.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -8911,7 +8911,7 @@ +@@ -8923,7 +8923,7 @@ * re configure beacons when it is a turbo mode switch. * HW seems to turn off beacons during turbo mode switch. */ diff --git a/package/madwifi/patches/333-apscan_mode.patch b/package/madwifi/patches/333-apscan_mode.patch index d869440de7..d8497a6d85 100644 --- a/package/madwifi/patches/333-apscan_mode.patch +++ b/package/madwifi/patches/333-apscan_mode.patch @@ -1,6 +1,6 @@ --- a/net80211/ieee80211_scan_ap.c +++ b/net80211/ieee80211_scan_ap.c -@@ -781,12 +781,6 @@ +@@ -783,12 +783,6 @@ /* break the loop as the subsequent chans won't be * better */ break; diff --git a/package/madwifi/patches/342-performance.patch b/package/madwifi/patches/342-performance.patch index d79349dce3..c9316c6533 100644 --- a/package/madwifi/patches/342-performance.patch +++ b/package/madwifi/patches/342-performance.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -3237,7 +3237,6 @@ +@@ -3241,7 +3241,6 @@ struct ath_softc *sc = dev->priv; struct ieee80211_node *ni = NULL; struct ath_buf *bf = NULL; @@ -8,7 +8,7 @@ ath_bufhead bf_head; struct ath_buf *tbf, *tempbf; struct sk_buff *tskb; -@@ -3249,6 +3248,7 @@ +@@ -3253,6 +3252,7 @@ */ int requeue = 0; #ifdef ATH_SUPERG_FF @@ -16,7 +16,7 @@ unsigned int pktlen; struct ieee80211com *ic = &sc->sc_ic; struct ath_node *an; -@@ -3314,27 +3314,9 @@ +@@ -3318,27 +3318,9 @@ requeue = 1; goto hardstart_fail; } diff --git a/package/madwifi/patches/343-txqueue_races.patch b/package/madwifi/patches/343-txqueue_races.patch index 74fd9be21d..20b6f527cf 100644 --- a/package/madwifi/patches/343-txqueue_races.patch +++ b/package/madwifi/patches/343-txqueue_races.patch @@ -2,7 +2,7 @@ Merged from madwifi trunk r3551, r3552 --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -8244,6 +8244,17 @@ +@@ -8254,6 +8254,17 @@ goto bf_fail; } diff --git a/package/madwifi/patches/345-minstrel_sampling.patch b/package/madwifi/patches/345-minstrel_sampling.patch index 51416e5bf8..0e68422f72 100644 --- a/package/madwifi/patches/345-minstrel_sampling.patch +++ b/package/madwifi/patches/345-minstrel_sampling.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -8094,6 +8094,7 @@ +@@ -8104,6 +8104,7 @@ ath_hal_setupxtxdesc(sc->sc_ah, ds, mrr.rate1, mrr.retries1, mrr.rate2, mrr.retries2, mrr.rate3, mrr.retries3); diff --git a/package/madwifi/patches/347-tuning.patch b/package/madwifi/patches/347-tuning.patch index deddd0de6b..4c8379a7c6 100644 --- a/package/madwifi/patches/347-tuning.patch +++ b/package/madwifi/patches/347-tuning.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -10265,11 +10265,11 @@ +@@ -10277,11 +10277,11 @@ sc->sc_currates = rt; sc->sc_curmode = mode; /* diff --git a/package/madwifi/patches/348-ackcts.patch b/package/madwifi/patches/348-ackcts.patch index a505ef86da..55acf74c00 100644 --- a/package/madwifi/patches/348-ackcts.patch +++ b/package/madwifi/patches/348-ackcts.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -2721,6 +2721,9 @@ +@@ -2725,6 +2725,9 @@ static int ath_set_ack_bitrate(struct ath_softc *sc, int high) { @@ -10,7 +10,7 @@ if (ar_device(sc->devid) == 5212 || ar_device(sc->devid) == 5213) { /* set ack to be sent at low bit-rate */ /* registers taken from the OpenBSD 5212 HAL */ -@@ -10780,8 +10783,13 @@ +@@ -10792,8 +10795,13 @@ break; #endif case ATH_ACKRATE: diff --git a/package/madwifi/patches/349-reset.patch b/package/madwifi/patches/349-reset.patch index 1047dd23d2..570193d251 100644 --- a/package/madwifi/patches/349-reset.patch +++ b/package/madwifi/patches/349-reset.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -8853,8 +8853,7 @@ +@@ -8865,8 +8865,7 @@ * needed to do the reset with chanchange = AH_FALSE in order * to receive traffic when peforming high velocity channel * changes. */ diff --git a/package/madwifi/patches/351-scanlist.patch b/package/madwifi/patches/351-scanlist.patch index 6a4ae8b2f5..3765264968 100644 --- a/package/madwifi/patches/351-scanlist.patch +++ b/package/madwifi/patches/351-scanlist.patch @@ -640,7 +640,7 @@ ss->ss_next = 0; /* XXX tunables */ ss->ss_mindwell = msecs_to_jiffies(200); /* 200ms */ -@@ -759,13 +538,6 @@ +@@ -761,13 +540,6 @@ if (IEEE80211_IS_CHAN_RADAR(c->chan)) continue; diff --git a/package/madwifi/patches/352-ani_fix.patch b/package/madwifi/patches/352-ani_fix.patch index 0129665238..aff0d4a428 100644 --- a/package/madwifi/patches/352-ani_fix.patch +++ b/package/madwifi/patches/352-ani_fix.patch @@ -23,7 +23,7 @@ return 0; bad3: ieee80211_ifdetach(ic); -@@ -2347,16 +2350,6 @@ +@@ -2351,16 +2354,6 @@ } if (status & HAL_INT_MIB) { sc->sc_stats.ast_mib++; @@ -40,7 +40,7 @@ /* Let the HAL handle the event. */ ath_hal_mibevent(ah, &sc->sc_halstats); } -@@ -2426,6 +2419,43 @@ +@@ -2430,6 +2423,43 @@ return flags; } @@ -84,7 +84,7 @@ /* * Context: process context */ -@@ -2491,8 +2521,7 @@ +@@ -2495,8 +2525,7 @@ if (sc->sc_softled) ath_hal_gpioCfgOutput(ah, sc->sc_ledpin); @@ -94,7 +94,7 @@ /* * This is needed only to setup initial state -@@ -2528,7 +2557,7 @@ +@@ -2532,7 +2561,7 @@ * Enable MIB interrupts when there are hardware phy counters. * Note we only do this (at the moment) for station mode. */ @@ -103,7 +103,7 @@ sc->sc_imask |= HAL_INT_MIB; ath_hal_intrset(ah, sc->sc_imask); -@@ -2785,9 +2814,7 @@ +@@ -2789,9 +2818,7 @@ EPRINTF(sc, "Unable to reset hardware: '%s' (HAL status %u)\n", ath_get_hal_status_desc(status), status); @@ -114,7 +114,7 @@ ath_update_txpow(sc); /* update tx power state */ ath_radar_update(sc); ath_setdefantenna(sc, sc->sc_defant); -@@ -4165,6 +4192,8 @@ +@@ -4173,6 +4200,8 @@ if (sc->sc_nmonvaps > 0) rfilt |= (HAL_RX_FILTER_CONTROL | HAL_RX_FILTER_BEACON | HAL_RX_FILTER_PROBEREQ | HAL_RX_FILTER_PROM); @@ -123,7 +123,7 @@ if (sc->sc_curchan.privFlags & CHANNEL_DFS) rfilt |= (HAL_RX_FILTER_PHYERR | HAL_RX_FILTER_PHYRADAR); return rfilt; -@@ -6513,9 +6542,6 @@ +@@ -6523,9 +6552,6 @@ rs->rs_rssi = 0; len = rs->rs_datalen; @@ -133,7 +133,7 @@ if (rs->rs_more) { /* -@@ -8865,9 +8891,7 @@ +@@ -8877,9 +8903,7 @@ if (sc->sc_softled) ath_hal_gpioCfgOutput(ah, sc->sc_ledpin); @@ -144,7 +144,7 @@ sc->sc_curchan = hchan; ath_update_txpow(sc); /* update tx power state */ ath_radar_update(sc); -@@ -10644,9 +10668,54 @@ +@@ -10656,9 +10680,54 @@ ATH_RP_IGNORED = 24, ATH_RADAR_IGNORED = 25, ATH_MAXVAPS = 26, @@ -199,7 +199,7 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos) { struct ath_softc *sc = ctl->extra1; -@@ -10832,6 +10901,11 @@ +@@ -10844,6 +10913,11 @@ case ATH_RADAR_IGNORED: sc->sc_radar_ignored = val; break; @@ -211,7 +211,7 @@ default: ret = -EINVAL; break; -@@ -10898,6 +10972,11 @@ +@@ -10910,6 +10984,11 @@ case ATH_RADAR_IGNORED: val = sc->sc_radar_ignored; break; @@ -223,7 +223,7 @@ default: ret = -EINVAL; break; -@@ -11075,6 +11154,24 @@ +@@ -11087,6 +11166,24 @@ .proc_handler = ath_sysctl_halparam, .extra2 = (void *)ATH_RADAR_IGNORED, }, diff --git a/package/madwifi/patches/355-eap_auth_disassoc.patch b/package/madwifi/patches/355-eap_auth_disassoc.patch index e85d93a788..303370dd0d 100644 --- a/package/madwifi/patches/355-eap_auth_disassoc.patch +++ b/package/madwifi/patches/355-eap_auth_disassoc.patch @@ -5,7 +5,7 @@ Signed-off-by: Felix Fietkau --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -8315,6 +8315,18 @@ +@@ -8325,6 +8325,18 @@ #endif if (ts->ts_status & HAL_TXERR_XRETRY) { sc->sc_stats.ast_tx_xretries++; diff --git a/package/madwifi/patches/363-fix_turbo.patch b/package/madwifi/patches/363-fix_turbo.patch new file mode 100644 index 0000000000..174e6953cb --- /dev/null +++ b/package/madwifi/patches/363-fix_turbo.patch @@ -0,0 +1,11 @@ +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -4914,7 +4914,7 @@ + * capability info and arrange for a mode change + * if needed. + */ +- if (sc->sc_dturbo) { ++ if (sc->sc_dturbo && NULL != avp->av_boff.bo_tim) { + u_int8_t dtim; + dtim = ((avp->av_boff.bo_tim[2] == 1) || + (avp->av_boff.bo_tim[3] == 1)); diff --git a/package/madwifi/patches/364-memory_alloc.patch b/package/madwifi/patches/364-memory_alloc.patch new file mode 100644 index 0000000000..d0d76a1792 --- /dev/null +++ b/package/madwifi/patches/364-memory_alloc.patch @@ -0,0 +1,13 @@ +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -539,8 +539,8 @@ + + /* Allocate space for dynamically determined maximum VAP count */ + sc->sc_bslot = +- kmalloc(ath_maxvaps * sizeof(struct ieee80211vap), GFP_KERNEL); +- memset(sc->sc_bslot, 0, ath_maxvaps * sizeof(struct ieee80211vap)); ++ kmalloc(ath_maxvaps * sizeof(struct ieee80211vap*), GFP_KERNEL); ++ memset(sc->sc_bslot, 0, ath_maxvaps * sizeof(struct ieee80211vap*)); + + /* + * Cache line size is used to size and align various diff --git a/package/madwifi/patches/365-turbo_channelsearch.patch b/package/madwifi/patches/365-turbo_channelsearch.patch new file mode 100644 index 0000000000..31caa1bfe7 --- /dev/null +++ b/package/madwifi/patches/365-turbo_channelsearch.patch @@ -0,0 +1,10 @@ +--- a/net80211/ieee80211.c ++++ b/net80211/ieee80211.c +@@ -684,6 +684,7 @@ + int i; + + /* Brute force search */ ++ flags &= IEEE80211_CHAN_ALLTURBO; + for (i = 0; i < ic->ic_nchans; i++) { + c = &ic->ic_channels[i]; + if (c->ic_freq == freq && diff --git a/package/madwifi/patches/366-bstuck_thresh.patch b/package/madwifi/patches/366-bstuck_thresh.patch new file mode 100644 index 0000000000..d04756e2f7 --- /dev/null +++ b/package/madwifi/patches/366-bstuck_thresh.patch @@ -0,0 +1,52 @@ +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -389,6 +389,7 @@ + static int ath_outdoor = AH_FALSE; /* enable outdoor use */ + static int ath_xchanmode = AH_TRUE; /* enable extended channels */ + static int ath_maxvaps = ATH_MAXVAPS_DEFAULT; /* set default maximum vaps */ ++static int bstuck_thresh = BSTUCK_THRESH; /* Stuck beacon count required for reset */ + static char *autocreate = NULL; + static char *ratectl = DEF_RATE_CTL; + static int rfkill = 0; +@@ -432,6 +433,7 @@ + #ifdef ATH_CAP_TPC + MODULE_PARM(tpc, "i"); + #endif ++MODULE_PARM(bstuck_thresh, "i"); + MODULE_PARM(autocreate, "s"); + MODULE_PARM(ratectl, "s"); + #else +@@ -445,6 +447,7 @@ + #ifdef ATH_CAP_TPC + module_param(tpc, int, 0600); + #endif ++module_param(bstuck_thresh, int, 0600); + module_param(autocreate, charp, 0600); + module_param(ratectl, charp, 0600); + #endif +@@ -457,6 +460,7 @@ + MODULE_PARM_DESC(tpc, "Enable/disable per-packet transmit power control (TPC) " + "capability"); + #endif ++MODULE_PARM_DESC(bstuck_thresh, "Override default stuck beacon threshold"); + MODULE_PARM_DESC(autocreate, "Create ath device in " + "[sta|ap|wds|adhoc|ahdemo|monitor] mode. defaults to sta, use " + "'none' to disable"); +@@ -5061,7 +5065,7 @@ + DPRINTF(sc, ATH_DEBUG_BEACON_PROC, + "Missed %u consecutive beacons (n_beacon=%u)\n", + sc->sc_bmisscount, n_beacon); +- if (sc->sc_bmisscount > BSTUCK_THRESH) ++ if (sc->sc_bmisscount > bstuck_thresh) + ATH_SCHEDULE_TQUEUE(&sc->sc_bstucktq, needmark); + return; + } +@@ -5217,7 +5221,7 @@ + * check will be true, in which case return + * without resetting the driver. + */ +- if (sc->sc_bmisscount <= BSTUCK_THRESH) ++ if (sc->sc_bmisscount <= bstuck_thresh) + return; + EPRINTF(sc, "Stuck beacon; resetting (beacon miss count: %u)\n", + sc->sc_bmisscount); diff --git a/package/madwifi/patches/406-monitor_r3711.patch b/package/madwifi/patches/406-monitor_r3711.patch new file mode 100644 index 0000000000..e1a56c01bf --- /dev/null +++ b/package/madwifi/patches/406-monitor_r3711.patch @@ -0,0 +1,20 @@ +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -6321,7 +6321,7 @@ + + /* Never copy the SKB, as it is ours on the RX side, and this is the + * last process on the TX side and we only modify our own headers. */ +- tskb = ath_skb_removepad(skb, 0 /* Copy SKB */); ++ tskb = ath_skb_removepad(skb, !tx /* Copy SKB */); + if (tskb == NULL) { + DPRINTF(sc, ATH_DEBUG_ANY, + "Dropping; ath_skb_removepad failed!\n"); +@@ -6329,6 +6329,8 @@ + } + + ieee80211_input_monitor(ic, tskb, bf, tx, tsf, sc); ++ if (tskb != skb) ++ ieee80211_dev_kfree_skb(&tskb); + } + + /* diff --git a/package/madwifi/patches/407-new_athinfo.patch b/package/madwifi/patches/407-new_athinfo.patch new file mode 100644 index 0000000000..1577949750 --- /dev/null +++ b/package/madwifi/patches/407-new_athinfo.patch @@ -0,0 +1,2352 @@ +--- a/tools/ath_info.c ++++ b/tools/ath_info.c +@@ -16,78 +16,8 @@ + * along with this program. If not, see . + */ + +-/* So here is how it works: +- * +- * First compile... +- * +- * gcc ath_info.c -o ath_info +- * +- * then find card's physical address +- * +- * lspci -v +- * +- * 02:02.0 Ethernet controller: Atheros Communications, Inc. AR5212 802.11abg NIC (rev 01) +- * Subsystem: Fujitsu Limited. Unknown device 1234 +- * Flags: bus master, medium devsel, latency 168, IRQ 23 +- * Memory at c2000000 (32-bit, non-prefetchable) [size=64K] +- * Capabilities: [44] Power Management version 2 +- * +- * address here is 0xc2000000 +- * +- * load madwifi-ng or madwifi-old if not already loaded (be sure the +- * interface is down!) +- * +- * modprobe ath_pci +- * +- * OR +- * +- * call: +- * setpci -s 02:02.0 command=0x41f cache_line_size=0x10 +- * +- * to enable access to the PCI device. +- * +- * and we run the thing... +- * +- * ./ath_info 0xc2000000 +- * +- * In order to change the regdomain to 0, call: +- * +- * ./ath_info -w 0xc2000000 regdomain 0 +- * +- * to change any PCI ID value, say: +- * +- * ./ath_info -w 0xc2000000 X +- * +- * with ::= pci_dev_id | pci_vendor_id | pci_class | +- * pci_subsys_dev_id | pci_subsys_vendor_id +- * +- * With newer chipsets (>= AR5004x, i.e. MAC >= AR5213), Atheros introduced +- * write protection on the EEPROM. On a GIGABYTE GN-WI01HT you can set GPIO 4 +- * to low to be able to write the EEPROM. This depends highly on the PCB layout, +- * so there may be different GPIO used. +- * This program currently sets GPIO 4 to low for a MAC >= AR5213, but you can +- * override this with the -g option: +- * +- * ./ath_info -g 5:0 -w 0xc2000000 regdomain X +- * +- * would set GPIO 5 to low (and wouldn't touch GPIO 4). -g can be given several times. +- * +- * The write function is currently not tested with 5210 devices. +- * +- * Use at your own risk, entering a false device address will have really +- * nasty results! +- * +- * Writing wrong values to the PCI id fields may prevent the driver from +- * detecting the card! +- * +- * Transmitting on illegal frequencies may violate state laws. Stick to the local +- * regulations! +- * +- * DISCLAIMER: +- * The authors are in no case responsible for damaged hardware or violation of +- * local laws by operating modified hardware. +- * +- */ ++/* Try accepting 64-bit device address even with 32-bit userspace */ ++#define _FILE_OFFSET_BITS 64 + + #include + #include +@@ -130,109 +60,103 @@ + */ + #define AR5K_GPIODI 0x401c + +-/* +- * Common silicon revision/version values +- */ +-enum ath5k_srev_type { +- AR5K_VERSION_VER, +- AR5K_VERSION_REV, +- AR5K_VERSION_RAD, +-}; +- + struct ath5k_srev_name { + const char *sr_name; +- enum ath5k_srev_type sr_type; +- u_int sr_val; ++ u_int8_t sr_val; + }; + +-#define AR5K_SREV_UNKNOWN 0xffff +- + /* Known MAC revision numbers */ +-#define AR5K_SREV_VER_AR5210 0x00 +-#define AR5K_SREV_VER_AR5311 0x10 +-#define AR5K_SREV_VER_AR5311A 0x20 +-#define AR5K_SREV_VER_AR5311B 0x30 +-#define AR5K_SREV_VER_AR5211 0x40 +-#define AR5K_SREV_VER_AR5212 0x50 +-#define AR5K_SREV_VER_AR5213 0x55 +-#define AR5K_SREV_VER_AR5213A 0x59 +-#define AR5K_SREV_VER_AR2424 0xa0 +-#define AR5K_SREV_VER_AR5424 0xa3 +-#define AR5K_SREV_VER_AR5413 0xa4 +-#define AR5K_SREV_VER_AR5414 0xa5 +-#define AR5K_SREV_VER_AR5416 0xc0 +-#define AR5K_SREV_VER_AR5418 0xca +-#define AR5K_SREV_VER_AR2425 0xe0 +- +-/* Known PHY revision nymbers */ +-#define AR5K_SREV_RAD_5110 0x00 +-#define AR5K_SREV_RAD_5111 0x10 +-#define AR5K_SREV_RAD_5111A 0x15 +-#define AR5K_SREV_RAD_2111 0x20 +-#define AR5K_SREV_RAD_5112 0x30 +-#define AR5K_SREV_RAD_5112A 0x35 +-#define AR5K_SREV_RAD_2112 0x40 +-#define AR5K_SREV_RAD_2112A 0x45 +-#define AR5K_SREV_RAD_SC1 0x63 /* Found on 5413/5414 */ +-#define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424/5424 */ +-#define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */ +- +-static const struct ath5k_srev_name ath5k_srev_names[] = { +- {"5210", AR5K_VERSION_VER, AR5K_SREV_VER_AR5210}, +- {"5311", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311}, +- {"5311A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311A}, +- {"5311B", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311B}, +- {"5211", AR5K_VERSION_VER, AR5K_SREV_VER_AR5211}, +- {"5212", AR5K_VERSION_VER, AR5K_SREV_VER_AR5212}, +- {"5213", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213}, +- {"5213A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213A}, +- {"2424", AR5K_VERSION_VER, AR5K_SREV_VER_AR2424}, +- {"5424", AR5K_VERSION_VER, AR5K_SREV_VER_AR5424}, +- {"5413", AR5K_VERSION_VER, AR5K_SREV_VER_AR5413}, +- {"5414", AR5K_VERSION_VER, AR5K_SREV_VER_AR5414}, +- {"5416", AR5K_VERSION_VER, AR5K_SREV_VER_AR5416}, +- {"5418", AR5K_VERSION_VER, AR5K_SREV_VER_AR5418}, +- {"2425", AR5K_VERSION_VER, AR5K_SREV_VER_AR2425}, +- {"xxxxx", AR5K_VERSION_VER, AR5K_SREV_UNKNOWN}, +- {"5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110}, +- {"5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111}, +- {"2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111}, +- {"5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112}, +- {"5112a", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A}, +- {"2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112}, +- {"2112a", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A}, +- {"SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC1}, +- {"SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC2}, +- {"5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133}, +- {"xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN}, ++#define AR5K_SREV_MAC_AR5210 0x00 ++#define AR5K_SREV_MAC_AR5311 0x10 ++#define AR5K_SREV_MAC_AR5311A 0x20 ++#define AR5K_SREV_MAC_AR5311B 0x30 ++#define AR5K_SREV_MAC_AR5211 0x40 ++#define AR5K_SREV_MAC_AR5212 0x50 ++#define AR5K_SREV_MAC_AR5213 0x55 ++#define AR5K_SREV_MAC_AR5213A 0x59 ++#define AR5K_SREV_MAC_AR5513 0x61 ++#define AR5K_SREV_MAC_AR2413 0x78 ++#define AR5K_SREV_MAC_AR2414 0x79 ++#define AR5K_SREV_MAC_AR2424 0xa0 ++#define AR5K_SREV_MAC_AR5424 0xa3 ++#define AR5K_SREV_MAC_AR5413 0xa4 ++#define AR5K_SREV_MAC_AR5414 0xa5 ++#define AR5K_SREV_MAC_AR5416 0xc0 ++#define AR5K_SREV_MAC_AR5418 0xca ++#define AR5K_SREV_MAC_AR2425 0xe2 ++ ++/* Known PHY revision numbers */ ++#define AR5K_SREV_PHY_5110 0x00 ++#define AR5K_SREV_PHY_5111 0x10 ++#define AR5K_SREV_PHY_5111A 0x15 ++#define AR5K_SREV_PHY_2111 0x20 ++#define AR5K_SREV_PHY_5112 0x30 ++#define AR5K_SREV_PHY_5112A 0x35 ++#define AR5K_SREV_PHY_2112 0x40 ++#define AR5K_SREV_PHY_2112A 0x45 ++#define AR5K_SREV_PHY_SC0 0x56 /* Found on 2413/2414 */ ++#define AR5K_SREV_PHY_SC1 0x63 /* Found on 5413/5414 */ ++#define AR5K_SREV_PHY_SC2 0xa2 /* Found on 2424/5424 */ ++#define AR5K_SREV_PHY_5133 0xc0 /* MIMO found on 5418 */ ++ ++static const struct ath5k_srev_name ath5k_mac_names[] = { ++ {"5210", AR5K_SREV_MAC_AR5210}, ++ {"5311", AR5K_SREV_MAC_AR5311}, ++ {"5311A", AR5K_SREV_MAC_AR5311A}, ++ {"5311B", AR5K_SREV_MAC_AR5311B}, ++ {"5211", AR5K_SREV_MAC_AR5211}, ++ {"5212", AR5K_SREV_MAC_AR5212}, ++ {"5213", AR5K_SREV_MAC_AR5213}, ++ {"5213A", AR5K_SREV_MAC_AR5213A}, ++ {"2413", AR5K_SREV_MAC_AR2413}, ++ {"2414", AR5K_SREV_MAC_AR2414}, ++ {"2424", AR5K_SREV_MAC_AR2424}, ++ {"5424", AR5K_SREV_MAC_AR5424}, ++ {"5413", AR5K_SREV_MAC_AR5413}, ++ {"5414", AR5K_SREV_MAC_AR5414}, ++ {"5416", AR5K_SREV_MAC_AR5416}, ++ {"5418", AR5K_SREV_MAC_AR5418}, ++ {"2425", AR5K_SREV_MAC_AR2425}, ++}; ++ ++static const struct ath5k_srev_name ath5k_phy_names[] = { ++ {"5110", AR5K_SREV_PHY_5110}, ++ {"5111", AR5K_SREV_PHY_5111}, ++ {"2111", AR5K_SREV_PHY_2111}, ++ {"5112", AR5K_SREV_PHY_5112}, ++ {"5112A", AR5K_SREV_PHY_5112A}, ++ {"2112", AR5K_SREV_PHY_2112}, ++ {"2112A", AR5K_SREV_PHY_2112A}, ++ {"SChip", AR5K_SREV_PHY_SC0}, ++ {"SChip", AR5K_SREV_PHY_SC1}, ++ {"SChip", AR5K_SREV_PHY_SC2}, ++ {"5133", AR5K_SREV_PHY_5133}, + }; + + /* + * Silicon revision register + */ + #define AR5K_SREV 0x4020 /* Register Address */ +-#define AR5K_SREV_REV 0x0000000f /* Mask for revision */ +-#define AR5K_SREV_REV_S 0 +-#define AR5K_SREV_VER 0x000000ff /* Mask for version */ +-#define AR5K_SREV_VER_S 4 ++#define AR5K_SREV_VER 0x000000f0 /* Mask for version */ ++#define AR5K_SREV_REV 0x000000ff /* Mask for revision */ + + /* + * PHY chip revision register + */ +-#define AR5K_PHY_CHIP_ID 0x9818 ++#define AR5K_PHY_CHIP_ID 0x9818 + + /* + * PHY register + */ +-#define AR5K_PHY_BASE 0x9800 +-#define AR5K_PHY(_n) (AR5K_PHY_BASE + ((_n) << 2)) ++#define AR5K_PHY_BASE 0x9800 ++#define AR5K_PHY(_n) (AR5K_PHY_BASE + ((_n) << 2)) + #define AR5K_PHY_SHIFT_2GHZ 0x00004007 + #define AR5K_PHY_SHIFT_5GHZ 0x00000007 + + #define AR5K_RESET_CTL 0x4000 /* Register Address */ + #define AR5K_RESET_CTL_PCU 0x00000001 /* Protocol Control Unit reset */ + #define AR5K_RESET_CTL_DMA 0x00000002 /* DMA (Rx/Tx) reset -5210 only */ +-#define AR5K_RESET_CTL_BASEBAND 0x00000002 /* Baseband reset (5211/5212) */ ++#define AR5K_RESET_CTL_BASEBAND 0x00000002 /* Baseband reset (5211/5212) */ + #define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband?) -5210 only */ + #define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset -5210 only */ + #define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */ +@@ -253,7 +177,7 @@ + #define AR5K_SLEEP_CTL_SLE_UNITS 0x00000008 /* not on 5210 */ + + #define AR5K_PCICFG 0x4010 /* Register Address */ +-#define AR5K_PCICFG_EEAE 0x00000001 /* Eeprom access enable [5210] */ ++#define AR5K_PCICFG_EEAE 0x00000001 /* EEPROM access enable [5210] */ + #define AR5K_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable [5211+] */ + #define AR5K_PCICFG_EESIZE 0x00000018 /* Mask for EEPROM size [5211+] */ + #define AR5K_PCICFG_EESIZE_S 3 +@@ -264,26 +188,118 @@ + + #define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status (5210) */ + +-#define AR5K_EEPROM_BASE 0x6000 ++#define AR5K_EEPROM_BASE 0x6000 + +-#define AR5K_EEPROM_MAGIC 0x003d /* Offset for EEPROM Magic number */ ++/* ++ * Common AR5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE) ++ */ ++#define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */ + #define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */ + #define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */ + #define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */ + #define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */ + ++#define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */ ++#define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */ ++#define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */ ++#define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */ ++#define AR5K_EEPROM_PROTECT_WR_32_63 0x0008 ++#define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */ ++#define AR5K_EEPROM_PROTECT_WR_64_127 0x0020 ++#define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */ ++#define AR5K_EEPROM_PROTECT_WR_128_191 0x0080 ++#define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */ ++#define AR5K_EEPROM_PROTECT_WR_192_207 0x0200 ++#define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */ ++#define AR5K_EEPROM_PROTECT_WR_208_223 0x0800 ++#define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */ ++#define AR5K_EEPROM_PROTECT_WR_224_239 0x2000 ++#define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */ ++#define AR5K_EEPROM_PROTECT_WR_240_255 0x8000 ++#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ ++#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ ++#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) ++#define AR5K_EEPROM_INFO_CKSUM 0xffff ++#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n)) ++ ++#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */ ++#define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */ ++#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2GHz (AR5211_rfregs) */ ++#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */ ++#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */ ++#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain ee_cck_ofdm_power_delta (eeprom_read_modes) */ ++#define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc*, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */ ++#define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */ ++#define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */ ++#define AR5K_EEPROM_VERSION_4_3 0x4003 ++#define AR5K_EEPROM_VERSION_4_4 0x4004 ++#define AR5K_EEPROM_VERSION_4_5 0x4005 ++#define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */ ++#define AR5K_EEPROM_VERSION_4_7 0x3007 ++ ++#define AR5K_EEPROM_MODE_11A 0 ++#define AR5K_EEPROM_MODE_11B 1 ++#define AR5K_EEPROM_MODE_11G 2 ++ ++#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */ ++#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1) ++#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1) ++#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1) ++#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2GHz (?) */ ++#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */ ++#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) ++#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5GHz (?) */ ++#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ ++ ++/* Misc values available since EEPROM 4.0 */ ++#define AR5K_EEPROM_MISC0 AR5K_EEPROM_INFO(4) ++#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff) ++#define AR5K_EEPROM_HDR_XR2_DIS(_v) (((_v) >> 12) & 0x1) ++#define AR5K_EEPROM_HDR_XR5_DIS(_v) (((_v) >> 13) & 0x1) ++#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3) ++#define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5) ++#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff) ++#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) ++ ++#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c ++#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2 ++#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002 ++#define AR5K_EEPROM_RFKILL_POLARITY_S 1 ++ ++/* Newer EEPROMs are using a different offset */ ++#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \ ++ (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0) ++ ++#define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3) ++#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((int8_t)(((_v) >> 8) & 0xff)) ++#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((int8_t)((_v) & 0xff)) ++ ++/* calibration settings */ ++#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4) ++#define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2) ++#define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d) ++#define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */ ++#define AR5K_EEPROM_CHANNELS_5GHZ(_v) AR5K_EEPROM_OFF(_v, 0x0100, 0x0150) /* List of calibrated 5GHz chans */ ++#define AR5K_EEPROM_TARGET_PWR_OFF_11A(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_CHANNELS_5GHZ(_v) + 0x0055, 0x0000) ++#define AR5K_EEPROM_TARGET_PWR_OFF_11B(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_CHANNELS_5GHZ(_v) + 0x0065, 0x0010) ++#define AR5K_EEPROM_TARGET_PWR_OFF_11G(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_CHANNELS_5GHZ(_v) + 0x0069, 0x0014) ++ ++/* [3.1 - 3.3] */ ++#define AR5K_EEPROM_OBDB0_2GHZ 0x00ec ++#define AR5K_EEPROM_OBDB1_2GHZ 0x00ed ++ + /* + * EEPROM data register + */ + #define AR5K_EEPROM_DATA_5211 0x6004 + #define AR5K_EEPROM_DATA_5210 0x6800 +-#define AR5K_EEPROM_DATA (mac_version == AR5K_SREV_VER_AR5210 ? \ ++#define AR5K_EEPROM_DATA (mac_version == AR5K_SREV_MAC_AR5210 ? \ + AR5K_EEPROM_DATA_5210 : AR5K_EEPROM_DATA_5211) + + /* + * EEPROM command register + */ +-#define AR5K_EEPROM_CMD 0x6008 /* Register Addres */ ++#define AR5K_EEPROM_CMD 0x6008 /* Register Address */ + #define AR5K_EEPROM_CMD_READ 0x00000001 /* EEPROM read */ + #define AR5K_EEPROM_CMD_WRITE 0x00000002 /* EEPROM write */ + #define AR5K_EEPROM_CMD_RESET 0x00000004 /* EEPROM reset */ +@@ -291,43 +307,163 @@ + /* + * EEPROM status register + */ +-#define AR5K_EEPROM_STAT_5210 0x6c00 /* Register Address [5210] */ +-#define AR5K_EEPROM_STAT_5211 0x600c /* Register Address [5211+] */ +-#define AR5K_EEPROM_STATUS (mac_version == AR5K_SREV_VER_AR5210 ? \ ++#define AR5K_EEPROM_STAT_5210 0x6c00 /* Register Address [5210] */ ++#define AR5K_EEPROM_STAT_5211 0x600c /* Register Address [5211+] */ ++#define AR5K_EEPROM_STATUS (mac_version == AR5K_SREV_MAC_AR5210 ? \ + AR5K_EEPROM_STAT_5210 : AR5K_EEPROM_STAT_5211) + #define AR5K_EEPROM_STAT_RDERR 0x00000001 /* EEPROM read failed */ + #define AR5K_EEPROM_STAT_RDDONE 0x00000002 /* EEPROM read successful */ + #define AR5K_EEPROM_STAT_WRERR 0x00000004 /* EEPROM write failed */ + #define AR5K_EEPROM_STAT_WRDONE 0x00000008 /* EEPROM write successful */ + +-#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* Offset for EEPROM regulatory domain */ +-#define AR5K_EEPROM_INFO_BASE 0x00c0 /* Offset for EEPROM header */ +-#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) +-#define AR5K_EEPROM_INFO_CKSUM 0xffff +-#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n)) +-#define AR5K_EEPROM_MODE_11A 0 +-#define AR5K_EEPROM_MODE_11B 1 +-#define AR5K_EEPROM_MODE_11G 2 ++/* ++ * EEPROM config register (?) ++ */ ++#define AR5K_EEPROM_CFG 0x6010 + +-#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) ++/* Some EEPROM defines */ ++#define AR5K_EEPROM_EEP_SCALE 100 ++#define AR5K_EEPROM_EEP_DELTA 10 ++#define AR5K_EEPROM_N_MODES 3 ++#define AR5K_EEPROM_N_5GHZ_CHAN 10 ++#define AR5K_EEPROM_N_2GHZ_CHAN 3 ++#define AR5K_EEPROM_MAX_CHAN 10 ++#define AR5K_EEPROM_N_PCDAC 11 ++#define AR5K_EEPROM_N_TEST_FREQ 8 ++#define AR5K_EEPROM_N_EDGES 8 ++#define AR5K_EEPROM_N_INTERCEPTS 11 ++#define AR5K_EEPROM_FREQ_M(_v) AR5K_EEPROM_OFF(_v, 0x7f, 0xff) ++#define AR5K_EEPROM_PCDAC_M 0x3f ++#define AR5K_EEPROM_PCDAC_START 1 ++#define AR5K_EEPROM_PCDAC_STOP 63 ++#define AR5K_EEPROM_PCDAC_STEP 1 ++#define AR5K_EEPROM_NON_EDGE_M 0x40 ++#define AR5K_EEPROM_CHANNEL_POWER 8 ++#define AR5K_EEPROM_N_OBDB 4 ++#define AR5K_EEPROM_OBDB_DIS 0xffff ++#define AR5K_EEPROM_CHANNEL_DIS 0xff ++#define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10) ++#define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32) ++#define AR5K_EEPROM_MAX_CTLS 32 ++#define AR5K_EEPROM_N_XPD_PER_CHANNEL 4 ++#define AR5K_EEPROM_N_XPD0_POINTS 4 ++#define AR5K_EEPROM_N_XPD3_POINTS 3 ++#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35 ++#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55 ++#define AR5K_EEPROM_POWER_M 0x3f ++#define AR5K_EEPROM_POWER_MIN 0 ++#define AR5K_EEPROM_POWER_MAX 3150 ++#define AR5K_EEPROM_POWER_STEP 50 ++#define AR5K_EEPROM_POWER_TABLE_SIZE 64 ++#define AR5K_EEPROM_N_POWER_LOC_11B 4 ++#define AR5K_EEPROM_N_POWER_LOC_11G 6 ++#define AR5K_EEPROM_I_GAIN 10 ++#define AR5K_EEPROM_CCK_OFDM_DELTA 15 ++#define AR5K_EEPROM_N_IQ_CAL 2 ++ ++enum ath5k_ant_setting { ++ AR5K_ANT_VARIABLE = 0, /* variable by programming */ ++ AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */ ++ AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */ ++ AR5K_ANT_MAX = 3, ++}; + +-#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */ +-#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1) /* Device has a support */ +-#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1) /* Device has b support */ +-#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1) /* Device has g support */ +-#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */ +-#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */ +-#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) +-#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz (?) */ +-#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ ++/* Per channel calibration data, used for power table setup */ ++struct ath5k_chan_pcal_info { ++ u_int16_t freq; /* Frequency */ ++ /* Power levels in dBm * 4 units */ ++ int16_t pwr_x0[AR5K_EEPROM_N_XPD0_POINTS]; ++ int16_t pwr_x3[AR5K_EEPROM_N_XPD3_POINTS]; ++ /* PCDAC tables in dBm * 2 units */ ++ u_int16_t pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS]; ++ u_int16_t pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS]; ++ /* Max available power */ ++ u_int16_t max_pwr; ++}; + +-/* Misc values available since EEPROM 4.0 */ +-#define AR5K_EEPROM_MISC0 0x00c4 +-#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff) +-#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3) +-#define AR5K_EEPROM_MISC1 0x00c5 +-#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff) +-#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) ++/* Per rate calibration data for each mode, used for power table setup */ ++struct ath5k_rate_pcal_info { ++ u_int16_t freq; /* Frequency */ ++ /* Power level for 6-24Mbit/s rates */ ++ u_int16_t target_power_6to24; ++ /* Power level for 36Mbit rate */ ++ u_int16_t target_power_36; ++ /* Power level for 48Mbit rate */ ++ u_int16_t target_power_48; ++ /* Power level for 54Mbit rate */ ++ u_int16_t target_power_54; ++}; ++ ++/* EEPROM calibration data */ ++struct ath5k_eeprom_info { ++ ++ /* Header information */ ++ u_int16_t ee_magic; ++ u_int16_t ee_protect; ++ u_int16_t ee_regdomain; ++ u_int16_t ee_version; ++ u_int16_t ee_header; ++ u_int16_t ee_ant_gain; ++ u_int16_t ee_misc0; ++ u_int16_t ee_misc1; ++ u_int16_t ee_cck_ofdm_gain_delta; ++ u_int16_t ee_cck_ofdm_power_delta; ++ u_int16_t ee_scaled_cck_delta; ++ ++ /* Used for tx thermal adjustment (eeprom_init, rfregs) */ ++ u_int16_t ee_tx_clip; ++ u_int16_t ee_pwd_84; ++ u_int16_t ee_pwd_90; ++ u_int16_t ee_gain_select; ++ ++ /* RF Calibration settings (reset, rfregs) */ ++ u_int16_t ee_i_cal[AR5K_EEPROM_N_MODES]; ++ u_int16_t ee_q_cal[AR5K_EEPROM_N_MODES]; ++ u_int16_t ee_fixed_bias[AR5K_EEPROM_N_MODES]; ++ u_int16_t ee_turbo_max_power[AR5K_EEPROM_N_MODES]; ++ u_int16_t ee_xr_power[AR5K_EEPROM_N_MODES]; ++ u_int16_t ee_switch_settling[AR5K_EEPROM_N_MODES]; ++ u_int16_t ee_ant_tx_rx[AR5K_EEPROM_N_MODES]; ++ u_int16_t ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC]; ++ u_int16_t ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; ++ u_int16_t ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; ++ u_int16_t ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES]; ++ u_int16_t ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES]; ++ u_int16_t ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES]; ++ u_int16_t ee_thr_62[AR5K_EEPROM_N_MODES]; ++ u_int16_t ee_xlna_gain[AR5K_EEPROM_N_MODES]; ++ u_int16_t ee_xpd[AR5K_EEPROM_N_MODES]; ++ u_int16_t ee_x_gain[AR5K_EEPROM_N_MODES]; ++ u_int16_t ee_i_gain[AR5K_EEPROM_N_MODES]; ++ u_int16_t ee_margin_tx_rx[AR5K_EEPROM_N_MODES]; ++ ++ /* Power calibration data */ ++ u_int16_t ee_false_detect[AR5K_EEPROM_N_MODES]; ++ u_int16_t ee_cal_piers_a; ++ struct ath5k_chan_pcal_info ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN]; ++ u_int16_t ee_cal_piers_b; ++ struct ath5k_chan_pcal_info ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN]; ++ u_int16_t ee_cal_piers_g; ++ struct ath5k_chan_pcal_info ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN]; ++ /* Per rate target power levels */ ++ u_int16_t ee_rate_target_pwr_num_a; ++ struct ath5k_rate_pcal_info ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN]; ++ u_int16_t ee_rate_target_pwr_num_b; ++ struct ath5k_rate_pcal_info ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN]; ++ u_int16_t ee_rate_target_pwr_num_g; ++ struct ath5k_rate_pcal_info ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN]; ++ ++ /* Conformance test limits (Unused) */ ++ u_int16_t ee_ctls; ++ u_int16_t ee_ctl[AR5K_EEPROM_MAX_CTLS]; ++ ++ /* Noise Floor Calibration settings */ ++ int16_t ee_noise_floor_thr[AR5K_EEPROM_N_MODES]; ++ int8_t ee_adc_desired_size[AR5K_EEPROM_N_MODES]; ++ int8_t ee_pga_desired_size[AR5K_EEPROM_N_MODES]; ++ ++ u_int32_t ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; ++}; + + /* + * Read data by masking +@@ -350,7 +486,6 @@ + (*((volatile u_int32_t *)(mem + (_reg))) = (_val)) + #endif + +- + #define AR5K_REG_ENABLE_BITS(_reg, _flags) \ + AR5K_REG_WRITE(_reg, AR5K_REG_READ(_reg) | (_flags)) + +@@ -359,7 +494,12 @@ + + #define AR5K_TUNE_REGISTER_TIMEOUT 20000 + +-/* names for eeprom fields */ ++#define AR5K_EEPROM_READ(_o, _v) do { \ ++ if ((ret = ath5k_hw_eeprom_read(mem, (_o), &(_v), mac_version)) != 0) \ ++ return (ret); \ ++} while (0) ++ ++/* Names for EEPROM fields */ + struct eeprom_entry { + const char *name; + int addr; +@@ -375,8 +515,6 @@ + {"regdomain", AR5K_EEPROM_REG_DOMAIN}, + }; + +-static const int eeprom_addr_len = sizeof(eeprom_addr) / sizeof(eeprom_addr[0]); +- + static int force_write = 0; + static int verbose = 0; + +@@ -398,8 +536,8 @@ + /* + * Get the PHY Chip revision + */ +-static u_int16_t +-ath5k_hw_radio_revision(u_int16_t mac_version, void *mem, u_int8_t chip) ++static u_int16_t ath5k_hw_radio_revision(u_int16_t mac_version, void *mem, ++ u_int8_t chip) + { + int i; + u_int32_t srev; +@@ -427,7 +565,7 @@ + for (i = 0; i < 8; i++) + AR5K_REG_WRITE(AR5K_PHY(0x20), 0x00010000); + +- if (mac_version == AR5K_SREV_VER_AR5210) { ++ if (mac_version == AR5K_SREV_MAC_AR5210) { + srev = AR5K_REG_READ(AR5K_PHY(256) >> 28) & 0xf; + + ret = (u_int16_t)ath5k_hw_bitswap(srev, 4) + 1; +@@ -447,9 +585,8 @@ + /* + * Write to EEPROM + */ +-static int +-ath5k_hw_eeprom_write(void *mem, u_int32_t offset, u_int16_t data, +- u_int8_t mac_version) ++static int ath5k_hw_eeprom_write(void *mem, u_int32_t offset, u_int16_t data, ++ u_int8_t mac_version) + { + u_int32_t status, timeout; + +@@ -457,7 +594,7 @@ + * Initialize EEPROM access + */ + +- if (mac_version == AR5K_SREV_VER_AR5210) { ++ if (mac_version == AR5K_SREV_MAC_AR5210) { + + AR5K_REG_ENABLE_BITS(AR5K_PCICFG, AR5K_PCICFG_EEAE); + +@@ -466,7 +603,7 @@ + + } else { + /* not 5210 */ +- /* reset eeprom access */ ++ /* reset EEPROM access */ + AR5K_REG_WRITE(AR5K_EEPROM_CMD, AR5K_EEPROM_CMD_RESET); + usleep(5); + +@@ -484,7 +621,7 @@ + status = AR5K_REG_READ(AR5K_EEPROM_STATUS); + if (status & AR5K_EEPROM_STAT_WRDONE) { + if (status & AR5K_EEPROM_STAT_WRERR) { +- err("eeprom write access to 0x%04x failed", ++ err("EEPROM write access to 0x%04x failed", + offset); + return 1; + } +@@ -499,16 +636,15 @@ + /* + * Read from EEPROM + */ +-static int +-ath5k_hw_eeprom_read(void *mem, u_int32_t offset, u_int16_t *data, +- u_int8_t mac_version) ++static int ath5k_hw_eeprom_read(void *mem, u_int32_t offset, u_int16_t *data, ++ u_int8_t mac_version) + { + u_int32_t status, timeout; + + /* + * Initialize EEPROM access + */ +- if (mac_version == AR5K_SREV_VER_AR5210) { ++ if (mac_version == AR5K_SREV_MAC_AR5210) { + AR5K_REG_ENABLE_BITS(AR5K_PCICFG, AR5K_PCICFG_EEAE); + (void)AR5K_REG_READ(AR5K_EEPROM_BASE + (4 * offset)); + } else { +@@ -531,50 +667,701 @@ + return 1; + } + +-static const char *ath5k_hw_get_part_name(enum ath5k_srev_type type, +- u_int32_t val) ++/* ++ * Translate binary channel representation in EEPROM to frequency ++ */ ++static u_int16_t ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, ++ u_int16_t bin, unsigned int mode) + { +- const char *name = "xxxxx"; +- int i; ++ u_int16_t val; + +- for (i = 0; i < ARRAY_SIZE(ath5k_srev_names); i++) { +- if (ath5k_srev_names[i].sr_type != type || +- ath5k_srev_names[i].sr_val == AR5K_SREV_UNKNOWN) +- continue; +- if ((val & 0xff) < ath5k_srev_names[i + 1].sr_val) { +- name = ath5k_srev_names[i].sr_name; ++ if (bin == AR5K_EEPROM_CHANNEL_DIS) ++ return bin; ++ ++ if (mode == AR5K_EEPROM_MODE_11A) { ++ if (ee->ee_version > AR5K_EEPROM_VERSION_3_2) ++ val = (5 * bin) + 4800; ++ else ++ val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 : ++ (bin * 10) + 5100; ++ } else { ++ if (ee->ee_version > AR5K_EEPROM_VERSION_3_2) ++ val = bin + 2300; ++ else ++ val = bin + 2400; ++ } ++ ++ return val; ++} ++ ++/* ++ * Read antenna info from EEPROM ++ */ ++static int ath5k_eeprom_read_ants(void *mem, u_int8_t mac_version, ++ struct ath5k_eeprom_info *ee, ++ u_int32_t *offset, unsigned int mode) ++{ ++ u_int32_t o = *offset; ++ u_int16_t val; ++ int ret, i = 0; ++ ++ AR5K_EEPROM_READ(o++, val); ++ ee->ee_switch_settling[mode] = (val >> 8) & 0x7f; ++ ee->ee_ant_tx_rx[mode] = (val >> 2) & 0x3f; ++ ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; ++ ++ AR5K_EEPROM_READ(o++, val); ++ ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf; ++ ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; ++ ee->ee_ant_control[mode][i++] = val & 0x3f; ++ ++ AR5K_EEPROM_READ(o++, val); ++ ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f; ++ ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f; ++ ee->ee_ant_control[mode][i] = (val << 2) & 0x3f; ++ ++ AR5K_EEPROM_READ(o++, val); ++ ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3; ++ ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f; ++ ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f; ++ ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; ++ ++ AR5K_EEPROM_READ(o++, val); ++ ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf; ++ ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; ++ ee->ee_ant_control[mode][i++] = val & 0x3f; ++ ++ /* Get antenna modes */ ++ ee->ee_antenna[mode][0] = ++ (ee->ee_ant_control[mode][0] << 4) | 0x1; ++ ee->ee_antenna[mode][AR5K_ANT_FIXED_A] = ++ ee->ee_ant_control[mode][1] | ++ (ee->ee_ant_control[mode][2] << 6) | ++ (ee->ee_ant_control[mode][3] << 12) | ++ (ee->ee_ant_control[mode][4] << 18) | ++ (ee->ee_ant_control[mode][5] << 24); ++ ee->ee_antenna[mode][AR5K_ANT_FIXED_B] = ++ ee->ee_ant_control[mode][6] | ++ (ee->ee_ant_control[mode][7] << 6) | ++ (ee->ee_ant_control[mode][8] << 12) | ++ (ee->ee_ant_control[mode][9] << 18) | ++ (ee->ee_ant_control[mode][10] << 24); ++ ++ /* return new offset */ ++ *offset = o; ++ ++ return 0; ++} ++ ++/* ++ * Read supported modes from EEPROM ++ */ ++static int ath5k_eeprom_read_modes(void *mem, u_int8_t mac_version, ++ struct ath5k_eeprom_info *ee, ++ u_int32_t *offset, unsigned int mode) ++{ ++ u_int32_t o = *offset; ++ u_int16_t val; ++ int ret; ++ ++ AR5K_EEPROM_READ(o++, val); ++ ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff; ++ ee->ee_thr_62[mode] = val & 0xff; ++ ++ if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2) ++ ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28; ++ ++ AR5K_EEPROM_READ(o++, val); ++ ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff; ++ ee->ee_tx_frm2xpa_enable[mode] = val & 0xff; ++ ++ AR5K_EEPROM_READ(o++, val); ++ ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff; ++ ++ if ((val & 0xff) & 0x80) ++ ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1); ++ else ++ ee->ee_noise_floor_thr[mode] = val & 0xff; ++ ++ if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2) ++ ee->ee_noise_floor_thr[mode] = ++ mode == AR5K_EEPROM_MODE_11A ? -54 : -1; ++ ++ AR5K_EEPROM_READ(o++, val); ++ ee->ee_xlna_gain[mode] = (val >> 5) & 0xff; ++ ee->ee_x_gain[mode] = (val >> 1) & 0xf; ++ ee->ee_xpd[mode] = val & 0x1; ++ ++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0) ++ ee->ee_fixed_bias[mode] = (val >> 13) & 0x1; ++ ++ if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) { ++ AR5K_EEPROM_READ(o++, val); ++ ee->ee_false_detect[mode] = (val >> 6) & 0x7f; ++ ++ if (mode == AR5K_EEPROM_MODE_11A) ++ ee->ee_xr_power[mode] = val & 0x3f; ++ else { ++ ee->ee_ob[mode][0] = val & 0x7; ++ ee->ee_db[mode][0] = (val >> 3) & 0x7; ++ } ++ } ++ ++ if (ee->ee_version < AR5K_EEPROM_VERSION_3_4) { ++ ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN; ++ ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA; ++ } else { ++ ee->ee_i_gain[mode] = (val >> 13) & 0x7; ++ ++ AR5K_EEPROM_READ(o++, val); ++ ee->ee_i_gain[mode] |= (val << 3) & 0x38; ++ ++ if (mode == AR5K_EEPROM_MODE_11G) ++ ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff; ++ } ++ ++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0 && ++ mode == AR5K_EEPROM_MODE_11A) { ++ ee->ee_i_cal[mode] = (val >> 8) & 0x3f; ++ ee->ee_q_cal[mode] = (val >> 3) & 0x1f; ++ } ++ ++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_6 && ++ mode == AR5K_EEPROM_MODE_11G) ++ ee->ee_scaled_cck_delta = (val >> 11) & 0x1f; ++ ++ /* return new offset */ ++ *offset = o; ++ ++ return 0; ++} ++ ++/* ++ * Read per channel calibration info from EEPROM ++ * This doesn't work on 2112+ chips (EEPROM versions >= 4.6), ++ * I only tested it on 5213 + 5112. This is still work in progress... ++ * ++ * This info is used to calibrate the baseband power table. Imagine ++ * that for each channel there is a power curve that's hw specific ++ * (depends on amplifier) and we try to "correct" this curve using offests ++ * we pass on to phy chip (baseband -> before amplifier) so that it can ++ * use acurate power values when setting tx power (takes amplifier's performance ++ * on each channel into account). ++ * ++ * EEPROM provides us with the offsets for some pre-calibrated channels ++ * and we have to scale (to create the full table for these channels) and ++ * interpolate (in order to create the table for any channel). ++ */ ++static int ath5k_eeprom_read_pcal_info(void *mem, u_int8_t mac_version, ++ struct ath5k_eeprom_info *ee, ++ u_int32_t *offset, unsigned int mode) ++{ ++ u_int32_t o = *offset; ++ unsigned int i, c; ++ int ret; ++ u_int16_t val; ++ struct ath5k_chan_pcal_info *chan_pcal_info; ++ u_int16_t cal_piers; ++ ++ switch (mode) { ++ case AR5K_EEPROM_MODE_11A: ++ chan_pcal_info = ee->ee_pwr_cal_a; ++ cal_piers = ee->ee_cal_piers_a; ++ break; ++ case AR5K_EEPROM_MODE_11B: ++ chan_pcal_info = ee->ee_pwr_cal_b; ++ cal_piers = ee->ee_cal_piers_b; ++ break; ++ case AR5K_EEPROM_MODE_11G: ++ chan_pcal_info = ee->ee_pwr_cal_g; ++ cal_piers = ee->ee_cal_piers_g; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < cal_piers; i++) { ++ /* Power values in dBm * 4 */ ++ for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) { ++ AR5K_EEPROM_READ(o++, val); ++ chan_pcal_info[i].pwr_x0[c] = (val & 0xff); ++ chan_pcal_info[i].pwr_x0[++c] = ((val >> 8) & 0xff); ++ } ++ ++ /* PCDAC steps (dBm * 2) */ ++ AR5K_EEPROM_READ(o++, val); ++ chan_pcal_info[i].pcdac_x0[1] = (val & 0x1f); ++ chan_pcal_info[i].pcdac_x0[2] = ((val >> 5) & 0x1f); ++ chan_pcal_info[i].pcdac_x0[3] = ((val >> 10) & 0x1f); ++ ++ /* No idea what these power levels are for (4 xpds ?) ++ I got zeroes on my card and the EEPROM info ++ dumps we found on the net also have weird values */ ++ AR5K_EEPROM_READ(o++, val); ++ chan_pcal_info[i].pwr_x3[0] = (val & 0xff); ++ chan_pcal_info[i].pwr_x3[1] = ((val >> 8) & 0xff); ++ ++ AR5K_EEPROM_READ(o++, val); ++ chan_pcal_info[i].pwr_x3[2] = (val & 0xff); ++ /* It's weird but they put it here, that's the ++ PCDAC starting step */ ++ chan_pcal_info[i].pcdac_x0[0] = ((val >> 8) & 0xff); ++ ++ /* Static values seen on EEPROM info dumps */ ++ chan_pcal_info[i].pcdac_x3[0] = 20; ++ chan_pcal_info[i].pcdac_x3[1] = 35; ++ chan_pcal_info[i].pcdac_x3[2] = 63; ++ ++ /* Last xpd0 power level is also channel maximum */ ++ chan_pcal_info[i].max_pwr = chan_pcal_info[i].pwr_x0[3]; ++ ++ /* Recreate pcdac_x0 table for this channel using pcdac steps */ ++ chan_pcal_info[i].pcdac_x0[1] += chan_pcal_info[i].pcdac_x0[0]; ++ chan_pcal_info[i].pcdac_x0[2] += chan_pcal_info[i].pcdac_x0[1]; ++ chan_pcal_info[i].pcdac_x0[3] += chan_pcal_info[i].pcdac_x0[2]; ++ } ++ ++ /* return new offset */ ++ (*offset) = o; ++ ++ return 0; ++} ++ ++/* ++ * Read per rate target power (this is the maximum tx power ++ * supported by the card). This info is used when setting ++ * tx power, no matter the channel. ++ * ++ * This also works for v5 EEPROMs. ++ */ ++static int ath5k_eeprom_read_target_rate_pwr_info(void *mem, ++ u_int8_t mac_version, ++ struct ath5k_eeprom_info *ee, ++ u_int32_t *offset, ++ unsigned int mode) ++{ ++ u_int32_t o = *offset; ++ u_int16_t val; ++ struct ath5k_rate_pcal_info *rate_pcal_info; ++ u_int16_t *rate_target_pwr_num; ++ int ret, i; ++ ++ switch (mode) { ++ case AR5K_EEPROM_MODE_11A: ++ rate_pcal_info = ee->ee_rate_tpwr_a; ++ ee->ee_rate_target_pwr_num_a = AR5K_EEPROM_N_5GHZ_CHAN; ++ rate_target_pwr_num = &ee->ee_rate_target_pwr_num_a; ++ break; ++ case AR5K_EEPROM_MODE_11B: ++ rate_pcal_info = ee->ee_rate_tpwr_b; ++ ee->ee_rate_target_pwr_num_b = 2; /* 3rd is g mode'ss 1st */ ++ rate_target_pwr_num = &ee->ee_rate_target_pwr_num_b; ++ break; ++ case AR5K_EEPROM_MODE_11G: ++ rate_pcal_info = ee->ee_rate_tpwr_g; ++ ee->ee_rate_target_pwr_num_g = AR5K_EEPROM_N_2GHZ_CHAN; ++ rate_target_pwr_num = &ee->ee_rate_target_pwr_num_g; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* Different freq mask for older eeproms (<= v3.2) */ ++ if(ee->ee_version <= 0x3002){ ++ for (i = 0; i < (*rate_target_pwr_num); i++) { ++ AR5K_EEPROM_READ(o++, val); ++ rate_pcal_info[i].freq = ++ ath5k_eeprom_bin2freq(ee, (val >> 9) & 0x7f, mode); ++ ++ rate_pcal_info[i].target_power_6to24 = ((val >> 3) & 0x3f); ++ rate_pcal_info[i].target_power_36 = (val << 3) & 0x3f; ++ ++ AR5K_EEPROM_READ(o++, val); ++ ++ if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS || ++ val == 0) { ++ (*rate_target_pwr_num) = i; ++ break; ++ } ++ ++ rate_pcal_info[i].target_power_36 |= ((val >> 13) & 0x7); ++ rate_pcal_info[i].target_power_48 = ((val >> 7) & 0x3f); ++ rate_pcal_info[i].target_power_54 = ((val >> 1) & 0x3f); ++ } ++ } else { ++ for (i = 0; i < (*rate_target_pwr_num); i++) { ++ AR5K_EEPROM_READ(o++, val); ++ rate_pcal_info[i].freq = ++ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); ++ ++ rate_pcal_info[i].target_power_6to24 = ((val >> 2) & 0x3f); ++ rate_pcal_info[i].target_power_36 = (val << 4) & 0x3f; ++ ++ AR5K_EEPROM_READ(o++, val); ++ ++ if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS || ++ val == 0) { ++ (*rate_target_pwr_num) = i; ++ break; ++ } ++ ++ rate_pcal_info[i].target_power_36 |= (val >> 12) & 0xf; ++ rate_pcal_info[i].target_power_48 = ((val >> 6) & 0x3f); ++ rate_pcal_info[i].target_power_54 = (val & 0x3f); ++ } ++ } ++ /* return new offset */ ++ (*offset) = o; ++ ++ return 0; ++} ++ ++/* ++ * Initialize EEPROM & capabilities data ++ */ ++static int ath5k_eeprom_init(void *mem, u_int8_t mac_version, ++ struct ath5k_eeprom_info *ee) ++{ ++ unsigned int mode, i; ++ int ret; ++ u_int32_t offset; ++ u_int16_t val; ++ ++ /* Initial TX thermal adjustment values */ ++ ee->ee_tx_clip = 4; ++ ee->ee_pwd_84 = ee->ee_pwd_90 = 1; ++ ee->ee_gain_select = 1; ++ ++ /* ++ * Read values from EEPROM and store them in the capability structure ++ */ ++ AR5K_EEPROM_READ(AR5K_EEPROM_MAGIC, ee->ee_magic); ++ AR5K_EEPROM_READ(AR5K_EEPROM_PROTECT, ee->ee_protect); ++ AR5K_EEPROM_READ(AR5K_EEPROM_REG_DOMAIN, ee->ee_regdomain); ++ AR5K_EEPROM_READ(AR5K_EEPROM_VERSION, ee->ee_version); ++ AR5K_EEPROM_READ(AR5K_EEPROM_HDR, ee->ee_header); ++ ++ /* Return if we have an old EEPROM */ ++ if (ee->ee_version < AR5K_EEPROM_VERSION_3_0) ++ return 0; ++ ++#ifdef notyet ++ /* ++ * Validate the checksum of the EEPROM date. There are some ++ * devices with invalid EEPROMs. ++ */ ++ for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) { ++ AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); ++ cksum ^= val; ++ } ++ if (cksum != AR5K_EEPROM_INFO_CKSUM) { ++ AR5K_PRINTF("Invalid EEPROM checksum 0x%04x\n", cksum); ++ return -EIO; ++ } ++#endif ++ ++ AR5K_EEPROM_READ(AR5K_EEPROM_ANT_GAIN(ee->ee_version), ee->ee_ant_gain); ++ ++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0) { ++ AR5K_EEPROM_READ(AR5K_EEPROM_MISC0, ee->ee_misc0); ++ AR5K_EEPROM_READ(AR5K_EEPROM_MISC1, ee->ee_misc1); ++ } ++ ++ if (ee->ee_version < AR5K_EEPROM_VERSION_3_3) { ++ AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val); ++ ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7; ++ ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7; ++ ++ AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val); ++ ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7; ++ ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7; ++ } ++ ++ /* ++ * Get conformance test limit values ++ */ ++ offset = AR5K_EEPROM_CTL(ee->ee_version); ++ ee->ee_ctls = 0; ++ ++ for (i = 0; i < AR5K_EEPROM_N_CTLS(ee->ee_version); i++) { ++ AR5K_EEPROM_READ(offset++, val); ++ ++ if (((val >> 8) & 0xff) == 0) ++ break; ++ ++ ee->ee_ctl[i] = (val >> 8) & 0xff; ++ ee->ee_ctls++; ++ ++ if ((val & 0xff) == 0) + break; ++ ++ ee->ee_ctl[i + 1] = val & 0xff; ++ ee->ee_ctls++; ++ } ++ ++ /* ++ * Get values for 802.11a (5GHz) ++ */ ++ mode = AR5K_EEPROM_MODE_11A; ++ ++ ee->ee_turbo_max_power[mode] = ++ AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header); ++ ++ offset = AR5K_EEPROM_MODES_11A(ee->ee_version); ++ ++ ret = ath5k_eeprom_read_ants(mem, mac_version, ee, &offset, mode); ++ if (ret) ++ return ret; ++ ++ AR5K_EEPROM_READ(offset++, val); ++ ee->ee_adc_desired_size[mode] = (int8_t)((val >> 8) & 0xff); ++ ee->ee_ob[mode][3] = (val >> 5) & 0x7; ++ ee->ee_db[mode][3] = (val >> 2) & 0x7; ++ ee->ee_ob[mode][2] = (val << 1) & 0x7; ++ ++ AR5K_EEPROM_READ(offset++, val); ++ ee->ee_ob[mode][2] |= (val >> 15) & 0x1; ++ ee->ee_db[mode][2] = (val >> 12) & 0x7; ++ ee->ee_ob[mode][1] = (val >> 9) & 0x7; ++ ee->ee_db[mode][1] = (val >> 6) & 0x7; ++ ee->ee_ob[mode][0] = (val >> 3) & 0x7; ++ ee->ee_db[mode][0] = val & 0x7; ++ ++ ret = ath5k_eeprom_read_modes(mem, mac_version, ee, &offset, mode); ++ if (ret) ++ return ret; ++ ++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_1) { ++ AR5K_EEPROM_READ(offset++, val); ++ ee->ee_margin_tx_rx[mode] = val & 0x3f; ++ } ++ ++ /* ++ * Get values for 802.11b (2.4GHz) ++ */ ++ mode = AR5K_EEPROM_MODE_11B; ++ offset = AR5K_EEPROM_MODES_11B(ee->ee_version); ++ ++ ret = ath5k_eeprom_read_ants(mem, mac_version, ee, &offset, mode); ++ if (ret) ++ return ret; ++ ++ AR5K_EEPROM_READ(offset++, val); ++ ee->ee_adc_desired_size[mode] = (int8_t)((val >> 8) & 0xff); ++ ee->ee_ob[mode][1] = (val >> 4) & 0x7; ++ ee->ee_db[mode][1] = val & 0x7; ++ ++ ret = ath5k_eeprom_read_modes(mem, mac_version, ee, &offset, mode); ++ if (ret) ++ return ret; ++ ++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0) { ++ AR5K_EEPROM_READ(offset++, val); ++ ++ ee->ee_cal_piers_b = 0; ++ ++ ee->ee_pwr_cal_b[0].freq = ++ ath5k_eeprom_bin2freq(ee, val & 0xff, mode); ++ if (ee->ee_pwr_cal_b[0].freq != AR5K_EEPROM_CHANNEL_DIS) ++ ee->ee_cal_piers_b++; ++ ++ ee->ee_pwr_cal_b[1].freq = ++ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); ++ if (ee->ee_pwr_cal_b[1].freq != AR5K_EEPROM_CHANNEL_DIS) ++ ee->ee_cal_piers_b++; ++ ++ AR5K_EEPROM_READ(offset++, val); ++ ee->ee_pwr_cal_b[2].freq = ++ ath5k_eeprom_bin2freq(ee, val & 0xff, mode); ++ if (ee->ee_pwr_cal_b[2].freq != AR5K_EEPROM_CHANNEL_DIS) ++ ee->ee_cal_piers_b++; ++ } ++ ++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_1) ++ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; ++ ++ /* ++ * Get values for 802.11g (2.4GHz) ++ */ ++ mode = AR5K_EEPROM_MODE_11G; ++ offset = AR5K_EEPROM_MODES_11G(ee->ee_version); ++ ++ ret = ath5k_eeprom_read_ants(mem, mac_version, ee, &offset, mode); ++ if (ret) ++ return ret; ++ ++ AR5K_EEPROM_READ(offset++, val); ++ ee->ee_adc_desired_size[mode] = (signed short int)((val >> 8) & 0xff); ++ ee->ee_ob[mode][1] = (val >> 4) & 0x7; ++ ee->ee_db[mode][1] = val & 0x7; ++ ++ ret = ath5k_eeprom_read_modes(mem, mac_version, ee, &offset, mode); ++ if (ret) ++ return ret; ++ ++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0) { ++ AR5K_EEPROM_READ(offset++, val); ++ ++ ee->ee_cal_piers_g = 0; ++ ++ ee->ee_pwr_cal_g[0].freq = ++ ath5k_eeprom_bin2freq(ee, val & 0xff, mode); ++ if (ee->ee_pwr_cal_g[0].freq != AR5K_EEPROM_CHANNEL_DIS) ++ ee->ee_cal_piers_g++; ++ ++ ee->ee_pwr_cal_g[1].freq = ++ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); ++ if (ee->ee_pwr_cal_g[1].freq != AR5K_EEPROM_CHANNEL_DIS) ++ ee->ee_cal_piers_g++; ++ ++ AR5K_EEPROM_READ(offset++, val); ++ ee->ee_turbo_max_power[mode] = val & 0x7f; ++ ee->ee_xr_power[mode] = (val >> 7) & 0x3f; ++ ++ AR5K_EEPROM_READ(offset++, val); ++ ee->ee_pwr_cal_g[2].freq = ++ ath5k_eeprom_bin2freq(ee, val & 0xff, mode); ++ if (ee->ee_pwr_cal_g[2].freq != AR5K_EEPROM_CHANNEL_DIS) ++ ee->ee_cal_piers_g++; ++ ++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_1) ++ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; ++ ++ AR5K_EEPROM_READ(offset++, val); ++ ee->ee_i_cal[mode] = (val >> 8) & 0x3f; ++ ee->ee_q_cal[mode] = (val >> 3) & 0x1f; ++ ++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_2) { ++ AR5K_EEPROM_READ(offset++, val); ++ ee->ee_cck_ofdm_gain_delta = val & 0xff; + } + } + +- return (name); ++ /* ++ * Read 5GHz EEPROM channels ++ */ ++ offset = AR5K_EEPROM_CHANNELS_5GHZ(ee->ee_version); ++ ee->ee_cal_piers_a = 0; ++ for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) { ++ AR5K_EEPROM_READ(offset++, val); ++ ++ if ((val & 0xff) == 0) ++ break; ++ ++ ee->ee_pwr_cal_a[i].freq = ++ ath5k_eeprom_bin2freq(ee, val & 0xff, AR5K_EEPROM_MODE_11A); ++ ee->ee_cal_piers_a++; ++ ++ if (((val >> 8) & 0xff) == 0) ++ break; ++ ++ ee->ee_pwr_cal_a[++i].freq = ++ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, AR5K_EEPROM_MODE_11A); ++ ee->ee_cal_piers_a++; ++ ++ } ++ ++ /* ++ * Read power calibration info ++ */ ++ mode = AR5K_EEPROM_MODE_11A; ++ ret = ath5k_eeprom_read_pcal_info(mem, mac_version, ee, &offset, mode); ++ if (ret) ++ return ret; ++ ++ mode = AR5K_EEPROM_MODE_11B; ++ ret = ath5k_eeprom_read_pcal_info(mem, mac_version, ee, &offset, mode); ++ if (ret) ++ return ret; ++ ++ mode = AR5K_EEPROM_MODE_11G; ++ ret = ath5k_eeprom_read_pcal_info(mem, mac_version, ee, &offset, mode); ++ if (ret) ++ return ret; ++ ++ ++ /* ++ * Read per rate target power info ++ */ ++ offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) + AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version); ++ mode = AR5K_EEPROM_MODE_11A; ++ ret = ath5k_eeprom_read_target_rate_pwr_info(mem, mac_version, ee, &offset, mode); ++ if (ret) ++ return ret; ++ ++ offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) + AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version); ++ mode = AR5K_EEPROM_MODE_11B; ++ ret = ath5k_eeprom_read_target_rate_pwr_info(mem, mac_version, ee, &offset, mode); ++ if (ret) ++ return ret; ++ ++ offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) + AR5K_EEPROM_TARGET_PWR_OFF_11G(ee->ee_version); ++ mode = AR5K_EEPROM_MODE_11G; ++ ret = ath5k_eeprom_read_target_rate_pwr_info(mem, mac_version, ee, &offset, mode); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static const char *ath5k_hw_get_mac_name(u_int8_t val) ++{ ++ static char name[16]; ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(ath5k_mac_names); i++) { ++ if (val <= ath5k_mac_names[i].sr_val) ++ break; ++ } ++ ++ if (val == ath5k_mac_names[i].sr_val) ++ return ath5k_mac_names[i].sr_name; ++ ++ snprintf(name, sizeof(name), "%s+", ath5k_mac_names[i - 1].sr_name); ++ return name; ++} ++ ++static const char *ath5k_hw_get_phy_name(u_int8_t val) ++{ ++ const char *name = "?????"; ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(ath5k_phy_names); i++) { ++ if (val < ath5k_phy_names[i + 1].sr_val) { ++ name = ath5k_phy_names[i].sr_name; ++ break; ++ } ++ } ++ ++ return name; + } + + /* returns -1 on unknown name */ + static int eeprom_name2addr(const char *name) + { +- int i; ++ unsigned int i; ++ + if (!name || !name[0]) + return -1; +- for (i = 0; i < eeprom_addr_len; i++) ++ for (i = 0; i < ARRAY_SIZE(eeprom_addr); i++) + if (!strcmp(name, eeprom_addr[i].name)) + return eeprom_addr[i].addr; + return -1; +-} /* eeprom_name2addr */ ++} + + /* returns "" on unknown address */ + static const char *eeprom_addr2name(int addr) + { +- int i; +- for (i = 0; i < eeprom_addr_len; i++) ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(eeprom_addr); i++) + if (eeprom_addr[i].addr == addr) + return eeprom_addr[i].name; + return ""; +-} /* eeprom_addr2name */ ++} + +-static int +-do_write_pairs(int anr, int argc, char **argv, unsigned char *mem, +- int mac_version) ++static int do_write_pairs(int anr, int argc, char **argv, unsigned char *mem, ++ int mac_version) + { + #define MAX_NR_WRITES 16 + struct { +@@ -635,7 +1422,7 @@ + } + anr++; + i++; +- } /* while (anr < (argc-1)) */ ++ } + + if (!(wr_ops_len = i)) { + err("no (addr,val) pairs given"); +@@ -702,20 +1489,22 @@ + } + + return errors ? 11 : 0; +-} /* do_write_pairs */ ++} + + static void usage(const char *n) + { +- int i; ++ unsigned int i; + +- fprintf(stderr, "%s [-w [-g N:M]] [-v] [-f] [-d] " ++ fprintf(stderr, "%s [-w [-g N:M]] [-v] [-f] [-d] [-R addr] [-W addr val] " + "[ [ ...]]\n\n", n); + fprintf(stderr, + "-w write values into EEPROM\n" + "-g N:M set GPIO N to level M (only used with -w)\n" + "-v verbose output\n" + "-f force; suppress question before writing\n" +- "-d dump eeprom (file 'ath-eeprom-dump.bin' and screen)\n" ++ "-d dump EEPROM (file 'ath-eeprom-dump.bin' and screen)\n" ++ "-R read register at (hex)\n" ++ "-W write (hex) into register at (hex)\n" + " device base address (see lspci output)\n\n"); + + fprintf(stderr, +@@ -725,8 +1514,8 @@ + " %s -w regdomain N\n\n" + "- set a PCI id field to value N:\n" + " %s -w N\n" +- " where is on of:\n ", n, n, n); +- for (i = 0; i < eeprom_addr_len; i++) ++ " where is one of:\n ", n, n, n); ++ for (i = 0; i < ARRAY_SIZE(eeprom_addr); i++) + fprintf(stderr, " %s", eeprom_addr[i].name); + fprintf(stderr, "\n\n"); + fprintf(stderr, +@@ -739,19 +1528,457 @@ + "unlawful radio transmissions!\n\n"); + } + ++static void dump_capabilities(struct ath5k_eeprom_info *ee) ++{ ++ u_int8_t has_a, has_b, has_g, has_rfkill, turbog_dis, turboa_dis; ++ u_int8_t xr2_dis, xr5_dis, has_crystal; ++ ++ has_a = AR5K_EEPROM_HDR_11A(ee->ee_header); ++ has_b = AR5K_EEPROM_HDR_11B(ee->ee_header); ++ has_g = AR5K_EEPROM_HDR_11G(ee->ee_header); ++ has_rfkill = AR5K_EEPROM_HDR_RFKILL(ee->ee_header); ++ has_crystal = AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1); ++ turbog_dis = AR5K_EEPROM_HDR_T_2GHZ_DIS(ee->ee_header); ++ turboa_dis = AR5K_EEPROM_HDR_T_5GHZ_DIS(ee->ee_header); ++ xr2_dis = AR5K_EEPROM_HDR_XR2_DIS(ee->ee_misc0); ++ xr5_dis = AR5K_EEPROM_HDR_XR5_DIS(ee->ee_misc0); ++ ++ printf("|================= Capabilities ================|\n"); ++ ++ printf("| 802.11a Support: "); ++ if (has_a) ++ printf(" yes |"); ++ else ++ printf(" no |"); ++ ++ printf(" Turbo-A disabled:"); ++ if (turboa_dis) ++ printf(" yes |\n"); ++ else ++ printf(" no |\n"); ++ ++ printf("| 802.11b Support: "); ++ if (has_b) ++ printf(" yes |"); ++ else ++ printf(" no |"); ++ ++ printf(" Turbo-G disabled:"); ++ if (turbog_dis) ++ printf(" yes |\n"); ++ else ++ printf(" no |\n"); ++ ++ printf("| 802.11g Support: "); ++ if (has_g) ++ printf(" yes |"); ++ else ++ printf(" no |"); ++ ++ printf(" 2GHz XR disabled:"); ++ if (xr2_dis) ++ printf(" yes |\n"); ++ else ++ printf(" no |\n"); ++ ++ printf("| RFKill Support: "); ++ if (has_rfkill) ++ printf(" yes |"); ++ else ++ printf(" no |"); ++ ++ printf(" 5GHz XR disabled:"); ++ if (xr5_dis) ++ printf(" yes |\n"); ++ else ++ printf(" no |\n"); ++ ++ if (has_crystal != 2) { ++ printf("| 32kHz Crystal: "); ++ if (has_crystal) ++ printf(" yes |"); ++ else ++ printf(" no |"); ++ ++ printf(" |\n"); ++ } ++ ++ printf("\\===============================================/\n"); ++} ++ ++static void dump_calinfo_for_mode(int mode, struct ath5k_eeprom_info *ee) ++{ ++ int i; ++ ++ printf("|=========================================================|\n"); ++ printf("| I power: 0x%02x |", ee->ee_i_cal[mode]); ++ printf(" Q power: 0x%02x |\n", ee->ee_q_cal[mode]); ++ printf("| Use fixed bias: 0x%02x |", ee->ee_fixed_bias[mode]); ++ printf(" Max turbo power: 0x%02x |\n", ee->ee_turbo_max_power[mode]); ++ printf("| Max XR power: 0x%02x |", ee->ee_xr_power[mode]); ++ printf(" Switch Settling Time: 0x%02x |\n", ee->ee_switch_settling[mode]); ++ printf("| Tx/Rx attenuation: 0x%02x |", ee->ee_ant_tx_rx[mode]); ++ printf(" TX end to XLNA On: 0x%02x |\n", ee->ee_tx_end2xlna_enable[mode]); ++ printf("| TX end to XPA Off: 0x%02x |", ee->ee_tx_end2xpa_disable[mode]); ++ printf(" TX end to XPA On: 0x%02x |\n", ee->ee_tx_frm2xpa_enable[mode]); ++ printf("| 62db Threshold: 0x%02x |", ee->ee_thr_62[mode]); ++ printf(" XLNA gain: 0x%02x |\n", ee->ee_xlna_gain[mode]); ++ printf("| XPD: 0x%02x |", ee->ee_xpd[mode]); ++ printf(" XPD gain: 0x%02x |\n", ee->ee_x_gain[mode]); ++ printf("| I gain: 0x%02x |", ee->ee_i_gain[mode]); ++ printf(" Tx/Rx margin: 0x%02x |\n", ee->ee_margin_tx_rx[mode]); ++ printf("| False detect backoff: 0x%02x |", ee->ee_false_detect[mode]); ++ printf(" Noise Floor Threshold: %3d |\n", ee->ee_noise_floor_thr[mode]); ++ printf("| ADC desired size: %3d |", ee->ee_adc_desired_size[mode]); ++ printf(" PGA desired size: %3d |\n", ee->ee_pga_desired_size[mode]); ++ printf("|=========================================================|\n"); ++ for (i = 0; i < AR5K_EEPROM_N_PCDAC; i++) { ++ printf("| Antenna control %2i: 0x%02x |", i, ee->ee_ant_control[mode][i]); ++ i++; ++ printf(" Antenna control %2i: 0x%02x |\n", i, ee->ee_ant_control[mode][i]); ++ } ++ printf("|=========================================================|\n"); ++ for (i = 0; i < AR5K_EEPROM_N_OBDB; i++) { ++ printf("| Octave Band %i: %2i |", i, ee->ee_ob[mode][i]); ++ printf(" db %i: %2i |\n", i, ee->ee_db[mode][i]); ++ } ++ printf("\\=========================================================/\n"); ++} ++ ++static void dump_power_calinfo_for_mode(int mode, struct ath5k_eeprom_info *ee) ++{ ++ struct ath5k_chan_pcal_info *chan_pcal_info; ++ u_int16_t cal_piers; ++ int i, c; ++ ++ switch (mode) { ++ case AR5K_EEPROM_MODE_11A: ++ chan_pcal_info = ee->ee_pwr_cal_a; ++ cal_piers = ee->ee_cal_piers_a; ++ break; ++ case AR5K_EEPROM_MODE_11B: ++ chan_pcal_info = ee->ee_pwr_cal_b; ++ cal_piers = ee->ee_cal_piers_b; ++ break; ++ case AR5K_EEPROM_MODE_11G: ++ chan_pcal_info = ee->ee_pwr_cal_g; ++ cal_piers = ee->ee_cal_piers_g; ++ break; ++ default: ++ return; ++ } ++ ++ printf("/=================== Per channel power calibration ====================\\\n"); ++ printf("| Freq | pwr_0 | pwr_1 | pwr_2 | pwr_3 |pwrx3_0|pwrx3_1|pwrx3_2|max_pwr|\n"); ++ printf("| | pcdac | pcdac | pcdac | pcdac | pcdac | pcdac | pcdac | |\n"); ++ ++ for (i = 0; i < cal_piers; i++) { ++ char buf[16]; ++ ++ printf("|======|=======|=======|=======|=======|=======|=======|=======|=======|\n"); ++ printf("| %4i |", chan_pcal_info[i].freq); ++ for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) { ++ printf(" %2i.%02i |", chan_pcal_info[i].pwr_x0[c] / 4, ++ chan_pcal_info[i].pwr_x0[c] % 4); ++ } ++ for (c = 0; c < AR5K_EEPROM_N_XPD3_POINTS; c++) { ++ printf(" %2i.%02i |", chan_pcal_info[i].pwr_x3[c] / 4, ++ chan_pcal_info[i].pwr_x3[c] % 4); ++ } ++ printf(" %2i.%02i |\n", chan_pcal_info[i].max_pwr / 4, ++ chan_pcal_info[i].max_pwr % 4); ++ ++ printf("| |"); ++ for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) { ++ snprintf(buf, sizeof(buf), "[%i]", ++ chan_pcal_info[i].pcdac_x0[c]); ++ printf("%6s |", buf); ++ } ++ for (c = 0; c < AR5K_EEPROM_N_XPD3_POINTS; c++) { ++ snprintf(buf, sizeof(buf), "[%i]", ++ chan_pcal_info[i].pcdac_x3[c]); ++ printf("%6s |", buf); ++ } ++ printf(" |\n"); ++ ++ } ++ printf("\\======================================================================/\n"); ++} ++ ++static void dump_rate_calinfo_for_mode(int mode, struct ath5k_eeprom_info *ee) ++{ ++ int i; ++ struct ath5k_rate_pcal_info *rate_pcal_info; ++ u_int16_t rate_target_pwr_num; ++ ++ switch (mode) { ++ case AR5K_EEPROM_MODE_11A: ++ rate_pcal_info = ee->ee_rate_tpwr_a; ++ rate_target_pwr_num = ee->ee_rate_target_pwr_num_a; ++ break; ++ case AR5K_EEPROM_MODE_11B: ++ rate_pcal_info = ee->ee_rate_tpwr_b; ++ rate_target_pwr_num = ee->ee_rate_target_pwr_num_b; ++ break; ++ case AR5K_EEPROM_MODE_11G: ++ rate_pcal_info = ee->ee_rate_tpwr_g; ++ rate_target_pwr_num = ee->ee_rate_target_pwr_num_g; ++ break; ++ default: ++ return; ++ } ++ ++ printf("/============== Per rate power calibration ===========\\\n"); ++ if (mode == AR5K_EEPROM_MODE_11B) ++ printf("| Freq | 1Mbit/s | 2Mbit/s | 5.5Mbit/s | 11Mbit/s |\n"); ++ else ++ printf("| Freq | 6-24Mbit/s | 36Mbit/s | 48Mbit/s | 54Mbit/s |\n"); ++ ++ for (i = 0; i < rate_target_pwr_num; i++) { ++ ++ printf("|======|============|==========|===========|==========|\n"); ++ printf("| %4i |", rate_pcal_info[i].freq); ++ printf(" %2i.%02i |",rate_pcal_info[i].target_power_6to24 /2, ++ rate_pcal_info[i].target_power_6to24 % 2); ++ printf(" %2i.%02i |",rate_pcal_info[i].target_power_36 /2, ++ rate_pcal_info[i].target_power_36 % 2); ++ printf(" %2i.%02i |",rate_pcal_info[i].target_power_48 /2, ++ rate_pcal_info[i].target_power_48 % 2); ++ printf(" %2i.%02i |\n",rate_pcal_info[i].target_power_54 /2, ++ rate_pcal_info[i].target_power_54 % 2); ++ } ++ printf("\\=====================================================/\n"); ++} ++ ++static u_int32_t extend_tu(u_int32_t base_tu, u_int32_t val, u_int32_t mask) ++{ ++ u_int32_t result; ++ ++ result = (base_tu & ~mask) | (val & mask); ++ if ((base_tu & mask) > (val & mask)) ++ result += mask + 1; ++ return result; ++} ++ ++static void dump_timers_register(void *mem, u_int16_t mac_version) ++{ ++#define AR5K_TIMER0_5210 0x802c /* next TBTT */ ++#define AR5K_TIMER0_5211 0x8028 ++#define AR5K_TIMER0 (mac_version == AR5K_SREV_MAC_AR5210 ? \ ++ AR5K_TIMER0_5210 : AR5K_TIMER0_5211) ++ ++#define AR5K_TIMER1_5210 0x8030 /* next DMA beacon */ ++#define AR5K_TIMER1_5211 0x802c ++#define AR5K_TIMER1 (mac_version == AR5K_SREV_MAC_AR5210 ? \ ++ AR5K_TIMER1_5210 : AR5K_TIMER1_5211) ++ ++#define AR5K_TIMER2_5210 0x8034 /* next SWBA interrupt */ ++#define AR5K_TIMER2_5211 0x8030 ++#define AR5K_TIMER2 (mac_version == AR5K_SREV_MAC_AR5210 ? \ ++ AR5K_TIMER2_5210 : AR5K_TIMER2_5211) ++ ++#define AR5K_TIMER3_5210 0x8038 /* next ATIM window */ ++#define AR5K_TIMER3_5211 0x8034 ++#define AR5K_TIMER3 (mac_version == AR5K_SREV_MAC_AR5210 ? \ ++ AR5K_TIMER3_5210 : AR5K_TIMER3_5211) ++ ++#define AR5K_TSF_L32_5210 0x806c /* TSF (lower 32 bits) */ ++#define AR5K_TSF_L32_5211 0x804c ++#define AR5K_TSF_L32 (mac_version == AR5K_SREV_MAC_AR5210 ? \ ++ AR5K_TSF_L32_5210 : AR5K_TSF_L32_5211) ++ ++#define AR5K_TSF_U32_5210 0x8070 ++#define AR5K_TSF_U32_5211 0x8050 ++#define AR5K_TSF_U32 (mac_version == AR5K_SREV_MAC_AR5210 ? \ ++ AR5K_TSF_U32_5210 : AR5K_TSF_U32_5211) ++ ++#define AR5K_BEACON_5210 0x8024 ++#define AR5K_BEACON_5211 0x8020 ++#define AR5K_BEACON (mac_version == AR5K_SREV_MAC_AR5210 ? \ ++ AR5K_BEACON_5210 : AR5K_BEACON_5211) ++ ++#define AR5K_LAST_TSTP 0x8080 ++ ++ const int timer_mask = 0xffff; ++ ++ u_int32_t timer0, timer1, timer2, timer3, now_tu; ++ u_int32_t timer0_tu, timer1_tu, timer2_tu, timer3_tu; ++ u_int64_t now_tsf; ++ ++ timer0 = AR5K_REG_READ(AR5K_TIMER0); /* 0x0000ffff */ ++ timer1 = AR5K_REG_READ(AR5K_TIMER1_5211); /* 0x0007ffff */ ++ timer2 = AR5K_REG_READ(AR5K_TIMER2_5211); /* 0x?1ffffff */ ++ timer3 = AR5K_REG_READ(AR5K_TIMER3_5211); /* 0x0000ffff */ ++ ++ now_tsf = ((u_int64_t)AR5K_REG_READ(AR5K_TSF_U32_5211) << 32) ++ | (u_int64_t)AR5K_REG_READ(AR5K_TSF_L32_5211); ++ ++ now_tu = now_tsf >> 10; ++ ++ timer0_tu = extend_tu(now_tu, timer0, 0xffff); ++ printf("TIMER0: 0x%08x, TBTT: %5u, TU: 0x%08x\n", timer0, ++ timer0 & timer_mask, timer0_tu); ++ timer1_tu = extend_tu(now_tu, timer1 >> 3, 0x7ffff >> 3); ++ printf("TIMER1: 0x%08x, DMAb: %5u, TU: 0x%08x (%+d)\n", timer1, ++ (timer1 >> 3) & timer_mask, timer1_tu, timer1_tu - timer0_tu); ++ timer2_tu = extend_tu(now_tu, timer2 >> 3, 0x1ffffff >> 3); ++ printf("TIMER2: 0x%08x, SWBA: %5u, TU: 0x%08x (%+d)\n", timer2, ++ (timer2 >> 3) & timer_mask, timer2_tu, timer2_tu - timer0_tu); ++ timer3_tu = extend_tu(now_tu, timer3, 0xffff); ++ printf("TIMER3: 0x%08x, ATIM: %5u, TU: 0x%08x (%+d)\n", timer3, ++ timer3 & timer_mask, timer3_tu, timer3_tu - timer0_tu); ++ printf("TSF: 0x%016llx, TSFTU: %5u, TU: 0x%08x\n", ++ (unsigned long long)now_tsf, now_tu & timer_mask, now_tu); ++ ++ printf("BEACON: 0x%08x\n", AR5K_REG_READ(AR5K_BEACON)); ++ printf("LAST_TSTP: 0x%08x\n", AR5K_REG_READ(AR5K_LAST_TSTP)); ++} ++ ++#define AR5K_KEYTABLE_0_5210 0x9000 ++#define AR5K_KEYTABLE_0_5211 0x8800 ++#define AR5K_KEYTABLE_0 (mac_version == AR5K_SREV_MAC_AR5210 ? \ ++ AR5K_KEYTABLE_0_5210 : \ ++ AR5K_KEYTABLE_0_5211) ++ ++#define AR5K_KEYTABLE(_n) (AR5K_KEYTABLE_0_5211 + ((_n) << 5)) ++#define AR5K_KEYTABLE_OFF(_n, x) (AR5K_KEYTABLE(_n) + ((x) << 2)) ++#define AR5K_KEYTABLE_VALID 0x00008000 ++ ++#define AR5K_KEYTABLE_SIZE_5210 64 ++#define AR5K_KEYTABLE_SIZE_5211 128 ++#define AR5K_KEYTABLE_SIZE (mac_version == AR5K_SREV_MAC_AR5210 ? \ ++ AR5K_KEYTABLE_SIZE_5210 : \ ++ AR5K_KEYTABLE_SIZE_5211) ++ ++static void keycache_dump(void *mem, u_int16_t mac_version) ++{ ++ int i, keylen; ++ u_int32_t val0, val1, val2, val3, val4, keytype, ant, mac0, mac1; ++ ++ /* dump all 128 entries */ ++ printf("Dumping keycache entries...\n"); ++ for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) { ++ mac1 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 7)); ++ if (mac1 & AR5K_KEYTABLE_VALID) { ++ val0 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 0)); ++ val1 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 1)); ++ val2 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 2)); ++ val3 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 3)); ++ val4 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 4)); ++ keytype = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 5)); ++ ant = keytype & 8; ++ keytype &= ~8; ++ switch (keytype) { ++ case 0: /* WEP40 */ keylen = 40 / 8; break; ++ case 1: /* WEP104 */ keylen = 104 / 8; break; ++ case 3: /* WEP128 */ keylen = 128 / 8; break; ++ case 4: /* TKIP */ keylen = 128 / 8; break; ++ case 5: /* AES */ keylen = 128 / 8; break; ++ case 6: /* CCM */ keylen = 128 / 8; break; ++ default: keylen = 0; break; ++ } ++ mac0 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 6)); ++ ++ printf("[%3u] keytype %d [%s%s%s%s%s%s%s%s] mac %02x:%02x:%02x:%02x:%02x:%02x key:%08x-%08x-%08x-%08x-%08x\n", ++ i, ++ keytype, ++ keytype == 0 ? "WEP40 " : "", ++ keytype == 1 ? "WEP104" : "", ++ keytype == 3 ? "WEP128" : "", ++ keytype == 4 ? "TKIP " : "", ++ keytype == 5 ? "AES " : "", ++ keytype == 6 ? "CCM " : "", ++ keytype == 7 ? "NULL " : "", ++ ant == 8 ? "+ANT" : "", ++ ((mac0 << 1) & 0xff), ++ ((mac0 >> 7) & 0xff), ++ ((mac0 >> 15) & 0xff), ++ ((mac0 >> 23) & 0xff), ++ ((mac1 << 1) & 0xff) | (mac0 >> 31), ++ ((mac1 >> 7) & 0xff), ++ val0, val1, val2, val3, val4); ++ } ++ } ++} ++ ++/* copy key index (0) to key index (idx) */ ++ ++static void keycache_copy(void *mem, u_int16_t mac_version, int idx) ++{ ++ u_int32_t val0, val1, val2, val3, val4, keytype, mac0, mac1; ++ ++ printf("Copying keycache entry 0 to %d\n", idx); ++ if (idx < 0 || idx >= AR5K_KEYTABLE_SIZE) { ++ printf("invalid keycache index\n"); ++ return; ++ } ++ ++ val0 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 0)); ++ val1 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 1)); ++ val2 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 2)); ++ val3 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 3)); ++ val4 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 4)); ++ keytype = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 5)); ++ mac0 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 6)); ++ mac1 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 7)); ++ ++ AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 0), val0); ++ AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 1), val1); ++ AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 2), val2); ++ AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 3), val3); ++ AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 4), val4); ++ AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 5), keytype); ++ AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 6), mac0); ++ AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 7), mac1); ++} ++ ++static void sta_id0_id1_dump(void *mem) ++{ ++#define AR5K_STA_ID0 0x8000 ++#define AR5K_STA_ID1 0x8004 ++#define AR5K_STA_ID1_AP 0x00010000 ++#define AR5K_STA_ID1_ADHOC 0x00020000 ++#define AR5K_STA_ID1_NO_KEYSRCH 0x00080000 ++ ++ u_int32_t sta_id0, sta_id1; ++ ++ sta_id0 = AR5K_REG_READ(AR5K_STA_ID0); ++ sta_id1 = AR5K_REG_READ(AR5K_STA_ID1); ++ printf("STA_ID0: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ (sta_id0 >> 0) & 0xff, ++ (sta_id0 >> 8) & 0xff, ++ (sta_id0 >> 16) & 0xff, ++ (sta_id0 >> 24) & 0xff, ++ (sta_id1 >> 0) & 0xff, ++ (sta_id1 >> 8) & 0xff); ++ printf("STA_ID1: 0x%08x, AP: %d, IBSS: %d, KeyCache Disable: %d\n", ++ sta_id1, ++ sta_id1 & AR5K_STA_ID1_AP ? 1 : 0, ++ sta_id1 & AR5K_STA_ID1_ADHOC ? 1 : 0, ++ sta_id1 & AR5K_STA_ID1_NO_KEYSRCH ? 1 : 0); ++} ++ + int + CMD(athinfo)(int argc, char *argv[]) + { +- u_int32_t dev_addr; +- u_int16_t eeprom_header, srev, phy_rev_5ghz, phy_rev_2ghz; +- u_int16_t eeprom_version, mac_version, regdomain, has_crystal, ee_magic; +- u_int8_t error, has_a, has_b, has_g, has_rfkill, eeprom_size; +- int byte_size = 0; ++ unsigned long long dev_addr; ++ u_int16_t srev, phy_rev_5ghz, phy_rev_2ghz, ee_magic; ++ u_int8_t mac_version, mac_revision; ++ u_int8_t error, eeprom_size, dev_type, eemap; ++ struct ath5k_eeprom_info *ee; ++ unsigned int byte_size = 0; + void *mem; + int fd; +- int i, anr = 1; ++ unsigned int i; ++ int anr = 1; + int do_write = 0; /* default: read only */ + int do_dump = 0; ++ int reg_read = 0; ++ int reg_write = 0; ++ unsigned int reg_write_val = 0; ++ unsigned int timer_count = 1; ++ int do_keycache_dump = 0; ++ int keycache_copy_idx = 0; + + struct { + int valid; +@@ -759,7 +1986,7 @@ + } gpio_set[AR5K_NUM_GPIO]; + int nr_gpio_set = 0; + +- for (i = 0; i < sizeof(gpio_set) / sizeof(gpio_set[0]); i++) ++ for (i = 0; i < ARRAY_SIZE(gpio_set); i++) + gpio_set[i].valid = 0; + + if (argc < 2) { +@@ -769,6 +1996,15 @@ + + while (anr < argc && argv[anr][0] == '-') { + switch (argv[anr][1]) { ++ case 't': ++ if (++anr < argc) { ++ timer_count = atoi(argv[anr]); ++ printf("timer_count:%d\n", timer_count); ++ } else { ++ usage(argv[0]); ++ return 0; ++ } ++ break; + case 'w': + do_write = 1; + break; +@@ -777,7 +2013,7 @@ + if (strlen(argv[anr]) != 3 || argv[anr][1] != ':' || + argv[anr][0] < '0' || argv[anr][0] > '5' || + (argv[anr][2] != '0' && argv[anr][2] != '1')) { +- err("invalid gpio spec. %s", argv[anr]); ++ err("invalid GPIO spec. %s", argv[anr]); + return 2; + } + gpio_set[argv[anr][0] - '0'].valid = 1; +@@ -797,6 +2033,25 @@ + do_dump = 1; + break; + ++ case 'R': ++ anr++; ++ reg_read = strtoul(argv[anr], NULL, 16); ++ break; ++ ++ case 'W': ++ anr++; ++ reg_write = strtoul(argv[anr++], NULL, 16); ++ reg_write_val = strtoul(argv[anr], NULL, 16); ++ break; ++ ++ case 'k': ++ do_keycache_dump = 1; ++ break; ++ ++ case 'K': ++ keycache_copy_idx = atoi(argv[++anr]); ++ break; ++ + case 'h': + usage(argv[0]); + return 0; +@@ -805,10 +2060,10 @@ + default: + err("unknown option %s", argv[anr]); + return 2; +- } /* switch (argv[anr][1]) */ ++ } + + anr++; +- } /* while (anr < argc && ...) */ ++ } + + if (anr >= argc) { + err("missing device address"); +@@ -816,7 +2071,7 @@ + return 3; + } + +- dev_addr = strtoul(argv[anr], NULL, 16); ++ dev_addr = strtoull(argv[anr], NULL, 16); + + fd = open("/dev/mem", O_RDWR); + if (fd < 0) { +@@ -828,7 +2083,7 @@ + MAP_SHARED | MAP_FILE, fd, dev_addr); + + if (mem == MAP_FAILED) { +- printf("Mmap of device at 0x%08X for 0x%X bytes failed - " ++ printf("mmap of device at 0x%08llX for 0x%X bytes failed - " + "%s\n", dev_addr, AR5K_PCI_MEM_SIZE, strerror(errno)); + return -3; + } +@@ -856,10 +2111,31 @@ + AR5K_REG_DISABLE_BITS(AR5K_PCICFG, AR5K_PCICFG_SPWR_DN); + usleep(500); + ++ if (reg_read) { ++ printf("READ %04x = %08x\n", reg_read, AR5K_REG_READ(reg_read)); ++ return 0; ++ } ++ ++ if (reg_write) { ++ printf("WRITE %04x = %08x\n", reg_write, reg_write_val); ++ AR5K_REG_WRITE(reg_write, reg_write_val); ++ return 0; ++ } ++ + srev = AR5K_REG_READ(AR5K_SREV); +- mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER) << 4; ++ if (srev >= 0x0100) { ++ printf("MAC revision 0x%04x is not supported!\n", srev); ++ return -1; ++ } ++ mac_version = srev & AR5K_SREV_VER; ++ mac_revision = srev & AR5K_SREV_REV; + +- /* Verify eeprom magic value first */ ++ printf(" -==Device Information==-\n"); ++ ++ printf("MAC Revision: %-5s (0x%02x)\n", ++ ath5k_hw_get_mac_name(mac_revision), mac_revision); ++ ++ /* Verify EEPROM magic value first */ + error = ath5k_hw_eeprom_read(mem, AR5K_EEPROM_MAGIC, &ee_magic, + mac_version); + +@@ -872,157 +2148,114 @@ + printf("Warning: Invalid EEPROM Magic number!\n"); + } + +- error = ath5k_hw_eeprom_read(mem, AR5K_EEPROM_HDR, &eeprom_header, +- mac_version); +- +- if (error) { +- printf("Unable to read EEPROM Header!\n"); +- return -1; +- } +- +- error = ath5k_hw_eeprom_read(mem, AR5K_EEPROM_VERSION, &eeprom_version, +- mac_version); +- +- if (error) { +- printf("Unable to read EEPROM version!\n"); ++ ee = calloc(sizeof(struct ath5k_eeprom_info), 1); ++ if (!ee) { ++ printf("Cannot allocate memory for EEPROM information\n"); + return -1; + } + +- error = ath5k_hw_eeprom_read(mem, AR5K_EEPROM_REG_DOMAIN, ®domain, +- mac_version); +- +- if (error) { +- printf("Unable to read Regdomain!\n"); ++ if (ath5k_eeprom_init(mem, mac_version, ee)) { ++ printf("EEPROM init failed\n"); + return -1; + } + +- if (eeprom_version >= 0x4000) { +- error = ath5k_hw_eeprom_read(mem, AR5K_EEPROM_MISC0, +- &has_crystal, mac_version); +- +- if (error) { +- printf("Unable to read EEPROM Misc data!\n"); +- return -1; +- } +- +- has_crystal = AR5K_EEPROM_HAS32KHZCRYSTAL(has_crystal); +- } else { +- has_crystal = 2; +- } +- + eeprom_size = AR5K_REG_MS(AR5K_REG_READ(AR5K_PCICFG), + AR5K_PCICFG_EESIZE); + +- has_a = AR5K_EEPROM_HDR_11A(eeprom_header); +- has_b = AR5K_EEPROM_HDR_11B(eeprom_header); +- has_g = AR5K_EEPROM_HDR_11G(eeprom_header); +- has_rfkill = AR5K_EEPROM_HDR_RFKILL(eeprom_header); ++ dev_type = AR5K_EEPROM_HDR_DEVICE(ee->ee_header); ++ eemap = AR5K_EEPROM_EEMAP(ee->ee_misc0); + +- if (has_a) ++ /* 1 = ?? 2 = ?? 3 = card 4 = wmac */ ++ printf("Device type: %1i\n", dev_type); ++ ++ if (AR5K_EEPROM_HDR_11A(ee->ee_header)) + phy_rev_5ghz = ath5k_hw_radio_revision(mac_version, mem, 1); + else + phy_rev_5ghz = 0; + +- if (has_b) ++ if (AR5K_EEPROM_HDR_11B(ee->ee_header)) + phy_rev_2ghz = ath5k_hw_radio_revision(mac_version, mem, 0); + else + phy_rev_2ghz = 0; + +- printf(" -==Device Information==-\n"); +- +- printf("MAC Version: %-5s (0x%02x)\n", +- ath5k_hw_get_part_name(AR5K_VERSION_VER, mac_version), +- mac_version); +- +- printf("MAC Revision: %-5s (0x%02x)\n", +- ath5k_hw_get_part_name(AR5K_VERSION_VER, srev), srev); +- +- /* Single-chip PHY with a/b/g support */ +- if (has_b && !phy_rev_2ghz) { +- printf("PHY Revision: %-5s (0x%02x)\n", +- ath5k_hw_get_part_name(AR5K_VERSION_RAD, phy_rev_5ghz), +- phy_rev_5ghz); +- phy_rev_5ghz = 0; +- } +- +- /* Single-chip PHY with b/g support */ +- if (!has_a) { +- printf("PHY Revision: %-5s (0x%02x)\n", +- ath5k_hw_get_part_name(AR5K_VERSION_RAD, phy_rev_2ghz), +- phy_rev_2ghz); +- phy_rev_2ghz = 0; +- } +- +- /* Different chip for 5Ghz and 2Ghz */ + if (phy_rev_5ghz) { +- printf("5Ghz PHY Revision: %-5s (0x%2x)\n", +- ath5k_hw_get_part_name(AR5K_VERSION_RAD, phy_rev_5ghz), +- phy_rev_5ghz); ++ printf("5GHz PHY Revision: %-5s (0x%02x)\n", ++ ath5k_hw_get_phy_name(phy_rev_5ghz), phy_rev_5ghz); + } + if (phy_rev_2ghz) { +- printf("2Ghz PHY Revision: %-5s (0x%2x)\n", +- ath5k_hw_get_part_name(AR5K_VERSION_RAD, phy_rev_2ghz), +- phy_rev_2ghz); ++ printf("2GHz PHY Revision: %-5s (0x%02x)\n", ++ ath5k_hw_get_phy_name(phy_rev_2ghz), phy_rev_2ghz); + } + +- printf(" -==EEPROM Information==-\n"); +- +- printf("EEPROM Version: %x.%x\n", +- (eeprom_version & 0xF000) >> 12, eeprom_version & 0xFFF); ++ printf("\n"); ++ printf("/============== EEPROM Information =============\\\n"); ++ printf("| EEPROM Version: %1x.%1x |", ++ (ee->ee_version & 0xF000) >> 12, ee->ee_version & 0xFFF); + +- printf("EEPROM Size: "); ++ printf(" EEPROM Size: "); + + if (eeprom_size == 0) { +- printf(" 4K\n"); +- byte_size = 4096; ++ printf(" 4 kbit |\n"); ++ byte_size = 4096 / 8; + } else if (eeprom_size == 1) { +- printf(" 8K\n"); +- byte_size = 8192; ++ printf(" 8 kbit |\n"); ++ byte_size = 8192 / 8; + } else if (eeprom_size == 2) { +- printf(" 16K\n"); +- byte_size = 16384; ++ printf(" 16 kbit |\n"); ++ byte_size = 16384 / 8; + } else +- printf(" ??\n"); ++ printf(" unknown |\n"); + +- printf("Regulatory Domain: 0x%X\n", regdomain); +- +- printf(" -==== Capabilities ====-\n"); +- +- printf("| 802.11a Support: "); +- if (has_a) +- printf("yes |\n"); +- else +- printf("no |\n"); +- +- printf("| 802.11b Support: "); +- if (has_b) +- printf("yes |\n"); +- else +- printf("no |\n"); ++ printf("| EEMAP: %i |", eemap); + +- printf("| 802.11g Support: "); +- if (has_g) +- printf("yes |\n"); +- else +- printf("no |\n"); ++ printf(" Reg. Domain: 0x%02X |\n", ee->ee_regdomain); + +- printf("| RFKill Support: "); +- if (has_rfkill) +- printf("yes |\n"); +- else +- printf("no |\n"); ++ dump_capabilities(ee); ++ printf("\n"); + +- if (has_crystal != 2) { +- printf("| 32KHz Crystal: "); +- if (has_crystal) +- printf("yes |\n"); +- else +- printf("no |\n"); ++ printf("/=========================================================\\\n"); ++ printf("| Calibration data common for all modes |\n"); ++ printf("|=========================================================|\n"); ++ printf("| CCK/OFDM gain delta: %2i |\n", ee->ee_cck_ofdm_gain_delta); ++ printf("| CCK/OFDM power delta: %2i |\n", ee->ee_cck_ofdm_power_delta); ++ printf("| Scaled CCK delta: %2i |\n", ee->ee_scaled_cck_delta); ++ printf("| 2GHz Antenna gain: %2i |\n", AR5K_EEPROM_ANT_GAIN_2GHZ(ee->ee_ant_gain)); ++ printf("| 5GHz Antenna gain: %2i |\n", AR5K_EEPROM_ANT_GAIN_5GHZ(ee->ee_ant_gain)); ++ printf("| Turbo 2W maximum dBm: %2i |\n", AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header)); ++ printf("| Target power start: 0x%03x |\n", AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1)); ++ printf("| EAR Start: 0x%03x |\n", AR5K_EEPROM_EARSTART(ee->ee_misc0)); ++ printf("\\=========================================================/\n"); ++ ++ printf("\n"); ++ if (AR5K_EEPROM_HDR_11A(ee->ee_header)) { ++ printf("/=========================================================\\\n"); ++ printf("| Calibration data for 802.11a operation |\n"); ++ dump_calinfo_for_mode(AR5K_EEPROM_MODE_11A, ee); ++ dump_rate_calinfo_for_mode(AR5K_EEPROM_MODE_11A, ee); ++ dump_power_calinfo_for_mode(AR5K_EEPROM_MODE_11A, ee); ++ printf("\n"); ++ } ++ ++ if (AR5K_EEPROM_HDR_11B(ee->ee_header)) { ++ printf("/=========================================================\\\n"); ++ printf("| Calibration data for 802.11b operation |\n"); ++ dump_calinfo_for_mode(AR5K_EEPROM_MODE_11B, ee); ++ dump_rate_calinfo_for_mode(AR5K_EEPROM_MODE_11B, ee); ++ dump_power_calinfo_for_mode(AR5K_EEPROM_MODE_11B, ee); ++ printf("\n"); ++ } ++ ++ if (AR5K_EEPROM_HDR_11G(ee->ee_header)) { ++ printf("/=========================================================\\\n"); ++ printf("| Calibration data for 802.11g operation |\n"); ++ dump_calinfo_for_mode(AR5K_EEPROM_MODE_11G, ee); ++ dump_rate_calinfo_for_mode(AR5K_EEPROM_MODE_11G, ee); ++ dump_power_calinfo_for_mode(AR5K_EEPROM_MODE_11G, ee); ++ printf("\n"); + } +- printf(" ========================\n"); + + /* print current GPIO settings */ +- printf("GPIO registers: CR %08x DO %08x DI %08x\n", ++ printf("GPIO registers: CR 0x%08x, DO 0x%08x, DI 0x%08x\n", + AR5K_REG_READ(AR5K_GPIOCR), AR5K_REG_READ(AR5K_GPIODO), + AR5K_REG_READ(AR5K_GPIODI)); + +@@ -1030,18 +2263,18 @@ + u_int16_t data; + FILE *dumpfile = fopen("ath-eeprom-dump.bin", "w"); + +- printf("\nEEPROM dump (%d byte)\n", byte_size); ++ printf("\nEEPROM dump (%d bytes)\n", byte_size); + printf("=============================================="); +- for (i = 1; i <= (byte_size / 2); i++) { ++ for (i = 0; i < byte_size / 2; i++) { + error = + ath5k_hw_eeprom_read(mem, i, &data, mac_version); + if (error) { + printf("\nUnable to read at %04x\n", i); + continue; + } +- if (!((i - 1) % 8)) +- printf("\n%04x: ", i); +- printf("%04x ", data); ++ if (!(i % 8)) ++ printf("\n%04x: ", i); ++ printf(" %04x", data); + fwrite(&data, 2, 1, dumpfile); + } + printf("\n==============================================\n"); +@@ -1054,18 +2287,18 @@ + u_int32_t old_cr = rcr, old_do = rdo; + int rc; + +- if (mac_version >= AR5K_SREV_VER_AR5213 && !nr_gpio_set) { +- dbg("new MAC %x (>= AR5213) set gpio4 to low", ++ if (mac_version >= AR5K_SREV_MAC_AR5213 && !nr_gpio_set) { ++ dbg("new MAC %x (>= AR5213) set GPIO4 to low", + mac_version); + gpio_set[4].valid = 1; + gpio_set[4].value = 0; + } + +- /* set gpios */ ++ /* set GPIOs */ + dbg("old GPIO CR %08x DO %08x DI %08x", + rcr, rdo, AR5K_REG_READ(AR5K_GPIODI)); + +- for (i = 0; i < sizeof(gpio_set) / sizeof(gpio_set[0]); i++) { ++ for (i = 0; i < ARRAY_SIZE(gpio_set); i++) { + if (gpio_set[i].valid) { + rcr |= AR5K_GPIOCR_OUT(i); /* we use mode 3 */ + rcr &= ~AR5K_GPIOCR_INT_SEL(i); +@@ -1111,5 +2344,17 @@ + + return rc; + } ++ ++ sta_id0_id1_dump(mem); ++ ++ for (i = 0; i < timer_count; i++) ++ dump_timers_register(mem, mac_version); ++ ++ if (do_keycache_dump) ++ keycache_dump(mem, mac_version); ++ ++ if (keycache_copy_idx > 0) ++ keycache_copy(mem, mac_version, keycache_copy_idx); ++ + return 0; + } -- 2.25.1