/* * Set country code */ int ieee80211_set_country_code(struct ieee80211com *ic, char *isoName, u_int16_t cc, enum ieee80211_clist_cmd cmd) { int error; if (!cc) { if (isoName == NULL) { if (!IEEE80211_IS_11D_ENABLED(ic)) return 0; } else if((ic->ic_country_iso[0] == isoName[0]) && (ic->ic_country_iso[1] == isoName[1]) && (ic->ic_country_iso[2] == isoName[2])) { return 0; } } IEEE80211_DISABLE_11D(ic); error = ic->ic_set_country(ic, isoName, cc, cmd); if (error) return error; /* update the country information for 11D */ ic->ic_get_currentCountry(ic, &ic->ic_country); /* update channel list */ ieee80211_update_channellist(ic, 1); ic->ic_country_iso[0] = ic->ic_country.iso[0]; ic->ic_country_iso[1] = ic->ic_country.iso[1]; ic->ic_country_iso[2] = ic->ic_country.iso[2]; ieee80211_build_countryie_all(ic); if (IEEE80211_IS_COUNTRYIE_ENABLED(ic)) { IEEE80211_ENABLE_11D(ic); } /* notify all vaps that the country changed */ wlan_iterate_vap_list(ic, wlan_notify_country_changed, (void *)ic->ic_country.iso); return 0; }
int ieee80211_ifattach(struct ieee80211com *ic, IEEE80211_REG_PARAMETERS *ieee80211_reg_parm) { u_int8_t bcast[IEEE80211_ADDR_LEN] = {0xff,0xff,0xff,0xff,0xff,0xff}; int error = 0; ic->ic_reg_parm = *ieee80211_reg_parm; /* set up broadcast address */ IEEE80211_ADDR_COPY(ic->ic_broadcast, bcast); /* initialize channel list */ ieee80211_update_channellist(ic, 0); /* initialize rate set */ ieee80211_init_rateset(ic); /* validate ic->ic_curmode */ if (!IEEE80211_SUPPORT_PHY_MODE(ic, ic->ic_curmode)) ic->ic_curmode = IEEE80211_MODE_AUTO; /* setup initial channel settings */ ic->ic_curchan = ieee80211_get_channel(ic, 0); /* arbitrarily pick the first channel */ /* Enable marking of dfs by default */ ic->ic_flags_ext |= IEEE80211_FEXT_MARKDFS; if (ic->ic_reg_parm.htEnableWepTkip) { ieee80211_ic_wep_tkip_htrate_set(ic); } else { ieee80211_ic_wep_tkip_htrate_clear(ic); } if (ic->ic_reg_parm.htVendorIeEnable) IEEE80211_ENABLE_HTVIE(ic); /* whether to ignore 11d beacon */ if (ic->ic_reg_parm.ignore11dBeacon) IEEE80211_ENABLE_IGNORE_11D_BEACON(ic); if (ic->ic_reg_parm.disallowAutoCCchange) { ieee80211_ic_disallowAutoCCchange_set(ic); } else { ieee80211_ic_disallowAutoCCchange_clear(ic); } (void) ieee80211_setmode(ic, ic->ic_curmode, ic->ic_opmode); ic->ic_intval = IEEE80211_BINTVAL_DEFAULT; /* beacon interval */ ic->ic_set_beacon_interval(ic); ic->ic_lintval = 1; /* listen interval */ ic->ic_lintval_assoc = IEEE80211_LINTVAL_MAX; /* listen interval to use in association */ ic->ic_bmisstimeout = IEEE80211_BMISS_LIMIT * ic->ic_intval; TAILQ_INIT(&ic->ic_vaps); ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX; /* Intialize WDS Auto Detect mode */ ic->ic_flags_ext |= IEEE80211_FEXT_WDS_AUTODETECT; /* ** Enable the 11d country code IE by default */ ic->ic_flags_ext |= IEEE80211_FEXT_COUNTRYIE; /* setup CWM configuration */ ic->ic_cwm_set_mode(ic, ic->ic_reg_parm.cwmMode); ic->ic_cwm_set_extoffset(ic, ic->ic_reg_parm.cwmExtOffset); ic->ic_cwm_set_extprotmode(ic, ic->ic_reg_parm.cwmExtProtMode); ic->ic_cwm_set_extprotspacing(ic, ic->ic_reg_parm.cwmExtProtSpacing); #if tbd /* XXX - TODO - move these into ath layer */ #else ic->ic_cwm_set_enable(ic, ic->ic_reg_parm.cwmEnable); ic->ic_cwm_set_extbusythreshold(ic, ic->ic_reg_parm.cwmExtBusyThreshold); #endif ic->ic_enable2GHzHt40Cap = ic->ic_reg_parm.enable2GHzHt40Cap; #ifdef ATH_COALESCING ic->ic_tx_coalescing = ic->ic_reg_parm.txCoalescingEnable; #endif ic->ic_ignoreDynamicHalt = ic->ic_reg_parm.ignoreDynamicHalt; /* default to auto ADDBA mode */ ic->ic_addba_mode = ADDBA_MODE_AUTO; if (ic->ic_reg_parm.ht20AdhocEnable) { /* * Support HT rates in Ad hoc connections. */ if (IEEE80211_SUPPORT_PHY_MODE(ic, IEEE80211_MODE_11NA_HT20) || IEEE80211_SUPPORT_PHY_MODE(ic, IEEE80211_MODE_11NG_HT20)) { ieee80211_ic_ht20Adhoc_set(ic); if (ic->ic_reg_parm.htAdhocAggrEnable) { ieee80211_ic_htAdhocAggr_set(ic); } } } if (ic->ic_reg_parm.ht40AdhocEnable) { /* * Support HT rates in Ad hoc connections. */ if (IEEE80211_SUPPORT_PHY_MODE(ic, IEEE80211_MODE_11NA_HT40PLUS) || IEEE80211_SUPPORT_PHY_MODE(ic, IEEE80211_MODE_11NA_HT40MINUS) || IEEE80211_SUPPORT_PHY_MODE(ic, IEEE80211_MODE_11NG_HT40PLUS) || IEEE80211_SUPPORT_PHY_MODE(ic, IEEE80211_MODE_11NG_HT40MINUS)) { ieee80211_ic_ht40Adhoc_set(ic); if (ic->ic_reg_parm.htAdhocAggrEnable) { ieee80211_ic_htAdhocAggr_set(ic); } } } OS_INIT_TIMER(ic->ic_osdev, &(ic->ic_inact_timer), ieee80211_inact_timeout, (void *) (ic)); #if UMAC_SUPPORT_WNM OS_INIT_TIMER(ic->ic_osdev, &(ic->ic_bssload_timer), ieee80211_bssload_timeout, (void *) (ic)); #endif if (ic->ic_reg_parm.disable2040Coexist) { ic->ic_flags |= IEEE80211_F_COEXT_DISABLE; } else { ic->ic_flags &= ~IEEE80211_F_COEXT_DISABLE; } /* setup other modules */ /* The TSF Timer module is required when P2P or Off-channel support are required */ ic->ic_tsf_timer = ieee80211_tsf_timer_attach(ic); #if UMAC_SUPPORT_TDLS_CHAN_SWITCH /* TDLS off-channel support requires TSF timer */ if (ic->ic_tsf_timer) { ieee80211_ic_off_channel_support_set(ic); } else { ieee80211_ic_off_channel_support_clear(ic); } #else ieee80211_ic_off_channel_support_clear(ic); #endif ieee80211_p2p_attach(ic); ieee80211_crypto_attach(ic); ieee80211_node_attach(ic); ieee80211_proto_attach(ic); ieee80211_power_attach(ic); ieee80211_mlme_attach(ic); #if ATH_SUPPORT_DFS ieee80211_dfs_attach(ic); #endif /* ATH_SUPPORT_DFS */ if (IEEE80211_ENAB_AOW(ic)) ieee80211_aow_attach(ic); error = ieee80211_scan_table_attach(ic, &(ic->ic_scan_table), ic->ic_osdev); if (error) { ieee80211_node_detach(ic); return error; } /* * By default overwrite probe response with beacon IE in scan entry. */ ieee80211_ic_override_proberesp_ie_set(ic); error = ieee80211_scan_attach(&(ic->ic_scanner), ic, ic->ic_osdev, ieee80211_is_connected, ieee80211_is_txq_empty, ieee80211_is_sw_txq_empty); if (error) { /* detach and free already allocated memory for scan */ ieee80211_scan_table_detach(&(ic->ic_scan_table)); ieee80211_node_detach(ic); return error; } ic->ic_resmgr = ieee80211_resmgr_create(ic, IEEE80211_RESMGR_MODE_SINGLE_CHANNEL); error = ieee80211_acs_attach(&(ic->ic_acs), ic, ic->ic_osdev); if (error) { /* detach and free already allocated memory for scan */ ieee80211_scan_table_detach(&(ic->ic_scan_table)); ieee80211_scan_detach(&(ic->ic_scanner)); ieee80211_node_detach(ic); return error; } ic->ic_notify_tx_bcn_mgr = ieee80211_notify_tx_bcn_attach(ic); ieee80211_rptplacement_attach(ic); IEEE80211_TDLS_ATTACH(ic); #if UMAC_SUPPORT_VI_DBG ieee80211_vi_dbg_attach(ic); #endif ieee80211_quiet_attach(ic); ieee80211_admctl_attach(ic); /* * Perform steps that require multiple objects to be initialized. * For example, cross references between objects such as ResMgr and Scanner. */ ieee80211_scan_attach_complete(ic->ic_scanner); ieee80211_resmgr_create_complete(ic->ic_resmgr); ieee80211_smartantenna_attach(ic); ieee80211_prdperfstats_attach(ic); ic->ic_get_ext_chan_info = ieee80211_get_extchan_info; /* initialization complete */ ic->ic_initialized = 1; return 0; }