diff options
-rw-r--r-- | sys/dev/ic/if_wi.c | 109 | ||||
-rw-r--r-- | sys/dev/ic/if_wireg.h | 10 | ||||
-rw-r--r-- | sys/dev/ic/if_wivar.h | 4 | ||||
-rw-r--r-- | sys/net80211/ieee80211_ioctl.c | 26 | ||||
-rw-r--r-- | sys/net80211/ieee80211_ioctl.h | 16 | ||||
-rw-r--r-- | sys/net80211/ieee80211_var.h | 6 |
6 files changed, 161 insertions, 10 deletions
diff --git a/sys/dev/ic/if_wi.c b/sys/dev/ic/if_wi.c index add84ce8de6..95851e093c4 100644 --- a/sys/dev/ic/if_wi.c +++ b/sys/dev/ic/if_wi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_wi.c,v 1.115 2005/01/15 05:24:11 brad Exp $ */ +/* $OpenBSD: if_wi.c,v 1.116 2005/02/15 19:44:15 reyk Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -127,7 +127,7 @@ u_int32_t widebug = WIDEBUG; #if !defined(lint) && !defined(__OpenBSD__) static const char rcsid[] = - "$OpenBSD: if_wi.c,v 1.115 2005/01/15 05:24:11 brad Exp $"; + "$OpenBSD: if_wi.c,v 1.116 2005/02/15 19:44:15 reyk Exp $"; #endif /* lint */ #ifdef foo @@ -167,6 +167,8 @@ STATIC int wi_get_nwkey(struct wi_softc *, struct ieee80211_nwkey *); STATIC int wi_sync_media(struct wi_softc *, int, int); STATIC int wi_set_pm(struct wi_softc *, struct ieee80211_power *); STATIC int wi_get_pm(struct wi_softc *, struct ieee80211_power *); +STATIC int wi_set_txpower(struct wi_softc *, struct ieee80211_txpower *); +STATIC int wi_get_txpower(struct wi_softc *, struct ieee80211_txpower *); STATIC int wi_get_debug(struct wi_softc *, struct wi_req *); STATIC int wi_set_debug(struct wi_softc *, struct wi_req *); @@ -1595,6 +1597,7 @@ wi_ioctl(ifp, command, data) case SIOCS80211NWID: case SIOCS80211NWKEY: case SIOCS80211POWER: + case SIOCS80211TXPOWER: error = suser(p, 0); if (error) { splx(s); @@ -1856,6 +1859,12 @@ wi_ioctl(ifp, command, data) case SIOCG80211POWER: error = wi_get_pm(sc, (struct ieee80211_power *)data); break; + case SIOCS80211TXPOWER: + error = wi_set_txpower(sc, (struct ieee80211_txpower *)data); + break; + case SIOCG80211TXPOWER: + error = wi_get_txpower(sc, (struct ieee80211_txpower *)data); + break; case SIOCHOSTAP_ADD: case SIOCHOSTAP_DEL: case SIOCHOSTAP_GET: @@ -2008,6 +2017,10 @@ wi_init_io(sc) WI_PRT_ARG(sc)); sc->wi_tx_mgmt_id = id; + /* Set txpower */ + if (sc->wi_flags & WI_FLAGS_TXPOWER) + wi_set_txpower(sc, NULL); + /* enable interrupts */ wi_intr_enable(sc, WI_INTRS); @@ -2878,6 +2891,98 @@ wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power) } STATIC int +wi_set_txpower(struct wi_softc *sc, struct ieee80211_txpower *txpower) +{ + u_int16_t cmd; + u_int16_t power; + int8_t tmp; + int error; + int alc; + + if (txpower == NULL) { + if (!(sc->wi_flags & WI_FLAGS_TXPOWER)) + return (EINVAL); + alc = 0; /* disable ALC */ + } else { + if (txpower->i_mode == IEEE80211_TXPOWER_MODE_AUTO) { + alc = 1; /* enable ALC */ + sc->wi_flags &= ~WI_FLAGS_TXPOWER; + } else { + alc = 0; /* disable ALC */ + sc->wi_flags |= WI_FLAGS_TXPOWER; + sc->wi_txpower = txpower->i_val; + } + } + + /* Set ALC */ + cmd = WI_CMD_DEBUG | (WI_DEBUG_CONFBITS << 8); + if ((error = wi_cmd(sc, cmd, alc, 0x8, 0)) != 0) + return (error); + + /* No need to set the TX power value if ALC is enabled */ + if (alc) + return (0); + + /* Convert dBM to internal TX power value */ + if (sc->wi_txpower > 20) + power = 128; + else if (sc->wi_txpower < -43) + power = 127; + else { + tmp = sc->wi_txpower; + tmp = -12 - tmp; + tmp <<= 2; + + power = (u_int16_t)tmp; + } + + /* Set manual TX power */ + cmd = WI_CMD_WRITE_MIF; + if ((error = wi_cmd(sc, cmd, + WI_HFA384X_CR_MANUAL_TX_POWER, power, 0)) != 0) + return (error); + + if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG) + printf("%s: %u (%d dBm)\n", sc->sc_dev.dv_xname, power, + sc->wi_txpower); + + return (0); +} + +STATIC int +wi_get_txpower(struct wi_softc *sc, struct ieee80211_txpower *txpower) +{ + u_int16_t cmd; + u_int16_t power; + int8_t tmp; + int error; + + /* Get manual TX power */ + cmd = WI_CMD_READ_MIF; + if ((error = wi_cmd(sc, cmd, + WI_HFA384X_CR_MANUAL_TX_POWER, 0, 0)) != 0) + return (error); + + power = CSR_READ_2(sc, WI_RESP0); + + /* Convert internal TX power value to dBM */ + if (power > 255) + txpower->i_val = 255; + else { + tmp = power; + tmp >>= 2; + txpower->i_val = (u_int16_t)(-12 - tmp); + } + + if (sc->wi_flags & WI_FLAGS_TXPOWER) + txpower->i_mode = IEEE80211_TXPOWER_MODE_FIXED; + else + txpower->i_mode = IEEE80211_TXPOWER_MODE_AUTO; + + return (0); +} + +STATIC int wi_set_ssid(ws, id, len) struct ieee80211_nwid *ws; u_int8_t *id; diff --git a/sys/dev/ic/if_wireg.h b/sys/dev/ic/if_wireg.h index c295d3a0150..602dbbc6b27 100644 --- a/sys/dev/ic/if_wireg.h +++ b/sys/dev/ic/if_wireg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_wireg.h,v 1.34 2004/03/02 21:59:29 millert Exp $ */ +/* $OpenBSD: if_wireg.h,v 1.35 2005/02/15 19:44:15 reyk Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -194,6 +194,8 @@ #define WI_CMD_INQUIRE 0x0011 #define WI_CMD_ACCESS 0x0021 #define WI_CMD_PROGRAM 0x0022 +#define WI_CMD_READ_MIF 0x0030 /* prism2 */ +#define WI_CMD_WRITE_MIF 0x0031 /* prism2 */ #define WI_CMD_CODE_MASK 0x003F @@ -604,3 +606,9 @@ struct wi_frame { #define WI_FCS_LEN 0x4 #define WI_ETHERTYPE_LEN 0x2 + +/* + * HFA3861/3863 (BBP) Control Registers + */ +#define WI_HFA384X_CR_A_D_TEST_MODES2 0x1a +#define WI_HFA384X_CR_MANUAL_TX_POWER 0x3e diff --git a/sys/dev/ic/if_wivar.h b/sys/dev/ic/if_wivar.h index cdc35f6aa6f..d9058470204 100644 --- a/sys/dev/ic/if_wivar.h +++ b/sys/dev/ic/if_wivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_wivar.h,v 1.24 2004/03/18 16:16:10 millert Exp $ */ +/* $OpenBSD: if_wivar.h,v 1.25 2005/02/15 19:44:15 reyk Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -93,6 +93,7 @@ struct wi_softc { u_int32_t wi_icv; int wi_icv_flag; int wi_ibss_port; + int16_t wi_txpower; struct { u_int16_t wi_sleep; @@ -137,6 +138,7 @@ struct wi_softc { #define WI_FLAGS_BUS_PCMCIA 0x0200 #define WI_FLAGS_BUS_USB 0x0400 #define WI_FLAGS_HAS_ENH_SECURITY 0x0800 +#define WI_FLAGS_TXPOWER 0x1000 #define WI_PRT_FMT "%s" #define WI_PRT_ARG(sc) (sc)->sc_dev.dv_xname diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index 0a1ea1f2fe6..36dd974b946 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_ioctl.c,v 1.4 2004/11/25 11:20:04 reyk Exp $ */ +/* $OpenBSD: ieee80211_ioctl.c,v 1.5 2005/02/15 19:44:15 reyk Exp $ */ /* $NetBSD: ieee80211_ioctl.c,v 1.15 2004/05/06 02:58:16 dyoung Exp $ */ /*- @@ -1130,6 +1130,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct ieee80211_bssid *bssid; struct ieee80211chanreq *chanreq; struct ieee80211_channel *chan; + struct ieee80211_txpower *txpower; struct ieee80211_wepkey keys[IEEE80211_WEP_NKID]; static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 @@ -1369,6 +1370,29 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) ifr = (struct ifreq *)data; copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats)); break; + case SIOCS80211TXPOWER: + txpower = (struct ieee80211_txpower *)data; + if ((error = suser(curproc, 0))) + break; + if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) { + error = EINVAL; + break; + } + if (!(IEEE80211_TXPOWER_MIN < txpower->i_val && + txpower->i_val < IEEE80211_TXPOWER_MAX)) { + error = EINVAL; + break; + } + ic->ic_txpower = txpower->i_val; + error = ENETRESET; + break; + case SIOCG80211TXPOWER: + txpower = (struct ieee80211_txpower *)data; + if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) + error = EINVAL; + else + txpower->i_val = ic->ic_txpower; + break; case SIOCSIFMTU: ifr = (struct ifreq *)data; if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h index 7716947b961..a3a205cf046 100644 --- a/sys/net80211/ieee80211_ioctl.h +++ b/sys/net80211/ieee80211_ioctl.h @@ -1,5 +1,4 @@ -/* $OpenBSD: ieee80211_ioctl.h,v 1.1 2004/06/22 22:53:52 millert Exp $ */ -/* $OpenBSD: ieee80211_ioctl.h,v 1.1 2004/06/22 22:53:52 millert Exp $ */ +/* $OpenBSD: ieee80211_ioctl.h,v 1.2 2005/02/15 19:44:15 reyk Exp $ */ /* $NetBSD: ieee80211_ioctl.h,v 1.7 2004/04/30 22:51:04 dyoung Exp $ */ /*- @@ -206,6 +205,19 @@ struct ieee80211_bssid { #define SIOCG80211BSSID _IOWR('i', 241, struct ieee80211_bssid) #define SIOCG80211STATS _IOWR('i', 242, struct ifreq) + +struct ieee80211_txpower { + char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ + int i_mode; /* auto, manual */ + int16_t i_val; /* dBm */ +}; + +#define SIOCS80211TXPOWER _IOW('i', 243, struct ieee80211_txpower) +#define SIOCG80211TXPOWER _IOWR('i', 244, struct ieee80211_txpower) + +#define IEEE80211_TXPOWER_MODE_FIXED 0 /* fixed tx power value */ +#define IEEE80211_TXPOWER_MODE_AUTO 1 /* auto level control */ + #endif #endif /* _NET80211_IEEE80211_IOCTL_H_ */ diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index 8903d3dcebc..26fd666bbd4 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_var.h,v 1.4 2004/12/25 20:40:19 deraadt Exp $ */ +/* $OpenBSD: ieee80211_var.h,v 1.5 2005/02/15 19:44:15 reyk Exp $ */ /* $NetBSD: ieee80211_var.h,v 1.7 2004/05/06 03:07:10 dyoung Exp $ */ /*- @@ -53,7 +53,7 @@ ((struct ieee80211_channel *) IEEE80211_CHAN_ANY) #define IEEE80211_TXPOWER_MAX 100 /* max power */ -#define IEEE80211_TXPOWER_MIN 0 /* kill radio (if possible) */ +#define IEEE80211_TXPOWER_MIN -50 /* kill radio (if possible) */ enum ieee80211_phytype { IEEE80211_T_DS, /* direct sequence spread spectrum */ @@ -225,7 +225,7 @@ struct ieee80211com { u_int16_t ic_txmin; /* min tx retry count */ u_int16_t ic_txmax; /* max tx retry count */ u_int16_t ic_txlifetime; /* tx lifetime */ - u_int16_t ic_txpower; /* tx power setting (dbM) */ + int16_t ic_txpower; /* tx power setting (dBm) */ u_int16_t ic_bmisstimeout;/* beacon miss threshold (ms) */ int ic_mgt_timer; /* mgmt timeout */ int ic_inact_timer; /* inactivity timer wait */ |