📄 if_ath.c
字号:
ah = _ath_hal_attach(devid, sc, NULL, (void *) dev->mem_start, &status); if (ah == NULL) { printk(KERN_ERR "%s: unable to attach hardware: '%s' (HAL status %u)\n", dev->name, ath_get_hal_status_desc(status), status); error = ENXIO; goto bad; } if (ah->ah_abi != HAL_ABI_VERSION) { printk(KERN_ERR "%s: HAL ABI mismatch; " "driver expects 0x%x, HAL reports 0x%x\n", dev->name, HAL_ABI_VERSION, ah->ah_abi); error = ENXIO; /* XXX */ goto bad; } sc->sc_ah = ah; /* * Check if the MAC has multi-rate retry support. * We do this by trying to setup a fake extended * descriptor. MAC's that don't have support will * return false w/o doing anything. MAC's that do * support it will return true w/o doing anything. */ sc->sc_mrretry = ath_hal_setupxtxdesc(ah, NULL, 0,0, 0,0, 0,0); /* * Check if the device has hardware counters for PHY * errors. If so we need to enable the MIB interrupt * so we can act on stat triggers. */ if (ath_hal_hwphycounters(ah)) sc->sc_needmib = 1; /* * Get the hardware key cache size. */ sc->sc_keymax = ath_hal_keycachesize(ah); if (sc->sc_keymax > ATH_KEYMAX) { printk("%s: Warning, using only %u entries in %u key cache\n", dev->name, ATH_KEYMAX, sc->sc_keymax); sc->sc_keymax = ATH_KEYMAX; } /* * Reset the key cache since some parts do not * reset the contents on initial power up. */ for (i = 0; i < sc->sc_keymax; i++) ath_hal_keyreset(ah, i); /* * Mark key cache slots associated with global keys * as in use. If we knew TKIP was not to be used we * could leave the +32, +64, and +32+64 slots free. * XXX only for splitmic. */ for (i = 0; i < IEEE80211_WEP_NKID; i++) { setbit(sc->sc_keymap, i); setbit(sc->sc_keymap, i+32); setbit(sc->sc_keymap, i+64); setbit(sc->sc_keymap, i+32+64); } /* * Collect the channel list using the default country * code and including outdoor channels. The 802.11 layer * is resposible for filtering this list based on settings * like the phy mode. */ if (countrycode != -1) ath_countrycode = countrycode; if (outdoor != -1) ath_outdoor = outdoor; if (xchanmode != -1) ath_xchanmode = xchanmode; error = ath_getchannels(dev, ath_countrycode, ath_outdoor, ath_xchanmode); if (error != 0) goto bad; ic->ic_country_code = ath_countrycode; ic->ic_country_outdoor = ath_outdoor; if (rfkill != -1) { printk(KERN_INFO "ath_pci: switching rfkill capability %s\n", rfkill ? "on" : "off"); ath_hal_setrfsilent(ah, rfkill); } /* * Setup rate tables for all potential media types. */ ath_rate_setup(dev, IEEE80211_MODE_11A); ath_rate_setup(dev, IEEE80211_MODE_11B); ath_rate_setup(dev, IEEE80211_MODE_11G); ath_rate_setup(dev, IEEE80211_MODE_TURBO_A); ath_rate_setup(dev, IEEE80211_MODE_TURBO_G); /* Setup for half/quarter rates */ ath_setup_subrates(dev); /* NB: setup here so ath_rate_update is happy */ ath_setcurmode(sc, IEEE80211_MODE_11A); /* * Allocate tx+rx descriptors and populate the lists. */ error = ath_desc_alloc(sc); if (error != 0) { printk(KERN_ERR "%s: failed to allocate descriptors: %d\n", dev->name, error); goto bad; } /* * Init ic_caps prior to queue init, since WME cap setting * depends on queue setup. */ ic->ic_caps = 0; /* * Allocate hardware transmit queues: one queue for * beacon frames and one data queue for each QoS * priority. Note that the hal handles reseting * these queues at the needed time. * * XXX PS-Poll */ sc->sc_bhalq = ath_beaconq_setup(ah); if (sc->sc_bhalq == (u_int) -1) { printk(KERN_ERR "%s: unable to setup a beacon xmit queue!\n", dev->name); error = EIO; goto bad2; } sc->sc_cabq = ath_txq_setup(sc, HAL_TX_QUEUE_CAB, 0); if (sc->sc_cabq == NULL) { printk(KERN_ERR "%s: unable to setup CAB xmit queue!\n", dev->name); error = EIO; goto bad2; } /* NB: ensure BK queue is the lowest priority h/w queue */ if (!ath_tx_setup(sc, WME_AC_BK, HAL_WME_AC_BK)) { printk(KERN_ERR "%s: unable to setup xmit queue for %s traffic!\n", dev->name, ieee80211_wme_acnames[WME_AC_BK]); error = EIO; goto bad2; } if (!ath_tx_setup(sc, WME_AC_BE, HAL_WME_AC_BE) || !ath_tx_setup(sc, WME_AC_VI, HAL_WME_AC_VI) || !ath_tx_setup(sc, WME_AC_VO, HAL_WME_AC_VO)) { /* * Not enough hardware tx queues to properly do WME; * just punt and assign them all to the same h/w queue. * We could do a better job of this if, for example, * we allocate queues when we switch from station to * AP mode. */ if (sc->sc_ac2q[WME_AC_VI] != NULL) ath_tx_cleanupq(sc, sc->sc_ac2q[WME_AC_VI]); if (sc->sc_ac2q[WME_AC_BE] != NULL) ath_tx_cleanupq(sc, sc->sc_ac2q[WME_AC_BE]); sc->sc_ac2q[WME_AC_BE] = sc->sc_ac2q[WME_AC_BK]; sc->sc_ac2q[WME_AC_VI] = sc->sc_ac2q[WME_AC_BK]; sc->sc_ac2q[WME_AC_VO] = sc->sc_ac2q[WME_AC_BK]; } else { /* * Mark WME capability since we have sufficient * hardware queues to do proper priority scheduling. */ ic->ic_caps |= IEEE80211_C_WME; sc->sc_uapsdq = ath_txq_setup(sc, HAL_TX_QUEUE_UAPSD, 0); if (sc->sc_uapsdq == NULL) DPRINTF(sc, ATH_DEBUG_UAPSD, "%s: unable to setup UAPSD xmit queue!\n", __func__); else { ic->ic_caps |= IEEE80211_C_UAPSD; /* * default UAPSD on if HW capable */ IEEE80211_COM_UAPSD_ENABLE(ic); } }#ifdef ATH_SUPERG_XR ath_xr_rate_setup(dev); sc->sc_xrpollint = XR_DEFAULT_POLL_INTERVAL; sc->sc_xrpollcount = XR_DEFAULT_POLL_COUNT; strcpy(sc->sc_grppoll_str, XR_DEFAULT_GRPPOLL_RATE_STR); sc->sc_grpplq.axq_qnum = -1; sc->sc_xrtxq = ath_txq_setup(sc, HAL_TX_QUEUE_DATA, HAL_XR_DATA);#endif /* * Special case certain configurations. Note the * CAB queue is handled by these specially so don't * include them when checking the txq setup mask. */ switch (sc->sc_txqsetup &~ ((1<<sc->sc_cabq->axq_qnum) | (sc->sc_uapsdq ? (1<<sc->sc_uapsdq->axq_qnum) : 0))) { case 0x01: ATH_INIT_TQUEUE(&sc->sc_txtq, ath_tx_tasklet_q0, dev); break; case 0x0f: ATH_INIT_TQUEUE(&sc->sc_txtq, ath_tx_tasklet_q0123, dev); break; } sc->sc_setdefantenna = ath_setdefantenna; sc->sc_rc = ath_rate_attach(sc); if (sc->sc_rc == NULL) { error = EIO; goto bad2; } init_timer(&sc->sc_cal_ch); sc->sc_cal_ch.function = ath_calibrate; sc->sc_cal_ch.data = (unsigned long) dev;#ifdef ATH_SUPERG_DYNTURBO init_timer(&sc->sc_dturbo_switch_mode); sc->sc_dturbo_switch_mode.function = ath_turbo_switch_mode; sc->sc_dturbo_switch_mode.data = (unsigned long) dev;#endif sc->sc_blinking = 0; sc->sc_ledstate = 1; sc->sc_ledon = 0; /* low true */ sc->sc_ledidle = msecs_to_jiffies(2700); /* 2.7sec */ sc->sc_dfstesttime = ATH_DFS_TEST_RETURN_PERIOD; init_timer(&sc->sc_ledtimer); init_timer(&sc->sc_dfswaittimer); init_timer(&sc->sc_dfstesttimer); sc->sc_ledtimer.data = (unsigned long) sc; /* * Auto-enable soft led processing for IBM cards and for * 5211 minipci cards. Users can also manually enable/disable * support with a sysctl. */ sc->sc_softled = (devid == AR5212_DEVID_IBM || devid == AR5211_DEVID); if (sc->sc_softled) { ath_hal_gpioCfgOutput(ah, sc->sc_ledpin); ath_hal_gpioset(ah, sc->sc_ledpin, !sc->sc_ledon); } /* NB: ether_setup is done by bus-specific code */ dev->open = ath_init; dev->stop = ath_stop; dev->hard_start_xmit = ath_hardstart; dev->tx_timeout = ath_tx_timeout; dev->watchdog_timeo = 5 * HZ; /* XXX */ dev->set_multicast_list = ath_mode_init; dev->do_ioctl = ath_ioctl; dev->get_stats = ath_getstats; dev->set_mac_address = ath_set_mac_address; dev->change_mtu = ath_change_mtu; dev->tx_queue_len = ATH_TXBUF - 1; /* 1 for mgmt frame */#ifdef USE_HEADERLEN_RESV dev->hard_header_len += sizeof(struct ieee80211_qosframe) + sizeof(struct llc) + IEEE80211_ADDR_LEN + IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;#ifdef ATH_SUPERG_FF dev->hard_header_len += ATH_FF_MAX_HDR;#endif#endif ic->ic_dev = dev; ic->ic_mgtstart = ath_mgtstart; ic->ic_init = ath_init; ic->ic_reset = ath_reset; ic->ic_newassoc = ath_newassoc; ic->ic_updateslot = ath_updateslot; ic->ic_wme.wme_update = ath_wme_update; ic->ic_uapsd_flush = ath_uapsd_flush; /* XXX not right but it's not used anywhere important */ ic->ic_phytype = IEEE80211_T_OFDM; ic->ic_opmode = IEEE80211_M_STA; sc->sc_opmode = HAL_M_STA; /* * Set the Atheros Advanced Capabilities from station config before * starting 802.11 state machine. Currently, set only fast-frames * capability. */ ic->ic_ath_cap = 0; sc->sc_fftxqmin = ATH_FF_TXQMIN;#ifdef ATH_SUPERG_FF ic->ic_ath_cap |= (ath_hal_fastframesupported(ah) ? IEEE80211_ATHC_FF : 0);#endif ic->ic_ath_cap |= (ath_hal_burstsupported(ah) ? IEEE80211_ATHC_BURST : 0);#ifdef ATH_SUPERG_COMP ic->ic_ath_cap |= (ath_hal_compressionsupported(ah) ? IEEE80211_ATHC_COMP : 0); #endif#ifdef ATH_SUPERG_DYNTURBO ic->ic_ath_cap |= (ath_hal_turboagsupported(ah) ? (IEEE80211_ATHC_TURBOP | IEEE80211_ATHC_AR) : 0);#endif#ifdef ATH_SUPERG_XR ic->ic_ath_cap |= (ath_hal_xrsupported(ah) ? IEEE80211_ATHC_XR : 0);#endif ic->ic_caps |= IEEE80211_C_IBSS /* ibss, nee adhoc, mode */ | IEEE80211_C_HOSTAP /* hostap mode */ | IEEE80211_C_MONITOR /* monitor mode */ | IEEE80211_C_AHDEMO /* adhoc demo mode */ | IEEE80211_C_SHPREAMBLE /* short preamble supported */ | IEEE80211_C_SHSLOT /* short slot time supported */ | IEEE80211_C_WPA /* capable of WPA1+WPA2 */ | IEEE80211_C_BGSCAN /* capable of bg scanning */ ; /* * Query the hal to figure out h/w crypto support. */ if (ath_hal_ciphersupported(ah, HAL_CIPHER_WEP)) ic->ic_caps |= IEEE80211_C_WEP; if (ath_hal_ciphersupported(ah, HAL_CIPHER_AES_OCB)) ic->ic_caps |= IEEE80211_C_AES; if (ath_hal_ciphersupported(ah, HAL_CIPHER_AES_CCM)) ic->ic_caps |= IEEE80211_C_AES_CCM; if (ath_hal_ciphersupported(ah, HAL_CIPHER_CKIP)) ic->ic_caps |= IEEE80211_C_CKIP; if (ath_hal_ciphersupported(ah, HAL_CIPHER_TKIP)) { ic->ic_caps |= IEEE80211_C_TKIP; /* * Check if h/w does the MIC and/or whether the * separate key cache entries are required to * handle both tx+rx MIC keys. */ if (ath_hal_ciphersupported(ah, HAL_CIPHER_MIC)) { ic->ic_caps |= IEEE80211_C_TKIPMIC; /* * Check if h/w does MIC correctly when * WMM is turned on. */ if (ath_hal_wmetkipmic(ah)) ic->ic_caps |= IEEE80211_C_WME_TKIPMIC; } if (ath_hal_tkipsplit(ah)) sc->sc_splitmic = 1; } sc->sc_hasclrkey = ath_hal_ciphersupported(ah, HAL_CIPHER_CLR);#if 0 sc->sc_mcastkey = ath_hal_getmcastkeysearch(ah);#endif /* * TPC support can be done either with a global cap or * per-packet support. The latter is not available on * all parts. We're a bit pedantic here as all parts * support a global cap. */ sc->sc_hastpc = ath_hal_hastpc(ah); if (sc->sc_hastpc || ath_hal_hastxpowlimit(ah)) ic->ic_caps |= IEEE80211_C_TXPMGT; /* * Default 11.h to start enabled. */ ic->ic_flags |= IEEE80211_F_DOTH; /* * Check for misc other capabilities. */ if (ath_hal_hasbursting(ah)) ic->ic_caps |= IEEE80211_C_BURST; sc->sc_hasbmask = ath_hal_hasbssidmask(ah); sc->sc_hastsfadd = ath_hal_hastsfadjust(ah); /* * Indicate we need the 802.11 header padded to a * 32-bit boundary for 4-address and QoS frames. */ ic->ic_flags |= IEEE80211_F_DATAPAD; /* * Query the hal about antenna support * Enable rx fast diversity if hal has support */ if (ath_hal_hasdiversity(ah)) { sc->sc_hasdiversity = 1; ath_hal_setdiversity(ah, AH_TRUE); sc->sc_diversity = 1; } else { sc->sc_hasdiversity = 0; sc->sc_diversity = 0; ath_hal_setdiversity(ah, AH_FALSE); } sc->sc_defant = ath_hal_getdefantenna(ah); /* * Not all chips have the VEOL support we want to * use with IBSS beacons; check here for it. */ sc->sc_hasveol = ath_hal_hasveol(ah); /* get mac address from hardware */ ath_hal_getmac(ah, ic->ic_myaddr); if (sc->sc_hasbmask) { ath_hal_getbssidmask(ah, sc->sc_bssidmask); ATH_SET_VAP_BSSID_MASK(sc->sc_bssidmask); ath_hal_setbssidmask(ah, sc->sc_bssidmask); } IEEE80211_ADDR_COPY(dev->dev_addr, ic->ic_myaddr); /* call MI attach routine. */ ieee80211_ifattach(ic); /* override default methods */ ic->ic_node_alloc = ath_node_alloc; sc->sc_node_free = ic->ic_node_free; ic->ic_node_free = ath_node_free; ic->ic_node_getrssi = ath_node_getrssi;#ifdef ATH_SUPERG_XR ic->ic_node_move_data = ath_node_move_data;#endif sc->sc_node_cleanup = ic->ic_node_cleanup; ic->ic_node_cleanup = ath_node_cleanup; sc->sc_recv_mgmt = ic->ic_recv_mgmt; ic->ic_recv_mgmt = ath_recv_mgmt; ic->ic_vap_create = ath_vap_create; ic->ic_vap_delete = ath_vap_delete;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -