#define ALLPRIO -1
/*
- * buffer length needed for wlc_format_ssid
* 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
*/
#define SSID_FMT_BUF_LEN ((4 * IEEE80211_MAX_SSID_LEN) + 1)
wlc_ucode_mac_upd(wlc);
}
-#if defined(BCMDBG)
-static int wlc_get_current_txpwr(struct wlc_info *wlc, void *pwr, uint len)
-{
- txpwr_limits_t txpwr;
- tx_power_t power;
- tx_power_legacy_t *old_power = NULL;
- int r, c;
- uint qdbm;
- bool override;
-
- if (len == sizeof(tx_power_legacy_t))
- old_power = (tx_power_legacy_t *) pwr;
- else if (len < sizeof(tx_power_t))
- return -EOVERFLOW;
-
- memset(&power, 0, sizeof(tx_power_t));
-
- power.chanspec = WLC_BAND_PI_RADIO_CHANSPEC;
- if (wlc->pub->associated)
- power.local_chanspec = wlc->home_chanspec;
-
- /* Return the user target tx power limits for the various rates. Note wlc_phy.c's
- * public interface only implements getting and setting a single value for all of
- * rates, so we need to fill the array ourselves.
- */
- wlc_phy_txpower_get(wlc->band->pi, &qdbm, &override);
- for (r = 0; r < WL_TX_POWER_RATES; r++) {
- power.user_limit[r] = (u8) qdbm;
- }
-
- power.local_max = wlc->txpwr_local_max * WLC_TXPWR_DB_FACTOR;
- power.local_constraint =
- wlc->txpwr_local_constraint * WLC_TXPWR_DB_FACTOR;
-
- power.antgain[0] = wlc->bandstate[BAND_2G_INDEX]->antgain;
- power.antgain[1] = wlc->bandstate[BAND_5G_INDEX]->antgain;
-
- wlc_channel_reg_limits(wlc->cmi, power.chanspec, &txpwr);
-
-#if WL_TX_POWER_CCK_NUM != WLC_NUM_RATES_CCK
-#error "WL_TX_POWER_CCK_NUM != WLC_NUM_RATES_CCK"
-#endif
-
- /* CCK tx power limits */
- for (c = 0, r = WL_TX_POWER_CCK_FIRST; c < WL_TX_POWER_CCK_NUM;
- c++, r++)
- power.reg_limit[r] = txpwr.cck[c];
-
-#if WL_TX_POWER_OFDM_NUM != WLC_NUM_RATES_OFDM
-#error "WL_TX_POWER_OFDM_NUM != WLC_NUM_RATES_OFDM"
-#endif
-
- /* 20 MHz OFDM SISO tx power limits */
- for (c = 0, r = WL_TX_POWER_OFDM_FIRST; c < WL_TX_POWER_OFDM_NUM;
- c++, r++)
- power.reg_limit[r] = txpwr.ofdm[c];
-
- if (WLC_PHY_11N_CAP(wlc->band)) {
-
- /* 20 MHz OFDM CDD tx power limits */
- for (c = 0, r = WL_TX_POWER_OFDM20_CDD_FIRST;
- c < WL_TX_POWER_OFDM_NUM; c++, r++)
- power.reg_limit[r] = txpwr.ofdm_cdd[c];
-
- /* 40 MHz OFDM SISO tx power limits */
- for (c = 0, r = WL_TX_POWER_OFDM40_SISO_FIRST;
- c < WL_TX_POWER_OFDM_NUM; c++, r++)
- power.reg_limit[r] = txpwr.ofdm_40_siso[c];
-
- /* 40 MHz OFDM CDD tx power limits */
- for (c = 0, r = WL_TX_POWER_OFDM40_CDD_FIRST;
- c < WL_TX_POWER_OFDM_NUM; c++, r++)
- power.reg_limit[r] = txpwr.ofdm_40_cdd[c];
-
-#if WL_TX_POWER_MCS_1_STREAM_NUM != WLC_NUM_RATES_MCS_1_STREAM
-#error "WL_TX_POWER_MCS_1_STREAM_NUM != WLC_NUM_RATES_MCS_1_STREAM"
-#endif
-
- /* 20MHz MCS0-7 SISO tx power limits */
- for (c = 0, r = WL_TX_POWER_MCS20_SISO_FIRST;
- c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
- power.reg_limit[r] = txpwr.mcs_20_siso[c];
-
- /* 20MHz MCS0-7 CDD tx power limits */
- for (c = 0, r = WL_TX_POWER_MCS20_CDD_FIRST;
- c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
- power.reg_limit[r] = txpwr.mcs_20_cdd[c];
-
- /* 20MHz MCS0-7 STBC tx power limits */
- for (c = 0, r = WL_TX_POWER_MCS20_STBC_FIRST;
- c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
- power.reg_limit[r] = txpwr.mcs_20_stbc[c];
-
- /* 40MHz MCS0-7 SISO tx power limits */
- for (c = 0, r = WL_TX_POWER_MCS40_SISO_FIRST;
- c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
- power.reg_limit[r] = txpwr.mcs_40_siso[c];
-
- /* 40MHz MCS0-7 CDD tx power limits */
- for (c = 0, r = WL_TX_POWER_MCS40_CDD_FIRST;
- c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
- power.reg_limit[r] = txpwr.mcs_40_cdd[c];
-
- /* 40MHz MCS0-7 STBC tx power limits */
- for (c = 0, r = WL_TX_POWER_MCS40_STBC_FIRST;
- c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
- power.reg_limit[r] = txpwr.mcs_40_stbc[c];
-
-#if WL_TX_POWER_MCS_2_STREAM_NUM != WLC_NUM_RATES_MCS_2_STREAM
-#error "WL_TX_POWER_MCS_2_STREAM_NUM != WLC_NUM_RATES_MCS_2_STREAM"
-#endif
-
- /* 20MHz MCS8-15 SDM tx power limits */
- for (c = 0, r = WL_TX_POWER_MCS20_SDM_FIRST;
- c < WLC_NUM_RATES_MCS_2_STREAM; c++, r++)
- power.reg_limit[r] = txpwr.mcs_20_mimo[c];
-
- /* 40MHz MCS8-15 SDM tx power limits */
- for (c = 0, r = WL_TX_POWER_MCS40_SDM_FIRST;
- c < WLC_NUM_RATES_MCS_2_STREAM; c++, r++)
- power.reg_limit[r] = txpwr.mcs_40_mimo[c];
-
- /* MCS 32 */
- power.reg_limit[WL_TX_POWER_MCS_32] = txpwr.mcs32;
- }
-
- wlc_phy_txpower_get_current(wlc->band->pi, &power,
- CHSPEC_CHANNEL(power.chanspec));
-
- /* copy the tx_power_t struct to the return buffer,
- * or convert to a tx_power_legacy_t struct
- */
- if (!old_power) {
- memcpy(pwr, &power, sizeof(tx_power_t));
- } else {
- int band_idx = CHSPEC_IS2G(power.chanspec) ? 0 : 1;
-
- memset(old_power, 0, sizeof(tx_power_legacy_t));
-
- old_power->txpwr_local_max = power.local_max;
- old_power->txpwr_local_constraint = power.local_constraint;
- if (CHSPEC_IS2G(power.chanspec)) {
- old_power->txpwr_chan_reg_max = txpwr.cck[0];
- old_power->txpwr_est_Pout[band_idx] =
- power.est_Pout_cck;
- old_power->txpwr_est_Pout_gofdm = power.est_Pout[0];
- } else {
- old_power->txpwr_chan_reg_max = txpwr.ofdm[0];
- old_power->txpwr_est_Pout[band_idx] = power.est_Pout[0];
- }
- old_power->txpwr_antgain[0] = power.antgain[0];
- old_power->txpwr_antgain[1] = power.antgain[1];
-
- for (r = 0; r < NUM_PWRCTRL_RATES; r++) {
- old_power->txpwr_band_max[r] = power.user_limit[r];
- old_power->txpwr_limit[r] = power.reg_limit[r];
- old_power->txpwr_target[band_idx][r] = power.target[r];
- if (CHSPEC_IS2G(power.chanspec))
- old_power->txpwr_bphy_cck_max[r] =
- power.board_limit[r];
- else
- old_power->txpwr_aphy_max[r] =
- power.board_limit[r];
- }
- }
-
- return 0;
-}
-#endif /* defined(BCMDBG) */
-
static u32 wlc_watchdog_backup_bi(struct wlc_info *wlc)
{
u32 bi;
return bi;
}
-/* Change to run the watchdog either from a periodic timer or from tbtt handler.
- * Call watchdog from tbtt handler if tbtt is true, watchdog timer otherwise.
- */
-void wlc_watchdog_upd(struct wlc_info *wlc, bool tbtt)
-{
- /* make sure changing watchdog driver is allowed */
- if (!wlc->pub->up || !wlc->pub->align_wd_tbtt)
- return;
- if (!tbtt && wlc->WDarmed) {
- wl_del_timer(wlc->wl, wlc->wdtimer);
- wlc->WDarmed = false;
- }
-
- /* stop watchdog timer and use tbtt interrupt to drive watchdog */
- if (tbtt && wlc->WDarmed) {
- wl_del_timer(wlc->wl, wlc->wdtimer);
- wlc->WDarmed = false;
- wlc->WDlast = OSL_SYSUPTIME();
- }
- /* arm watchdog timer and drive the watchdog there */
- else if (!tbtt && !wlc->WDarmed) {
- wl_add_timer(wlc->wl, wlc->wdtimer, TIMER_INTERVAL_WATCHDOG,
- true);
- wlc->WDarmed = true;
- }
- if (tbtt && !wlc->WDarmed) {
- wl_add_timer(wlc->wl, wlc->wdtimer, wlc_watchdog_backup_bi(wlc),
- true);
- wlc->WDarmed = true;
- }
-}
-
ratespec_t wlc_lowest_basic_rspec(struct wlc_info *wlc, wlc_rateset_t *rs)
{
ratespec_t lowest_basic_rspec;
bool bool_val;
int bcmerror;
d11regs_t *regs;
- uint i;
struct scb *nextscb;
bool ta_ok;
uint band;
bcmerror = 0;
regs = wlc->regs;
- /* A few commands don't need any arguments; all the others do. */
- switch (cmd) {
- case WLC_UP:
- case WLC_OUT:
- case WLC_DOWN:
- case WLC_DISASSOC:
- case WLC_RESTART:
- case WLC_REBOOT:
- case WLC_START_CHANNEL_QA:
- case WLC_INIT:
- break;
-
- default:
- if ((arg == NULL) || (len <= 0)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Command %d needs "
- "arguments\n",
- wlc->pub->unit, __func__, cmd);
- bcmerror = -EINVAL;
- goto done;
- }
+ if ((arg == NULL) || (len <= 0)) {
+ wiphy_err(wlc->wiphy, "wl%d: %s: Command %d needs arguments\n",
+ wlc->pub->unit, __func__, cmd);
+ bcmerror = -EINVAL;
+ goto done;
}
switch (cmd) {
-#if defined(BCMDBG)
- case WLC_GET_MSGLEVEL:
- *pval = wl_msg_level;
- break;
-
- case WLC_SET_MSGLEVEL:
- wl_msg_level = val;
- break;
-#endif
-
- case WLC_GET_INSTANCE:
- *pval = wlc->pub->unit;
- break;
-
- case WLC_GET_CHANNEL:{
- channel_info_t *ci = (channel_info_t *) arg;
-
- if (len <= (int)sizeof(ci)) {
- bcmerror = EOVERFLOW;
- goto done;
- }
-
- ci->hw_channel =
- CHSPEC_CHANNEL(WLC_BAND_PI_RADIO_CHANSPEC);
- ci->target_channel =
- CHSPEC_CHANNEL(wlc->default_bss->chanspec);
- ci->scan_channel = 0;
-
- break;
- }
-
case WLC_SET_CHANNEL:{
chanspec_t chspec = CH20MHZ_CHSPEC(val);
break;
}
-#if defined(BCMDBG)
- case WLC_GET_UCFLAGS:
- if (!wlc->pub->up) {
- bcmerror = -ENOLINK;
- break;
- }
-
- /* optional band is stored in the second integer of incoming buffer */
- band =
- (len <
- (int)(2 * sizeof(int))) ? WLC_BAND_AUTO : ((int *)arg)[1];
-
- /* bcmerror checking */
- bcmerror = wlc_iocregchk(wlc, band);
- if (bcmerror)
- break;
-
- if (val >= MHFMAX) {
- bcmerror = -EINVAL;
- break;
- }
-
- *pval = wlc_bmac_mhf_get(wlc->hw, (u8) val, WLC_BAND_AUTO);
- break;
-
- case WLC_SET_UCFLAGS:
- if (!wlc->pub->up) {
- bcmerror = -ENOLINK;
- break;
- }
-
- /* optional band is stored in the second integer of incoming buffer */
- band =
- (len <
- (int)(2 * sizeof(int))) ? WLC_BAND_AUTO : ((int *)arg)[1];
-
- /* bcmerror checking */
- bcmerror = wlc_iocregchk(wlc, band);
- if (bcmerror)
- break;
-
- i = (u16) val;
- if (i >= MHFMAX) {
- bcmerror = -EINVAL;
- break;
- }
-
- wlc_mhf(wlc, (u8) i, 0xffff, (u16) (val >> NBITS(u16)),
- WLC_BAND_AUTO);
- break;
-
- case WLC_GET_SHMEM:
- ta_ok = true;
-
- /* optional band is stored in the second integer of incoming buffer */
- band =
- (len <
- (int)(2 * sizeof(int))) ? WLC_BAND_AUTO : ((int *)arg)[1];
-
- /* bcmerror checking */
- bcmerror = wlc_iocregchk(wlc, band);
- if (bcmerror)
- break;
-
- if (val & 1) {
- bcmerror = -EINVAL;
- break;
- }
-
- *pval = wlc_read_shm(wlc, (u16) val);
- break;
-
- case WLC_SET_SHMEM:
- ta_ok = true;
-
- /* optional band is stored in the second integer of incoming buffer */
- band =
- (len <
- (int)(2 * sizeof(int))) ? WLC_BAND_AUTO : ((int *)arg)[1];
-
- /* bcmerror checking */
- bcmerror = wlc_iocregchk(wlc, band);
- if (bcmerror)
- break;
-
- if (val & 1) {
- bcmerror = -EINVAL;
- break;
- }
-
- wlc_write_shm(wlc, (u16) val,
- (u16) (val >> NBITS(u16)));
- break;
-
- case WLC_R_REG: /* MAC registers */
- ta_ok = true;
- r = (rw_reg_t *) arg;
- band = WLC_BAND_AUTO;
-
- if (len < (int)(sizeof(rw_reg_t) - sizeof(uint))) {
- bcmerror = -EOVERFLOW;
- break;
- }
-
- if (len >= (int)sizeof(rw_reg_t))
- band = r->band;
-
- /* bcmerror checking */
- bcmerror = wlc_iocregchk(wlc, band);
- if (bcmerror)
- break;
-
- if ((r->byteoff + r->size) > sizeof(d11regs_t)) {
- bcmerror = -EINVAL;
- break;
- }
- if (r->size == sizeof(u32))
- r->val =
- R_REG((u32 *)((unsigned char *)(unsigned long)regs +
- r->byteoff));
- else if (r->size == sizeof(u16))
- r->val =
- R_REG((u16 *)((unsigned char *)(unsigned long)regs +
- r->byteoff));
- else
- bcmerror = -EINVAL;
- break;
-
- case WLC_W_REG:
- ta_ok = true;
- r = (rw_reg_t *) arg;
- band = WLC_BAND_AUTO;
-
- if (len < (int)(sizeof(rw_reg_t) - sizeof(uint))) {
- bcmerror = -EOVERFLOW;
- break;
- }
-
- if (len >= (int)sizeof(rw_reg_t))
- band = r->band;
-
- /* bcmerror checking */
- bcmerror = wlc_iocregchk(wlc, band);
- if (bcmerror)
- break;
-
- if (r->byteoff + r->size > sizeof(d11regs_t)) {
- bcmerror = -EINVAL;
- break;
- }
- if (r->size == sizeof(u32))
- W_REG((u32 *)((unsigned char *)(unsigned long) regs +
- r->byteoff), r->val);
- else if (r->size == sizeof(u16))
- W_REG((u16 *)((unsigned char *)(unsigned long) regs +
- r->byteoff), r->val);
- else
- bcmerror = -EINVAL;
- break;
-#endif /* BCMDBG */
-
- case WLC_GET_TXANT:
- *pval = wlc->stf->txant;
- break;
-
- case WLC_SET_TXANT:
- bcmerror = wlc_stf_ant_txant_validate(wlc, (s8) val);
- if (bcmerror < 0)
- break;
-
- wlc->stf->txant = (s8) val;
-
- /* if down, we are done */
- if (!wlc->pub->up)
- break;
-
- wlc_suspend_mac_and_wait(wlc);
-
- wlc_stf_phy_txant_upd(wlc);
- wlc_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec);
-
- wlc_enable_mac(wlc);
-
- break;
-
- case WLC_GET_ANTDIV:{
- u8 phy_antdiv;
-
- /* return configured value if core is down */
- if (!wlc->pub->up) {
- *pval = wlc->stf->ant_rx_ovr;
-
- } else {
- if (wlc_phy_ant_rxdiv_get
- (wlc->band->pi, &phy_antdiv))
- *pval = (int)phy_antdiv;
- else
- *pval = (int)wlc->stf->ant_rx_ovr;
- }
-
- break;
- }
- case WLC_SET_ANTDIV:
- /* values are -1=driver default, 0=force0, 1=force1, 2=start1, 3=start0 */
- if ((val < -1) || (val > 3)) {
- bcmerror = -EINVAL;
- break;
- }
-
- if (val == -1)
- val = ANT_RX_DIV_DEF;
-
- wlc->stf->ant_rx_ovr = (u8) val;
- wlc_phy_ant_rxdiv_set(wlc->band->pi, (u8) val);
- break;
-
- case WLC_GET_RX_ANT:{ /* get latest used rx antenna */
- u16 rxstatus;
-
- if (!wlc->pub->up) {
- bcmerror = -ENOLINK;
- break;
- }
-
- rxstatus = R_REG(&wlc->regs->phyrxstatus0);
- if (rxstatus == 0xdead || rxstatus == (u16) -1) {
- bcmerror = -EBADE;
- break;
- }
- *pval = (rxstatus & PRXS0_RXANT_UPSUBBAND) ? 1 : 0;
- break;
- }
-
-#if defined(BCMDBG)
- case WLC_GET_UCANTDIV:
- if (!wlc->clk) {
- bcmerror = -EIO;
- break;
- }
-
- *pval =
- (wlc_bmac_mhf_get(wlc->hw, MHF1, WLC_BAND_AUTO) &
- MHF1_ANTDIV);
- break;
-
- case WLC_SET_UCANTDIV:{
- if (!wlc->pub->up) {
- bcmerror = -ENOLINK;
- break;
- }
-
- /* if multiband, band must be locked */
- if (IS_MBAND_UNLOCKED(wlc)) {
- bcmerror = -ENOMEDIUM;
- break;
- }
-
- wlc_mhf(wlc, MHF1, MHF1_ANTDIV,
- (val ? MHF1_ANTDIV : 0), WLC_BAND_AUTO);
- break;
- }
-#endif /* defined(BCMDBG) */
-
- case WLC_GET_SRL:
- *pval = wlc->SRL;
- break;
-
case WLC_SET_SRL:
if (val >= 1 && val <= RETRY_SHORT_MAX) {
int ac;
bcmerror = -EINVAL;
break;
- case WLC_GET_LRL:
- *pval = wlc->LRL;
- break;
-
case WLC_SET_LRL:
if (val >= 1 && val <= 255) {
int ac;
bcmerror = -EINVAL;
break;
- case WLC_GET_CWMIN:
- *pval = wlc->band->CWmin;
- break;
-
- case WLC_SET_CWMIN:
- if (!wlc->clk) {
- bcmerror = -EIO;
- break;
- }
-
- if (val >= 1 && val <= 255) {
- wlc_set_cwmin(wlc, (u16) val);
- } else
- bcmerror = -EINVAL;
- break;
-
- case WLC_GET_CWMAX:
- *pval = wlc->band->CWmax;
- break;
-
- case WLC_SET_CWMAX:
- if (!wlc->clk) {
- bcmerror = -EIO;
- break;
- }
-
- if (val >= 255 && val <= 2047) {
- wlc_set_cwmax(wlc, (u16) val);
- } else
- bcmerror = -EINVAL;
- break;
-
- case WLC_GET_RADIO: /* use mask if don't want to expose some internal bits */
- *pval = wlc->pub->radio_disabled;
- break;
-
- case WLC_SET_RADIO:{ /* 32 bits input, higher 16 bits are mask, lower 16 bits are value to
- * set
- */
- u16 radiomask, radioval;
- uint validbits =
- WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE;
- mbool new = 0;
-
- radiomask = (val & 0xffff0000) >> 16;
- radioval = val & 0x0000ffff;
-
- if ((radiomask == 0) || (radiomask & ~validbits)
- || (radioval & ~validbits)
- || ((radioval & ~radiomask) != 0)) {
- wiphy_err(wlc->wiphy, "SET_RADIO with wrong "
- "bits 0x%x\n", val);
- bcmerror = -EINVAL;
- break;
- }
-
- new =
- (wlc->pub->radio_disabled & ~radiomask) | radioval;
- wlc->pub->radio_disabled = new;
-
- wlc_radio_hwdisable_upd(wlc);
- wlc_radio_upd(wlc);
- break;
- }
-
- case WLC_GET_PHYTYPE:
- *pval = WLC_PHYTYPE(wlc->band->phytype);
- break;
-
-#if defined(BCMDBG)
- case WLC_GET_KEY:
- if ((val >= 0) && (val < WLC_MAX_WSEC_KEYS(wlc))) {
- wl_wsec_key_t key;
-
- wsec_key_t *src_key = wlc->wsec_keys[val];
-
- if (len < (int)sizeof(key)) {
- bcmerror = -EOVERFLOW;
- break;
- }
-
- memset((char *)&key, 0, sizeof(key));
- if (src_key) {
- key.index = src_key->id;
- key.len = src_key->len;
- memcpy(key.data, src_key->data, key.len);
- key.algo = src_key->algo;
- if (WSEC_SOFTKEY(wlc, src_key, bsscfg))
- key.flags |= WL_SOFT_KEY;
- if (src_key->flags & WSEC_PRIMARY_KEY)
- key.flags |= WL_PRIMARY_KEY;
-
- memcpy(key.ea, src_key->ea, ETH_ALEN);
- }
-
- memcpy(arg, &key, sizeof(key));
- } else
- bcmerror = -EINVAL;
- break;
-#endif /* defined(BCMDBG) */
-
- case WLC_SET_KEY:
- bcmerror =
- wlc_iovar_op(wlc, "wsec_key", NULL, 0, arg, len, IOV_SET,
- wlcif);
- break;
-
- case WLC_GET_KEY_SEQ:{
- wsec_key_t *key;
-
- if (len < DOT11_WPA_KEY_RSC_LEN) {
- bcmerror = -EOVERFLOW;
- break;
- }
-
- /* Return the key's tx iv as an EAPOL sequence counter.
- * This will be used to supply the RSC value to a supplicant.
- * The format is 8 bytes, with least significant in seq[0].
- */
-
- key = WSEC_KEY(wlc, val);
- if ((val >= 0) && (val < WLC_MAX_WSEC_KEYS(wlc)) &&
- (key != NULL)) {
- u8 seq[DOT11_WPA_KEY_RSC_LEN];
- u16 lo;
- u32 hi;
- /* group keys in WPA-NONE (IBSS only, AES and TKIP) use a global TXIV */
- if ((bsscfg->WPA_auth & WPA_AUTH_NONE) &&
- is_zero_ether_addr(key->ea)) {
- lo = bsscfg->wpa_none_txiv.lo;
- hi = bsscfg->wpa_none_txiv.hi;
- } else {
- lo = key->txiv.lo;
- hi = key->txiv.hi;
- }
-
- /* format the buffer, low to high */
- seq[0] = lo & 0xff;
- seq[1] = (lo >> 8) & 0xff;
- seq[2] = hi & 0xff;
- seq[3] = (hi >> 8) & 0xff;
- seq[4] = (hi >> 16) & 0xff;
- seq[5] = (hi >> 24) & 0xff;
- seq[6] = 0;
- seq[7] = 0;
-
- memcpy(arg, seq, sizeof(seq));
- } else {
- bcmerror = -EINVAL;
- }
- break;
- }
-
case WLC_GET_CURR_RATESET:{
wl_rateset_t *ret_rs = (wl_rateset_t *) arg;
wlc_rateset_t *rs;
break;
}
- case WLC_GET_RATESET:{
- wlc_rateset_t rs;
- wl_rateset_t *ret_rs = (wl_rateset_t *) arg;
-
- memset(&rs, 0, sizeof(wlc_rateset_t));
- wlc_default_rateset(wlc, (wlc_rateset_t *) &rs);
-
- if (len < (int)(rs.count + sizeof(rs.count))) {
- bcmerror = -EOVERFLOW;
- break;
- }
-
- /* Copy only legacy rateset section */
- ret_rs->count = rs.count;
- memcpy(&ret_rs->rates, &rs.rates, rs.count);
- break;
- }
-
case WLC_SET_RATESET:{
wlc_rateset_t rs;
wl_rateset_t *in_rs = (wl_rateset_t *) arg;
break;
}
- case WLC_GET_BCNPRD:
- if (BSSCFG_STA(bsscfg) && bsscfg->BSS && bsscfg->associated)
- *pval = current_bss->beacon_period;
- else
- *pval = wlc->default_bss->beacon_period;
- break;
-
case WLC_SET_BCNPRD:
/* range [1, 0xffff] */
if (val >= DOT11_MIN_BEACON_PERIOD
bcmerror = -EINVAL;
break;
- case WLC_GET_DTIMPRD:
- if (BSSCFG_STA(bsscfg) && bsscfg->BSS && bsscfg->associated)
- *pval = current_bss->dtim_period;
- else
- *pval = wlc->default_bss->dtim_period;
- break;
-
- case WLC_SET_DTIMPRD:
- /* range [1, 0xff] */
- if (val >= DOT11_MIN_DTIM_PERIOD
- && val <= DOT11_MAX_DTIM_PERIOD) {
- wlc->default_bss->dtim_period = (u8) val;
- } else
- bcmerror = -EINVAL;
- break;
-
-#ifdef SUPPORT_PS
- case WLC_GET_PM:
- *pval = wlc->PM;
- break;
-
- case WLC_SET_PM:
- if ((val >= PM_OFF) && (val <= PM_MAX)) {
- wlc->PM = (u8) val;
- if (wlc->pub->up) {
- }
- /* Change watchdog driver to align watchdog with tbtt if possible */
- wlc_watchdog_upd(wlc, PS_ALLOWED(wlc));
- } else
- bcmerror = -EBADE;
- break;
-#endif /* SUPPORT_PS */
-
-#ifdef SUPPORT_PS
-#ifdef BCMDBG
- case WLC_GET_WAKE:
- if (AP_ENAB(wlc->pub)) {
- bcmerror = -BCME_NOTSTA;
- break;
- }
- *pval = wlc->wake;
- break;
-
- case WLC_SET_WAKE:
- if (AP_ENAB(wlc->pub)) {
- bcmerror = -BCME_NOTSTA;
- break;
- }
-
- wlc->wake = val ? true : false;
-
- /* if down, we're done */
- if (!wlc->pub->up)
- break;
-
- /* apply to the mac */
- wlc_set_ps_ctrl(wlc);
- break;
-#endif /* BCMDBG */
-#endif /* SUPPORT_PS */
-
- case WLC_GET_REVINFO:
- bcmerror = wlc_get_revision_info(wlc, arg, (uint) len);
- break;
-
- case WLC_GET_AP:
- *pval = (int)AP_ENAB(wlc->pub);
- break;
-
- case WLC_GET_ATIM:
- if (bsscfg->associated)
- *pval = (int)current_bss->atim_window;
- else
- *pval = (int)wlc->default_bss->atim_window;
- break;
-
- case WLC_SET_ATIM:
- wlc->default_bss->atim_window = (u32) val;
- break;
-
-#ifdef SUPPORT_HWKEY
- case WLC_GET_WSEC:
- bcmerror =
- wlc_iovar_op(wlc, "wsec", NULL, 0, arg, len, IOV_GET,
- wlcif);
- break;
-
- case WLC_SET_WSEC:
- bcmerror =
- wlc_iovar_op(wlc, "wsec", NULL, 0, arg, len, IOV_SET,
- wlcif);
- break;
-
- case WLC_GET_WPA_AUTH:
- *pval = (int)bsscfg->WPA_auth;
- break;
-
- case WLC_SET_WPA_AUTH:
- /* change of WPA_Auth modifies the PS_ALLOWED state */
- if (BSSCFG_STA(bsscfg)) {
- bsscfg->WPA_auth = (u16) val;
- } else
- bsscfg->WPA_auth = (u16) val;
- break;
-#endif /* SUPPORT_HWKEY */
-
- case WLC_GET_BANDLIST:
- /* count of number of bands, followed by each band type */
- *pval++ = NBANDS(wlc);
- *pval++ = wlc->band->bandtype;
- if (NBANDS(wlc) > 1)
- *pval++ = wlc->bandstate[OTHERBANDUNIT(wlc)]->bandtype;
- break;
-
- case WLC_GET_BAND:
- *pval = wlc->bandlocked ? wlc->band->bandtype : WLC_BAND_AUTO;
- break;
-
case WLC_GET_PHYLIST:
{
unsigned char *cp = arg;
break;
}
- case WLC_GET_SHORTSLOT:
- *pval = wlc->shortslot;
- break;
-
- case WLC_GET_SHORTSLOT_OVERRIDE:
- *pval = wlc->shortslot_override;
- break;
-
case WLC_SET_SHORTSLOT_OVERRIDE:
if ((val != WLC_SHORTSLOT_AUTO) &&
(val != WLC_SHORTSLOT_OFF) && (val != WLC_SHORTSLOT_ON)) {
break;
- case WLC_GET_LEGACY_ERP:
- *pval = wlc->include_legacy_erp;
- break;
-
- case WLC_SET_LEGACY_ERP:
- if (wlc->include_legacy_erp == bool_val)
- break;
-
- wlc->include_legacy_erp = bool_val;
-
- if (AP_ENAB(wlc->pub) && wlc->clk) {
- wlc_update_beacon(wlc);
- wlc_update_probe_resp(wlc, true);
- }
- break;
-
- case WLC_GET_GMODE:
- if (wlc->band->bandtype == WLC_BAND_2G)
- *pval = wlc->band->gmode;
- else if (NBANDS(wlc) > 1)
- *pval = wlc->bandstate[OTHERBANDUNIT(wlc)]->gmode;
- break;
-
- case WLC_SET_GMODE:
- if (!wlc->pub->associated)
- bcmerror = wlc_set_gmode(wlc, (u8) val, true);
- else {
- bcmerror = -EISCONN;
- break;
- }
- break;
-
- case WLC_GET_GMODE_PROTECTION:
- *pval = wlc->protection->_g;
- break;
-
- case WLC_GET_PROTECTION_CONTROL:
- *pval = wlc->protection->overlap;
- break;
-
- case WLC_SET_PROTECTION_CONTROL:
- if ((val != WLC_PROTECTION_CTL_OFF) &&
- (val != WLC_PROTECTION_CTL_LOCAL) &&
- (val != WLC_PROTECTION_CTL_OVERLAP)) {
- bcmerror = -EINVAL;
- break;
- }
-
- wlc_protection_upd(wlc, WLC_PROT_OVERLAP, (s8) val);
-
- /* Current g_protection will sync up to the specified control alg in watchdog
- * if the driver is up and associated.
- * If the driver is down or not associated, the control setting has no effect.
- */
- break;
-
- case WLC_GET_GMODE_PROTECTION_OVERRIDE:
- *pval = wlc->protection->g_override;
- break;
-
- case WLC_SET_GMODE_PROTECTION_OVERRIDE:
- if ((val != WLC_PROTECTION_AUTO) &&
- (val != WLC_PROTECTION_OFF) && (val != WLC_PROTECTION_ON)) {
- bcmerror = -EINVAL;
- break;
- }
-
- wlc_protection_upd(wlc, WLC_PROT_G_OVR, (s8) val);
-
- break;
-
- case WLC_SET_SUP_RATESET_OVERRIDE:{
- wlc_rateset_t rs, new;
-
- /* copyin */
- if (len < (int)sizeof(wlc_rateset_t)) {
- bcmerror = -EOVERFLOW;
- break;
- }
- memcpy(&rs, arg, sizeof(wlc_rateset_t));
-
- /* check for bad count value */
- if (rs.count > WLC_NUMRATES) {
- bcmerror = -EINVAL;
- break;
- }
-
- /* this command is only appropriate for gmode operation */
- if (!(wlc->band->gmode ||
- ((NBANDS(wlc) > 1)
- && wlc->bandstate[OTHERBANDUNIT(wlc)]->gmode))) {
- /* gmode only command when not in gmode */
- bcmerror = -EINVAL;
- break;
- }
-
- /* check for an empty rateset to clear the override */
- if (rs.count == 0) {
- memset(&wlc->sup_rates_override, 0,
- sizeof(wlc_rateset_t));
- break;
- }
-
- /*
- * validate rateset by comparing pre and
- * post sorted against 11g hw rates
- */
- wlc_rateset_filter(&rs, &new, false,
- WLC_RATES_CCK_OFDM, WLC_RATE_MASK,
- BSS_N_ENAB(wlc, bsscfg));
- wlc_rate_hwrs_filter_sort_validate(&new,
- &cck_ofdm_rates,
- false,
- wlc->stf->txstreams);
- if (rs.count != new.count) {
- bcmerror = -EINVAL;
- break;
- }
-
- /* apply new rateset to the override */
- memcpy(&wlc->sup_rates_override, &new,
- sizeof(wlc_rateset_t));
-
- /* update bcn and probe resp if needed */
- if (wlc->pub->up && AP_ENAB(wlc->pub)
- && wlc->pub->associated) {
- wlc_update_beacon(wlc);
- wlc_update_probe_resp(wlc, true);
- }
- break;
- }
-
- case WLC_GET_SUP_RATESET_OVERRIDE:
- /* this command is only appropriate for gmode operation */
- if (!(wlc->band->gmode ||
- ((NBANDS(wlc) > 1)
- && wlc->bandstate[OTHERBANDUNIT(wlc)]->gmode))) {
- /* gmode only command when not in gmode */
- bcmerror = -EINVAL;
- break;
- }
- if (len < (int)sizeof(wlc_rateset_t)) {
- bcmerror = -EOVERFLOW;
- break;
- }
- memcpy(arg, &wlc->sup_rates_override, sizeof(wlc_rateset_t));
-
- break;
-
- case WLC_GET_PRB_RESP_TIMEOUT:
- *pval = wlc->prb_resp_timeout;
- break;
-
- case WLC_SET_PRB_RESP_TIMEOUT:
- if (wlc->pub->up) {
- bcmerror = -EISCONN;
- break;
- }
- if (val < 0 || val >= 0xFFFF) {
- bcmerror = -EINVAL; /* bad value */
- break;
- }
- wlc->prb_resp_timeout = (u16) val;
- break;
-
- case WLC_GET_KEY_PRIMARY:{
- wsec_key_t *key;
-
- /* treat the 'val' parm as the key id */
- key = WSEC_BSS_DEFAULT_KEY(bsscfg);
- if (key != NULL) {
- *pval = key->id == val ? true : false;
- } else {
- bcmerror = -EINVAL;
- }
- break;
- }
-
- case WLC_SET_KEY_PRIMARY:{
- wsec_key_t *key, *old_key;
-
- bcmerror = -EINVAL;
-
- /* treat the 'val' parm as the key id */
- for (i = 0; i < WSEC_MAX_DEFAULT_KEYS; i++) {
- key = bsscfg->bss_def_keys[i];
- if (key != NULL && key->id == val) {
- old_key = WSEC_BSS_DEFAULT_KEY(bsscfg);
- if (old_key != NULL)
- old_key->flags &=
- ~WSEC_PRIMARY_KEY;
- key->flags |= WSEC_PRIMARY_KEY;
- bsscfg->wsec_index = i;
- bcmerror = 0;
- }
- }
- break;
- }
-
-#ifdef BCMDBG
- case WLC_INIT:
- wl_init(wlc->wl);
- break;
-#endif
-
- case WLC_SET_VAR:
- case WLC_GET_VAR:{
- char *name;
- /* validate the name value */
- name = (char *)arg;
- for (i = 0; i < (uint) len && *name != '\0';
- i++, name++)
- ;
-
- if (i == (uint) len) {
- bcmerror = -EOVERFLOW;
- break;
- }
- i++; /* include the null in the string length */
-
- if (cmd == WLC_GET_VAR) {
- bcmerror =
- wlc_iovar_op(wlc, arg,
- (void *)((s8 *) arg + i),
- len - i, arg, len, IOV_GET,
- wlcif);
- } else
- bcmerror =
- wlc_iovar_op(wlc, arg, NULL, 0,
- (void *)((s8 *) arg + i),
- len - i, IOV_SET, wlcif);
-
- break;
- }
-
- case WLC_SET_WSEC_PMK:
- bcmerror = -ENOTSUPP;
- break;
-
-#if defined(BCMDBG)
- case WLC_CURRENT_PWR:
- if (!wlc->pub->up)
- bcmerror = -ENOLINK;
- else
- bcmerror = wlc_get_current_txpwr(wlc, arg, len);
- break;
-#endif
-
- case WLC_LAST:
- wiphy_err(wlc->wiphy, "%s: WLC_LAST\n", __func__);
}
done:
return bcmerror;
}
-#if defined(BCMDBG)
-/* consolidated register access ioctl error checking */
-int wlc_iocregchk(struct wlc_info *wlc, uint band)
-{
- /* if band is specified, it must be the current band */
- if ((band != WLC_BAND_AUTO) && (band != (uint) wlc->band->bandtype))
- return -EINVAL;
-
- /* if multiband and band is not specified, band must be locked */
- if ((band == WLC_BAND_AUTO) && IS_MBAND_UNLOCKED(wlc))
- return -ENOMEDIUM;
-
- /* must have core clocks */
- if (!wlc->clk)
- return -EIO;
-
- return 0;
-}
-#endif /* defined(BCMDBG) */
-
/* Look up the given var name in the given table */
static const bcm_iovar_t *wlc_iovar_lookup(const bcm_iovar_t *table,
const char *name)
return NULL; /* var name not found */
}
-/* simplified integer get interface for common WLC_GET_VAR ioctl handler */
int wlc_iovar_getint(struct wlc_info *wlc, const char *name, int *arg)
{
return wlc_iovar_op(wlc, name, NULL, 0, arg, sizeof(s32), IOV_GET,
NULL);
}
-/* simplified integer set interface for common WLC_SET_VAR ioctl handler */
int wlc_iovar_setint(struct wlc_info *wlc, const char *name, int arg)
{
return wlc_iovar_op(wlc, name, NULL, 0, (void *)&arg, sizeof(arg),
}
#endif /* defined(BCMDBG) */
-#if defined(BCMDBG)
-int wlc_format_ssid(char *buf, const unsigned char ssid[], uint ssid_len)
-{
- uint i, c;
- char *p = buf;
- char *endp = buf + SSID_FMT_BUF_LEN;
-
- if (ssid_len > IEEE80211_MAX_SSID_LEN)
- ssid_len = IEEE80211_MAX_SSID_LEN;
-
- for (i = 0; i < ssid_len; i++) {
- c = (uint) ssid[i];
- if (c == '\\') {
- *p++ = '\\';
- *p++ = '\\';
- } else if (isprint((unsigned char) c)) {
- *p++ = (char)c;
- } else {
- p += snprintf(p, (endp - p), "\\x%02X", c);
- }
- }
- *p = '\0';
- return (int)(p - buf);
-}
-#endif /* defined(BCMDBG) */
-
static u16 wlc_rate_shm_offset(struct wlc_info *wlc, u8 rate)
{
return wlc_bmac_rate_shm_offset(wlc->hw, rate);
memset((char *)bsscfg->txrspec, 0, sizeof(bsscfg->txrspec));
}
-/* Retrieve a consolidated set of revision information,
- * typically for the WLC_GET_REVINFO ioctl
- */
-int wlc_get_revision_info(struct wlc_info *wlc, void *buf, uint len)
-{
- wlc_rev_info_t *rinfo = (wlc_rev_info_t *) buf;
-
- if (len < WL_REV_INFO_LEGACY_LENGTH)
- return -EOVERFLOW;
-
- rinfo->vendorid = wlc->vendorid;
- rinfo->deviceid = wlc->deviceid;
- rinfo->radiorev = (wlc->band->radiorev << IDCODE_REV_SHIFT) |
- (wlc->band->radioid << IDCODE_ID_SHIFT);
- rinfo->chiprev = wlc->pub->sih->chiprev;
- rinfo->corerev = wlc->pub->corerev;
- rinfo->boardid = wlc->pub->sih->boardtype;
- rinfo->boardvendor = wlc->pub->sih->boardvendor;
- rinfo->boardrev = wlc->pub->boardrev;
- rinfo->ucoderev = wlc->ucode_rev;
- rinfo->driverrev = EPI_VERSION_NUM;
- rinfo->bus = wlc->pub->sih->bustype;
- rinfo->chipnum = wlc->pub->sih->chip;
-
- if (len >= (offsetof(wlc_rev_info_t, chippkg))) {
- rinfo->phytype = wlc->band->phytype;
- rinfo->phyrev = wlc->band->phyrev;
- rinfo->anarev = 0; /* obsolete stuff, suppress */
- }
-
- if (len >= sizeof(*rinfo)) {
- rinfo->chippkg = wlc->pub->sih->chippkg;
- }
-
- return 0;
-}
-
void wlc_default_rateset(struct wlc_info *wlc, wlc_rateset_t *rs)
{
wlc_rateset_default(rs, NULL, wlc->band->phytype, wlc->band->bandtype,
memcpy(wlc->cfg->BSSID, addr, ETH_ALEN);
}
-void wlc_set_cwmin(struct wlc_info *wlc, u16 newmin)
-{
- wlc->band->CWmin = newmin;
- wlc_bmac_set_cwmin(wlc->hw, newmin);
-}
-
-void wlc_set_cwmax(struct wlc_info *wlc, u16 newmax)
-{
- wlc->band->CWmax = newmax;
- wlc_bmac_set_cwmax(wlc->hw, newmax);
-}
-
-/* Search mem rw utilities */
-
void wlc_pllreq(struct wlc_info *wlc, bool set, mbool req_bit)
{
wlc_bmac_pllreq(wlc->hw, set, req_bit);